Disciplines · Audits

Eve Task Board execution audit — 19 September 2026

Two revisions matter because the worker continued publishing during the review:

7sections21 minread

On this page

Verdict: the agent is producing substantial, tested work, but completion is not yet dependable. Earlier audit feedback has led to real improvements. This review nevertheless reproduced defects that the existing passing tests miss, found a configuration-dependent serving failure in the newest code, and found recent closures bypassing the prescribed completion command.

This is an audit and a set of proposed adjustments. No implementation, task, status, configuration, commit, push, deployment, or provider-account change was made. This report is the only intended workspace change. Recommendations below have not been applied.

Scope and evidence boundaries#

Two revisions matter because the worker continued publishing during the review:

Snapshot Revision How examined
Shared checkout ab546895c0f3ddc4e1ff8b2ad68d41295c0c8434 Source, task journal, board checks, focused automated tests, and isolated reproductions
Newer origin/main 5ffe6f4048a082449540a9e38dbd398a4e1c5c66 Retrieved into a separate temporary Git repository; inspected changes, tracker, SQLite journal, and reproduced the prompt-hash issue with an isolated source overlay

The newer snapshot includes EI.7.04 and the EI.0.12/EI.0.13 repairs. Those repairs are credited below; failures reproduced on the older checkout must not be presented as an independently measured current-main total. The shared checkout was not updated or reset.

The review concentrates on the recent presentation-integration work and the board mechanisms controlling its execution. It does not certify every item in this large monorepo. No live model requests, database migrations, database-writing integration suites, browser stack, or staging deployment were run. Existing integration evidence was inspected and is distinguished from tests independently rerun here.

The host had approximately 15 GiB RAM, 15 GiB swap, and 13 GiB free on the root filesystem. Tests ran in narrow groups with one worker; no full-workspace build or test sweep was attempted. Runtime for the independent tests: Node 22.23.1, Vitest 4.1.7, Linux.

What is going well#

  • The board is structurally healthy at the tested revision. ./eve check passed eight checks and validated 1,411 checkbox files across 51 families. ./eve drift --fail-on-drift reported zero edited, checked, or unknown open items across 24,822 open boxes. This establishes consistency of the checked structures, not feature correctness.
  • The worker is testing meaningful behavior. The notes integration tests exercise real SQL isolation and erasure; the newer EI.7.04 evidence describes real confirmation, decline, replay, tenant propagation, and audit-event tests. Several commits document negative controls rather than only successful examples. The prior audit independently reported the store and route suites passing; this audit did not rerun their database writes.
  • Feedback is being acted on. The newer source claims the four notes routes, inventories the database variable, adds a notes threat plane, and repairs the journey parity assertions with an explanation of the two new domains. EI.0.12 and EI.0.13 are closed in the newer board. The source changes were reviewed here; their reported passing results were not independently rerun on that complete revision.
  • Claim timing improved in the sampled journal. Of 43 recorded worker done events in Phase 0 at the checkout revision, 18 followed their latest claim by under a minute. Among the 11 after 12:45 UTC, only one did; median time from claim to completion was 280 seconds. That one was an administrative closure of previously completed work. Timing is a coordination signal, not proof of when coding began.
  • The latest work adds useful safeguards. EI.7.04 limits note reads, gates mutations on confirmation capability, records audit events, and explicitly acknowledges remaining stored-note threat-model gaps.

These strengths support continuing the work after addressing the following issues. They do not support treating checked boxes or passing narrow suites as complete acceptance.

Findings requiring adjustment#

F01 — High: enabling notes changes the supposedly fixed prompt census#

Status: reproduced using the newer source; not covered by the existing floor-only repair description.

EI.7.04 makes the three note tools conditional on a configured notes database. Its builder provides a presentationNotesAvailable override for complete tool inventories. However, collectHashableToolDefinitions() still calls that builder with only includeOperatorMemory: true.

With the remote tool/store code and the unchanged hash collector, an isolated probe produced:

Configuration Tools in hash Prompt hash
Both database variables absent 96 3b320e8acc3627b5e8e576f554c2f25e705305b88714f47f6ee3d6ca5ac3b717
Notes database variable present, dummy URL 99 f82199d5d516bc171028b0e147732c4a31f5a0fe009380ff2ca1ccc77288e8d6

