harness-everything 0.46.3 → 0.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +23 -1
- package/benchmarks/results/live-host/claude-341-outline-dispatch-2026-10-28/README.md +33 -8
- package/benchmarks/results/live-host/claude-341-outline-dispatch-2026-10-28/inventory/2741bd4514d2cd68f57d93a2b3ce94cbe597ca62d30e26f0ca58e882df5b03c6.md +128 -0
- package/benchmarks/results/live-host/claude-341-outline-dispatch-2026-10-28/sanitize-outline-capture.js +105 -0
- package/ci/mechanism-e1-derived-regenerate.test.js +333 -0
- package/ci/mechanism-outline-sanitizer.test.js +79 -0
- package/ci/mechanism-prb-outline-review.test.js +278 -31
- package/docs/doc-workflow-reconciliation.md +12 -8
- package/docs/platform-capabilities.md +1 -1
- package/harness-everything/SKILL.md +1 -1
- package/harness-everything/scripts/doc-check.js +106 -8
- package/harness-everything/scripts/doc-lifecycle.js +49 -1
- package/hooks/scripts/lib/doc-reconciliation-events.js +22 -0
- package/hooks/scripts/lib/doc-reconciliation-outline-capture.sanitized.jsonl +24 -0
- package/hooks/scripts/lib/doc-reconciliation-pilot.js +3 -1
- package/hooks/scripts/lib/doc-reconciliation-provider.js +168 -15
- package/hooks/scripts/lib/doc-reconciliation-qualification.json +20 -0
- package/opencode-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
- package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-events.js +22 -0
- package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-outline-capture.sanitized.jsonl +24 -0
- package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-pilot.js +3 -1
- package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-provider.js +168 -15
- package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-qualification.json +20 -0
- package/plugins/harness-everything/plugin.json +1 -1
- package/plugins/harness-everything/skills/harness-everything/SKILL.md +1 -1
- package/plugins/harness-everything/skills/harness-everything/scripts/doc-check.js +106 -8
- package/plugins/harness-everything/skills/harness-everything/scripts/doc-lifecycle.js +49 -1
- package/sbom.cdx.json +7 -7
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"name": "harness-everything",
|
|
11
11
|
"source": "./",
|
|
12
12
|
"description": "Harness OS: an orchestrated agent operating system — tier routing, circuit breaker guardrails, verification gates, WAL session memory, and self-evolving workspace rules.",
|
|
13
|
-
"version": "0.
|
|
13
|
+
"version": "0.47.0",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "Miya Daniel"
|
|
16
16
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harness-everything",
|
|
3
3
|
"description": "Harness OS: an orchestrated agent operating system — tier routing, circuit breaker guardrails, verification gates, WAL session memory, and self-evolving workspace rules.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.47.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Miya Daniel"
|
|
7
7
|
},
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.47.0](https://github.com/dyphn1/Harness-everything/compare/v0.46.3...v0.47.0) (2026-10-29)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* **doc-reconciliation:** qualify claude outline dispatch from flat run8 capture ([dc524e5](https://github.com/dyphn1/Harness-everything/commit/dc524e50596429e9b9d504e11fb5584a5b75805c))
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **doc-reconciliation:** give derived-regenerate a registered production producer ([a070b65](https://github.com/dyphn1/Harness-everything/commit/a070b6562f6d0c3931d014abfdb3a6f23aa3cfc9))
|
|
14
|
+
* **doc-reconciliation:** let a post-draft reviewer start outside the draft interval ([ae60b04](https://github.com/dyphn1/Harness-everything/commit/ae60b045da6313b17a151ece0be3c424a48477d4))
|
|
15
|
+
* **doc-reconciliation:** map pinned evid rows and select only verdict reviews ([ecf907d](https://github.com/dyphn1/Harness-everything/commit/ecf907d46827aaff3f4fc645f9a7b1547e26b146))
|
|
16
|
+
* **doc-reconciliation:** sanitize outline dispatch tokens and test the derived seam end to end ([c30b20b](https://github.com/dyphn1/Harness-everything/commit/c30b20ba6d5899805a6f6e6468fe68b04a71ef31))
|
|
17
|
+
|
|
18
|
+
## [Unreleased]
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* **doc-reconciliation:** pin the owner-approved VERI-to-EVID row mapping and exclude ordinary SubagentStop completions from quality-review candidates.
|
|
23
|
+
* **doc-reconciliation:** allow uniquely identified same-root reviewers that start after the correlated draft worker stops.
|
|
24
|
+
|
|
5
25
|
## [0.46.3](https://github.com/dyphn1/Harness-everything/compare/v0.46.2...v0.46.3) (2026-10-28)
|
|
6
26
|
|
|
7
27
|
### Bug Fixes
|
|
@@ -56,11 +76,13 @@ All notable changes to this project are documented in this file.
|
|
|
56
76
|
### Added
|
|
57
77
|
|
|
58
78
|
- **doc-governance:** declare six ADR domains (ROUTE, GATE, EVID, SONE, DOCS, DIST) and record the eight DOCS ADRs (DOCS-001 to DOCS-008) for already-in-effect document-lifecycle mechanisms.
|
|
79
|
+
- **doc-reconciliation:** add registered derived-view checks that bind in-memory lifecycle-index generation to the unchanged source corpus, config and target bytes.
|
|
59
80
|
|
|
60
81
|
### Features
|
|
61
82
|
|
|
62
83
|
* **doc-lifecycle:** add complete full-corpus conflict-check evidence with snapshot-bound scope and corpus identity.
|
|
63
|
-
* **doc-reconciliation:** add a dedicated pre-draft outline review lane bound to the pinned inventory and exact O→D Git cycle
|
|
84
|
+
* **doc-reconciliation:** add a dedicated pre-draft outline review lane bound to the pinned inventory and exact O→D Git cycle.
|
|
85
|
+
* **doc-reconciliation:** qualify the retained Claude Code 2.1.312 run8 outline mapping only; OpenCode, Codex, other Claude versions and E1 remain unqualified.
|
|
64
86
|
|
|
65
87
|
### Fixed
|
|
66
88
|
|
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
# Live-host capture: claude-341-outline-dispatch (2026-10-28)
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Run8 now qualifies the retained Claude Code 2.1.312 outline-dispatch profile** at main baseline `1bd0f805031c5577a6e7f72a9bc5b41618b71fc1`, using a separate sanitized capture. This does not enforce a running host version or establish an E1 qualifying cycle. OpenCode, Codex and other Claude Code versions remain unqualified. The earlier probe below remains historical field-availability evidence only.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Run8: retained qualification evidence
|
|
6
|
+
|
|
7
|
+
| Item | Value |
|
|
8
|
+
|---|---|
|
|
9
|
+
| Host profile | Claude Code 2.1.312 |
|
|
10
|
+
| Staged source baseline | `1bd0f805031c5577a6e7f72a9bc5b41618b71fc1` |
|
|
11
|
+
| Sanitized capture | `hooks/scripts/lib/doc-reconciliation-outline-capture.sanitized.jsonl` |
|
|
12
|
+
| Sanitized capture SHA-256 | `6feb440af12aaf878a0bed5cb750f29e27d271a9add93001e151746980230b7f` |
|
|
13
|
+
| Pinned inventory bytes for the production-path fixture | `inventory/2741bd4514d2cd68f57d93a2b3ce94cbe597ca62d30e26f0ca58e882df5b03c6.md` |
|
|
14
|
+
|
|
15
|
+
The inventory copy is byte-identical to the pinned run8 artifact and lets the no-DI integration regression run without a machine-local path.
|
|
16
|
+
|
|
17
|
+
The retained `PIN.txt` records the staged plugin baseline and host. Run8's `assess.json` records an accepted mapping and `resolveIfQualified.status: accepted`; its production qualification was closed before this separate export existed. This is retained assessment evidence, not an independent rerun.
|
|
18
|
+
|
|
19
|
+
Reproduce from the repository root:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
node benchmarks/results/live-host/claude-341-outline-dispatch-2026-10-28/sanitize-outline-capture.js \
|
|
23
|
+
<raw-hooks.jsonl> hooks/scripts/lib/doc-reconciliation-outline-capture.sanitized.jsonl
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The sanitizer flattens each wrapper's observed payload, assigns `event` from `hook_event_name`, and preserves record order and field absence. It removes only wrapper timestamp `t` and `transcript_path`; `agent_transcript_path` is retained with a synthetic absolute path, and its encoded Claude project-folder slug is scrubbed. Private roots map to absolute `/sanitized/run8/...` paths; session, prompt, tool-use and agent IDs receive stable one-to-one placeholders, including `tool_response.agentId`. Each distinct dispatch-marker `token=` value receives a stable, nonempty, whitespace-free placeholder at every nested occurrence; longer tokens are replaced first to avoid partial overlap. It does not synthesize interruption, parent dispatch, background, isolation or completion fields. It fails when private path strings, original IDs or dispatch tokens remain.
|
|
27
|
+
|
|
28
|
+
Raw hooks and transcripts stay private. The sanitized file qualifies only the observed Claude Code 2.1.312 profile; it does not qualify OpenCode, Codex, other Claude Code versions or an E1 cycle. The host payload does not attest its own version.
|
|
29
|
+
|
|
30
|
+
## Earlier probe: what was captured
|
|
6
31
|
|
|
7
32
|
```mermaid
|
|
8
33
|
sequenceDiagram
|
|
@@ -16,7 +41,7 @@ sequenceDiagram
|
|
|
16
41
|
C->>C: PostToolUse Agent, tool_use_id matches Pre<br/>agent id only in tool_response.agentId, no interrupted
|
|
17
42
|
```
|
|
18
43
|
|
|
19
|
-
##
|
|
44
|
+
## Earlier probe pins
|
|
20
45
|
|
|
21
46
|
| Item | Value |
|
|
22
47
|
|---|---|
|
|
@@ -33,7 +58,7 @@ sequenceDiagram
|
|
|
33
58
|
| staged `hooks/hooks.json` | `aca70167da0fa792e34fb55e2904e2935c83f8f087de9e3cd130dd536b01eafd` |
|
|
34
59
|
| staged `hooks/scripts/lib/doc-reconciliation-provider.js` | `1e0a9cc6fd040c074d96a79ec6445c328957951a7c0074427687d0a22179ec3b` |
|
|
35
60
|
|
|
36
|
-
##
|
|
61
|
+
## Earlier probe command (sanitized)
|
|
37
62
|
|
|
38
63
|
```text
|
|
39
64
|
cd <scratch>/project # fresh git repo, one commit
|
|
@@ -50,7 +75,7 @@ No bypass flag. Marker: `HARNESS_OUTLINE_DISPATCH_V1 taskId=<id> attemptId=a1 to
|
|
|
50
75
|
- **Run 1** used `taskId=cap-00N`. The plugin rejected it as `dispatch-marker-invalid`, because task ids must match `task-*`. This was a fixture error. The raw host payloads are still valid field evidence.
|
|
51
76
|
- **Run 2** used `taskId=task-cap-00N`. The plugin parsed the marker and recorded `workflow-task-binding-invalid`. That rejection is expected, since no accepted review, handoff or lease exists in this bounded fixture.
|
|
52
77
|
|
|
53
|
-
##
|
|
78
|
+
## Earlier probe mapping observations
|
|
54
79
|
|
|
55
80
|
| Mapping clause | 2.1.312 observed | Evidence |
|
|
56
81
|
|---|---|---|
|
|
@@ -62,14 +87,14 @@ No bypass flag. Marker: `HARNESS_OUTLINE_DISPATCH_V1 taskId=<id> attemptId=a1 to
|
|
|
62
87
|
| `taskResultDispatchField: tool_use_id` | **yes** | PostToolUse `tool_use_id` equals the Pre's, 4/4 |
|
|
63
88
|
| Result `agent_id` + `interrupted === false` | **no** | No top-level `agent_id` (the plugin journal lifts `tool_response.agentId`). No `interrupted` field on the Agent result at all |
|
|
64
89
|
|
|
65
|
-
##
|
|
90
|
+
## Earlier probe finding: async launch
|
|
66
91
|
|
|
67
92
|
In Run 2 dispatch 1 the model omitted `run_in_background`. The host launched the worker asynchronously: PostToolUse `status: async_launched`, `isAsync: true`, and it fired **before** SubagentStop (+2040 ms vs +3490 ms). A PostToolUse is therefore not proof that the worker finished. Any result correlation must require `status: completed` or an explicit `run_in_background: false`.
|
|
68
93
|
|
|
69
|
-
##
|
|
94
|
+
## Earlier probe limit at the time
|
|
70
95
|
|
|
71
96
|
- Correlate worker start without `parent_tool_use_id`: for example, by the order of Pre end → next SubagentStart within the same `session_id` while one dispatch is in flight, or by `tool_response.agentId` ↔ SubagentStart `agent_id` after the fact.
|
|
72
97
|
- Replace `interrupted === false` with `tool_response.status === 'completed'`.
|
|
73
98
|
- Define worker-root for isolation worktrees, where the path is derived from `agent_id`, not predeclared.
|
|
74
99
|
|
|
75
|
-
|
|
100
|
+
That was the earlier position. Advisor answer 12 subsequently approved the run8 field mapping; the observations above remain limited to their original probe.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Report INV — existing-mechanism inventory for retroactive ADRs
|
|
2
|
+
|
|
3
|
+
run id `e1-inv-1` · packet rev 1 · input SHA `0ef0541c6cae550e8269ba712e03797e0e987dfb` (verified: `git rev-parse HEAD` — **executed**).
|
|
4
|
+
Facts only, no decisions. Issue states: **executed** via read-only `gh issue view N --json state` (57 numbers queried 2026-10-27). File/test/issue-number mapping: **source-traced** (grep of `ci/`, `docs/*.md`, `git log --oneline --all --grep`, code citations). ADR shape: **source-traced** (code citations, no execution). Status flags: my classification of those facts.
|
|
5
|
+
|
|
6
|
+
## 1. ADR shape — the exact minimum file this repo's checker accepts
|
|
7
|
+
|
|
8
|
+
Checker: `harness-everything/scripts/doc-lifecycle.js` (run via `doc-check.js`; config from `project-docs-resolver.js`). `describes:` is **not** recognized by `doc-lifecycle.js` (absent — grep, **source-traced**).
|
|
9
|
+
|
|
10
|
+
| Rule | Value | Citation |
|
|
11
|
+
| --- | --- | --- |
|
|
12
|
+
| ID regex | `/^([A-Z][A-Z0-9]{1,9})-(\d{3,})$/` — domain 2–10 uppercase alnum chars, number ≥ 3 digits | doc-lifecycle.js:20 |
|
|
13
|
+
| ID required | `missing-id` when `id` absent/empty | doc-lifecycle.js:1075–1076 |
|
|
14
|
+
| ID malformed | `invalid-id` when regex fails | doc-lifecycle.js:1077 |
|
|
15
|
+
| Domain declared | `unknown-domain` unless domain ∈ `config.domains` (set from config, doc-lifecycle.js:1035; never hardcoded) | doc-lifecycle.js:1078 |
|
|
16
|
+
| Status required | `missing-status` / `invalid-status` vs `ROLE_STATUSES.adr` | doc-lifecycle.js:1070–1073 |
|
|
17
|
+
| ADR status vocabulary | exactly `proposed` / `accepted` / `rejected` / `superseded` | doc-lifecycle.js:14 |
|
|
18
|
+
| Frontmatter `role` | optional; if present must equal path role (`role-mismatch`) | doc-lifecycle.js:1063–1064 |
|
|
19
|
+
| Frontmatter fields recognized | `id`, `role`, `status`, `aliases`, `supersedes`, `conflicts_with` (+ PRD-only fields); leading `---` YAML subset, no tabs | doc-lifecycle.js:119–147, 1082–1092, 1210–1221, 1315–1321 |
|
|
20
|
+
| `aliases[]` | strings matching ID pattern; no `legacy:` prefix, not self (`invalid-alias`); collisions → `alias-collision` | doc-lifecycle.js:1082–1092, 1159+ |
|
|
21
|
+
| `supersedes` | list of resolvable refs; effective edge requires target `status: superseded`; self/cycle → `supersede-cycle` | doc-lifecycle.js:1210–1221, 1259–1268 |
|
|
22
|
+
| `conflicts_with` | refs must resolve or stay `recorded-conflict` until an effective `supersedes` | doc-lifecycle.js:1315–1321 |
|
|
23
|
+
| Location | **config-driven, not hardcoded**: file must match a `governed` glob entry carrying `role: "adr"` (collection doc-lifecycle.js:295–300; `roleAtPath` 2147–2152; no `docs/adr` hardcode in the checker). Resolver infers `docs/adr`/`docs/decisions` only when *generating* config | project-docs-resolver.js:578,599 |
|
|
24
|
+
| Ratchet | schema checks apply to governed files named in `changedPaths`; full mode only with `--all` | docs/document-lifecycle.md:132 |
|
|
25
|
+
|
|
26
|
+
Minimum accepted new ADR (given a config that declares the domain and an ADR glob):
|
|
27
|
+
|
|
28
|
+
```markdown
|
|
29
|
+
---
|
|
30
|
+
id: ROUTE-001
|
|
31
|
+
status: accepted
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
# ROUTE-001 — <title>
|
|
35
|
+
|
|
36
|
+
## Decision
|
|
37
|
+
<text>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
That is the whole required shape: `id` + `status` (+ declared domain). `Decision`-section presence matters only for D6.5 normative-trigger classification, not lint. Pending/edge extras: optional `role`, `aliases`, `supersedes` (with target `superseded`), `conflicts_with`.
|
|
41
|
+
|
|
42
|
+
## 2. Mechanism inventory
|
|
43
|
+
|
|
44
|
+
Path abbreviations: **H/** `hooks/scripts/`, **R/** `harness-everything/scripts/`, **C/** `ci/`. States: `M`=merged PR, `C`=closed, `O`=open. All issue states **executed**; attributions **source-traced**.
|
|
45
|
+
|
|
46
|
+
| # | Mechanism | Decision it embodies | Implementing file(s) | Tests (grep C/) | Issues (state) | Flag |
|
|
47
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
48
|
+
| 01 | Kernel routing | Route before execute: tier/strategy/invariants before mutation | R/kernel-router.js, R/tier-router.js, R/router-contract.js, R/routing-keywords.json | C/invariant-routing, C/router-workflow-plan, C/router-phase2-safety, C/prompt-contract-regressions, C/skill-routing-check | #142 (M), #217 (C) | CONSISTENT |
|
|
49
|
+
| 02 | Step-scoped binding resolution | Disclose only active-step knowledge; unknown stays visible | R/kernel-router.js, H/lib/binding-resolver.js, R/kernel-router-core.js | C/mechanism-2ar-binding-resolution, C/invariant-routing | #297 (C) | CONSISTENT |
|
|
50
|
+
| 03 | Workflow lifecycle evidence | Objective evidence before completion; explicit dispositions | H/workflow-stop-gate.js, H/workflow-disposition.js, H/lib/workflow-obligations.js, H/lib/fable-contracts.js | C/mechanism-2an, C/mechanism-2ah, C/mechanism-2as, C/mechanism-2az, C/workflow-execution-contract | #143 (M), #242 (C) | CONSISTENT |
|
|
51
|
+
| 04 | Worktree/Fable isolation | Isolate broad mutation before it starts | H/lib/workflow-isolation.js, R/kernel-router.js | C/mechanism-2af, C/mechanism-2ai, C/mechanism-34-worktree-submodule-reachability | #150,#152,#154,#156,#158 (all M) | CONSISTENT |
|
|
52
|
+
| 05 | Harness Status protocol | One user-visible status block for non-trivial work (semantic, no lock) | skill text (routing docs); no dedicated runtime file | C/reference-check only (no mechanism test) | NO-ISSUE found | NO-TEST |
|
|
53
|
+
| 06 | Action gate | Explicit approval for destructive/external side effects (hard block) | H/action-gate.js, H/action-gate-rules.json, H/codex-action-gate-pre.js, H/codex-action-gate-post.js, H/codex-permission-request.js | C/action-gate, C/mechanism-2ad, C/mechanism-2aa, C/mechanism-2au, C/action-gate-platform-doc | #144 (M); live approval matrix #100 (C) | CONSISTENT |
|
|
54
|
+
| 07 | Rule-of-3 / zoom-out | Stop after 3 same-signature failures; hard boundary | H/rule-of-3.js, H/rule-of-3-tracker.js, H/reset-circuit-breaker.js | C/mechanism-2a-rule-of-3, C/self-evolve-loop | #201 (C) | CONSISTENT |
|
|
55
|
+
| 08 | Stop gate | No completion without observed successful verification | H/stop-gate.js | C/mechanism-2f-stop-gate | #190 (C) | CONSISTENT |
|
|
56
|
+
| 09 | Advisory guard trio | Warn about broad searches, blind overwrites, context pressure (fail-open) | H/boundary-guard.js, H/depth-guard.js, H/context-compact.js | C/mechanism-2b (boundary only); depth/context **no test** | #190 (C) | NO-TEST (2 of 3) |
|
|
57
|
+
| 10 | State persistence / WAL | Persist tool outcomes, mutations, verification milestones | H/state-persist.js, H/lib/harness-state.js | C/mechanism-2c, C/mechanism-2ah, C/telemetry | #160 (M), #147 (M) | CONSISTENT |
|
|
58
|
+
| 11 | Subagent scope guard + contract test | Snapshot/diff around subagent bursts; inter-agent contract testing | H/subagent-scope-guard.js, H/contract-test.js | C/mechanism-2e, C/workflow-plan-consumers, C/workflow-plan-consumers-edge | NO-ISSUE found | NO-ISSUE |
|
|
59
|
+
| 12 | Memory capability token | One-time workflow-bound capability for memory writes | R/kernel-router.js (`issueMemoryCapability`) | **no function-level test** (adjacent: C/phase4-ensemble-memory) | #145 (M) | NO-TEST |
|
|
60
|
+
| 13 | Ensemble policy | MAY-level multi-agent composition under high uncertainty | R/ensemble-policy.js | C/phase4-ensemble-memory | NO-ISSUE found | NO-ISSUE |
|
|
61
|
+
| 14 | Bootstrap / self-repo guard / self-heal | Session bootstrap, env detection, environment repair | R/bootstrap.js, R/self-heal.js, R/runtime-paths.js | C/mechanism-2m-self-repo-guard, C/mechanism-2an-environment-detection-readonly | NO-ISSUE found | NO-ISSUE |
|
|
62
|
+
| 15 | Contract-integrity audit | Prove artifact↔spec traceability | contract-integrity/scripts/audit.js | C/contract-integrity.test | #84 (C), #58 (C) | CONSISTENT |
|
|
63
|
+
| 16 | Verify gate | Treat verification as observed, timed evidence | R/verify-gate.js | C/mechanism-35-verification-contract, C/mechanism-36-verify-timeout | #242 (C) | CONSISTENT |
|
|
64
|
+
| 17 | verify:all aggregate gate | One CI-ordered gate list with PASS/FAIL/UNCHECKED report | scripts/verify-all.js | C/mechanism-38-verify-all (self-regression subset) | NO-ISSUE found | CONSISTENT (see Open Q1) |
|
|
65
|
+
| 18 | Paired behavioral / benchmark evidence | No "improved" claim without paired baseline-vs-treatment evidence | behavioral-evals/run.js, benchmarks/run.js, C/ab-test-harness.js | C/mechanism-2j, C/mechanism-32, C/mechanism-335, C/mechanism-2v | #71 (**O**), #130 (M), #242 (C) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
66
|
+
| 19 | Doc config resolution (D5) | Committed host-neutral config wholly overrides host manifests; AGENTS.md never config | R/project-docs-resolver.js, R/doc-check.js | C/mechanism-2aw, C/reference-check | #325 (**O**) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
67
|
+
| 20 | ADR/REQ identity + supersession + index (D6.1–D6.4) | Domain-scoped IDs, aliases, legacy refs, generated index | R/doc-lifecycle.js | C/mechanism-2ax, C/reference-check | #325 (**O**) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
68
|
+
| 21 | PRD revision contract (D6.9) | Effective PRD = frozen revision chain with approval record | R/doc-lifecycle.js | C/mechanism-2ay | #325 (**O**) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
69
|
+
| 22 | `doc-change` step type | Explicit doc-edit step type, no implicit TDD binding | H/lib/step-types.json, H/lib/workflow-obligations.js | C/mechanism-2az-step-type-registry | #326 (C), #328 (M) | CONSISTENT |
|
|
70
|
+
| 23 | Doc obligations + evidence producer (3a) | Fail-closed doc MUSTs with trusted-producer identity binding | R/doc-obligations.js, R/doc-evidence.js, R/doc-evidence-capture.js | C/mechanism-325-3a-doc-obligations, C/mechanism-325-3a-doc-evidence, C/mechanism-335-baseline-evidence | #334 (M), #335 (C, fixed by #342 — executed state for #342 not queried, result merged) | CONSISTENT |
|
|
71
|
+
| 24 | Reconciliation pilot S1/F4 | Default-OFF opt-in gate; limited credit for `doc-lint`/`link-check` only | H/lib/doc-reconciliation-*.js, H/codex-user-prompt.js (switch) | C/mechanism-325-3b-preparation, C/mechanism-325-3b-s1-review, C/mechanism-341-opencode-lane | #341 (**O**), #350 (**O**), #358 (M), #375 (M: E1 zero qualifying cycles) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
72
|
+
| 25 | Shared doc craft + derived views (F2/F3) | Regenerate-equals for authorized generators; shared references | R/doc-obligations.js, harness-everything/references/documentation/_shared/ | C/mechanism-325-f3-derived-views, C/reference-check | #356 (M), #357 (M) | CONSISTENT |
|
|
73
|
+
| 26 | #320 obligation abstraction (bounded consumer) | Doc workflow reconciliation consumes workflow abstractions; broad promotion gated | H/lib/doc-reconciliation-core.js + R/doc-obligations.js | same as #24 tests | #320 (**O**) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
74
|
+
| 27 | System One observation capture | Local, content-private turn observation; fail-open, silent | H/observation-hook.js, hooks/scripts/lib/telemetry.js | C/mechanism-34-observations, C/mechanism-2am-observations-session-import | #233 (**O**) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
75
|
+
| 28 | System One engine (tier-4 experimental) | Learned intent routing + resident/eval pipeline | scripts/system-one-*.js/py, R/system-one/ (install) | C/mechanism-system-one-*.test.js suite; ci.yml Windows S1 lanes | #233 (**O**) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
76
|
+
| 29 | S1 intent/suggestion/noise gates | Weak-intent gating with Laya teacher; `rule_v2` noise gate | docs-system-one-* scripts (corpus/evaluate/label) | C/mechanism-system-one-evaluation, C/system-one-*.py | #255 (**O**), #265 (**O**), #297 (C) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
77
|
+
| 30 | Skill telemetry | Privacy-safe skill load start/close telemetry window | H/telemetry-adapter.js, H/lib/telemetry.js, telemetry/scripts/ | C/telemetry.test | #147 (M), #37 (C), #122 top-level blocker (**O**) | CONSISTENT |
|
|
78
|
+
| 31 | OpenCode plugin | Project-scope `.js` loading + edit/verify state on OpenCode 1.18.31 (macOS, retained evidence only) | opencode-plugin/ | C/mechanism-2n, C/mechanism-30-loadability, C/mechanism-31-hardlock-evidence, C/mechanism-2p, C/mechanism-39, C/mechanism-341-opencode-lane | #128 (M), #129 (M), #82 (**O**) | **ISSUE-OPEN-BUT-SHIPPED** (live claim bounded) |
|
|
79
|
+
| 32 | Codex plugin hooks compat | Codex hook adapters/package-level parity with Claude hooks | H/lib/platforms/codex.js, scripts/codex-hooks-compat.js | C/mechanism-2al, C/mechanism-2au, C/mechanism-2ao | #110 (**O**), #122 (**O**), #135 (C), #98 (M), #109 (C) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
80
|
+
| 33 | Platform adapter matrix | Per-host capability/evidence claims centralized and claimed as tested contract | H/lib/platforms/ (claude/codex/cursor/copilot/continue/hermes), docs/platform-capabilities.md | C/mechanism-2w-platform-compatibility, C/mechanism-2t-platform-skill-targets, C/mechanism-2g-platform-ignore | #82 (**O**), #123 (M), #127 (C), #135 (C) | **ISSUE-OPEN-BUT-SHIPPED** |
|
|
81
|
+
| 34 | Plugin packaging (Claude + OpenAI + submission) | Generated distribution manifests are facts, byte-consistent copies | scripts/stage-claude-plugin.js, scripts/validate-claude-plugin.js, scripts/sync-openai-plugin.js, scripts/build-openai-submission.js, .claude-plugin/ | C/mechanism-2z, C/openai-plugin-package, C/openai-plugin-submission, C/openai-plugin-runtime, C/mechanism-packaging-bytecode | #123 (M), #128 (M), #129 (M) | CONSISTENT |
|
|
82
|
+
| 35 | Release automation | semantic-release owns SemVer; nested versions synced; skip-CI version bumps | scripts/sync-release-version.js, .github/workflows/release.yml, scripts/generate-sbom.js | C/mechanism-2x (×2), C/mechanism-2y, C/mechanism-2ap-sbom, C/mechanism-2u-issue-44, C/semantic-release-analyzer | #20 (C) | CONSISTENT |
|
|
83
|
+
| 36 | Manifest sync across hosts | All distribution manifests generated from canonical skills | scripts/plugin-sync.js (.sh/.ps1), scripts/repository-contract.js | C/mechanism-2ao, C/mechanism-2ab, C/repository-contract.test | #123 (M) | CONSISTENT |
|
|
84
|
+
| 37 | Installer | Interactive/non-interactive install, verify, uninstall, shared store | scripts/installer.js, bin/cli.js | C/installer-roundtrip, C/mechanism-2h, C/mechanism-2i (×2), C/mechanism-2p-installer-links, C/mechanism-2q, C/mechanism-2r | NO-ISSUE found | NO-ISSUE |
|
|
85
|
+
| 38 | Skill routing evals / collision gate | Every routed skill has a trigger eval; descriptions must not collide | evals/<skill>/eval.yaml, C/description-collision.js, C/skill-routing-check.js | (these files are the gates) | NO-ISSUE found | CONSISTENT (see Open Q1) |
|
|
86
|
+
| 39 | Commit discipline | Conventional commits enforced locally via husky+commitlint | commitlint.config.js, .husky/ | C/mechanism-33-issues-205-207, C/mechanism-2x-release-commit-message | #205 (C), #207 (C) | CONSISTENT |
|
|
87
|
+
|
|
88
|
+
Counts: 39 rows · CONSISTENT 21 · ISSUE-OPEN-BUT-SHIPPED 11 · NO-ISSUE 5 · NO-TEST 2 (02 rows flagged NO-TEST cover 3 sub-mechanisms).
|
|
89
|
+
|
|
90
|
+
## 3. Area grouping + candidate domain prefixes
|
|
91
|
+
|
|
92
|
+
Formats follow `^[A-Z][A-Z0-9]{1,9}$` (checked against doc-lifecycle.js:20 ADR_ID domain form). No domains are declared today (`.agents/harness-everything/project-docs.json` governs two `reference` files only, no `domains` key) — so every candidate is new, and adopting any requires editing `project-docs.json`, which under #325 D6.8 is the project's own declared list (Harness never hard-codes it).
|
|
93
|
+
|
|
94
|
+
| Area | Rows | Candidate prefix | Why |
|
|
95
|
+
| --- | --- | --- | --- |
|
|
96
|
+
| Routing & workflow contract | 01–05 | `ROUTE` | Kernel routing / topology / bindings are one decision family |
|
|
97
|
+
| Enforcement & safety boundaries | 06–15 | `ENFC` | Approval, breaker, stop evidence, persistence — the hook-path contract |
|
|
98
|
+
| Verification & evidence | 16–18, 15 | `VERI` | Shared "objective evidence before claiming done" decision |
|
|
99
|
+
| Document lifecycle (#325) | 19–26 | `DOCS` | Already contract-scoped to #325; natural domain |
|
|
100
|
+
| System One (experimental) | 27–29 | `SONE` | Clearly-labeled tier-4 experimental family |
|
|
101
|
+
| Platform, packaging, release | 30–39 | `DIST` | Distribution/platform claims and tooling |
|
|
102
|
+
|
|
103
|
+
Zero-commit numbers (#71, #84, #109, #110, #122, #127, #135, #217, #350 — doc-referenced only in this clone) are kept **with state flags** rather than dropped, so a future ADR citing them shows they lack commit-message anchors in this SHA's history.
|
|
104
|
+
|
|
105
|
+
**Single-domain alternative:** one prefix `HARN` for every retroactive ADR (Harness-wide decisions), splitting later via `supersedes`/aliases once areas stabilize. Cheaper to ship (one `domains` entry, no per-area risk of overlap collisions); loses the ability to grep decisions by area from the ID alone.
|
|
106
|
+
|
|
107
|
+
## 4. Mismatch list (non-CONSISTENT rows) — the "功能與 issues 狀態" findings
|
|
108
|
+
|
|
109
|
+
1. **depth-guard.js, context-compact.js — NO-TEST.** Shipped on the hook path (`hooks/hooks.json:99–115`) under closed issue #190, but their basenames appear nowhere in `ci/` outside `archive/`. Candidate: ISSUE-CLOSED-BUT-MISSING *test coverage*, not mechanism.
|
|
110
|
+
2. **memory capability token (kernel-router.js#issueMemoryCapability) — NO-TEST** despite merged #145. Function itself untested; only adjacent ensemble-memory policy tests exist.
|
|
111
|
+
3. **Harness Status protocol (row 05) — NO-TEST.** Mandated in AGENTS.md #11 and docs/routing.md; no mechanism test exists (it is semantic, not enforced — #11 itself says "Not a hard lock").
|
|
112
|
+
4. **#71 OPEN vs shipped policy.** architecture.md and the validation boundary require paired behavioral evidence for lifecycle-effectiveness claims — the requirement is live and unmet while the machinery (rows 18, 24) ships around it: the classic "shipped, gate pending" split. #375 (merged) reports E1 with zero qualifying cycles.
|
|
113
|
+
5. **#341/#350 OPEN vs shipped default-OFF pilot.** S1 + F4 shipped as opt-in (`HARNESS_DOC_RECONCILIATION_PILOT=1`) with fail-closed withholding; expansion explicitly not approved (E1 gate). Consistent-with-docs but issue-open → flagged.
|
|
114
|
+
6. **#82/#110/#122 OPEN: live-host verification umbrella.** platform-capabilities claims are held to mechanism-package evidence; live-host firing is still open for Codex (#110, #122 mount/attribution blocker) and the #82 compatibility program. All OpenCode/Codex live rows inherit this.
|
|
115
|
+
7. **#233/#255/#265 OPEN vs shipped System One.** Experimental engine, gates and Windows CI lanes are live in `ci.yml` while their governing experiment issues are open — intentional (labeled experimental) but must be reflected, not hidden, in the ADR set.
|
|
116
|
+
8. **#325 OPEN vs merged doc-lifecycle slices.** The owner-decision umbrella (#325) stays open by design; all shipped phases (#327/#334/#356/#357/#358, …) flag ISSUE-OPEN-BUT-SHIPPED. Not a defect — a structural fact for the retroactive ADRs' status choices.
|
|
117
|
+
9. **#201 as Rule-of-3 anchor (row 07) is the only issue found** — "advisory re-trip contract (#201)" from this clone's log. Earlier origin of the mechanism may be unreferenced; treating #201 as governing is an inference (label: source-traced, weak).
|
|
118
|
+
|
|
119
|
+
## 5. Open questions
|
|
120
|
+
|
|
121
|
+
1. **Q1 — CI routing-gate coverage (inconclusive):** `package.json` exposes `test:routing:skills`/`test:routing:invariants` and `scripts/verify-all.js` runs them, but `.github/workflows/ci.yml` jobs do not invoke them by name (consistency job runs `test:consistency`, `test:references`, `test:release`, `test:collision`, `test:plugin:openai`, `test:plugin:submission`, `test:platform:compatibility`, `test:portability`; self-regression job runs `npm test` + `test:mutations`). Whether `npm test` self-regression reaches the routing tests was not traced end to end — rows 01 and 38 keep CONSISTENT subject to Q1.
|
|
122
|
+
2. **Q2 — ADR scope boundary:** does "已經存在的機制" (existing mechanisms) cover semantic/instruction-only contracts (rows 05, plus skill-text obligations), or only runtime code with hooks/tests? Recommendation-shaped, not a fact: mechanism code first.
|
|
123
|
+
3. **Q3 — domain assignment ownership:** adopting `ROUTE/ENFC/…` (or `HARN`) requires a `project-docs.json` `domains` edit + ADR glob + `project-overrides-host` warning reconciliation under D5; owner decides under #325.
|
|
124
|
+
4. **Q4 — #342 executed state:** #335's own state was queried (closed, executed) but the first fix PR #342's state was not queried in the batch (its merge is source-traced from docs only).
|
|
125
|
+
5. **Q5 — alias stability:** issues with zero commit-message matches in this clone (71, 84, 109, 110, 122, 127, 135, 217, 350) may exist in other branches/clone histories; anchor-richness is lower than for #233/#325.
|
|
126
|
+
|
|
127
|
+
<!-- harness-label {"judgement":"facts-only inventory report per packet; no repo writes","risk":"none"} -->
|
|
128
|
+
STATUS: DONE
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const assert = require('assert');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const [input, output, ...extra] = process.argv.slice(2);
|
|
9
|
+
if (!input || !output || extra.length) throw new Error('usage: node sanitize-outline-capture.js <raw-hooks.jsonl> <output.jsonl>');
|
|
10
|
+
|
|
11
|
+
const wrappers = fs.readFileSync(input, 'utf8').split(/\r?\n/).filter(line => line.trim()).map(line => JSON.parse(line));
|
|
12
|
+
const payloads = wrappers.map(item => {
|
|
13
|
+
assert(item && item.payload && typeof item.payload === 'object' && !Array.isArray(item.payload), 'raw record has no payload object');
|
|
14
|
+
assert(typeof item.payload.hook_event_name === 'string' && item.payload.hook_event_name, 'raw payload has no observed hook event');
|
|
15
|
+
return item.payload;
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const ids = new Map();
|
|
19
|
+
const sensitiveIds = new Set();
|
|
20
|
+
const nextId = (kind, value) => {
|
|
21
|
+
const key = `${kind}\0${value}`;
|
|
22
|
+
sensitiveIds.add(value);
|
|
23
|
+
if (!ids.has(key)) ids.set(key, `<${kind}-${[...ids.keys()].filter(id => id.startsWith(`${kind}\0`)).length + 1}>`);
|
|
24
|
+
return ids.get(key);
|
|
25
|
+
};
|
|
26
|
+
const collectIds = (value, key) => {
|
|
27
|
+
if (typeof value === 'string') {
|
|
28
|
+
if (value && ['session_id', 'prompt_id'].includes(key)) nextId(key === 'session_id' ? 'session' : 'prompt', value);
|
|
29
|
+
if (value && ['agent_id', 'agentId'].includes(key)) nextId('agent', value);
|
|
30
|
+
for (const match of value.matchAll(/toolu_[A-Za-z0-9]+/g)) nextId('tool-use', match[0]);
|
|
31
|
+
} else if (Array.isArray(value)) value.forEach(item => collectIds(item, key));
|
|
32
|
+
else if (value && typeof value === 'object') {
|
|
33
|
+
for (const [childKey, child] of Object.entries(value)) collectIds(child, childKey);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
payloads.forEach(payload => collectIds(payload, ''));
|
|
37
|
+
|
|
38
|
+
const dispatchTokens = new Map();
|
|
39
|
+
const collectDispatchTokens = value => {
|
|
40
|
+
if (typeof value === 'string') {
|
|
41
|
+
for (const match of value.matchAll(/HARNESS_OUTLINE_DISPATCH_V1[^\r\n]*?\btoken=([^\s]+)/g)) {
|
|
42
|
+
if (!dispatchTokens.has(match[1])) dispatchTokens.set(match[1], `sanitized-dispatch-token-${dispatchTokens.size + 1}`);
|
|
43
|
+
}
|
|
44
|
+
} else if (Array.isArray(value)) value.forEach(collectDispatchTokens);
|
|
45
|
+
else if (value && typeof value === 'object') {
|
|
46
|
+
for (const child of Object.values(value)) collectDispatchTokens(child);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
payloads.forEach(collectDispatchTokens);
|
|
50
|
+
|
|
51
|
+
const transcriptPaths = new Map();
|
|
52
|
+
const privateProjectSlugs = new Set();
|
|
53
|
+
const collectTranscriptPaths = (value, key = '') => {
|
|
54
|
+
if (typeof value === 'string') {
|
|
55
|
+
if (key === 'agent_transcript_path' && !transcriptPaths.has(value)) {
|
|
56
|
+
transcriptPaths.set(value, `/sanitized/run8/agent-transcripts/transcript-${transcriptPaths.size + 1}.jsonl`);
|
|
57
|
+
const projectsMarker = '/.claude/projects/';
|
|
58
|
+
const projectsIndex = value.replace(/\\/g, '/').indexOf(projectsMarker);
|
|
59
|
+
if (projectsIndex >= 0) {
|
|
60
|
+
const slug = value.replace(/\\/g, '/').slice(projectsIndex + projectsMarker.length).split('/')[0];
|
|
61
|
+
if (slug) privateProjectSlugs.add(slug);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} else if (Array.isArray(value)) value.forEach(item => collectTranscriptPaths(item, key));
|
|
65
|
+
else if (value && typeof value === 'object') {
|
|
66
|
+
for (const [childKey, child] of Object.entries(value)) collectTranscriptPaths(child, childKey);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
payloads.forEach(payload => collectTranscriptPaths(payload));
|
|
70
|
+
|
|
71
|
+
const records = payloads.map(payload => {
|
|
72
|
+
const { transcript_path, hook_event_name, ...record } = payload;
|
|
73
|
+
return { ...record, event: hook_event_name };
|
|
74
|
+
});
|
|
75
|
+
let text = JSON.stringify(records);
|
|
76
|
+
for (const [original, replacement] of transcriptPaths) text = text.split(original).join(replacement);
|
|
77
|
+
for (const slug of privateProjectSlugs) text = text.split(slug).join('sanitized-run8-project');
|
|
78
|
+
const workerRoots = new Set();
|
|
79
|
+
for (const record of records) {
|
|
80
|
+
if (typeof record.tool_input?.prompt !== 'string') continue;
|
|
81
|
+
const match = record.tool_input.prompt.match(/(?:^|\s)workerRoot=(\S+)/);
|
|
82
|
+
if (match && path.isAbsolute(match[1])) workerRoots.add(match[1]);
|
|
83
|
+
}
|
|
84
|
+
const runRoots = [...workerRoots].map(root => path.dirname(root)).sort((a, b) => b.length - a.length);
|
|
85
|
+
for (let i = 0; i < runRoots.length; i++) text = text.split(runRoots[i]).join(`/sanitized/run8${i ? `/root-${i + 1}` : ''}`);
|
|
86
|
+
text = text.replace(/\/Users\/[^/"\\\s]+/g, '/sanitized/home').replaceAll('/private/', '/sanitized/private/');
|
|
87
|
+
const tokenPattern = [...dispatchTokens.keys()].sort((a, b) => b.length - a.length)
|
|
88
|
+
.map(value => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
|
|
89
|
+
if (tokenPattern) text = text.replace(new RegExp(tokenPattern, 'g'), value => dispatchTokens.get(value));
|
|
90
|
+
for (const [key, placeholder] of [...ids].sort((a, b) => b[0].length - a[0].length)) {
|
|
91
|
+
const value = key.slice(key.indexOf('\0') + 1);
|
|
92
|
+
text = text.split(value).join(placeholder);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const sanitized = JSON.parse(text);
|
|
96
|
+
assert(sanitized.length === records.length, 'sanitization changed record count');
|
|
97
|
+
assert(sanitized.every(record => record && typeof record === 'object' && !Array.isArray(record)), 'sanitized record is not an object');
|
|
98
|
+
assert(!/\/Users\/|\/private\/|toolu_/.test(text), 'sanitized output retains a private path or tool id');
|
|
99
|
+
assert([...sensitiveIds].every(value => !text.includes(value)), 'sanitized output retains a session or agent id');
|
|
100
|
+
assert([...transcriptPaths.keys(), ...privateProjectSlugs].every(value => !text.includes(value)), 'sanitized output retains a private transcript path');
|
|
101
|
+
assert([...dispatchTokens.keys()].every(value => !text.includes(value)), 'sanitized output retains a dispatch token');
|
|
102
|
+
assert([...dispatchTokens.values()].every(value => value.length > 0 && !/\s/.test(value)), 'synthetic dispatch token is invalid');
|
|
103
|
+
fs.mkdirSync(path.dirname(path.resolve(output)), { recursive: true });
|
|
104
|
+
fs.writeFileSync(output, sanitized.map(record => JSON.stringify(record)).join('\n') + '\n');
|
|
105
|
+
console.log(`sanitized records=${sanitized.length}; privacy audit=clear`);
|