repo-harness 0.16.0 → 0.16.2
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/AGENTS.md +2 -2
- package/CLAUDE.md +2 -2
- package/README.es.md +2 -2
- package/README.fr.md +2 -2
- package/README.ja.md +2 -2
- package/README.md +13 -5
- package/README.zh-CN.md +13 -5
- package/assets/partials/03-philosophy.partial.md +6 -0
- package/assets/partials-agents/04-task-protocol.partial.md +0 -1
- package/assets/partials-agents/06-quality-safety.partial.md +1 -0
- package/assets/reference-configs/external-tooling.md +45 -9
- package/assets/reference-configs/global-working-rules.md +8 -0
- package/assets/reference-configs/sprint-contracts.md +2 -0
- package/assets/skill-commands/manifest.json +40 -1
- package/assets/skill-version.json +10 -2
- package/assets/templates/helpers/acceptance-receipt.ts +78 -4
- package/assets/templates/helpers/architecture-event.ts +22 -5
- package/assets/templates/helpers/check-agent-tooling.sh +102 -19
- package/assets/templates/helpers/contract-worktree.sh +210 -37
- package/assets/templates/helpers/ensure-task-workflow.sh +1 -0
- package/assets/templates/helpers/install-agent-fleet.sh +6 -15
- package/assets/templates/helpers/merge-gate.ts +79 -26
- package/assets/templates/helpers/ship-worktrees.sh +28 -10
- package/assets/templates/helpers/sprint-backlog.sh +63 -2
- package/assets/templates/helpers/verify-contract.sh +1 -1
- package/assets/templates/helpers/verify-sprint.sh +105 -8
- package/dist/hook-entry.js +582 -287
- package/package.json +5 -5
- package/scripts/acceptance-receipt.ts +78 -4
- package/scripts/architecture-event.ts +22 -5
- package/scripts/check-agent-tooling.sh +102 -19
- package/scripts/contract-worktree.sh +210 -37
- package/scripts/ensure-task-workflow.sh +1 -0
- package/scripts/install-agent-fleet.sh +6 -15
- package/scripts/lib/project-init-lib.sh +1 -0
- package/scripts/merge-gate.ts +79 -26
- package/scripts/run-skill-hook.ts +16 -1
- package/scripts/ship-worktrees.sh +28 -10
- package/scripts/sprint-backlog.sh +63 -2
- package/scripts/verify-contract.sh +1 -1
- package/scripts/verify-sprint.sh +105 -8
- package/src/cli/commands/architecture-projection.ts +23 -0
- package/src/cli/commands/cross-review.ts +101 -1
- package/src/cli/commands/global-runtime.ts +189 -29
- package/src/cli/commands/init-hook.ts +4 -0
- package/src/cli/commands/init.ts +21 -8
- package/src/cli/commands/mcp.ts +12 -6
- package/src/cli/commands/run.ts +113 -3
- package/src/cli/commands/sprint.ts +77 -2
- package/src/cli/hook/architecture-drift.ts +64 -0
- package/src/cli/hook/circuit-breaker.ts +2 -1
- package/src/cli/hook/stop-handler.ts +16 -0
- package/src/cli/hook/subagent-handler.ts +109 -49
- package/src/cli/index.ts +19 -4
- package/src/cli/installer/install-profile.ts +22 -1
- package/src/cli/mcp/coding-tools.ts +9 -1
- package/src/cli/mcp/coding-workspaces.ts +210 -22
- package/src/cli/mcp/guarded-write.ts +192 -0
- package/src/cli/mcp/setup.ts +16 -1
- package/src/cli/mcp/tools.ts +92 -20
- package/src/cli/mcp/transports/http.ts +54 -21
- package/src/cli/runtime/helper-runner.ts +73 -86
- package/src/cli/runtime/protected-helper-platform.ts +469 -0
- package/src/cli/tools/codegraph.ts +36 -0
- package/src/core/adoption/standard-plan.ts +8 -0
- package/src/core/architecture/restamp-publication.ts +90 -0
- package/src/core/review/cross-review.ts +11 -3
- package/src/core/skill-surface/catalog.ts +149 -0
- package/src/core/state/coordination-identity.ts +47 -0
- package/src/effects/architecture/archctx-provider.ts +33 -3
- package/src/effects/architecture/projection-jobs.ts +23 -0
- package/src/effects/architecture/restamp-publication.ts +264 -0
- package/src/effects/process-runner.ts +14 -8
- package/src/effects/process-supervisor.ts +19 -16
- package/src/effects/review/cross-review-runner.ts +14 -0
- package/src/effects/runtime/node-candidates.ts +48 -0
package/AGENTS.md
CHANGED
|
@@ -36,7 +36,7 @@ This repository self-hosts the `repo-harness` contract; the former `repo-harness
|
|
|
36
36
|
- Treat `deploy/` as the trackable deployment and operations surface for runbooks, submission materials, release checklists, helper scripts, ordered SQL files, and env examples; follow `.ai/harness/policy.json#operations.deploy_sql` for configured SQL roots and naming modes, otherwise keep SQL directly under `deploy/sql/` with 4-digit ascending prefixes.
|
|
37
37
|
- Treat `_ops/` as ignored local operations state for secrets, real env files, provider state, artifacts, logs, and scratch files; do not commit or agent-edit `_ops/*`.
|
|
38
38
|
- Treat contract-level task execution as worktree-first: `repo-harness run plan-to-todo --plan <approved-plan>` starts `repo-harness run contract-worktree start --plan <approved-plan>` when policy enables it, and completed blocks finish through Waza `/check` plus `repo-harness run contract-worktree finish`.
|
|
39
|
-
- Treat the EXECUTION_BOUNDARY anti-extras clause as mandatory
|
|
39
|
+
- Treat the EXECUTION_BOUNDARY anti-extras clause as mandatory exactly once in each delegated runner's final rendered task packet: absent requirements are forbidden design space, not permission to improve, and unrequested extras fail closed. Each runner path names one injection owner and no other surface on that path may carry the clause — the Codex native-child path is owned by `SubagentStart.context` (contract- and writability-aware; generated personas and the delegation advisor carry none), the standalone contract worker path by its worker prompt, and the MCP path by the `codex-goal` document. Composed-path tests verify the count.
|
|
40
40
|
- After Codex Plan mode, Waza `/think`, or `repo-harness-plan` produces a decision-complete work-package plan, capture it with `repo-harness run capture-plan --artifact-level work-package --slug <slug> --title <title>` so `plans/` becomes the file-backed source of truth; if the user has already approved implementation, capture with `--status Approved --execute --promotion-reason <merge_boundary|rollback_boundary|verification_boundary|risk_boundary|human_decision_boundary|worktree_boundary>` or run `repo-harness run plan-to-todo --plan <active-plan>`.
|
|
41
41
|
- Promote work into a top-level `plans/plan-*.md` only when `Artifact Level: work-package` is justified by a merge/PR unit, rollback surface, independent verification boundary, review/acceptance boundary, high-risk surface, or otherwise cannot remain a checklist item in the current active plan or sprint backlog. Inline sprint rows and checklist rows stay in the sprint backlog or active plan `## Task Breakdown`; contract rows may expand into plan -> contract -> review -> notes only through the work-package gate.
|
|
42
42
|
- If current repo state conflicts with the task, open an isolated `codex/<task-slug>` worktree, finish there, run Waza `/check`-style validation, then merge back to `main` without absorbing unrelated dirty changes.
|
|
@@ -59,7 +59,7 @@ This repository self-hosts the `repo-harness` contract; the former `repo-harness
|
|
|
59
59
|
## Required Checks
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
bun test
|
|
62
|
+
bun test --timeout 60000
|
|
63
63
|
bash scripts/check-deploy-sql-order.sh
|
|
64
64
|
bash scripts/check-architecture-sync.sh
|
|
65
65
|
bash scripts/check-task-sync.sh
|
package/CLAUDE.md
CHANGED
|
@@ -36,7 +36,7 @@ This repository self-hosts the `repo-harness` contract; the former `repo-harness
|
|
|
36
36
|
- Treat `deploy/` as the trackable deployment and operations surface for runbooks, submission materials, release checklists, helper scripts, ordered SQL files, and env examples; follow `.ai/harness/policy.json#operations.deploy_sql` for configured SQL roots and naming modes, otherwise keep SQL directly under `deploy/sql/` with 4-digit ascending prefixes.
|
|
37
37
|
- Treat `_ops/` as ignored local operations state for secrets, real env files, provider state, artifacts, logs, and scratch files; do not commit or agent-edit `_ops/*`.
|
|
38
38
|
- Treat contract-level task execution as worktree-first: `repo-harness run plan-to-todo --plan <approved-plan>` starts `repo-harness run contract-worktree start --plan <approved-plan>` when policy enables it, and completed blocks finish through Waza `/check` plus `repo-harness run contract-worktree finish`.
|
|
39
|
-
- Treat the EXECUTION_BOUNDARY anti-extras clause as mandatory
|
|
39
|
+
- Treat the EXECUTION_BOUNDARY anti-extras clause as mandatory exactly once in each delegated runner's final rendered task packet: absent requirements are forbidden design space, not permission to improve, and unrequested extras fail closed. Each runner path names one injection owner and no other surface on that path may carry the clause — the Codex native-child path is owned by `SubagentStart.context` (contract- and writability-aware; generated personas and the delegation advisor carry none), the standalone contract worker path by its worker prompt, and the MCP path by the `codex-goal` document. Composed-path tests verify the count.
|
|
40
40
|
- After Codex Plan mode, Waza `/think`, or `repo-harness-plan` produces a decision-complete work-package plan, capture it with `repo-harness run capture-plan --artifact-level work-package --slug <slug> --title <title>` so `plans/` becomes the file-backed source of truth; if the user has already approved implementation, capture with `--status Approved --execute --promotion-reason <merge_boundary|rollback_boundary|verification_boundary|risk_boundary|human_decision_boundary|worktree_boundary>` or run `repo-harness run plan-to-todo --plan <active-plan>`.
|
|
41
41
|
- Promote work into a top-level `plans/plan-*.md` only when `Artifact Level: work-package` is justified by a merge/PR unit, rollback surface, independent verification boundary, review/acceptance boundary, high-risk surface, or otherwise cannot remain a checklist item in the current active plan or sprint backlog. Inline sprint rows and checklist rows stay in the sprint backlog or active plan `## Task Breakdown`; contract rows may expand into plan -> contract -> review -> notes only through the work-package gate.
|
|
42
42
|
- If current repo state conflicts with the task, open an isolated `codex/<task-slug>` worktree, finish there, run Waza `/check`-style validation, then merge back to `main` without absorbing unrelated dirty changes.
|
|
@@ -59,7 +59,7 @@ This repository self-hosts the `repo-harness` contract; the former `repo-harness
|
|
|
59
59
|
## Required Checks
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
bun test
|
|
62
|
+
bun test --timeout 60000
|
|
63
63
|
bash scripts/check-deploy-sql-order.sh
|
|
64
64
|
bash scripts/check-architecture-sync.sh
|
|
65
65
|
bash scripts/check-task-sync.sh
|
package/README.es.md
CHANGED
|
@@ -467,8 +467,8 @@ repositorio adopte la misma política.
|
|
|
467
467
|
|
|
468
468
|
## Versión actual
|
|
469
469
|
|
|
470
|
-
- Paquete npm: `repo-harness@0.16.
|
|
471
|
-
- Sello de workflow generado: `repo-harness@0.16.
|
|
470
|
+
- Paquete npm: `repo-harness@0.16.2`
|
|
471
|
+
- Sello de workflow generado: `repo-harness@0.16.2+template@0.16.2`
|
|
472
472
|
- Repositorio de GitHub: `Ancienttwo/repo-harness`
|
|
473
473
|
- Notas de versión e historial: [`docs/CHANGELOG.md`](docs/CHANGELOG.md)
|
|
474
474
|
|
package/README.fr.md
CHANGED
|
@@ -462,8 +462,8 @@ adopte la même policy.
|
|
|
462
462
|
|
|
463
463
|
## Release actuelle
|
|
464
464
|
|
|
465
|
-
- Package npm : `repo-harness@0.16.
|
|
466
|
-
- Generated workflow stamp : `repo-harness@0.16.
|
|
465
|
+
- Package npm : `repo-harness@0.16.2`
|
|
466
|
+
- Generated workflow stamp : `repo-harness@0.16.2+template@0.16.2`
|
|
467
467
|
- Dépôt GitHub : `Ancienttwo/repo-harness`
|
|
468
468
|
- Notes et historique de release : [`docs/CHANGELOG.md`](docs/CHANGELOG.md)
|
|
469
469
|
|
package/README.ja.md
CHANGED
|
@@ -470,8 +470,8 @@ commit script や hooks に組み込まないでください。
|
|
|
470
470
|
|
|
471
471
|
## 現在の Release
|
|
472
472
|
|
|
473
|
-
- npm package:`repo-harness@0.16.
|
|
474
|
-
- Generated workflow stamp:`repo-harness@0.16.
|
|
473
|
+
- npm package:`repo-harness@0.16.2`
|
|
474
|
+
- Generated workflow stamp:`repo-harness@0.16.2+template@0.16.2`
|
|
475
475
|
- GitHub repository:`Ancienttwo/repo-harness`
|
|
476
476
|
- Release notes and history:[`docs/CHANGELOG.md`](docs/CHANGELOG.md)
|
|
477
477
|
|
package/README.md
CHANGED
|
@@ -41,9 +41,10 @@ with a tasks-first agent contract that keeps Claude and Codex aligned.
|
|
|
41
41
|
|
|
42
42
|
### 1. Install the CLI
|
|
43
43
|
|
|
44
|
-
Prerequisites: a Git working tree
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
Prerequisites: a Git working tree and `bun`; macOS/Linux also require `bash`,
|
|
45
|
+
while Windows requires Git for Windows (including its Bash and `usr/bin`
|
|
46
|
+
tools). `jq` is optional. No Node.js required — the installer uses Bun >=
|
|
47
|
+
1.1.35 as the runtime, installing or upgrading Bun first when needed.
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
50
|
# macOS / Linux
|
|
@@ -70,6 +71,13 @@ npx -y repo-harness@latest install # npx fallback; the CLI still runs on Bun
|
|
|
70
71
|
repo-harness install
|
|
71
72
|
```
|
|
72
73
|
|
|
74
|
+
On Windows, keep Git for Windows on the install/update `PATH`. That explicit
|
|
75
|
+
ceremony validates and pins `git.exe`, its matching `bash.exe`/`usr/bin`, and
|
|
76
|
+
the install account's absolute `TEMP` directory plus native `System32` tools in the OS account's
|
|
77
|
+
`~/.repo-harness/config.json#protectedHelperRuntime`. Protected workflow
|
|
78
|
+
helpers do not rediscover tools from a caller's `PATH`; rerun
|
|
79
|
+
`repo-harness update` after relocating or replacing Git for Windows.
|
|
80
|
+
|
|
73
81
|
The global bootstrap: installs the npm package as the global CLI, refreshes
|
|
74
82
|
repo-harness skill aliases, installs user-level hook adapters, and records an
|
|
75
83
|
explicit install profile. It is idempotent and does not apply repo-local workflow
|
|
@@ -442,8 +450,8 @@ repo-harness commit scripts or hooks unless that repo adopts the same policy.
|
|
|
442
450
|
|
|
443
451
|
## Current Release
|
|
444
452
|
|
|
445
|
-
- npm package: `repo-harness@0.16.
|
|
446
|
-
- Generated workflow stamp: `repo-harness@0.16.
|
|
453
|
+
- npm package: `repo-harness@0.16.2`
|
|
454
|
+
- Generated workflow stamp: `repo-harness@0.16.2+template@0.16.2`
|
|
447
455
|
- GitHub repository: `Ancienttwo/repo-harness`
|
|
448
456
|
- Release notes and history: [`docs/CHANGELOG.md`](docs/CHANGELOG.md)
|
|
449
457
|
|
package/README.zh-CN.md
CHANGED
|
@@ -41,9 +41,10 @@ checks 和 review evidence 写回项目文件,让下一个 agent 会话从文
|
|
|
41
41
|
|
|
42
42
|
### 1. 安装 CLI
|
|
43
43
|
|
|
44
|
-
前置条件:一个 Git working tree
|
|
45
|
-
|
|
46
|
-
Bun
|
|
44
|
+
前置条件:一个 Git working tree 和 `bun`;macOS/Linux 还需要 `bash`,
|
|
45
|
+
Windows 则需要 Git for Windows(包括其 Bash 与 `usr/bin` 工具)。`jq`
|
|
46
|
+
可选。不需要 Node.js——installer 使用 Bun >= 1.1.35 作为 runtime,需要时会
|
|
47
|
+
先安装或升级 Bun。
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
50
|
# macOS / Linux
|
|
@@ -70,6 +71,13 @@ npx -y repo-harness@latest install # npx fallback; the CLI still runs on Bun
|
|
|
70
71
|
repo-harness install
|
|
71
72
|
```
|
|
72
73
|
|
|
74
|
+
Windows 上应在执行 install/update 时让 Git for Windows 位于 `PATH`。
|
|
75
|
+
这次显式配置会验证 `git.exe`、同一安装根下的 `bash.exe`/`usr/bin` 以及原生
|
|
76
|
+
`System32` 工具和安装账号的绝对 `TEMP` 目录,并将这些路径固定到 OS 账号的
|
|
77
|
+
`~/.repo-harness/config.json#protectedHelperRuntime`。protected workflow
|
|
78
|
+
helper 运行时不会再从调用者 `PATH` 搜索工具;Git for Windows 被移动或替换
|
|
79
|
+
后,必须重新运行 `repo-harness update`。
|
|
80
|
+
|
|
73
81
|
这个全局 bootstrap 会把 npm 包安装成全局 CLI,刷新 repo-harness 的 skill
|
|
74
82
|
aliases,安装 user-level hook adapters,并记录一份明确的 install profile。
|
|
75
83
|
它是幂等的,不会把 repo-local workflow 文件应用到当前目录。`--dry-run
|
|
@@ -449,8 +457,8 @@ policy。
|
|
|
449
457
|
|
|
450
458
|
## 当前 Release
|
|
451
459
|
|
|
452
|
-
- npm package:`repo-harness@0.16.
|
|
453
|
-
- Generated workflow stamp:`repo-harness@0.16.
|
|
460
|
+
- npm package:`repo-harness@0.16.2`
|
|
461
|
+
- Generated workflow stamp:`repo-harness@0.16.2+template@0.16.2`
|
|
454
462
|
- GitHub repository:`Ancienttwo/repo-harness`
|
|
455
463
|
- Release notes 和 history:[`docs/CHANGELOG.md`](docs/CHANGELOG.md)
|
|
456
464
|
|
|
@@ -24,6 +24,12 @@ BUG_FIX_FLOW:
|
|
|
24
24
|
3. Re-run full verification
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
#### Artifact Hygiene
|
|
28
|
+
|
|
29
|
+
- Write comments, commit messages, and PR text from the final diff only, as if discarded intermediate attempts never existed.
|
|
30
|
+
- Comments state only the non-obvious reason at the owning boundary; never restate the operation, preserve intermediate attempts, or list speculative future work.
|
|
31
|
+
- PR text states final behavior plus only the material rationale or trade-off a reviewer cannot recover from the diff; never mention never-merged states or reverted work.
|
|
32
|
+
|
|
27
33
|
Detailed playbooks:
|
|
28
34
|
- `docs/reference-configs/harness-overview.md`
|
|
29
35
|
- `docs/reference-configs/agentic-development-flow.md`
|
|
@@ -53,7 +53,6 @@ RULES:
|
|
|
53
53
|
- Promote factors only after hypothesis and backtest summary artifacts exist
|
|
54
54
|
- Run the configured factor-lab check before claiming factor-lab work is complete
|
|
55
55
|
{{/IF}}
|
|
56
|
-
|
|
57
56
|
ACTIVE_PLAN:
|
|
58
57
|
- .ai/harness/active-plan selects the current active plan only for its owning worktree; .ai/harness/active-worktree records that owner
|
|
59
58
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
- Do not silently expand scope beyond approved plan.
|
|
13
13
|
- If unexpected repo changes appear, stop and ask.
|
|
14
14
|
- Prefer modifying existing files over unnecessary file creation.
|
|
15
|
+
- Write comments, commit messages, and PR text from the final diff only: comments state only the non-obvious reason at the owning boundary; PR text states final behavior plus only rationale a reviewer cannot recover from the diff; never mention discarded attempts, reverted work, or never-merged states.
|
|
15
16
|
|
|
16
17
|
### Final Response Contract
|
|
17
18
|
1. What changed — list modified files with one-line summary each
|
|
@@ -224,7 +224,7 @@ boundary explicit:
|
|
|
224
224
|
| Capability | Owner | Required for |
|
|
225
225
|
|---|---|---|
|
|
226
226
|
| `bun` | repo-harness | repo-harness-owned global installs, local dependency install, tests, and runtime execution |
|
|
227
|
-
| `bash` | repo-harness | helper scripts, migration, setup checks, and contract verification wrappers |
|
|
227
|
+
| `bash` | repo-harness | helper scripts, migration, setup checks, and contract verification wrappers; Git-for-Windows Bash is the Windows platform contract |
|
|
228
228
|
| `npm` | npm registry | registry readbacks, publish gates, and opt-in update checks; not repo-harness-owned global install repair |
|
|
229
229
|
| `npx` / `skills_cli` | external Skills CLI | Waza and Mermaid skill bootstrap/update commands |
|
|
230
230
|
| `rsync` | platform filesystem | Waza staging-to-Codex sync and installed-copy runtime mirroring |
|
|
@@ -236,6 +236,31 @@ CLI dependencies until a separate plan replaces that integration. Missing
|
|
|
236
236
|
optional capabilities should degrade the named feature, not blur command
|
|
237
237
|
ownership.
|
|
238
238
|
|
|
239
|
+
On Windows, `repo-harness install` and `repo-harness update` are the only
|
|
240
|
+
protected-helper tool discovery ceremonies. They resolve `git.exe` and
|
|
241
|
+
`taskkill.exe` from that invocation's `PATH`, require the latter to match
|
|
242
|
+
`SystemRoot\\System32\\taskkill.exe`, require Git, Bash, and `usr/bin` to
|
|
243
|
+
resolve under one non-symlink Git-for-Windows root, require the ceremony's
|
|
244
|
+
`TEMP` to be an absolute non-symlink directory, probe the executables, and
|
|
245
|
+
atomically persist protocol 1 under the OS account's
|
|
246
|
+
`~/.repo-harness/config.json#protectedHelperRuntime`. Existing sibling config
|
|
247
|
+
fields are preserved.
|
|
248
|
+
|
|
249
|
+
Normal `acceptance-receipt`, `merge-gate`, `contract-worktree`, and
|
|
250
|
+
`ship-worktrees` dispatch reads that exact contract. The protected child gets
|
|
251
|
+
the platform `PATH` delimiter, account home, pinned temp/SystemRoot values,
|
|
252
|
+
pinned Bun/Git/Bash, the Git-for-Windows POSIX directories, and the exact
|
|
253
|
+
`taskkill.exe` passed to both supervisor termination paths; caller binary overrides, `HOME`, shell
|
|
254
|
+
startup hooks, and general `PATH` entries are discarded. A missing, malformed,
|
|
255
|
+
relocated, symlinked, cross-root, or incomplete contract fails before helper
|
|
256
|
+
execution and instructs the operator to rerun install/update. There is no
|
|
257
|
+
runtime discovery fallback. The protected TypeScript entrypoints re-resolve the
|
|
258
|
+
same host contract themselves when invoked directly, so their Git and temp
|
|
259
|
+
authority does not depend on dispatcher-only environment variables. Optional
|
|
260
|
+
feature dependencies such as `jq` and `gh` remain separately operator-owned
|
|
261
|
+
and are not installed by this contract; the required merge-gate path does not
|
|
262
|
+
depend on `jq`.
|
|
263
|
+
|
|
239
264
|
Installed-copy sync has two explicit modes. `AGENTIC_DEV_LINK_INSTALLED_COPIES=1`
|
|
240
265
|
uses symlinks and does not require `rsync`; if symlink creation fails, the
|
|
241
266
|
script reports unsupported link-mode and tells the caller to use copy-mode.
|
|
@@ -584,9 +609,9 @@ The exact target base commit enables the local gate in
|
|
|
584
609
|
`.ai/harness/policy.json#merge_gate`; the candidate cannot disable that base
|
|
585
610
|
requirement. Runtime setup installs no merge-gate skill, agent, or provider
|
|
586
611
|
runtime. Caller `HOME`, helper-source, and runner environment overrides are ignored for
|
|
587
|
-
the protected ship/gate helpers. The official runner
|
|
588
|
-
|
|
589
|
-
minimal host runtime path. The host state directories, AcceptanceReceipt, and
|
|
612
|
+
the protected ship/gate helpers. The official runner pins Bash, Git, and Bun;
|
|
613
|
+
where a fixed trusted host `gh` is present it pins that executable too, and it
|
|
614
|
+
replaces caller `PATH` with the minimal host runtime path. The host state directories, AcceptanceReceipt, and
|
|
590
615
|
seal must be owned by the OS account and not group/world writable. After
|
|
591
616
|
`contract-worktree finish` creates the candidate commit, the installed helper
|
|
592
617
|
binds the seal to repository root, target base ref/SHA, candidate head SHA,
|
|
@@ -642,11 +667,22 @@ mismatched, invalid, or unverified native observation blocks a role-routing
|
|
|
642
667
|
claim and authorizes no alternate fleet runner. repo-harness must not scrape
|
|
643
668
|
rollout JSONL or SQLite as a compatibility path.
|
|
644
669
|
|
|
645
|
-
`developer_instructions` is the packaged `.md` body
|
|
646
|
-
EXECUTION_BOUNDARY anti-extras clause,
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
670
|
+
`developer_instructions` is the packaged `.md` role body only. Generated
|
|
671
|
+
personas carry no EXECUTION_BOUNDARY anti-extras clause, and neither does the
|
|
672
|
+
Codex delegation advisor hook: on the native-child path `SubagentStart.context`
|
|
673
|
+
is the single injection owner, so the clause appears exactly once in each
|
|
674
|
+
rendered task packet under the marker
|
|
675
|
+
`[repo-harness:execution-boundary/v1]`. The hook renders it only when both
|
|
676
|
+
halves of the scope decision are known — a resolved active contract and a child
|
|
677
|
+
whose selected profile declares `sandbox_mode = "workspace-write"`; a
|
|
678
|
+
`read-only` child gets the inverse note, and an unresolved contract or
|
|
679
|
+
unverified routing gets neither.
|
|
680
|
+
|
|
681
|
+
`sandbox_mode` is therefore required in every custom-agent TOML and validated
|
|
682
|
+
fail-closed. Writability is read from the selected profile, never inferred from
|
|
683
|
+
the agent name and never defaulted: a profile missing `sandbox_mode`, or
|
|
684
|
+
declaring anything other than `read-only` or `workspace-write`, routes the child
|
|
685
|
+
to native-role-routing `invalid` and receives no implementation boundary.
|
|
650
686
|
|
|
651
687
|
### `install_mode`: self-host vs. downstream
|
|
652
688
|
|
|
@@ -75,6 +75,14 @@ For architecture reviews, bug hunts, risky refactors, deployment issues, auth/pa
|
|
|
75
75
|
|
|
76
76
|
Reports must be concise and grounded in files, commands, runtime behavior, observed code, or verified system state.
|
|
77
77
|
|
|
78
|
+
## Artifact Hygiene
|
|
79
|
+
|
|
80
|
+
Write comments, commit messages, and PR text from the final diff only, as if discarded intermediate attempts never existed. Session history is not documentation material.
|
|
81
|
+
|
|
82
|
+
- Comments state only the non-obvious reason at the owning boundary; never restate the operation, preserve intermediate attempts, or list speculative future work.
|
|
83
|
+
- PR text states final behavior plus only the material rationale or trade-off a reviewer cannot recover from the diff; never mention never-merged states, reverted work, or why something is absent (no "(without X)" titles, no paragraphs justifying a removal the reviewer never saw).
|
|
84
|
+
- When the user rejects an addition, the correct artifact output is the version where that addition never existed — not an annotated explanation of its removal.
|
|
85
|
+
|
|
78
86
|
## Completion Summary Rule
|
|
79
87
|
|
|
80
88
|
For non-trivial completed tasks, include a short `下一刀` section only when verified state shows a concrete next bottleneck, unresolved risk, failing check, deployment gap, review gap, or active-plan item that materially affects the user's stated goal.
|
|
@@ -231,6 +231,8 @@ evaluator never guesses semantic equivalence.
|
|
|
231
231
|
worktree start records immutable provenance.
|
|
232
232
|
- Execute the sprint in that linked worktree. The primary worktree remains a merge target and must stay clean before merge-back.
|
|
233
233
|
- After implementation, run `repo-harness run verify-sprint --prepare-acceptance`, obtain exactly one semantic disposition from the contract-frozen reviewer (or an explicitly allowed typed user waiver), record the `AcceptanceReceipt`, then run `repo-harness run verify-sprint`. The final verification projects the receipt into the review file. The finish command consumes that same receipt, creates a provider-free exact local seal, applies the allowlisted lifecycle archive, and publishes one synthesized target commit whose tree is byte-identical to the verified lifecycle HEAD. The target base must remain frozen and its worktree must remain clean through publication.
|
|
234
|
+
- When architecture projection policy is `automatic`, `--prepare-acceptance` materializes it before computing the review subject. The generated `docs/architecture/.projection-manifest.json` is an exact workflow-owned publication output and does not need to be repeated in every contract `allowed_paths`; every other generated architecture/context path still needs explicit contract scope and otherwise fails closed. Provider unavailability or a non-publishable projection status aborts preparation. After a synthesized commit containing a manifest delta lands, closeout verifies the exact clean published tree and advances the architecture drift cursor to that publication SHA; recovery retries this acknowledgement before committing its journal. Post-publication Stop projection is recovery only, and closeout never restores or discards a dirty target manifest.
|
|
235
|
+
- On the primary checkout, a Stop drain whose only effect is a digest-only manifest restamp publishes itself as one single-path commit, so the steady state stays clean for those dirty gates instead of needing a manual batching commit. The classifier is the provider's own result — exactly one `update` entry for `docs/architecture/.projection-manifest.json` and no pending human action — so a semantic projection delta is never auto-committed. The git gate is fail-closed on top of that: primary worktree, attached local branch, clean index, the manifest as the only dirty tracked path, and no `commit.gpgsign`. The commit is synthesized with `commit-tree` plus an `update-ref` compare-and-swap, which runs no user hooks and reads no untracked or unstaged state, so staged content and working files are never swept in. Nothing is pushed and the architecture drift cursor is not touched; a publication that leaves the branch ahead of its remote prints one push advisory, and every skip or fault prints one advisory and still exits 0. `repo-harness architecture-projection publish-restamp --json` runs the same classifier, gate, and synthesis for manual recovery and exits non-zero unless it published.
|
|
234
236
|
|
|
235
237
|
## Publication Granularity
|
|
236
238
|
|
|
@@ -151,7 +151,10 @@
|
|
|
151
151
|
],
|
|
152
152
|
"discoverability": "profile-facade",
|
|
153
153
|
"component": "adaptive-workflow",
|
|
154
|
-
"requires": [
|
|
154
|
+
"requires": [
|
|
155
|
+
"obsidian-markdown",
|
|
156
|
+
"obsidian-cli"
|
|
157
|
+
],
|
|
155
158
|
"mutatesRepoByDefault": false,
|
|
156
159
|
"summary": "Cross-project long-term memory over the user's Obsidian brain vault: recall relevant notes before a task and persist distilled conclusions after it. Repo artifacts stay the source of truth; sync direction is repo -> brain. Explicitly invoked by the model or operator, never from hooks. Requires the runtime-referenced official obsidian-markdown and obsidian-cli skills.",
|
|
157
160
|
"retirementCandidate": null
|
|
@@ -336,6 +339,42 @@
|
|
|
336
339
|
"mutatesRepoByDefault": false,
|
|
337
340
|
"summary": "Explicit-opt-in reverse-engineering and security-task router pack. Fetched from zhaoxuya520/reverse-skill via bunx skills add after independent authorization review.",
|
|
338
341
|
"retirementCandidate": null
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
"name": "obsidian-markdown",
|
|
345
|
+
"kind": "external",
|
|
346
|
+
"source": null,
|
|
347
|
+
"provider": "kepano/obsidian-skills@a1dc48e68138490d522c04cbf5822214c6eb1202",
|
|
348
|
+
"integrity": "sha256:ac9b702f9697f0bbf5f0fdc0c6896d94efef01438a59a4b508e5d7346da050e6",
|
|
349
|
+
"hosts": [
|
|
350
|
+
"claude",
|
|
351
|
+
"codex"
|
|
352
|
+
],
|
|
353
|
+
"profiles": [],
|
|
354
|
+
"discoverability": "external-marketplace",
|
|
355
|
+
"component": "adaptive-workflow",
|
|
356
|
+
"requires": [],
|
|
357
|
+
"mutatesRepoByDefault": false,
|
|
358
|
+
"summary": "Explicit-opt-in official Obsidian Markdown authoring companion Skill. Pinned to kepano/obsidian-skills and verified before projection.",
|
|
359
|
+
"retirementCandidate": null
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"name": "obsidian-cli",
|
|
363
|
+
"kind": "external",
|
|
364
|
+
"source": null,
|
|
365
|
+
"provider": "kepano/obsidian-skills@a1dc48e68138490d522c04cbf5822214c6eb1202",
|
|
366
|
+
"integrity": "sha256:58b3eaf9ccaadfcbe3b8d0eddb0d1fe872ef42c4cf289393a72d4e9a6d896f6f",
|
|
367
|
+
"hosts": [
|
|
368
|
+
"claude",
|
|
369
|
+
"codex"
|
|
370
|
+
],
|
|
371
|
+
"profiles": [],
|
|
372
|
+
"discoverability": "external-marketplace",
|
|
373
|
+
"component": "adaptive-workflow",
|
|
374
|
+
"requires": [],
|
|
375
|
+
"mutatesRepoByDefault": false,
|
|
376
|
+
"summary": "Explicit-opt-in official Obsidian CLI companion Skill. Does not install or require the Obsidian executable or desktop App.",
|
|
377
|
+
"retirementCandidate": null
|
|
339
378
|
}
|
|
340
379
|
],
|
|
341
380
|
"expectedProjections": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.16.
|
|
3
|
-
"templateVersion": "0.16.
|
|
2
|
+
"version": "0.16.2",
|
|
3
|
+
"templateVersion": "0.16.2",
|
|
4
4
|
"skillName": "repo-harness",
|
|
5
5
|
"contractId": "tasks-first-harness-v1",
|
|
6
6
|
"compatibility": {
|
|
@@ -255,6 +255,14 @@
|
|
|
255
255
|
{
|
|
256
256
|
"version": "0.16.0",
|
|
257
257
|
"description": "Completes the kanban coordination program on top of the 0.15.3 lease plane: adds the deterministic board projection `state board --json` emitting the frozen BoardDocumentV1 with four precedence-ordered columns, three separated dimensions, per-dimension and composite input revisions, and a stable | changed_during_read snapshot-consistency verdict from a single-retry collector; adds a bind-time resumed receipt so a steal-then-rebind no longer inherits the previous claim's no-progress receipts; injects a byte-identical read-only BoardSliceV1 at Codex SubagentStart context and the Claude PreToolUse.subagent Task|Agent branch through one pure projector and one shared renderer; arms a PreToolUse.edit lease gate only behind the double predicate of a unique claim token matching the active-plan marker and a linked worktree, failing closed with an explicit reason token per step while leaving non-sprint execution untouched; and retires the merged worktree at the tail of contract-worktree finish --merge"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"version": "0.16.1",
|
|
261
|
+
"description": "Replaces the boolean `overwrite` flag on the seven MCP workflow-artifact write tools with an optional `expected_sha256` revision precondition (absent = create-only with WOULD_OVERWRITE, supplied = guarded overwrite with REVISION_CONFLICT and no current-hash echo), routes those writes through a guarded synchronous writer with lstat symlink and regular-file guards plus temp+fsync+rename+parent-fsync, returns sha256/previousSha256 on success, and rejects undeclared parameters server-side with UNKNOWN_PARAMETER while `overwrite` specifically returns RETIRED_PARAMETER naming `expected_sha256`"
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"version": "0.16.2",
|
|
265
|
+
"description": "Fixes MCP runtime issues from #204, binds MCP HTTP sessions to the startup profile with fail-closed config-flip handling, publishes the architecture queue lock owner record atomically via staged hard-link creation, requires and fail-closed-validates sandbox_mode in Codex custom-agent TOMLs with EXECUTION_BOUNDARY persona de-duplication, and adds artifact-hygiene rules (final-diff-only comments and PR text) to the global working rules and generated agent contracts"
|
|
258
266
|
}
|
|
259
267
|
],
|
|
260
268
|
"generatedProjectStamp": {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
writeFileSync,
|
|
14
14
|
} from 'fs';
|
|
15
15
|
import { userInfo } from 'os';
|
|
16
|
+
import { createRequire } from 'module';
|
|
16
17
|
import { basename, dirname, isAbsolute, join, relative, resolve } from 'path';
|
|
17
18
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
18
19
|
import { spawnSync } from 'child_process';
|
|
@@ -87,10 +88,81 @@ type Options = {
|
|
|
87
88
|
};
|
|
88
89
|
|
|
89
90
|
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
|
|
90
|
-
const PACKAGE_ROOT = SCRIPT_DIR
|
|
91
|
+
const PACKAGE_ROOT = basename(SCRIPT_DIR) === 'helpers'
|
|
92
|
+
&& basename(dirname(SCRIPT_DIR)) === 'templates'
|
|
93
|
+
&& basename(dirname(dirname(SCRIPT_DIR))) === 'assets'
|
|
91
94
|
? resolve(SCRIPT_DIR, '../../..')
|
|
92
95
|
: resolve(SCRIPT_DIR, '..');
|
|
93
|
-
|
|
96
|
+
type ProtectedRuntime = {
|
|
97
|
+
platform: NodeJS.Platform;
|
|
98
|
+
accountHome: string;
|
|
99
|
+
accountUsername: string;
|
|
100
|
+
gitBin: string;
|
|
101
|
+
bashBin: string;
|
|
102
|
+
bunExecutable: string;
|
|
103
|
+
pathEntries: readonly string[];
|
|
104
|
+
pathDelimiter: ':' | ';';
|
|
105
|
+
tempDir: string;
|
|
106
|
+
systemRoot?: string;
|
|
107
|
+
};
|
|
108
|
+
type ProtectedPlatformModule = {
|
|
109
|
+
resolveProtectedHelperPlatform: () => ProtectedRuntime;
|
|
110
|
+
protectedHelperRuntimeEnv: (runtime: ProtectedRuntime) => NodeJS.ProcessEnv;
|
|
111
|
+
};
|
|
112
|
+
type ProtectedGitRuntime = {
|
|
113
|
+
readonly gitBin: string;
|
|
114
|
+
readonly env: NodeJS.ProcessEnv;
|
|
115
|
+
};
|
|
116
|
+
const requireFromHelper = createRequire(import.meta.url);
|
|
117
|
+
let protectedGitRuntimeCache: ProtectedGitRuntime | null = null;
|
|
118
|
+
|
|
119
|
+
function fixedPosixExecutable(label: string, candidates: readonly string[]): string {
|
|
120
|
+
for (const candidate of candidates) {
|
|
121
|
+
if (!isAbsolute(candidate) || !existsSync(candidate)) continue;
|
|
122
|
+
const source = lstatSync(candidate);
|
|
123
|
+
if (source.isSymbolicLink() || !source.isFile()) continue;
|
|
124
|
+
const actual = realpathSync(candidate);
|
|
125
|
+
const target = lstatSync(actual);
|
|
126
|
+
if (target.isSymbolicLink() || !target.isFile() || (target.mode & 0o111) === 0) continue;
|
|
127
|
+
return actual;
|
|
128
|
+
}
|
|
129
|
+
throw new Error(`required system executable is unavailable: ${label}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function resolveProtectedGitRuntime(): ProtectedGitRuntime {
|
|
133
|
+
if (protectedGitRuntimeCache) return protectedGitRuntimeCache;
|
|
134
|
+
if (process.platform !== 'win32') {
|
|
135
|
+
const account = userInfo();
|
|
136
|
+
const gitBin = fixedPosixExecutable('git', ['/usr/bin/git', '/bin/git']);
|
|
137
|
+
const bashBin = fixedPosixExecutable('bash', ['/bin/bash']);
|
|
138
|
+
const protectedPath = `${dirname(process.execPath)}:/usr/bin:/bin:/usr/sbin:/sbin`;
|
|
139
|
+
protectedGitRuntimeCache = {
|
|
140
|
+
gitBin,
|
|
141
|
+
env: {
|
|
142
|
+
HOME: account.homedir,
|
|
143
|
+
USER: account.username,
|
|
144
|
+
LOGNAME: account.username,
|
|
145
|
+
PATH: protectedPath,
|
|
146
|
+
TMPDIR: '/tmp',
|
|
147
|
+
REPO_HARNESS_BASH_BIN: bashBin,
|
|
148
|
+
REPO_HARNESS_GIT_BIN: gitBin,
|
|
149
|
+
REPO_HARNESS_BUN_BIN: process.execPath,
|
|
150
|
+
REPO_HARNESS_PROTECTED_PATH: protectedPath,
|
|
151
|
+
REPO_HARNESS_PROTECTED_TMPDIR: '/tmp',
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
return protectedGitRuntimeCache;
|
|
155
|
+
}
|
|
156
|
+
const protectedPlatform = requireFromHelper(
|
|
157
|
+
join(PACKAGE_ROOT, 'src', 'cli', 'runtime', 'protected-helper-platform.ts'),
|
|
158
|
+
) as ProtectedPlatformModule;
|
|
159
|
+
const runtime = protectedPlatform.resolveProtectedHelperPlatform();
|
|
160
|
+
protectedGitRuntimeCache = {
|
|
161
|
+
gitBin: runtime.gitBin,
|
|
162
|
+
env: protectedPlatform.protectedHelperRuntimeEnv(runtime),
|
|
163
|
+
};
|
|
164
|
+
return protectedGitRuntimeCache;
|
|
165
|
+
}
|
|
94
166
|
|
|
95
167
|
function fail(message: string, code = 1): never {
|
|
96
168
|
const error = new Error(message) as Error & { exitCode?: number };
|
|
@@ -123,7 +195,8 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
123
195
|
}
|
|
124
196
|
|
|
125
197
|
function gitText(root: string, args: string[]): string {
|
|
126
|
-
const
|
|
198
|
+
const runtime = resolveProtectedGitRuntime();
|
|
199
|
+
const result = spawnSync(runtime.gitBin, ['-C', root, ...args], { encoding: 'utf-8', env: runtime.env });
|
|
127
200
|
if (result.status !== 0) fail(`git ${args.join(' ')} failed: ${result.stderr.trim() || 'unknown error'}`);
|
|
128
201
|
return result.stdout.trim();
|
|
129
202
|
}
|
|
@@ -478,7 +551,8 @@ function resolveArchived(root: string, path: string, family: 'plans' | 'tasks',
|
|
|
478
551
|
if (existsSync(resolve(root, path))) return path;
|
|
479
552
|
const archiveRoot = join(root, family, 'archive');
|
|
480
553
|
if (!existsSync(archiveRoot)) fail(`receipt authority file is missing: ${path}`);
|
|
481
|
-
const
|
|
554
|
+
const runtime = resolveProtectedGitRuntime();
|
|
555
|
+
const tracked = spawnSync(runtime.gitBin, ['-C', root, 'ls-files', `${family}/archive`], { encoding: 'utf-8', env: runtime.env })
|
|
482
556
|
.stdout.split(/\r?\n/).filter(Boolean);
|
|
483
557
|
const matches = tracked.filter((candidate) => {
|
|
484
558
|
const absolute = resolve(root, candidate);
|
|
@@ -3,6 +3,7 @@ import { createHash, randomUUID } from "crypto";
|
|
|
3
3
|
import {
|
|
4
4
|
closeSync,
|
|
5
5
|
existsSync,
|
|
6
|
+
linkSync,
|
|
6
7
|
lstatSync,
|
|
7
8
|
mkdirSync,
|
|
8
9
|
openSync,
|
|
@@ -520,18 +521,34 @@ function acquireQueueLock(requestsDir: string, ownerPid: number, ownerToken: str
|
|
|
520
521
|
assertSafeWriteTarget(`${requestsDir}/.write-probe`);
|
|
521
522
|
const lockFile = ".ai/harness/architecture/.architecture-queue.lock";
|
|
522
523
|
assertSafeWriteTarget(lockFile);
|
|
524
|
+
const candidateToken = createHash("sha256").update(ownerToken).digest("hex").slice(0, 16);
|
|
525
|
+
const candidateFile = `${lockFile}.${ownerPid}.${candidateToken}.tmp`;
|
|
526
|
+
assertSafeWriteTarget(candidateFile);
|
|
523
527
|
const deadline = Date.now() + 10_000;
|
|
524
528
|
while (true) {
|
|
525
529
|
try {
|
|
526
|
-
const fd = openSync(
|
|
530
|
+
const fd = openSync(candidateFile, "wx", 0o600);
|
|
527
531
|
try {
|
|
528
532
|
writeAllSync(fd, JSON.stringify({ pid: ownerPid, token: ownerToken, created_at: new Date().toISOString() }));
|
|
529
533
|
} finally {
|
|
530
534
|
closeSync(fd);
|
|
531
535
|
}
|
|
532
|
-
|
|
536
|
+
const holdBeforePublishMs = Number(process.env.REPO_HARNESS_ARCHITECTURE_HOLD_BEFORE_LOCK_PUBLISH_MS || "0");
|
|
537
|
+
if (Number.isFinite(holdBeforePublishMs) && holdBeforePublishMs > 0) {
|
|
538
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, holdBeforePublishMs);
|
|
539
|
+
}
|
|
540
|
+
try {
|
|
541
|
+
linkSync(candidateFile, lockFile);
|
|
542
|
+
return lockFile;
|
|
543
|
+
} catch (error: any) {
|
|
544
|
+
if (error?.code !== "EEXIST") throw error;
|
|
545
|
+
}
|
|
533
546
|
} catch (error: any) {
|
|
534
|
-
if (error?.code !== "EEXIST"
|
|
547
|
+
if (error?.code !== "EEXIST") throw error;
|
|
548
|
+
} finally {
|
|
549
|
+
rmSync(candidateFile, { force: true });
|
|
550
|
+
}
|
|
551
|
+
if (existsSync(lockFile)) {
|
|
535
552
|
try {
|
|
536
553
|
const owner = JSON.parse(readFileSync(lockFile, "utf8"));
|
|
537
554
|
if (!processIsAlive(Number(owner.pid))) {
|
|
@@ -545,9 +562,9 @@ function acquireQueueLock(requestsDir: string, ownerPid: number, ownerToken: str
|
|
|
545
562
|
continue;
|
|
546
563
|
}
|
|
547
564
|
}
|
|
548
|
-
if (Date.now() >= deadline) throw new Error(`architecture queue lock unavailable: ${lockFile}`);
|
|
549
|
-
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 25);
|
|
550
565
|
}
|
|
566
|
+
if (Date.now() >= deadline) throw new Error(`architecture queue lock unavailable: ${lockFile}`);
|
|
567
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 25);
|
|
551
568
|
}
|
|
552
569
|
}
|
|
553
570
|
|