The three added definitions were presentation_add_note, presentation_list_notes, and presentation_resolve_note. No database connection was needed. The approved constant remains the first hash.

Impact: a test environment without database configuration can pass the hash assertion while a configured deployment fails it. wireNormalizedAssistantModelLifecycle() compares this hash with the approved value and suspends serving on a mismatch. This is a concrete conditional failure, not proof that a particular deployed instance was observed failing.

Proposed task adjustment: extend EI.0.10 with this defect, or add an explicit prerequisite repair. Require a deterministic union of all offerable definitions, including the three note tools, independent of database configuration. Then follow the existing measured re-stamp procedure. Do not hand-edit the expected hash to conceal the missing census.

Acceptance: compare tool names and hashes with both database variables absent and with each configured separately; the census must be identical and include all three tools. Run the prompt gate and a configured lifecycle boot test. Changing any note-tool description or input schema must invalidate the approved hash.

Sources: hash collector, around line 102; lifecycle boot, lines 77 and 108; remote admin-agent-tools.ts, options around line 140 and configuration gate around line 1523. Probe output: /tmp/eve-audit-hash-repro-2026-09-19.log.

F02 — High: the shipped notes DELETE proxy fails ordinary requests#

Status: independently reproduced; relevant proxy code is unchanged in the newer snapshot.

The DELETE proxy uses forwardAdminBffPost(), which always sets content-type: application/json and forwards await request.text(). A normal DELETE with no body therefore reaches Fastify as empty JSON. A temporary probe called the real exported admin DELETE handler against an in-process Fastify route using the installed framework:

text
upstream status: 400
code: FST_ERR_CTP_EMPTY_JSON_BODY
handlerReached: false

There is a second independent defect: when the upstream correctly returns a bodyless 204, the helper reads "" and constructs new NextResponse(body, { status: 204 }). The same probe returned:

text
TypeError: Response constructor: Invalid response status code 204

Why existing verification missed it: the current proxy tests send a synthetic JSON body even for DELETE and mock an upstream 200 response. All 16 proxy/binary tests passed in this audit. The BFF route tests separately exercise a correctly formed bodyless request, so neither side tests the actual composition.

Proposed task adjustment: create a corrective task linked to shipped EI.7.03, and make EI.7.05 depend on it. Require correct forwarding of bodyless methods and correct construction of bodyless responses.

Acceptance: real admin proxy to real BFF semantics for create, read, update, resolve, DELETE 204, repeated DELETE 404, missing session, and foreign scope. The browser test must delete a persisted note and verify its absence after reload. Retain the credential-leak tests.

Sources: proxy helper, lines 94–125; DELETE proxy; BFF handler, around line 1797; proxy tests. Reproduction: /tmp/eve-audit-proxy-repro.ts and its dated log.

F03 — High: note staleness does not cover the slide JSON it claims to cover#

Status: independently reproduced; the relevant digest/projection is unchanged in the newer snapshot.

EI.7.01 specifies slide_content_sha256 as the hash of the slide JSON the note was written against. The implementation hashes a selected projection: id, title, subtitle, takeaway, notes, questions, sources, layout, and source revision. The loader drops fields including composition, points, rows, and columns.

The real library contains 1,721 slides, including 1,459 with compositions, 214 with points, and 119 with rows and columns. On portfolio-tracks, changing an existing composition node's visible title left slideContentDigest() unchanged. Thus the digest cannot detect that kind of visible content change.

The existing staleness integration case changes a synthetic takeaway digest and accepts either true or null when the note is read. It never proves the necessary transition: an actually current note is false, its real library slide changes, and the note becomes true.

Proposed task adjustment: add a corrective task for EI.7.01/EI.7.02 and make the stale badge in EI.7.05 depend on it. Define a canonical hash over the full relevant slide object, with documented handling of key order and non-content metadata. Reuse that definition in EI.8.02/EI.9.01 to prevent competing meanings of “same slide.”

Acceptance: test false → true using a temporary real library; separately edit title, composition node text, a table cell, and a point. Preserve the null behavior for an unreadable library. Also test a slide changing while a note confirmation is pending: reject/reconfirm or explicitly bind the approved version, rather than silently recording a later one.

