> **Status**: Backlog > **Updated**: 2026-09-13 03:17 > **Scope**: Medium/long-term goals deferred from active plan execution Current plan tasks live in the active plan's `## Task Breakdown`. Do not duplicate that execution checklist here. Record only work intentionally deferred beyond this slice, with the tradeoff and revisit trigger. Audit evidence and closure rationale: `docs/researches/20260907-deferred-goal-ledger-reconciliation.md`. Conditional rows remain deferred; this ledger does not...
Scanned 9/21/2026
Install to Claude Code
npx -y skills add Ancienttwo/repo-harness --skill archive --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Archive?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/ancienttwo-archive-01e11127)More formats (shields.io, HTML) on the badges page.
> **Archived**: 2026-09-13 04:17
> **Related Plan**: plans/archive/plan-20260913-0258-repo-harness-test-skill.md
> **Outcome**: Completed
> **Source Plan**: (none)
> **Parent Run ID**: run-20260913-0417
# Deferred Goal Ledger
> **Status**: Backlog
> **Updated**: 2026-09-13 03:17
> **Scope**: Medium/long-term goals deferred from active plan execution
Current plan tasks live in the active plan's `## Task Breakdown`.
Do not duplicate that execution checklist here. Record only work intentionally deferred beyond this slice, with the tradeoff and revisit trigger.
Audit evidence and closure rationale: `docs/researches/20260907-deferred-goal-ledger-reconciliation.md`. Conditional rows remain deferred; this ledger does not authorize their implementation.
## Deferred Goals
| Goal | Why Deferred | Tradeoff | Revisit Trigger |
|------|--------------|----------|-----------------|
| Reduce repeated real CLI setup across the split helper-script suites | The fixture audit measured on the pre-split monolith at `9b8b347b` found 204.6 seconds inside 240 direct Bash CLI invocations out of a 252.62-second local run; after the split, `tests/helpers/helper-script-fixture.ts`, `tests/helpers/repo-fixture.ts` and the per-script test files still install full helper fixtures and run real entrypoints, and seven related dedicated suites protect distinct entrypoints and failure branches, so no complete redundant case was established | Removing fixture-only shells and unrelated SQL setup reduces deterministic work but leaves real CLI execution dominant; sharing mutable repositories or dropping boundary coverage would distort the tests | The next helper-suite optimization: identify one repeated composition setup in `tests/helpers/helper-script-fixture.ts` or `tests/helpers/repo-fixture.ts` that sits below an existing test seam, retain real entrypoint coverage in the per-script test files and measure invocation/setup cost before and after |
| Make the MCP HTTP direct-coding E2E consume process completion | Main run `34684444855` on `6a8439a8` failed on Windows at `tests/cli/mcp-http.test.ts:1337`: the 3000 ms initial yield returned a valid running session after 3011 ms, but the test immediately required exit 0 and complete output; the test and process manager were unchanged from the passing PR run | A bounded CI job retry can recover delivery but does not repair this timing-sensitive assertion; no product-process failure is established by the observed running snapshot | The next recurrence or edit to `tests/cli/mcp-http.test.ts`: follow the returned session with `write_stdin` to a bounded completion deadline, accumulate output and retain the exit/output assertions; do not increase the initial yield or add sleep-based retries |
| Reassess hosted Governance/Test scheduling cost | The CI audit reported 3 of the latest 12 failed runs failed only Governance, while each independent Test job consumed about 20 minutes; the owner explicitly retained parallel scheduling in this slice | Parallel jobs preserve functional failure visibility after a governance failure, as required by the 2026-09-09 lesson; serial scheduling would save those minutes but suppress that evidence | Measure again two weeks after the CI selection rework merges, then decide whether the observed cost justifies changing the policy |
| Harden the CI documentation lane after #415 | Gatekeeper review of #415 left two should-fix items and three nits that were not worth cancelling the in-flight full run: `scripts/replay-ci-coverage.ts` is outside tsconfig `include`, so `check:type` only sees the selector and scanner through test imports; the documentation job has no explicit `jq` install step; Required / CI prints no draft-specific message before exiting; the migrated documentation contracts lost the SSD-06 rationale comment; `scripts/ci-documentation-consumers.ts` relies on `typescript/unstable/*` APIs without a pin note | Until fixed, a change to the test imports could silently drop two production scripts from typecheck, and the docs lane depends on the runner image shipping `jq` | The next change touching `.github/workflows/ci.yml` or `scripts/*.ts`, batched with it rather than shipped alone |
| BRC14 — fresh GPT Pro main audit 与 exact-SHA 版本准入消费 | Owner 于 2026-09-10 禁止容器执行基底,而 campaign 的执行证据契约整条绑死容器 receipt(`scripts/contract-run.ts:181-183,234-239`、`src/effects/automation/campaign-worker.ts:140`、`src/core/automation/campaign-runtime.ts:20-21,51-73`、`src/effects/automation/campaign-runtime.ts:28-91,110-131`);纯宿主机 BRC 路径未设计、未实作,fresh audit 与版本准入没有可运行的对应物 | fresh audit 从未执行,exact-SHA 准入未接线,group 2/3 sequencing 未验证;sprint 行以 Owner scope amendment 关闭,Phase A 的 audit 收口能力在纸面上存在但从未被证明 | Owner 决定宿主机 BRC 执行证据契约,或重新允许容器 worker |
| BRC15 — Canary 1(model-free 故障集)与 activation ladder 推进 | 同一个执行基底冲突:Canary 1 的闭集错误词汇断言与 ladder 的每一级都绑定当前容器证据形状,换基底后旧观测不可跨基底复用;2026-09-09/10 的 9 个 campaign 均停在 worker preparation 之后 | Canary 1 未做,Canary 3 只做到「PR 自动生成 + 人工 merge」,自动 Issue closure/cleanup/fresh audit 未跑通;`development_campaign.mode` 停在 `off`,`active/manual` 未被真实 canary 证明 | Owner 决定宿主机 BRC 执行证据契约,或重新允许容器 worker |
| Derive the claim-scope canonical fence from the lease record | The fleet collector still reads the main checkout's active-sprint marker to resolve a claim's canonical source, which is the wrong authority when the claim's own lease already names one | A worktree whose lease points at a different sprint than the main checkout's marker is observed against the wrong canonical row | A repository observed with two live sprints, or the next change to `readActiveSprintPath` callers |
| Let R1 delivery and reachability contribute to the Fleet card `attention_owner` | Whether an unreachable Agent Runtime is the operator's problem or the agent's is a product contract decision, not an implementation detail of the card projection | A card whose runtime is unreachable reports `attention_owner: 'none'` unless another signal raises it | The Task Board defining who owns a stalled runtime |
| Decide whether `addressed_to_current_claim` means more than `unread_count > 0` | The Fleet card currently derives it from the unread count alone, so it carries no independent fact; whether an unread message is addressed to the live claim is a Task Board product contract decision, not a projection detail | An operator reading the card cannot distinguish "there is unread mail" from "the current claimant is the addressee" | The Task Board defining per-claim addressing, or the next change to the card's inbox projection |
| Split the Fleet card `task_label: null` into "no sprint row" and "empty Task cell" | The projection has one null for two different observations and no consumer has yet needed to tell them apart | A card with a real but blank Task cell is indistinguishable from a card with no canonical row at all, so a board reader cannot tell a data gap from an authoring gap | A board consumer that must act differently on the two cases, or the next change to the sprint row reader feeding the card |
| Carry `superseded_revision_count` into the Fleet card summary | #320 surfaced it through `repo-harness fleet inbox list --json`, which serializes the whole `listTaskInbox` result; the card summary has its own projection and adding a field there is a transport change the containment slice did not need | Skipped stale inbox events are observable from the CLI but invisible on the board, so an operator sees a quiet inbox without knowing events were passed over | An operator reporting messages that never appear on a card, or the next additive change to `OperatorFleetSnapshotV1` |
| Content-verify automation reconciliation `evidence_refs` | The refs are shape-checked (scheme-prefixed typed refs with a digest) and a not-started reconciliation must name the run, but nothing resolves a ref to bytes: the digest-addressed authority that could — provider usage records and #287 attempt receipts — does not exist for this path yet | A reconciliation can cite a well-formed ref that resolves to nothing, so `reconciled_not_started` rests on the caller's honesty about a run it names rather than on evidence the store re-reads | The provider usage/evidence authority becoming readable by digest (#287 attempt receipts or the provider adapter), whichever lands first |
| Make the automation store's time source a permission boundary | The clock seam is closed twice (internal-only module plus an env gate), but a same-process caller can set the env var and import the module, so it is a test-only convenience, not a boundary. A real boundary needs process isolation between the controller and the budget store | Under threat model A this is sufficient; a caller with the store's own privileges can move the store's clock, which is the same privilege as writing the store's files | Process isolation between an automation controller and the budget authority, or the first deployment where the controller is not already trusted at the process level |
| Enable automation token and cost budget limits by wiring provider-attested usage | The #282 slice has no authority for it: metric support would have to be read from the provider capability store by revision, and each charge would have to reference a provider-attested usage record the budget store re-reads and re-parses. Accepting a caller's token number instead would be a self-asserted limit, which is worse than no limit, so the store refuses a configured hard token/cost limit at preflight | Wall clock, steps, acquisitions, runner invocations and the no-progress streak are enforced; token and cost spend is unbounded by this ledger and must be bounded elsewhere | The first automation run whose provider path persists attributable usage the budget store can re-read by digest — evidence required: the store/effect that owns it, the usage record shape, and the capability revision it binds |
| Unify the task-contract `delegation.budget` reader | #282 needed the budget store to parse a contract's delegation budget from the contract's own bytes, and the existing reader lives inside `scripts/contract-run.ts`, a CLI script with no importable surface. Extracting it is a separate refactor across the contract-run path | Two parsers read the same block, so a change to the contract's delegation shape has to land in both `src/core/automation/budget.ts#parseContractDelegationBudget` and `scripts/contract-run.ts` | The next change to the `delegation.budget` block shape, or the next consumer that needs the same parse |
| `plan-source-ref-task-cell-coupling` — move the plan-to-row binding in `proveCanonicalTaskPlan()` (`src/effects/state/coordination-canonical-source.ts:155,223`) off the exact Task cell. It builds the expected plan `Source Ref` as `sprint:<sprint path>#<exact Task cell>`, so a Task rename still fails the proof with `plan_source_mismatch` even though `task_id` survived; that failure code gates external-source binding and every contract-mode Fleet offer | Issue #283 scoped the change to task identity. The `Source Ref` grammar is a different authority (which plan document owns this row, not who owns the work), and changing it would rewrite the `> **Source Ref**:` header of every existing plan under `plans/` and `plans/archive/` in the same slice | Identity, leases, messages, Work Graph joins and binding receipts all survive a rename now; what still breaks is one derived proof whose failure is loud, typed, and repaired by editing one plan header. The cost of leaving it is that a rename is not yet fully free — it is cheap instead of free | The first real title edit on a task that already has a bound plan: if repairing the plan header is not acceptable at that moment, move the binding to `sprint:<sprint path>#<task_id>` with a one-shot header migration |
| `sprint-schema-v1-parser-removal` — remove the sprint backlog schema 1 parser: `src/core/state/sprint-schema-v1.ts`, `repo-harness sprint migrate-schema`, and the schema 1 branches in `src/core/state/sprint-backlog-rows.ts`, `scripts/sprint-backlog.sh`, `scripts/check-task-workflow.sh`, `scripts/refresh-current-status.sh`, and `scripts/heartbeat-triage.sh`, plus its one authorised runtime consumer `lookupLegacyTaskForReconcile()` reached from `sprint reconcile` in `src/effects/state/coordination-sprint.ts` (the bounded pre-migration recovery window: a `completing` residue over a completed row). Compatibility owner: the repo-harness coordination-identity maintainer | Schema 2 landed with issue #283 and both tracked sprints under `plans/sprints/` migrated with it (the succession sprint's row 10 `completing` residue cleared through the bounded `sprint reconcile` window in `772cc059`; the repair campaign sprint in `ed1a01de`). What still holds the parser is the twelve archived schema 1 sprints under `plans/archive/` and downstream repos that have not run the one-shot migration | The v1 parser is unreachable from any identity-minting path (it only feeds the migration command and read-only status counting), so the cost is dead code and two grammar branches to keep in sync across TypeScript and awk, not a live dual-read window | Every tracked sprint under `plans/sprints/` reports `Backlog Schema: 2` and no archived sprint needs re-activation; the remaining blockers are the archived schema 1 sprints and downstream repo migrations |
| Decide the remediation path for a non-collaboration delegated run whose goal legitimately contains the literal `[CoordinationContextUntrusted]`: the C7 discriminator classifies it as a collaboration dispatch and refuses it as `binding_missing` with no way to proceed | Plausible in this self-hosting repo, where the marker appears in source, docs and test fixtures, but no such run has been observed; inventing an escape hatch now would be the compatibility fallback the program forbids, and any escape hatch is exactly the bypass the fence exists to prevent | The current behaviour is semantically consistent and fail-closed — a goal bearing the marker is treated as carrying injected context until a binding says otherwise — but it is untested and a caller hitting it gets a refusal with no documented next step | The first false-positive report, or C9's canary runs putting real repository prose into a delegated goal |
| Complete the deferred C2/C5 direct entrypoint declarations for `src/core/collaboration` | The collaboration capability already declares responsibilities and several later entrypoints; `collaboration-substrate-program.md` still records the C2/C5 direct declarations as deferred. Adding those entries remains a separately accepted semantic model change | Prefix-based resolution works, but the deferred direct entrypoints are not model-declared; existing responsibilities must not be treated as wholly absent | The next collaboration model change that needs these direct entrypoints; use `architecture-projection accept` for the observed semantic delta |
| Correct the architecture-acceptance audit trail: C1 and C3 recorded their accepted major changes as `event.user-approval-20260829-c1-collaboration-architecture` and `event.user-approval-20260830-c3-collaboration-architecture`, but the approver in both rounds was the orchestrator agent, not the user | The `event.user-approval-*` shape came from the ME-series precedent in `docs/researches/20260824-persistent-module-engineer-organization.md` and was copied forward before anyone asked who the approver actually was. The new acceptance verb preserves an explicit approval reference instead of minting a user prefix, but rewriting two merged historical records is a separate audit migration outside that CLI work-package | Two merged acceptance records name a human approver for a decision an agent made. Nothing downstream reads these ids, so no gate is wrong today, but an audit that trusts the id prefix would attribute an agent approval to the user | The next bounded audit-history migration touching either C1 or C3 acceptance evidence; correct both records together and verify every durable pointer |
| Re-run ME-2B writable delegation admission when the Host grows dynamic writer enforcement | The 2026-08-26 model-free canary on Codex CLI 0.149.0 proved static `:read-only`/`:workspace` profiles, but the exact version-pinned launch-only adapter has no supported dynamic Parent-revocation or effect-principal probe | Writable Workers remain disabled; Module Engineers may use only the accepted read-only ME-2A/ME-3B path. This avoids a false one-writer claim and avoids building a repo-harness Agent Runtime | Provider/Host ships both (1) live Parent sandbox replacement that preserves non-mutating Parent control and (2) an effect-time authenticated runtime principal plus grant epoch. Add an explicit version-pinned Host probe adapter and re-run `bun scripts/me2b-runtime-admission-canary.ts`; do not reopen on prompt/config/store-only changes |
| BDD3-VH1 fixed-boundary visual-hierarchy micro-test (conditional) | Conditional, not scheduled — no observed pain to test against yet; see `docs/researches/20260713-bdd3-ea1-direction-adjudication.md` | ImageGen variants vs. a structured text wireframe, measured on downstream implementation-correction rate; opening it without observed pain risks testing a synthetic preference question, the same failure mode that killed EI3 | An actually observed visual-hierarchy rework pain occurs in real work, not a calendar date |
| Lite ceremony phase-3: promotion-time deterministic envelope projection (when the risk floor promotes mid-session, the harness scaffolds plan/contract skeletons by code so the model fills deltas instead of authoring four documents), plus benchmark criteria re-bucketing by resolved profile and fixing the `cross-capability-feature` scenario prompt that literally instructs "create its required workflow artifacts" | Phase B regrade (run f6684c28) proved the mechanism works where lite applies (true-lite bucket: 1.076x duration vs strict, 1.334x tokens vs no-harness, 0 artifacts) but aggregate criteria 1-3 fail on the two scenarios that are prompt-instructed or floor-promoted past lite; a SessionStart-only guidance field cannot bound a mid-session promotion | Lite's aggregate benchmark story stays "documented partial" until the follow-up ships; the 2-4x runtime envelope-authoring cost at promotion time remains unaddressed | Owner adjudicates scope (B3 mechanism + criteria/scenario revision were explicitly deferred to owner during phase-2 execution); open as its own work-package |
| Rendered-surface anti-extras verification: prove in a real implementation (not an eval) that a design brief's backstage-only concepts and its `UX-{{SLUG}}-N1` scenario actually stop an unauthorized developer-view concept from shipping | No leak has been observed yet; the sealed BDD² Phase E / BDD3-EA1 / BDD3-PS1 kill rounds (`docs/researches/20260714-bdd3-ea1-typed-evidence-authority-outcome.md`, `docs/researches/20260714-bdd3-ps1-protected-shape-outcome.md`) rule out enforcement machinery (validator/ledger/classifier) for this kind of check, so opening it without an observed failure would test a synthetic case — the same failure mode those rounds already killed | The role-aware concept-boundary fields (design brief, design-options, design-proposal) ship now on prose discipline alone, unverified against a real rendered surface, until a concrete leak is observed | First observed case in real work where a confirmed design brief with backstage-only concepts and an N1 scenario still ships an unauthorized developer-view concept; required evidence: task/brief/scenario IDs, DOM or screenshot proof, the exact leaked concept, and why the hand-written scenario test missed it; the response starts with a bounded review and a feature-specific assertion in the affected repo — no global vocabulary, classifier, lifecycle, or new eval suite |
| ChatGPT delegate-mode engine projection fix: parse Oracle >=0.16's `conversationUrl` and model-selection verification directly into `BrowserSessionMeta` instead of leaving `model.verified`/`conversationUrl` null for a session that actually completed | The closeout correction changes only the delegate security gate and explicit host projection lifecycle; a real canary (engine session `chgpt_20260729_013746_*` vs. its transport-native `.ai/harness/chatgpt/oracle-home/sessions/<providerSessionId>/meta.json`) proved the metadata gap exists, but parsing Oracle's transport-native schema is an independent provider-contract boundary | Until fixed, `delegate.md`'s Claude transport must cross-reference transport-native Oracle meta by hand via `providerSessionId` instead of trusting the engine's own session meta fields for `conversationUrl`/model verification | The first real delegation that actually needs an engine-level (not manually cross-referenced) conversation handle, e.g. automation that reads `conversationUrl` programmatically instead of a human/agent reading oracle-home meta directly |
| Delegate-mode-specific read posture: consider allowing direct attachment of `src/**` (and similar currently-denied-by-omission source paths) instead of requiring the stage-into-`bundle/`-then-attach workaround | The current browser read policy (`BROWSER_READ_POLICY` in `src/cli/chatgpt-browser/file-policy.ts`) is shared across consult/continue/delegate and deliberately narrow; widening it for delegate alone is an independent policy change outside the exact-egress/host-projection closeout | Staging preserves the narrow default read surface and is now protected by the mandatory exact-bundle Gitleaks gate plus immutable Oracle staging, but still adds a local copy step; widening would remove that step while granting the engine broader default source-tree read access | Real delegation use shows the copy step is an actual repeated bottleneck, e.g. delegations routinely need most of `src/**`; manual secret-review inconvenience alone is no longer a trigger because the machine gate is authoritative |
| Closeout transaction journal GC: stale `aborted`/different-key journal directories under `<git-common-dir>/repo-harness/transactions/` accumulate unbounded (same-key retry is the only cleanup path) | WP1's acceptance covers crash-durability correctness only — the `in_progress` filter makes stale entries inert, so a GC in the same slice would be an unrequested extra under EXECUTION_BOUNDARY; the acceptance gate classed it manual/deferred | No correctness or blocking impact; cost is disk growth and inspect noise in the transactions dir only | Transactions dir growth becomes observable in real use (entry count or size noticed), or the next work-package touching the closeout journal primitive in `scripts/contract-worktree.sh`/`scripts/ship-worktrees.sh` |
| `evals/` verification-tier ownership: give the ~52k-line evals tier one owner and one command, or fold its load-bearing parts into Required Checks | Report-only inward finding of the LoopX research (§7.2); round-3 sweep correction (2026-08-03): LoopX's examples tier is actually *owned* — nightly scheduled shards (`.github/workflows/full-public-smokes.yml`, cron `37 18 * * *`) plus a cadence audit that verifies declared cadence against the real workflow files (`canary/smoke_health.py:427-476`, `pr_fast_workflow_drift`) — so the comparison argues for action here, not complacency; still independent maintainability work, fenced out of the anti-drift sprint | `evals/` (52,585 lines, ~86% of `src/`'s 61,247 as of 2026-08-20; the earlier ~104% ratio predates `src/` growth) stays reachable only via `benchmark:skills`, outside CI and Required Checks — a second verification tier that produces the feeling of confidence without a named owner or gate. Smallest shape when the trigger fires: a scheduled workflow that actually executes the tier plus one drift assertion that gate-blocking suites appear in `ci.yml` — not the cadence-auditor machinery | The next work-package that adds to `evals/`, or the first regression that an evals-only check would have caught shipping unnoticed |
| Closeout claim liveness is PID-only (`closeout_claim_owner_live`): a reused PID pins a claim live with no sanctioned escape | Fail-closed trade-off accepted at WP5 acceptance; recording the owner process start time (or documenting a manual escape) is an independent hardening slice, not part of the conformance closure | Delayed recovery in the rare PID-reuse case, never an unsafe takeover — a live-reading claim always refuses rather than stealing ownership | The first observed stuck claim whose live-reading owner is actually dead, or the next work-package touching the closeout claim block in `scripts/contract-worktree.sh`/`scripts/ship-worktrees.sh` |
| Reduce legacy Stop cascade fan-out and repeated dirty-path work, and account for its child processes | Stop now shares a 20-second deferred-work deadline with `processArchitectureCascade`, which passes remaining time to each helper; timeout containment is implemented. The projection-disabled path still loops over changed paths, and repeated dirty paths and cascade subprocess accounting remain separate concerns | Large dirty trees consume the bounded window and retain unfinished drift for retry; the deadline does not itself deduplicate work, bound call count, or make `metrics.child_processes` complete. The manual drain path must be checked separately before changing it | A repeated-dirty-tree or projection-disabled Stop workload shows costly retries, or the next change to this cascade; verify call count, retry behavior, and child-process accounting together |
| `architecture-projection discard --job-id`: acknowledge a dead-letter job and its matching journal events without retrying it | Residual of the 2026-08-11 projection-journal hardening: the poisoning source and recovery machinery have since landed (out-of-repo paths are dropped at enqueue in `src/cli/hook/mutation-observed.ts:93`; the projection queue dead-letters failures and offers `retry-dead-letter --job-id` in `src/cli/commands/architecture-projection.ts`), leaving only the acknowledge-and-drop verb missing | A dead-letter job that should never be retried (e.g. its source path no longer exists) can only be cleared by operator `rm` of the dead-letter file plus matching journal events, since the permission classifier blocks agent deletion of state files | The first dead-letter job in real use that is wrong to retry, or the next work-package touching the architecture-projection queue commands |
| Minimal-change audit receipt schema hardening: absorb the reclaim-code-entropy evidence-record fields (`evidence` / `cut` / `tradeoff` / `verify` per decision) as required keys in `.ai/harness/checks/minimal-change-audit.latest.json`, and print that skeleton in the enforce block-reason receipt template — absorbing the skill's format, not its text, so the contract chain stays uncoupled from skill presence (v2 frozen decision 7 unchanged) | Zero real receipts exist: enforce shipped in `b9092491`; the runtime-refresh precondition has since occurred (installed CLI is 0.16.0 as of 2026-08-20) but no `minimal-change-audit.latest.json` exists on disk yet, so zero real receipts still exist and tightening now would design against imagined receipts — the same zero-data trap this slice's `tasks/lessons.md` entry (2026-08-17) exists to prevent | Until hardened, `decisions` only requires non-empty strings, so a perfunctory one-line receipt satisfies the gate; cost is bounded because the receipt is an accountability record, not an authorization boundary, and the file is uncommitted single-machine runtime cache, so a later schema tightening breaks nothing | After runtime refresh, the first few real enforce blocks produce receipts — read `.ai/harness/checks/minimal-change-audit.latest.json` and judge the `decisions` quality; visibly perfunctory receipts are the evidence that triggers the hardening slice |
| `resolveEffectiveState`'s retry loop has zero backoff and its lock scope amplifies retries 24x: `runtime.ts:308-315`'s 3-attempt outer loop has no sleep between attempts, `resolveStableEffectiveState` (`resolve-effective-state.ts:821-836`) runs its own 1+3 stability loop, and `resolveEffectiveState`'s outer 2x mismatch retry (`:789-809`) wraps the entire thing inside `withStateLock` — so one contended resolution can run `resolveEffectiveStateUnlocked` up to 8 times while holding the lock, times the runtime's outer 3 retries = 24x worst case, each read scanning ~13 source files plus a git-backed `buildReviewSubject` call | Deep-research pass (deep-reasoner, 2026-08-18); `LOCK_WAIT_MS = 5_000` (`exclusive-directory-lock.ts:19`) means the current zero-backoff 3-attempt loop can already block SessionStart up to 15s worst case before failing closed; the held-lock amplification is a positive-feedback risk under concurrent agents (longer hold time → more contention for others) | Narrowing `withStateLock`'s scope to only the commit phase (not the whole stability loop) changes the atomicity guarantee that is `resolveAndCommitEffectiveState`'s core invariant — materially riskier than a contained classifier change and must not land in the same change; adding bounded backoff alone is low-risk but still adds ~200ms worst-case latency to an already-15s fail-closed path | `SessionStart.default` p95 (currently 696ms per this repo's own `.ai/harness/runs/hook-events.jsonl` telemetry) rising past 2s, or parallel-agent count routinely exceeding 3 |
| SessionStart's 7 lower-tier context providers (capability queue, architecture queue, pending plan capture, current status, active sprint, etc.) are concatenated by `sessionStartMainContent` (`src/cli/hook/session-context.ts:1345-1351`) into one single priority-5 section via `appendBlock`, rather than 7 independent sections; `budgetSessionContext` (`session-context-budget.ts:422-446`) drops at section granularity, so all 7 providers vanish together as soon as the blob doesn't fit, instead of degrading provider-by-provider | Deep-research pass (deep-reasoner, 2026-08-18): `capResumeContent`'s cap is 12,000 chars ≈ 3,000 estimated tokens (`session-context.ts:685`) against a `SESSION_CONTEXT_TOKEN_BUDGET` of only 1,500 (`session-context-budget.ts:5`) — a non-empty resume section alone is already 2x the total budget, so the all-or-nothing blob is not a 10x-scale hypothetical, it is a condition this repo hits today whenever resume has content | Splitting requires `sessionStartMainContent` to return `SessionContextSection[]` instead of a string, which changes the `content_hash` surface (`:315-322`) and the `included_sections`/`dropped_sections` evidence contract that `session-context-budget.json` downstream consumers rely on; it also abandons the code comment at `:1326-1331` stating the current concatenation order deliberately mirrors the legacy `session-start-context.sh` migration contract, and risks up to 7 `[ContextRef:...]` noise lines needing their own cap | `session-context-budget.json`'s `dropped_sections` showing repeated `{id: 'session-start-context.sh', reason: 'budget'}` entries in real use |
| SessionStart provider failures caught by `safely()` (`session-context.ts:1312-1323`) are written only to `.ai/harness/state/session-context-budget.json` — an ignored-runtime-evidence path per this repo's own CLAUDE.md convention — and never surface in the actual context text the agent sees, except for the one `effective-state` provider which gets an explicit fallback section via `projectUnavailableStateSessionSection` (`runtime.ts:238-256`) | Deep-research pass (deep-reasoner, 2026-08-18) traced every `observeDiagnostic` call site; a provider that silently throws today produces zero agent-visible signal and zero durable evidence outside a path CLAUDE.md already classifies as not-for-durable-conclusions | Making diagnostics agent-visible competes directly with the already-scarce 1,500-token SessionStart budget (see the provider-blob split Todo above) — this needs a product decision (is a provider failure mandatory-visible or best-effort) before any implementation, not just an engineering change | One real incident where a silently-failed provider caused observably wrong agent behavior and no one noticed until later; until then the evidence file is sufficient for manual investigation |
| `trace-observer.ts`'s `rotateTrace` (`:134-143`) reads the entire `.claude/.trace.jsonl` file into memory and splits it on every single `PostToolUse` event just to count lines against a 10,000-line cap, instead of using the `statSync` already available on `TraceObserverFs` (`:15`) to gate on file size | Deep-research pass (deep-reasoner, 2026-08-18) measured directly on this repo's real 3,015,065-byte trace file: `readFileSync`+`split` averaged 0.91ms vs `statSync`'s 0.0019ms (~480x); but cross-checked against this repo's own `hook-events.jsonl` telemetry, `PostToolUse.always` (the route this fires on) is p50 3.4ms / only 3.4% of total measured hook time — the architecture doc's §3.3 claim that this route is "the first tail-latency source at 10x" is contradicted by the repo's own evidence (Stop and `PostToolUse.bash` dominate instead); the ~1ms saved here is likely smaller than the untracked per-dispatch `git rev-parse` fork cost (`runtime.ts:151`) that happens before telemetry timing even starts | Switching the rotation trigger from line-count to byte-size changes retained-record-count semantics (currently ~10,000 lines guaranteed, would become "however many lines fit under N bytes"), and `tests/trace-observer.test.ts` is the only coverage that would need updating | Lowest priority of this batch — only worth doing if `PostToolUse.always` p95 exceeds 50ms or `.trace.jsonl` steady-state size exceeds 10MB; do the other items in this batch first |
| Claim-token garbage collection on the WP1 release path: `sprint release` / `steal` / `reconcile` should retire the worktree-local `.ai/harness/sprint/claims/*.claim` capability the same way they retire the lease record | Out of scope by WP3's plan Non-goals. `write_claim_token` (`scripts/sprint-backlog.sh:655`) is the only writer and the only deletion path is inline `release_task_lease` (:806), so a contract-mode token outlives its lease forever; closing it means changing the shell ownership verbs, which is a WP1-side authority change, not a hook change | WP3's arming predicate binds the token to `unit_ref === <active-plan marker>`, which makes a stale token inert FOR THE LEASE GATE specifically — it does not make stale tokens harmless repository-wide, and any future consumer that reads a token without that binding inherits the original trap | The next work-package touching `sprint-backlog.sh`'s ownership verbs or `src/cli/commands/sprint.ts`'s release/steal paths, or the first consumer that needs to read a claim token outside the `unit_ref` binding |
| WP4 worktree metadata relocation into the coordination plane (conditional) | Not required to fix duplicate claims, and `contract_worktree_metadata_select()` (`scripts/verify-sprint.sh:233`) is the declared sole selection authority whose comment records the regression just fixed on main: "An earlier version emitted every matching row and let each caller pick, which let an all-empty record satisfy the guard while the resolver walked past it to a stale one." Moving every worktree's record into one directory and globbing it reintroduces that bug on a larger corpus, so binding it to the lease fix would couple two independent authority migrations | WP2's board reads each worktree's existing local metadata through the existing selector instead, which costs one read per worktree; a non-authoritative `worktree-id -> realpath` index in the coordination plane is the cheaper intermediate if only lookup is the problem | WP2 measurement shows per-worktree metadata reads are an actual bottleneck or an actual consistency problem — not before |
| Declare and enforce task-level parallel safety beyond persisted identity and dependency readiness | #283 now persists immutable Sprint task IDs, #284 resolves declared dependency authorities, and #280 provides canonical acquire-next ordering. None of those proves that two otherwise-ready tasks may safely execute concurrently: capability concurrency keys and the orchestrator still own that decision | Blind multi-agent acquisition remains forbidden when parallel safety is not explicitly proven; this preserves correctness but keeps some independent-looking work serialized or manually dispatched | The first real campaign where dependency-ready tasks are repeatedly serialized solely because the Sprint/Work Graph cannot express a reviewed parallel-safety relation |
| Board conflict projection (spec §12 `actual_path_overlap` / `scope_overlap`) plus contract `allowed_paths` overlap classification for parallel safety | Cut from WP2 entirely (plan verdict D, 2026-08-19): the changed-set authority is a cwd-bound bash function, so a TypeScript rewrite would be a shadow parser of the same semantic data. Separately, a naive "overlapping prefixes = hard conflict" rule false-positives on almost every contract, because contracts routinely list broad prefixes (`src/`, `tests/`, `docs/`, `tasks/`, `plans/`) and workflow closeout paths overlap by construction | The board's card `diagnostics` omit both fields rather than emitting `[]`, so a consumer cannot mistake "not computed" for "no overlap"; until this opens, two agents editing the same file are caught at the merge/rebase/finish gate, not before. The graded shape when it opens: exact-file overlap and exact-file-inside-another's-writable-prefix are hard conflicts; prefix-vs-prefix is `unknown_conflict` routed to the orchestrator; lifecycle paths (`plans/`, `tasks/contracts/`, reviews, notes) are classified separately; only a proven implementation-path collision reaches a hard block | WP3 merged and a real case of two agents colliding on the same file is observed |
| Decide whether to split the single tracked sprint file | Instrumentation landed (`coordination-wait-metrics`, 2026-08-20): `acquire_backlog_lock()` emits `backlog_lock_wait` and `finish_worktree()` emits `finish_attempt` into `.ai/harness/runs/coordination/waits.jsonl`, and verification duration was already recorded as `total_duration_ms` in `.ai/harness/runs/run-*-<contract>.json`. The split decision itself stays deferred until that ledger has data | The sprint file keeps its short-critical-section single-writer shape, which serializes rather than conflicts; splitting now would still be designing against an imagined threshold, only with an empty ledger instead of no ledger | Read `.ai/harness/runs/coordination/waits.jsonl` after sustained multi-agent use and act only if lock waits or repeated refused finishes are large enough to matter. Caveat when reading it: the ledger has no total-attempt denominator — gate-failure rounds (`verify_acceptance_receipt`, `check_architecture_freshness`, `verify-sprint.sh`) are unrecorded, so use absolute counts and magnitudes, never ratios |
| WP1 residual spec conformance leftovers after the coordination-lease-hardening slice: per-task `events/<task-id>.jsonl` audit log (spec §4/§7/§8.4/§9.4), reconcile git-topology orphan cleanup for leases whose worktree left `git worktree list` (spec §8.5), reconcile completing the finish journal (spec §9.3), claim-time canonical-worktree dirty check for the sprint path (spec §3.1 precondition 3), and guarding `begin-completion` without `--finish-transaction-key` against nulling an already-stamped key (`src/cli/commands/sprint.ts` `?? null` coalescing; P3 finding in the 20260819-1519 acceptance receipt — harmless while the field has no consumer and the closeout key is deterministically re-derivable, must be fixed in the same WP that makes reconcile read the field) | The 2026-08-19 as-landed conformance review (`docs/researches/20260819-GPT-kanban.md`, 落地状态与符合度修订) classified these as MEDIUM/LOW: none of them widens the duplicate-claim or false-completion surface, unlike the HIGH deviations routed into `plans/plan-20260819-1519-coordination-lease-hardening.md`; the bind-time `resumed` receipt (spec §8.2) shipped with WP2 on 2026-08-19, and fenced finish-abort recovery shipped in `plans/plan-20260820-1245-finish-abort-recovery.md` after its ledger trigger became due | Until then: preemption history beyond the last `stolen_from` is unrecorded, a bound lease whose worktree was removed needs manual release with the original claim id, finish-journal reconciliation still has no automatic recovery path, and a dirty canonical sprint copy can coexist with a claim | The next work-package whose acceptance needs one of these remaining guarantees |
| Explicit per-turn hook latency budget: upgrade the "PostToolUse-class hooks stay light" design convention into a typed budget with evidence, peer to `SESSION_CONTEXT_TOKEN_BUDGET` | Deferred from the boundary-dedup slice (out of scope by frozen decision); `docs/researches/20260820-model-infra-harness-boundary.md` ranks local hook execution time as the cache-window cost repo-harness fully owns, per the model-infra article's fourth circle | Per-turn lightness stays a convention, not a gate; `hook-events.jsonl` telemetry records latency but nothing alerts on regression | `PostToolUse`-class p95 rising in hook-events telemetry (past ~50ms), or the next work-package touching the hook dispatcher hot path |
| Extend provider cache telemetry from the eval benchmark into routine run evidence, splitting cache_read/cache_write out of the combined `input_tokens`/`cached_input_tokens` pair | Out of scope of boundary-dedup; capture already exists in `scripts/run-harness-profile-benchmark.ts:1058-1094` but only on the benchmark surface, keeping `usage_authority` fail-closed semantics | Ordinary sessions cannot substantiate cache-hit claims until then; the boundary-dedup measurement deliberately claimed static-size reduction only | The first optimization claim that needs `cached_input_tokens` proof outside an eval, or the next work-package touching the benchmark usage schema |
| Migrate the `contract-run` standalone worker prompt to the single-owner boundary shape (role/evidence/stop delta plus one marked boundary plus the contract) | Explicitly excluded from the boundary-dedup slice to keep it bounded; `scripts/contract-run.ts` is a separate runner path whose copy is pinned by the parity test in `tests/workflow-contract.test.ts` | The standalone path keeps the older shape (Why/self-verify/Notes/Stop plus full boundary plus full contract appended) and its static-token cost | The next work-package touching `scripts/contract-run.ts`'s prompt builder, or observed contract-run child confusion attributable to prompt bloat |
| Decide the component-level read semantics for `engineering-overlay` so a single-pass unreadable component stops throwing `engineering_overlay_invalid` | The ME-1B fix made the profile pass degrade, but one level down the asymmetry survives: when `bindings`, `claims`, `messages`, or `provider_effects` fails in only one pass while profiles stay readable, `components[c].support` takes the two-pass intersection (`unreadable`) while the per-Engineer projection comes from `after` alone and reports `available`, colliding at the `${component} component support does not match Engineer observations` invariant (`src/core/engineers/engineering-overlay.ts:325-336`). Closing it needs two decisions this slice was not authorized to make: which pass owns a per-Engineer component read when the passes disagree, and what a `before` read means for an Engineer that only exists in `after`. Detail in `tasks/notes/20260826-2233-me1-acceptance-followup.notes.md` Open Questions | Until decided, a transient single-pass read failure on any of the four non-profile components still hard-fails the whole overlay instead of degrading, so the profile-level degradation is only a partial guarantee | The next slice that touches the two-pass read semantics of `engineering-overlay` (`src/core/engineers/engineering-overlay.ts:325-336` intersection vs `src/effects/engineers/engineering-overlay.ts:231` after-only) |
| Merge the two canonical-context builders: `canonicalTaskContext` in `src/effects/fleet/task-message-request.ts` and `canonicalInboxContext` in `src/cli/commands/fleet.ts` are deliberately duplicated | The CLI copy sits outside the operator-board-redesign contract scope, so unifying it would have widened the work-package past its review boundary. The duplication was taken knowingly rather than by omission | Two independent definitions of the same canonical shape can drift; a change to one is not caught by the other's tests | The next change that has to touch either builder — unify them in that slice rather than adding a third copy |
| Verify the signal-store `EEXIST` reconciliation branch under a cross-thread publish race | `signal-store.ts` locks by thread key while signal identity is derived from repository, actor and idempotency key. The current EEXIST branch re-reads and reconciles published bytes; same-thread serialization alone does not prove this branch unreachable | Existing concurrent-writer coverage uses one thread key and does not establish the cross-thread collision behavior. Do not assert an observed `collaboration_unavailable` failure or remove the branch without a reproduction | A real cross-thread identity collision or the next change to signal identity/locking; reproduce with two thread keys and one signal identity, then decide from the observed result |
| Replace the hardcoded capability counts in `tests/architecture-projection-e2e.test.ts` and `tests/capability-archcontext-export.test.ts` with a count derived from the model | C1 had to move both numbers to register `capability.runtime-harness.collaboration`; deriving them instead is a test-authority change that would have widened this contract past its acceptance boundary | Any branch that adds a capability turns both tests red on merge, and two such branches in flight red each other rather than the model — the failure names a number, not the drift it is meant to catch | The next capability registration (the first row outside C0-C9, since C2-C9 add none), or the first observed collision between two parallel capability-adding branches |
| Run the 100 Work Packages / 10 Engineers scale benchmark against the collaborative work exchange snapshot and context packet | The C6 sprint task list named this benchmark, but the property it was there to establish — that the snapshot and packet are deterministic — was proven directly and more strongly by byte identity: two collections over the same sources render byte-identical canonical output, which holds at any size. Building a 100-package / 10-engineer fixture would have added a fixture generator and a timing harness to a slice whose acceptance was already met, so the run was deferred rather than the property left open | Determinism is proven; the scale dimension is unmeasured. Nothing establishes how collection latency, the double-read cost, or the 1,500-token packet budget behave once the store holds ~100 work packages and ~10 concurrent engineers, so a projection cost that degrades non-linearly would first appear in real use rather than in a gate | C9's real multi-agent canary runs — it is the first row with live concurrent actors to measure against — or, earlier, the first real repository whose collaboration store exceeds roughly 20 concurrent work packages |
| Replace the `await Bun.sleep(2500)` stand-in in `tests/architecture-queue.test.ts` ("record never reclaims a live shared rotation lock at the old two-second threshold") with an observable condition on the child's lock-wait state | The test proves a real invariant — the reclaim threshold must not fire while a peer still holds the shared rotation lock — but it has no handle on the child's lock-wait state, so it approximates "the child is still waiting" by sleeping past the old two-second threshold; giving it a real handle means exposing an observable wait signal from the lock path, which is a source change outside the CI test-gate slice | The suite pays a fixed 2.5s on every run and the assertion is timing-derived rather than state-derived, so it flakes under CI load — observed on run 33980326026 — and a flake there is indistinguishable from a genuine reclaim regression | The next flake of this test, or the next work-package touching the shared rotation lock in `architecture-queue` |
| Add a documentation-to-CLI resolution gate: extract every `repo-harness <group> <sub>` token from the five READMEs and the current changelog section, resolve each against the parent command's `--help` subcommand list, and fail CI on an unresolved token | The 0.19.0 release prep documented three commands that do not exist (`automation authorization mint|list`, `campaign stop`) plus an out-of-bounds `--maximum-duration-ms` example, and every existing check stayed green: `tests/readme-dx.test.ts` asserts literal strings and only ever spawns the CLI for `init --dry-run`, so no gate resolves a documented verb against the real command tree. The defects were caught by the acceptance gate reading `--help` by hand, which does not scale | Until it exists, README and changelog command accuracy rests on a reviewer manually resolving each verb; the failure mode is silent and ships to the npm README. Note the naive detector is unsound — commander prints the parent's help instead of erroring on an unknown subcommand, so the check must test membership in the parent's listed subcommands, not the exit status | The next release-prep pass, or the first user-reported nonexistent command in the published README |
| Canonicalize the two remaining `resolve`-only repo roots outside the CLI: `src/effects/engineers/work-demand-store.ts:101` resolves `input.repo_root` before `repoHarnessRepoIdFor`, and `src/cli/chatgpt-browser/engine.ts:87` `resolveRepoRoot` is `resolve`-only | Found by the acceptance gate while reviewing the `--repo` canonicalization sweep, which was scoped to `src/cli/commands/`. Neither is the reported defect and neither has an observed failure, so fixing them in that slice would have widened it past its review boundary | `work-demand-store` is genuinely symlink-blind on the same `repoHarnessRepoIdFor` contract, so a symlinked `repo_root` reaching it derives a different identity than the registry stored — the same class of false mismatch, just through a different entrypoint. `engine.ts` is path-keyed rather than id-keyed, so its exposure is lower | The first WorkDemand operation observed failing on an identity mismatch, or the next change to either entrypoint's root handling |
| Harden the CI test job pool in `scripts/lib/ci-run-tests.sh` after #425 | Gatekeeper review of #425 left four non-blocking items that were not worth another CI round: only the EXIT trap is saved and restored, so `trap - EXIT INT TERM` resets a caller's INT/TERM handlers; an INT during the pool removes the scratch dir but drains the remaining files as "lost worker" entries instead of aborting; the `BUN_TEST_JOBS=1` byte-identity case in `tests/check-ci-isolate-aggregation.test.ts` compares the new serial branch against itself instead of a frozen pre-change fixture; the 10 s barrier in the concurrency case spawns three real `bun test` processes while the file itself runs under the 4-way hosted pool | None of the four affects the aggregation contract or the 17 min to about 8.5 min Test job gain; the barrier deadline is the only one that can surface as a flake under load | The next change to `scripts/lib/ci-run-tests.sh` or `tests/check-ci-isolate-aggregation.test.ts`, or the first hosted flake of the concurrency case; batch all four into that change |
## User uninstall follow-up
- Deferred: explicit repository unadoption. Independent MCP setup teardown is implemented by `mcp uninstall`; service shutdown, remote Connector/tunnel cleanup and workspace lifecycle remain explicit operator actions. Revisit repository unadoption when requested; preserve repository content and archives.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!