|
| 1 | +# Freeze Project Harness Components for Qoder |
| 2 | + |
| 3 | +## Traceability |
| 4 | + |
| 5 | +- Spec ID: `harness-component-snapshot-v1` |
| 6 | +- Roadmap: `LC-02` |
| 7 | +- Status: Implemented |
| 8 | +- AI involvement: Codex (GPT 5.6 Sol), implementation; Codex (GPT 5.6 Terra), independent review |
| 9 | + |
| 10 | +## Intent |
| 11 | + |
| 12 | +Give maintainers and later loop capabilities a deterministic, privacy-safe way |
| 13 | +to identify the exact project-owned Qoder Rules, Skills, Hooks, Commands, and |
| 14 | +Workflows that existed at one observation boundary. A versioned snapshot and |
| 15 | +bounded diff must distinguish component identity, content revision, and |
| 16 | +activation evidence so later evaluation or intervention work can bind to facts |
| 17 | +without treating configured presence as observed use. |
| 18 | + |
| 19 | +This is the first read-only `LC-02` slice. It establishes one complete host |
| 20 | +contract before generalizing across providers. |
| 21 | + |
| 22 | +## Acceptance Scenarios |
| 23 | + |
| 24 | +- **HCS-AC-1 (bounded Qoder inventory):** Given a workspace, snapshot creation |
| 25 | + uses Qoder's public project inventory for Rules, Skills, Hooks, and Commands, |
| 26 | + plus only `.qoder/workflows/` and `.agents/workflows/` for Workflows. User, |
| 27 | + plugin, inherited, runtime-cache, Memory, MCP, and subagent assets are out of |
| 28 | + scope and are neither collected nor completeness gates. The Qoder inventory |
| 29 | + request explicitly allowlists only Rules, Skills, Hooks, and Commands. Every |
| 30 | + supported kind reports `observed` coverage even when its result is empty. |
| 31 | + Malformed Hook JSON, user-home/project-root aliasing, unsupported |
| 32 | + symlinks, or a collector depth/count/probe overflow fails closed instead of |
| 33 | + silently claiming complete observation. |
| 34 | +- **HCS-AC-2 (stable component identity):** Every component receives a stable, |
| 35 | + provider-, scope-, and population-qualified ID from `qoder`, `project`, a |
| 36 | + privacy-safe population reference, its kind, and a normalized |
| 37 | + workspace-relative route. Hook identity adds a digest of its event, matcher, |
| 38 | + and handler type plus an ordinal only for duplicate routing identities; |
| 39 | + declaration position belongs to revision evidence. Collector/component output |
| 40 | + ordering and host path separators do not affect identity. The safe default |
| 41 | + binds population to a hash of the canonical workspace boundary; callers use |
| 42 | + an explicit opaque population key when the same project must retain identity |
| 43 | + across relocation, drive letters, or operating systems. |
| 44 | +- **HCS-AC-3 (separate evidence dimensions):** Content revision, identity, and |
| 45 | + activation are independent fields. File content, a bounded Skill tree, or a |
| 46 | + bounded hook configuration plus its workspace script determines a SHA-256 |
| 47 | + revision. Hook command/script content and declaration order do not enter its |
| 48 | + routing identity; a routing tuple change is an identity change. Activation |
| 49 | + remains explicitly `unknown` with `unavailable` runtime evidence. File-backed |
| 50 | + provenance is `observed` and never claims execution. |
| 51 | +- **HCS-AC-4 (privacy-safe frozen contract):** `HarnessComponentSnapshotV1` is |
| 52 | + deeply frozen, canonically ordered, versioned, content-addressed, and contains |
| 53 | + no raw component content, command text, secret values, or absolute workspace |
| 54 | + or user-home paths. Symlink or relative-path escapes fail closed. Evidence |
| 55 | + reads reuse one canonical workspace boundary scoped to the current snapshot; |
| 56 | + they do not retain caller paths in a process-lifetime cache. |
| 57 | +- **HCS-AC-5 (minimal graph):** Each component has one typed `declared-in` |
| 58 | + relationship to its privacy-safe workspace artifact reference. Relationship |
| 59 | + validation rejects unknown component IDs, absolute targets, and mismatched |
| 60 | + provenance instead of inferring semantic dependencies. |
| 61 | +- **HCS-AC-6 (tamper-safe validation):** Validation recomputes component |
| 62 | + identity, relationship integrity, rollback references, ordering, and the |
| 63 | + snapshot digest. Stale or edited snapshots fail with stable diagnostic codes. |
| 64 | +- **HCS-AC-7 (bounded diff):** Two valid snapshots from the same provider and |
| 65 | + scope and exact population reference produce deterministic `added`, `removed`, `changed`, and `unchanged` |
| 66 | + counts. Revision changes are named `content`; route identity changes appear |
| 67 | + as one removal and one addition. Activation and provenance remain fixed, |
| 68 | + explicit evidence dimensions in this v1 producer and therefore cannot be |
| 69 | + reported as changed without a future contract revision. Returned entries |
| 70 | + obey an explicit bounded limit and report truncation. Different populations |
| 71 | + fail closed. |
| 72 | +- **HCS-AC-8 (non-authorizing rollback reference):** Every component exposes a |
| 73 | + parseable reference binding provider, scope, population-qualified component |
| 74 | + ID, and revision. |
| 75 | + Resolution requires a valid matching snapshot and returns |
| 76 | + `mutationAuthorized: false`; it does not read prior content or execute a |
| 77 | + restore. |
| 78 | +- **HCS-AC-9 (public automation surface):** A capability-owned public |
| 79 | + `index.mjs` exports create, validate, diff, parse, and rollback-resolution |
| 80 | + functions. A strict `cli.mjs` exposes `create`, optional opaque |
| 81 | + `--population-key`, `validate`, `diff`, and `resolve` with parser-safe JSON |
| 82 | + stdout and usage/runtime failures on stderr. Runtime diagnostics expose a |
| 83 | + stable code without echoing caller-selected paths or untrusted snapshot |
| 84 | + fields. Public API failures use stable sanitized messages without appending |
| 85 | + filesystem or parser error details. Global and leaf help remain help-only |
| 86 | + human text and do not inspect a workspace. |
| 87 | +- **HCS-AC-10 (portable evidence):** Fixtures cover Windows, macOS, and Linux |
| 88 | + route forms, stable input ordering, provider/scope isolation, secret and home |
| 89 | + sentinels, hook activation, tampering, bounded diff states, and rollback |
| 90 | + resolution. Package verification and the full test suite remain green apart |
| 91 | + from already-known environment-specific failures recorded as evidence. |
| 92 | + |
| 93 | +## Non-goals |
| 94 | + |
| 95 | +- Supporting providers other than Qoder, user/global assets, installed plugins, |
| 96 | + inherited assets, MCPs, Memories, or subagents. |
| 97 | +- Inferring runtime activation, observed use, causal impact, semantic |
| 98 | + dependencies, or cross-component invocation from configured presence. |
| 99 | +- Storing raw component bodies, hook commands, environment values, absolute |
| 100 | + homes, transcripts, prompts, or private Memory content. |
| 101 | +- Creating a graph database, trace runner, scheduler, evaluator, automatic |
| 102 | + reviewer, mutation planner, apply command, or rollback executor. |
| 103 | +- Registering a new root `better-harness` command. The v1 slice remains an |
| 104 | + atomic capability-owned direct CLI; root command naming, audience, and |
| 105 | + discovery integration are an explicit follow-up decision. |
| 106 | +- Reusing `plugin-lifecycle` identity, contract, runtime, or host-support APIs. |
| 107 | + A future adapter may project accepted lifecycle observations into this |
| 108 | + component contract only after their evidence semantics are reviewed. |
| 109 | + |
| 110 | +## Plan and Tasks |
| 111 | + |
| 112 | +1. Add `scripts/harness-component-snapshot/` as the atomic owner, with a |
| 113 | + versioned capability-private contract, canonical hashing, path safety, |
| 114 | + snapshot assembly, bounded diff, rollback-reference resolution, public |
| 115 | + exports, and a direct CLI. |
| 116 | +2. Compose Qoder Rules, Skills, Hooks, and Commands through an explicit project |
| 117 | + collection allowlist on `scripts/agent-customize/index.mjs`. Add a narrow |
| 118 | + Qoder workflow collector locally because the existing cross-provider |
| 119 | + practices inventory groups unrelated host workflow roots and has no |
| 120 | + workflow-only public API. |
| 121 | +3. Use one snapshot-scoped canonical workspace read context, workspace-relative |
| 122 | + artifact references, population references, and SHA-256 digests only. Keep |
| 123 | + activation unavailable and provenance file-backed; make unsupported or |
| 124 | + escaped evidence a hard failure. |
| 125 | +4. Add fixture-driven contract and CLI tests. Test route normalization as a pure |
| 126 | + boundary so Windows/macOS/Linux behavior is reproducible on every CI host. |
| 127 | +5. Run focused tests, documentation-link validation, package verification, and |
| 128 | + the full suite. Perform a Change Traceability Review Readiness Check before |
| 129 | + handoff. |
| 130 | + |
| 131 | +### Boundary with the plugin lifecycle control plane |
| 132 | + |
| 133 | +The merged plugin lifecycle control plane describes installation, discovery, |
| 134 | +enablement, version relation, and read-only mutation plans for the Better |
| 135 | +Harness plugin itself across multiple hosts. This spec instead snapshots |
| 136 | +project-owned Qoder harness assets. It does not reuse plugin identity, expose |
| 137 | +host-support profiles, claim lifecycle/runtime state, or modify the root CLI |
| 138 | +registry. The only intentional conceptual seam is a future explicit adapter |
| 139 | +from accepted host evidence to the component snapshot contract. |
| 140 | + |
| 141 | +## Test and Review Evidence |
| 142 | + |
| 143 | +- **HCS-AC-1..5:** `node --test test/harness-component-snapshot.test.mjs` |
| 144 | + validates inventory filtering, IDs, revisions, graph edges, privacy, deep |
| 145 | + freezing, ordering, and path fixtures. |
| 146 | +- **HCS-AC-6..8:** The same focused test injects stale digests, edited fields, |
| 147 | + unknown relationships, population mismatch, all diff states, limits, and |
| 148 | + rollback-reference mismatches. |
| 149 | +- **HCS-AC-9:** `node --test test/harness-component-snapshot-cli.test.mjs` |
| 150 | + verifies help, strict parsing, JSON stdout, path-safe stderr failures, and all |
| 151 | + four direct CLI operations. Contract tests also verify that malformed Hook |
| 152 | + input cannot expose parser details, caller paths, or private sentinels through |
| 153 | + the public API error message. |
| 154 | +- **HCS-AC-10:** `node --test test/doc-link-graph.test.mjs`, |
| 155 | + `npm run pack:verify`, and `npm test` provide documentation, distribution, and |
| 156 | + repository-wide regression evidence. |
| 157 | +- **Observed evidence (2026-08-05):** On the rebased final tree, the focused |
| 158 | + contract/CLI run passed 21 tests with 0 failures and 0 skips; documentation- |
| 159 | + link validation passed 6/6. The repository-wide run passed 1,288, failed 0, |
| 160 | + and skipped 1 existing platform-specific case. Package verification passed |
| 161 | + with 458 npm and 480 runtime-zip entries. An independent Terra contract and |
| 162 | + adversarial review ended with no P1/P2 findings after the Qoder collection |
| 163 | + allowlist, path-safe CLI diagnostics, tilde-home alias guard, architecture |
| 164 | + routing, and Windows drive-relative route fixes were applied. Copilot review |
| 165 | + follow-up additionally replaced per-read workspace-root resolution with a |
| 166 | + snapshot-scoped boundary and removed parser/filesystem details from public |
| 167 | + Hook configuration errors. |
| 168 | +- **Risk — privacy:** A route or source field could expose an absolute home. |
| 169 | + Mitigation: accept only normalized workspace-relative routes and serialize |
| 170 | + no inventory path fields. |
| 171 | +- **Risk — false activation:** Configured assets could be presented as used. |
| 172 | + Mitigation: freeze `activation.state = unknown` and |
| 173 | + `activation.evidenceState = unavailable` in this version. |
| 174 | +- **Risk — unstable hook identity:** Hook array reordering changes registration |
| 175 | + positions but retains each distinct routing identity; revisions change because |
| 176 | + order can affect execution. Editing the event, matcher, or handler type is an |
| 177 | + identity change. Inserting or removing indistinguishable duplicate routing |
| 178 | + declarations may renumber only those duplicates. Tests separately cover |
| 179 | + irrelevant collector ordering and meaningful hook declaration reordering. |
| 180 | +- **Risk — project relocation:** Default population identity deliberately binds |
| 181 | + to the canonical workspace boundary so unrelated projects with identical |
| 182 | + files cannot cross-diff or resolve rollback references. Repositories that |
| 183 | + relocate or compare across operating systems must provide the same opaque |
| 184 | + population key; only its domain-separated digest enters artifacts. |
| 185 | +- **Risk — incomplete rollback:** A privacy-safe snapshot cannot itself restore |
| 186 | + omitted source bytes. The v1 reference is resolvable and non-authorizing; |
| 187 | + executable restore remains gated on a future content-store or Git provenance |
| 188 | + contract. |
| 189 | +- **Risk — boundedness:** Snapshot assembly rejects more than 20,000 component |
| 190 | + descriptors before starting evidence reads and processes accepted populations |
| 191 | + with eight workers. All evidence workers share one canonical workspace root |
| 192 | + scoped to that snapshot, so an input near the limit cannot create unbounded |
| 193 | + root-resolution I/O, process-lifetime cache growth, or in-flight content |
| 194 | + buffers. |
| 195 | +- **Risk — root CLI drift:** The merged lifecycle work established a richer root |
| 196 | + command registry after this slice was designed. Mitigation: keep the v1 |
| 197 | + entrypoint capability-local and leave root registry/help untouched until a |
| 198 | + separately reviewed command name, audience, and discovery contract is chosen. |
0 commit comments