Sources: digest, around line 58; library projection, around line 261; current staleness test, around line 187. Probe output: /tmp/eve-audit-slide-digest-repro-2026-09-19.log.

F04 — High: recent closures bypass the prescribed evidence and completion mechanism#

Status: confirmed in the newer committed SQLite journal.

EI.7.04, EI.0.12, and EI.0.13 were marked shipped by tracker import, with actor markdown, followed by worker notes. They do not have corresponding done events. EI.7.04's journal explicitly says “Closed via tracker import.” Their long inline DONE narratives also bypass ./eve done's 160-word limit.

The imported commit references are not reliable implementation references: EI.7.04's import records 0bab294f6aa, which predates its implementation in 7a8c1824; EI.0.13 records 7cf0f518234, preceding its implementation in 5ffe6f40. At the older snapshot, 56 worker done events also had no structured commit reference.

Impact: the apparent completion path can omit fencing-token validation, evidence limits, and reliable attribution. Structural checks still pass. next and claim accept shipped dependencies, so a premature closure can unlock dependent work. This establishes a process weakness; it does not establish that the worker fabricated its test results.

Proposed task adjustment: add a board-integrity task covering closure provenance. Keep import recovery available, but distinguish recovered historical closures from a normal agent completion. Require normal worker closures through ./eve done; attach the actual implementation commit or an immutable evidence manifest before independent verification. Add a reconciliation check for recent imported closures lacking that evidence.

Acceptance: checking a tracker box and importing it cannot produce the same assurance signal as a token-validated, evidenced completion. A legitimate recovery remains possible and visibly labelled. Verification references the implementation revision and rechecks applicable acceptance criteria.

The newer Phase 0 snapshot contains 43 shipped and six verified rows. Those are different assurance levels and should remain visibly different in reports.

Sources: remote TODOS/eve-task-board.sqlite, events for the three keys; completion implementation; verification implementation; dependency admission.

F05 — High: upcoming draft/apply/revert tasks leave essential contracts unassigned#

Status: specification gaps, not failures of code that has not yet been built.

Three gaps should be resolved before the authoring chain is implemented:

  1. Ownership before preview and discard. EI.8.05 requires the BFF to answer whether a draft belongs to the operator; EI.8.06 requires discard. EI.8.02 defines replacement slides and basedOn, but no durable owner/tenant record. The first explicitly required persisted change row is EI.9.03, after apply. Assign ownership persistence and owner-checked lookup/discard endpoints before preview needs them; do not leave each later task to invent them.
  2. Revert requires before-content, not just hashes. EI.9.04 consumes recorded “before” objects, but EI.9.03 explicitly requires before/after hashes, not preservation of those objects. Require recoverable before-content, its integrity checks, lifetime, and access scope before promising revert.
  3. Rollback verification covers too little. EI.9.01 promises restoration of every touched file but checks hashes only under content/ and decks/. The builder also produces catalog.json, index.html, coverage.json, and narration-script.json. Extend the check to the complete write set, including newly created files. Define recovery for interruption between file changes, build completion, and receipt persistence, and coordinate later narration/PDF rebuilds with apply.

Proposed task adjustment: amend EI.8.02–EI.8.06 and EI.9.01–EI.9.06 with these concrete responsibilities and dependencies. Keep the chosen local-operator architecture; these gaps do not require introducing a deployed worker.

Acceptance: foreign-operator and foreign-tenant preview/discard/apply/receipt/revert requests are refused; confirmation is bound to the exact draft revision; failed or interrupted operations recover consistently; rollback restores the complete generated output set; revert succeeds after restart using durable before-content.

Sources: Phase 0 task definitions, sections 0.9–0.10; builder output set, around lines 673–706.

F06 — Medium: the new read cap needs an explicit HTTP completeness contract#

Status: confirmed by inspection of the newer source.

EI.7.04 correctly adds a 200-row cap to the store and a measured truncated flag for the tool's 50-row page. The HTTP GET handler still returns only { notes }, without a cursor, total, or truncation indicator. EI.7.05 asks for a whole-guide count and a notes list.

Impact: a busy operator can receive a silently incomplete HTTP result. The planned UI has no reliable way to distinguish an exact whole-guide count from the page cap or retrieve later rows.

Proposed task adjustment: extend the notes API contract before EI.7.05 consumes it. Define stable pagination and explicit completeness/count semantics. Keep the server-side cap.

Acceptance: seed more than 200 notes, including equal timestamps; every intended note is retrievable without omission or duplication, scope remains enforced, and the UI never labels a partial page as an exact total.

Sources: remote presentation-notes.ts, listNotes(); HTTP GET, around line 1691; EI.7.05.

F07 — Medium: the board's supported-runtime test suite still fails#

Status: independently reproduced; no repair for these cases appears in the newer diff.

The CLI/library suite returned 270 passed, three failed, zero skipped. The failures are in check.spec.mjs, list.spec.mjs, and show.spec.mjs: Node's SQLite ExperimentalWarning contaminates stderr that the tests count as problem lines or parse as one JSON document.

A diagnostic rerun of those three files with NODE_NO_WARNINGS=1 passed 27/27, supporting the warning-contamination diagnosis. That control is not a proposed permanent workaround and does not make the ordinary command green.

Proposed task adjustment: add an explicit board task to make error-output assertions/protocol handling robust on supported Node versions, with the exact failing command in its acceptance criteria. A commit message acknowledging these failures is useful evidence, but it is not a tracked repair.

Sources: check tests, around line 246; list tests, around line 254; show tests, around line 244. Logs: /tmp/eve-audit-board-tests-2026-09-19.log and /tmp/eve-audit-board-warning-control-2026-09-19.log.

F08 — Medium: shared slides are assigned to the first guide, regardless of viewing context#

Status: real-library lookup and source inspection; database behavior not independently rerun.

The library has 15 slides used by multiple guides. For example, whereUsed('three-release-contract') returns orientation followed by release-acceptance. Both the POST route and the newer add-note tool choose whereUsed(slideId)[0] for the stored guide_id; neither accepts and validates the guide the operator was viewing.

Consequently, a note made while viewing that slide in release-acceptance would be stored against orientation. A read filtered by the viewed guide would exclude it. This matters to EI.7.05's whole-guide count and to the list-notes tool's guide filter, even though a read filtered only by slide can still find the note.

Proposed task adjustment: define shared-slide semantics before finishing EI.7.05. Either notes belong to the viewed guide, in which case persist the validated guide/slide pair, or they belong globally to the slide, in which case guide reads must use actual membership rather than an arbitrary stored first guide.

Acceptance: create/read/count a note from each guide containing a shared slide, reject a guide that does not contain it, and verify that browser and model-tool paths follow the same rule.

Sources: POST route, around line 1743; remote admin-agent-tools.ts, around line 550; real-library lookup recorded in /tmp/eve-audit-slide-digest-repro-2026-09-19.log.

Existing audit tasks: retain, refine, or credit#

Item Audit assessment Proposed adjustment
EI.0.12 — security inventories Repair present in newer main; worker reports the named negative control Credit the repair; independently verify on its implementation revision. Do not reopen solely because the older checkout fails.
EI.0.13 — journey parity Repair present in newer main with an explanation of curated versus mined domains Credit the repair; retain the measured stamp and negative control.
EI.0.14 — voice mock/sandbox discrepancy Still open; 14 failures independently reproduced on this Linux checkout Retain. Require the cause, matching runtime/configuration evidence, and passing results in the named environments.
EI.0.15 — provider route Still open; prior audit corrected the unsupported account-wide blocker diagnosis Retain its concurrent route probe and actual binding check. Preserve retention/admission requirements; do not infer account policy from a single pinned route's refusal. No provider behavior was remeasured here.
EI.0.10 — prompt ratchet/floors Still open; floor coverage fails, and F01 adds a separate configuration-sensitive census problem Repair the census, then perform the measured re-stamp/floor work. Explicitly verify configured and unconfigured environments.
EI.6.04 / EI.6.05 — final ratchet and live deck Necessary final acceptance work remains Keep live results distinct from scripted-provider tests. Record exact case/attempt/skip counts, model binding, cost, and source revision.
EI.5.06 / EI.5.08 — local deploy configuration versus staging proof The split is recorded, but EI.5.06 still mixes its old third check with a later sentence excluding it Rewrite the acceptance paragraph cleanly so only the two retained checks remain; keep the staging check solely in EI.5.08.
EI.7.05 — notes UI Ready by existing dependencies, but its underlying feature has F02/F03/F06/F08 gaps Add repair dependencies and browser acceptance for full CRUD, reload, staleness, pagination, denied scope, and error states. Follow the mandatory frontend skill during implementation.

The priority is to make acceptance harder to misread or bypass, rather than add more general prose rules.

  1. Repair F01 and F02 first. They affect serving and the basic notes workflow. Resolve the content-digest and API-completeness contracts before finishing the notes UI.
  2. Give every task an explicit verification set. List commands, expected cases, required services, and allowed skips. The ordinary BFF Vitest configuration excludes *.integration.spec.ts; running src/assistant does not run the notes store or confirmation integration suites. Include their integration configuration explicitly where applicable.
  3. Require configured and unconfigured tests for conditional features. Database presence, confirmation capability, mounted library, and authoring interpreter are separate configurations with different behavior. F01 shows why a passing default configuration is insufficient.
  4. Test the composed boundary. Proxy and BFF tests are valuable, but include at least one path through both. UI CRUD needs a browser test backed by the real route/store path; a mocked stream or mocked 200 response cannot prove that path works.
  5. Use compact, revision-bound evidence. Record task key, implementation SHA, command/configuration, pass/fail/skip counts, required-service availability, negative-control result, and links to durable logs. Put extended explanations in a separate evidence file. Imported closures require reconciliation; they must not silently gain the same trust as reviewed completions.
  6. Keep exceptions explicit and owned. Do not count known failures as passing. If an unrelated failure is allowed temporarily, name its exact case, repair task, and review condition; any additional failure is a new finding. Reconcile this with the repository's all-applicable-checks requirement instead of relying on informal exceptions.
  7. Resolve F05 before assigning the authoring chain. Assign ownership, before-content preservation, complete rollback, and interruption recovery to named tasks now, while changing the plan is inexpensive.

Suggested evidence shape for future closures:

text
Task / implementation SHA / runtime and test configuration
Required checks: command → passed, failed, skipped
Real services/data exercised; explicit unavailable coverage
Negative control and observed failure
Known failure → owner task; durable evidence path

Independent verification ledger#

Check Result Boundary
./eve check Eight checks clean; registry clean Checkout revision
./eve drift --fail-on-drift Zero edited/checked/unknown open items Checkout revision; does not reconcile every closed item's stored body/line
BFF security, prompt hash, model inventory, journey parity, and STT files 223 passed, 19 failed, 12 files Checkout revision only
Failure breakdown 14 STT; two parity; one family-floor; one environment inventory; one threat-model coverage Last two plus parity have newer source repairs; no new-main aggregate claimed
Admin notes proxy and binary proxy suites 16 passed Passing tests miss F02
Board CLI/library suite 270 passed, three failed, zero skipped Checkout revision, normal warnings enabled
Board warning diagnostic 27 passed Three affected files only, warnings suppressed for diagnosis
Actual DELETE proxy reproduction Empty DELETE → 400; upstream 204 → TypeError In-process framework probe; no database writes
Slide digest reproduction Changed visible composition title → same digest Real library object, in-memory change only
Newer note-tool hash reproduction Database absent: 96 tools; configured: 99 tools, different hash Isolated source overlay; dummy URL, no database/provider request

The BFF test command was:

bash
cd apps/oshun/bff
VITEST_MAX_WORKERS=1 ../../../node_modules/.bin/vitest run \
  src/assistant/security \
  src/assistant/eve-smx-prompt-hash.spec.ts \
  src/assistant/model-leg-inventory.spec.ts \
  src/assistant/journey-inventory-graph-parity.spec.ts \
  src/assistant/openrouter-stt.spec.ts --reporter=dot

The board suite was:

bash
node --test --test-concurrency=1 \
  tools/eve-task-board/cli.spec.mjs \
  tools/eve-task-board/lib/*.spec.mjs

The audit used the installed Node binary through an explicit process-local PATH because the shell's default PATH lacked Node. Temporary logs and probes remain under /tmp/eve-audit-*; the findings and acceptance criteria above are recorded here so the report remains useful without those temporary files.

Completion boundary: this report proposes changes only. No repairs, new board items, closure changes, independent-verification marks, commits, or pushes were performed, in accordance with the request to take no action.

Adoption record — 19 September 2026#

Added by the session that acted on this report, at the owner's request ("act on all recommendations you think are correct and worthwhile"). Before anything was filed, five of the report's code claims were re-checked against source on origin/main (F01, F02, F03, F08 and the lifecycle gate F01 depends on); all five held. Every repair is a board item closed through ./eve done by claude-fable-audit, pushed to main.

Finding Item Commit What shipped
F01 EI.0.17 ea97dd7921c The hash collector passes the builder's census override. Measured in three environments: the same 99 names and f82199d5 each time, which is this report's configured-stack hash, so no served byte changed. Constant, ratchet and scorecard re-stamped from that measurement; a spec case computes the census under each environment.
F02 EI.7.06 0d06426c033 A bodyless request is forwarded with no body and no content type; 204, 205 and 304 are relayed with a null body. A spec drives the real admin handlers against a listening Fastify: create, list, PATCH, DELETE 204, the same DELETE 404, no session 401.
F03 EI.7.07 eb685850046 The digest is canonical JSON of the whole slide object as its chapter file holds it, with a digest version (migration 20260919190000) so existing notes are compared under the definition they were written with. On a temporary copy of real chapter files: false, then true after a title edit, a composition node's text, a table cell, a point.
F08 EI.7.08 cd8c6ad0846 Decided: a note belongs to its slide. A read by guide goes through membership; guide_id records where the note was written, validated against the library. The tool's definition did not change.
F06 EI.7.09 3e0f72fd51c { notes, nextCursor, total }: a cursor on the last note's id compared in SQL, a real COUNT. 205 notes with forty sharing a millisecond are walked without loss or repeat.
F07 ETB.5.06 2496547544f lib/db.mjs is the one import of node:sqlite and drops its experimental warning, by name and text. The suite is 291 passed, 0 failed with warnings on.
F04 ETB.5.05 0aa4e8cbf02 ./eve show prints closed by; ./eve check prints a warning: line for every task shipped by import since 2026-09-19 with no done and no verify. The import door stays. Eight are listed today: EI.7.04, EI.0.12, EI.0.13, EI.0.15 and ETB.8.02–8.05.
F05 EI.8.02, 8.04, 8.05, 8.06, EI.9.01, 9.03, 9.04 df1a4400cf4 Specification only, before the chain is built: the draft records who proposed it and EI.8.04 owns the one owner-checked lookup and discard; rollback covers the builder's whole products set with a journal and a recover command; the receipt keeps the before objects a revert rebuilds from.
Table EI.5.06, EI.7.05, EI.0.10 df1a4400cf4 EI.5.06's Verify clause names only its two checks. EI.7.05 depends on EI.7.06–7.09 and its browser check runs over the real proxy and store. EI.0.10 carries a note that the approved hash moved.

Recommendations 3, 4 and part of 5 became three measured rules in the phase's "Rules for this phase" section (one spec crosses the seam; a feature behind configuration is measured in both states; close through ./eve done, after the commit it names exists).

Not adopted, and why.

  • Recommendation 2's supporting claim is wrong: the ordinary BFF Vitest configuration does NOT exclude *.integration.spec.ts. Its include is src/**/*.{test,spec}.ts with no exclude, and vitest.integration.config.ts is the one that narrows. No rule was written on it.
  • The EI.0.15 row was stale when read: 5320fb7ec26 had already shipped it.
  • F04's severity. Closing by import is a recovery path the board provides on purpose, so nothing was made to refuse it; the defect was that it could not be told apart, and that is what was fixed.
  • Recommendations 5 and 6 as prose (an evidence template, an exceptions register). The 160-word evidence limit and the phase's existing known-red list already do that work; the report itself asks for fewer general rules.

One thing this session got wrong, recorded because it is this report's own F04. EI.7.08's done event names 45a9cd7b941, the commit before the work: the code commit had failed its lint hook and the command chain carried on. The journal has a correction note naming cd8c6ad0846, and every later closure here compared git rev-parse HEAD before and after the commit first.

Left open. EI.0.14, EI.0.10's floor, EI.6.04, EI.6.05 and EI.5.08 are as the report found them. The eight closures ./eve check now lists want a second session's ./eve verify.