@lannguyensi/harness 0.14.0 → 0.15.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/CHANGELOG.md +23 -0
- package/README.md +3 -1
- package/dist/cli/init/composer.d.ts +29 -0
- package/dist/cli/init/composer.js +377 -0
- package/dist/cli/init/composer.js.map +1 -0
- package/dist/cli/init/dependencies.d.ts +25 -0
- package/dist/cli/init/dependencies.js +100 -10
- package/dist/cli/init/dependencies.js.map +1 -1
- package/dist/cli/init/index.d.ts +18 -1
- package/dist/cli/init/index.js +17 -7
- package/dist/cli/init/index.js.map +1 -1
- package/dist/cli/init/interactive.d.ts +31 -2
- package/dist/cli/init/interactive.js +321 -79
- package/dist/cli/init/interactive.js.map +1 -1
- package/dist/cli/init/templates.d.ts +1 -1
- package/dist/cli/init/templates.js +60 -9
- package/dist/cli/init/templates.js.map +1 -1
- package/dist/cli/pack/hook-pre-tool-use.d.ts +1 -1
- package/dist/cli/pack/hook-pre-tool-use.js +37 -3
- package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
- package/dist/cli/validate/checks.d.ts +1 -1
- package/dist/cli/validate/checks.js +1 -7
- package/dist/cli/validate/checks.js.map +1 -1
- package/dist/io/harness-lock.js +1 -9
- package/dist/io/harness-lock.js.map +1 -1
- package/dist/policies/ledger-client.js +3 -9
- package/dist/policies/ledger-client.js.map +1 -1
- package/dist/policies/producers.d.ts +12 -0
- package/dist/policies/producers.js +61 -0
- package/dist/policies/producers.js.map +1 -0
- package/dist/runtime/expand-home.d.ts +14 -0
- package/dist/runtime/expand-home.js +54 -0
- package/dist/runtime/expand-home.js.map +1 -0
- package/dist/runtime/intercept.js +13 -2
- package/dist/runtime/intercept.js.map +1 -1
- package/dist/runtime/ledger-add.js +10 -3
- package/dist/runtime/ledger-add.js.map +1 -1
- package/dist/runtime/ledger-record.js +11 -10
- package/dist/runtime/ledger-record.js.map +1 -1
- package/dist/schema/index.d.ts +281 -101
- package/dist/schema/permission-profiles.d.ts +125 -125
- package/dist/schema/policies.d.ts +261 -0
- package/dist/schema/policies.js +50 -0
- package/dist/schema/policies.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.15.0] - 2026-05-16
|
|
11
|
+
|
|
12
|
+
**Headline: interactive wizard major upgrade.** `harness init --interactive` gains a runtime multiselect for the wire-now step (Claude Code + Codex, with `opencode` parked until its adapter lands) and a real Custom-profile composer at full reference-policy parity (1 pack, 4 MCPs, 6 reference policies, ticked à la carte). The old Custom branch, an advertised menu item that printed "use --template full and hand-edit" and aborted, is gone. Adjacent: every policy's deny envelope now carries a one-line producer hint so a blocked operator sees not just the missing tag but the satisfying contract; runtime tilde expansion on MCP env values at spawn time closes the "literal `~/foo` creates rogue cwd files" footgun for every wired server, not just `grounding-mcp`.
|
|
13
|
+
|
|
14
|
+
Operator note: no required action. Custom is still opt-in from the wizard, and the new producer hints are additive.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Interactive wizard: runtime multiselect** (#147, agent-tasks/696f7560). The wire-now step is now an `@inquirer/prompts` `checkbox` over `claude-code` and `codex`; whichever runtimes `detect()` found configured are pre-checked so the historical single-runtime flow stays one Enter press. Selecting Codex runs `harness apply --runtime codex` and prints the manual-merge instruction for `~/.codex/config.toml`; selecting both warns the operator that `harness.lock` reflects the last-applied runtime. `opencode` listed disabled until task `f34eb233` lands the runtime adapter.
|
|
19
|
+
- **Interactive wizard: Custom-profile composer** (#148 + #149, agent-tasks/31d2fbb5 + 5dd3d8a6). Custom is a real à-la-carte builder: three checkbox prompts (packs / MCPs / policies) feed `composeCustom(selection)` which emits YAML the rest of the wizard's tail (validate → wire-now) consumes unchanged. v0.15.0 ships parity with `--template full`: 1 pack (`understanding-before-execution`), 4 MCPs (`agent-tasks`, `grounding-mcp`, `memory-router` routed under `memory.router`, `codebase-oracle` with an env-var advisory), 6 reference policies (review-before-merge, preflight-before-investigation, review-subagent-before-pr-create, preflight-before-push, dogfood-before-release, two-reviewers-required). Producer-coupling advisories print to stderr when a selected policy has no producer for its ledger tag.
|
|
20
|
+
- **Policy deny envelope: producer hints** (#141 + #142 + #143). Every reference policy in `FULL_TEMPLATE` now has a populated `producers:` field rendered into the deny envelope + `harness explain` output. The understanding-gate deny envelope picks up the same treatment so a blocked agent sees the `harness approve understanding` golden path rendered verbatim. The producer choice (`harness session-start preflight` vs `mcp__agent-grounding__ledger_add`) is recorded next to the tag the operator must produce.
|
|
21
|
+
- **Wizard dep table: min_version floor** (#144). The "Profile X depends on these binaries" table now shows `pkg@x.y.z+` next to packages whose `min_version` is declared, so operators see the floor a feature needs even without running `harness doctor`.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **`dependenciesForCustom` resolves codebase-oracle + agent-preflight** (#149 dependency layer). Custom selections that tick `codebase-oracle` or any `preflight-*` policy now get the matching binaries added to the wizard's `npm i -g` list, mirroring `PROFILE_DEPENDENCIES.full`.
|
|
26
|
+
- **Internal: shared `expandHome` helper** (#146). Three duplicate implementations consolidated into `src/runtime/expand-home.ts`. No behaviour change; refactor lands in the same release as #145 so the fix and the consolidation can be reasoned about together.
|
|
27
|
+
- **`codebase-oracle` stays out of the FULL default** (#138 + #139 + #140 net). The thrash trio settles on "not in default, opt-in via Custom composer or hand-edit"; the FULL template now carries an explicit comment explaining the omission plus the manual wiring recipe with required env vars (`ORACLE_SCAN_ROOT`, `OPENAI_API_KEY`).
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **MCP env values: leading `~/` expands at spawn time** (#145). Previously a literal `~/foo` in an `env:` block was passed verbatim, and the receiving MCP server (process started by the runtime, not a login shell) saw no tilde expansion, creating rogue cwd-relative files. Now every value beginning with `~/` is rewritten to `$HOME/...` at the runtime spawn boundary. Closes the same class of incident grounding-mcp hit in v0.14.0.
|
|
32
|
+
|
|
10
33
|
## [0.14.0] - 2026-05-15
|
|
11
34
|
|
|
12
35
|
**Headline: understanding-gate self-approval backdoor closed.** Through v0.13.0 the gate read a `understanding-approved:<sessionId>` row from the evidence ledger as approval. The agent has direct MCP access to that ledger via `grounding-mcp`'s `ledger_add`, so any agent could write the row for its own session and self-approve, collapsing the human-in-the-loop control to advisory. v0.14.0 moves the canonical signal to a filesystem marker at `harness.generated/.approvals/<sessionId>` written by `harness approve understanding` from the operator's shell. Edit / Write / Bash are all gated by the same PreToolUse hook and no configured MCP exposes filesystem writes, so the marker is reachable only from operator-launched processes. Headline regression test (`tests/cli/pack-hook-pre-tool-use.test.ts`): an injected ledger row with `source: "mcp"` (exact shape `ledger_add` produces) MUST still block. Pinned for Claude and Codex blockers alike.
|
package/README.md
CHANGED
|
@@ -305,7 +305,9 @@ conversation is the origin of this repo.
|
|
|
305
305
|
local preflight validator; the canonical implementation of
|
|
306
306
|
preflight-hook content harness wires.
|
|
307
307
|
- [`codebase-oracle`](https://github.com/LanNguyenSi/codebase-oracle):
|
|
308
|
-
|
|
308
|
+
an opt-in MCP surface for multi-repo RAG search. Not in the Full
|
|
309
|
+
default; operators wire it via `harness add mcp codebase-oracle
|
|
310
|
+
--command codebase-oracle,mcp`.
|
|
309
311
|
- [`agent-dx`](https://github.com/LanNguyenSi/agent-dx): ships
|
|
310
312
|
`git-batch-cli`, a day-to-day tool whose inventory appears in
|
|
311
313
|
`harness describe`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type CustomPackKey = "understanding-before-execution";
|
|
2
|
+
export type CustomMcpKey = "agent-tasks" | "grounding-mcp" | "memory-router" | "codebase-oracle";
|
|
3
|
+
export type CustomPolicyKey = "review-before-merge" | "preflight-before-investigation" | "review-subagent-before-pr-create" | "preflight-before-push" | "dogfood-before-release" | "two-reviewers-required";
|
|
4
|
+
export interface ComposableOption<K extends string> {
|
|
5
|
+
key: K;
|
|
6
|
+
label: string;
|
|
7
|
+
description: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const COMPOSABLE_PACKS: ReadonlyArray<ComposableOption<CustomPackKey>>;
|
|
10
|
+
export declare const COMPOSABLE_MCPS: ReadonlyArray<ComposableOption<CustomMcpKey>>;
|
|
11
|
+
export declare const COMPOSABLE_POLICIES: ReadonlyArray<ComposableOption<CustomPolicyKey>>;
|
|
12
|
+
export interface CustomSelection {
|
|
13
|
+
packs: CustomPackKey[];
|
|
14
|
+
mcps: CustomMcpKey[];
|
|
15
|
+
policies: CustomPolicyKey[];
|
|
16
|
+
/** Optional override for memory.directories[0].path; defaults to the wizard's standard. */
|
|
17
|
+
memoryDir?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ComposeResult {
|
|
20
|
+
yaml: string;
|
|
21
|
+
/**
|
|
22
|
+
* Non-fatal advisories: policy selected without its producing MCP,
|
|
23
|
+
* pack selected without its baseline tools, etc. These are surfaced
|
|
24
|
+
* to stderr by the wizard so the operator can adjust without the
|
|
25
|
+
* manifest itself being rejected (`harness validate` stays clean).
|
|
26
|
+
*/
|
|
27
|
+
warnings: string[];
|
|
28
|
+
}
|
|
29
|
+
export declare function composeCustom(sel: CustomSelection): ComposeResult;
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
// À la carte manifest composer for `harness init --interactive` Custom
|
|
2
|
+
// profile (tasks 31d2fbb5 + 5dd3d8a6). The composer turns a discrete
|
|
3
|
+
// checkbox selection into a YAML manifest that `harness validate`
|
|
4
|
+
// accepts.
|
|
5
|
+
//
|
|
6
|
+
// Current surface (parity with FULL_TEMPLATE): one policy pack
|
|
7
|
+
// (understanding-before-execution), four MCPs (agent-tasks,
|
|
8
|
+
// grounding-mcp, memory-router — wired under memory.router, NOT
|
|
9
|
+
// tools.mcp[] — and codebase-oracle), and six reference policies
|
|
10
|
+
// (review-before-merge, preflight-before-investigation,
|
|
11
|
+
// review-subagent-before-pr-create, preflight-before-push,
|
|
12
|
+
// dogfood-before-release, two-reviewers-required). The opencode pack
|
|
13
|
+
// stays disabled in the wire-now multiselect until its runtime adapter
|
|
14
|
+
// (agent-tasks/f34eb233) lands.
|
|
15
|
+
//
|
|
16
|
+
// Design: build a plain object matching the Manifest schema, then
|
|
17
|
+
// serialise via the `yaml` library. The shared `init()` path
|
|
18
|
+
// (validateBeforeWrite, file lock, overwrite guard) handles persistence
|
|
19
|
+
// so Custom rejoins the same write/validate semantics as
|
|
20
|
+
// solo/team/full.
|
|
21
|
+
import { stringify } from "yaml";
|
|
22
|
+
export const COMPOSABLE_PACKS = [
|
|
23
|
+
{
|
|
24
|
+
key: "understanding-before-execution",
|
|
25
|
+
label: "understanding-before-execution",
|
|
26
|
+
description: "Force agents to expose their interpretation and wait for approval before any write-capable tool fires.",
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
export const COMPOSABLE_MCPS = [
|
|
30
|
+
{
|
|
31
|
+
key: "agent-tasks",
|
|
32
|
+
label: "agent-tasks",
|
|
33
|
+
description: "Backlog + PR workflow MCP bridge (agent-tasks-mcp-bridge).",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
key: "grounding-mcp",
|
|
37
|
+
label: "grounding-mcp",
|
|
38
|
+
description: "Evidence ledger + understanding-gate approval surface.",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
key: "memory-router",
|
|
42
|
+
label: "memory-router (wired under memory.router, not tools.mcp[])",
|
|
43
|
+
description: "Cross-conversation memory routing via UserPromptSubmit.",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
key: "codebase-oracle",
|
|
47
|
+
label: "codebase-oracle (needs ORACLE_SCAN_ROOT + OPENAI_API_KEY env vars)",
|
|
48
|
+
description: "Multi-repo semantic search MCP server. Set ORACLE_SCAN_ROOT to an absolute path (tilde is NOT expanded) and an embedding-provider key before the first call.",
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
export const COMPOSABLE_POLICIES = [
|
|
52
|
+
{
|
|
53
|
+
key: "review-before-merge",
|
|
54
|
+
label: "review-before-merge",
|
|
55
|
+
description: "Block mcp__agent-tasks__pull_requests_merge unless a review:<pr-number> ledger entry exists.",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
key: "preflight-before-investigation",
|
|
59
|
+
label: "preflight-before-investigation",
|
|
60
|
+
description: "Block git status/log/diff/branch unless preflight:<repo> ledger entry exists for this repo (within 1h).",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
key: "review-subagent-before-pr-create",
|
|
64
|
+
label: "review-subagent-before-pr-create",
|
|
65
|
+
description: "Block mcp__agent-tasks__pull_requests_create unless a review-subagent:<task-id> ledger entry exists.",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
key: "preflight-before-push",
|
|
69
|
+
label: "preflight-before-push",
|
|
70
|
+
description: "Block git push unless preflight:<branch> ledger entry exists for the current branch (within 10m).",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
key: "dogfood-before-release",
|
|
74
|
+
label: "dogfood-before-release",
|
|
75
|
+
description: "Block npm publish / git tag v* unless a dogfood:<session-id> ledger entry exists in this session (within 24h).",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
key: "two-reviewers-required",
|
|
79
|
+
label: "two-reviewers-required (warn-level companion to review-before-merge)",
|
|
80
|
+
description: "Warn when PR-merge runs without TWO distinct review:<pr-number> ledger entries. Enforcement: warn.",
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
const HOOK_FOR_POLICY = {
|
|
84
|
+
"review-before-merge": {
|
|
85
|
+
name: "require-review-evidence",
|
|
86
|
+
event: "PreToolUse",
|
|
87
|
+
match: "mcp__agent-tasks__pull_requests_merge",
|
|
88
|
+
command: "harness policy intercept",
|
|
89
|
+
blocking: "hard",
|
|
90
|
+
budget_ms: 2000,
|
|
91
|
+
},
|
|
92
|
+
"preflight-before-investigation": {
|
|
93
|
+
name: "require-preflight-evidence",
|
|
94
|
+
event: "PreToolUse",
|
|
95
|
+
match: "Bash",
|
|
96
|
+
bash_match: "(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* (status|log|diff|branch)\\b",
|
|
97
|
+
command: "harness policy intercept",
|
|
98
|
+
blocking: "hard",
|
|
99
|
+
budget_ms: 1000,
|
|
100
|
+
},
|
|
101
|
+
"review-subagent-before-pr-create": {
|
|
102
|
+
name: "require-review-subagent-evidence",
|
|
103
|
+
event: "PreToolUse",
|
|
104
|
+
match: "mcp__agent-tasks__pull_requests_create",
|
|
105
|
+
command: "harness policy intercept",
|
|
106
|
+
blocking: "hard",
|
|
107
|
+
budget_ms: 2000,
|
|
108
|
+
},
|
|
109
|
+
"preflight-before-push": {
|
|
110
|
+
name: "require-preflight-push-evidence",
|
|
111
|
+
event: "PreToolUse",
|
|
112
|
+
match: "Bash",
|
|
113
|
+
bash_match: "(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* push\\b",
|
|
114
|
+
command: "harness policy intercept",
|
|
115
|
+
blocking: "hard",
|
|
116
|
+
budget_ms: 1000,
|
|
117
|
+
},
|
|
118
|
+
"dogfood-before-release": {
|
|
119
|
+
name: "require-dogfood-evidence",
|
|
120
|
+
event: "PreToolUse",
|
|
121
|
+
match: "Bash",
|
|
122
|
+
bash_match: "(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*(npm publish\\b|git( -C \\S+)* tag v)",
|
|
123
|
+
command: "harness policy intercept",
|
|
124
|
+
blocking: "hard",
|
|
125
|
+
budget_ms: 2000,
|
|
126
|
+
},
|
|
127
|
+
// two-reviewers-required shares review-before-merge's hook; the policy
|
|
128
|
+
// intercept engine evaluates both policies under the same trigger and
|
|
129
|
+
// each enforces independently (block vs warn). We still need a hook
|
|
130
|
+
// entry so the policy's `hook:` field round-trips through validate,
|
|
131
|
+
// but it's the same row as require-review-evidence.
|
|
132
|
+
"two-reviewers-required": {
|
|
133
|
+
name: "require-review-evidence",
|
|
134
|
+
event: "PreToolUse",
|
|
135
|
+
match: "mcp__agent-tasks__pull_requests_merge",
|
|
136
|
+
command: "harness policy intercept",
|
|
137
|
+
blocking: "hard",
|
|
138
|
+
budget_ms: 2000,
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
const POLICY = {
|
|
142
|
+
"review-before-merge": {
|
|
143
|
+
name: "review-before-merge",
|
|
144
|
+
description: "Block PR merges unless a ledger entry tagged review:<pr-number> exists for this session.",
|
|
145
|
+
trigger: {
|
|
146
|
+
event: "PreToolUse",
|
|
147
|
+
match: "mcp__agent-tasks__pull_requests_merge",
|
|
148
|
+
extract: { PR_NUMBER: "toolArgs.prNumber" },
|
|
149
|
+
},
|
|
150
|
+
requires: { ledger_tag: "review:${PR_NUMBER}" },
|
|
151
|
+
hook: "require-review-evidence",
|
|
152
|
+
enforcement: "block",
|
|
153
|
+
},
|
|
154
|
+
"preflight-before-investigation": {
|
|
155
|
+
name: "preflight-before-investigation",
|
|
156
|
+
description: "Block investigative git reads (status/log/diff/branch) when agent-preflight has not run recently with ready:true for the current repo.",
|
|
157
|
+
trigger: {
|
|
158
|
+
event: "PreToolUse",
|
|
159
|
+
match: "Bash",
|
|
160
|
+
bash_match: "(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* (status|log|diff|branch)\\b",
|
|
161
|
+
},
|
|
162
|
+
requires: { ledger_tag: "preflight:${REPO}", within: "1h" },
|
|
163
|
+
hook: "require-preflight-evidence",
|
|
164
|
+
enforcement: "block",
|
|
165
|
+
},
|
|
166
|
+
"review-subagent-before-pr-create": {
|
|
167
|
+
name: "review-subagent-before-pr-create",
|
|
168
|
+
description: "Block agent-tasks PR creation unless a review-subagent ledger entry tagged for this task already exists. Forces the rigorous review BEFORE the PR opens, not after.",
|
|
169
|
+
trigger: {
|
|
170
|
+
event: "PreToolUse",
|
|
171
|
+
match: "mcp__agent-tasks__pull_requests_create",
|
|
172
|
+
extract: { TASK_ID: "toolArgs.taskId" },
|
|
173
|
+
},
|
|
174
|
+
requires: { ledger_tag: "review-subagent:${TASK_ID}" },
|
|
175
|
+
hook: "require-review-subagent-evidence",
|
|
176
|
+
enforcement: "block",
|
|
177
|
+
},
|
|
178
|
+
"preflight-before-push": {
|
|
179
|
+
name: "preflight-before-push",
|
|
180
|
+
description: "Block git push unless a fresh preflight ledger entry exists for the current branch. Catches the stale-checkout class of incident at the last reversible step.",
|
|
181
|
+
trigger: {
|
|
182
|
+
event: "PreToolUse",
|
|
183
|
+
match: "Bash",
|
|
184
|
+
bash_match: "(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* push\\b",
|
|
185
|
+
},
|
|
186
|
+
requires: { ledger_tag: "preflight:${BRANCH}", within: "10m" },
|
|
187
|
+
hook: "require-preflight-push-evidence",
|
|
188
|
+
enforcement: "block",
|
|
189
|
+
},
|
|
190
|
+
"dogfood-before-release": {
|
|
191
|
+
name: "dogfood-before-release",
|
|
192
|
+
description: "Block npm publish / git tag v* without a recent dogfood ledger entry.",
|
|
193
|
+
trigger: {
|
|
194
|
+
event: "PreToolUse",
|
|
195
|
+
match: "Bash",
|
|
196
|
+
bash_match: "(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*(npm publish\\b|git( -C \\S+)* tag v)",
|
|
197
|
+
},
|
|
198
|
+
requires: { ledger_tag: "dogfood:${SESSION_ID}", within: "24h" },
|
|
199
|
+
hook: "require-dogfood-evidence",
|
|
200
|
+
enforcement: "block",
|
|
201
|
+
},
|
|
202
|
+
"two-reviewers-required": {
|
|
203
|
+
name: "two-reviewers-required",
|
|
204
|
+
description: "At least two distinct reviewer ledger entries must exist for the PR.",
|
|
205
|
+
trigger: {
|
|
206
|
+
event: "PreToolUse",
|
|
207
|
+
match: "mcp__agent-tasks__pull_requests_merge",
|
|
208
|
+
extract: { PR_NUMBER: "toolArgs.prNumber" },
|
|
209
|
+
},
|
|
210
|
+
requires: { ledger_tag: "review:${PR_NUMBER}", count: { min: 2 } },
|
|
211
|
+
hook: "require-review-evidence",
|
|
212
|
+
enforcement: "warn",
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
const MCP_ENTRY = {
|
|
216
|
+
"agent-tasks": {
|
|
217
|
+
name: "agent-tasks",
|
|
218
|
+
command: ["agent-tasks-mcp-bridge"],
|
|
219
|
+
min_version: "0.6.0",
|
|
220
|
+
health: { verb: "projects_list", timeout_ms: 5000 },
|
|
221
|
+
enabled: true,
|
|
222
|
+
},
|
|
223
|
+
"grounding-mcp": {
|
|
224
|
+
name: "grounding-mcp",
|
|
225
|
+
command: ["grounding-mcp"],
|
|
226
|
+
min_version: "0.2.0",
|
|
227
|
+
health: { verb: "ledger_status", timeout_ms: 5000 },
|
|
228
|
+
enabled: true,
|
|
229
|
+
},
|
|
230
|
+
// codebase-oracle: harness wires the MCP entry but cannot prompt for
|
|
231
|
+
// the absolute ORACLE_SCAN_ROOT path or the OPENAI_API_KEY (or any
|
|
232
|
+
// other embedding-provider key). The wizard emits a composer.warning
|
|
233
|
+
// when this is picked so the operator knows the env vars still need
|
|
234
|
+
// to be set in their shell or settings.json before the first call.
|
|
235
|
+
// Note: passing a literal tilde in env values bypasses shell expansion
|
|
236
|
+
// (see grounding-mcp incident in FULL_TEMPLATE comments), so the
|
|
237
|
+
// wizard does NOT auto-default ORACLE_SCAN_ROOT to ~/code — the
|
|
238
|
+
// operator must supply an absolute path themselves.
|
|
239
|
+
"codebase-oracle": {
|
|
240
|
+
name: "codebase-oracle",
|
|
241
|
+
command: ["codebase-oracle", "mcp"],
|
|
242
|
+
enabled: true,
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
const HEADER = [
|
|
246
|
+
"# ~/.claude/harness.yaml",
|
|
247
|
+
"#",
|
|
248
|
+
"# Bootstrapped by `harness init --interactive` (Custom profile).",
|
|
249
|
+
"#",
|
|
250
|
+
"# Composed à la carte from your checkbox picks. Re-run the wizard",
|
|
251
|
+
"# or edit by hand to add / remove components.",
|
|
252
|
+
"",
|
|
253
|
+
].join("\n");
|
|
254
|
+
export function composeCustom(sel) {
|
|
255
|
+
const warnings = [];
|
|
256
|
+
const mcpSet = new Set(sel.mcps);
|
|
257
|
+
// Producer-consistency advisories: each policy's `requires.ledger_tag`
|
|
258
|
+
// implies some producer must populate that tag. agent-tasks-coupled
|
|
259
|
+
// policies need the agent-tasks MCP wired; preflight-coupled policies
|
|
260
|
+
// need either grounding-mcp (so ledger_add reaches the gate) or a
|
|
261
|
+
// SessionStart preflight hook. The Custom v1 surface does not expose
|
|
262
|
+
// the SessionStart hook yet, so only check the MCP coupling.
|
|
263
|
+
if (sel.policies.includes("review-before-merge") && !mcpSet.has("agent-tasks")) {
|
|
264
|
+
warnings.push("policy review-before-merge fires on agent-tasks MCP verbs; selecting it without the agent-tasks MCP is allowed but the gate has no event to evaluate.");
|
|
265
|
+
}
|
|
266
|
+
if (sel.policies.includes("review-subagent-before-pr-create") &&
|
|
267
|
+
!mcpSet.has("agent-tasks")) {
|
|
268
|
+
warnings.push("policy review-subagent-before-pr-create fires on agent-tasks MCP verbs; selecting it without the agent-tasks MCP is allowed but the gate has no event to evaluate.");
|
|
269
|
+
}
|
|
270
|
+
if (sel.policies.includes("two-reviewers-required") && !mcpSet.has("agent-tasks")) {
|
|
271
|
+
warnings.push("policy two-reviewers-required fires on agent-tasks MCP verbs; selecting it without the agent-tasks MCP is allowed but the gate has no event to evaluate.");
|
|
272
|
+
}
|
|
273
|
+
// Note: understanding-before-execution does NOT produce preflight tags
|
|
274
|
+
// (it produces the operator-approve marker, a different gate signal).
|
|
275
|
+
// The pack is therefore NOT a substitute for grounding-mcp here; the
|
|
276
|
+
// only Custom-surface producer the wizard can wire is grounding-mcp's
|
|
277
|
+
// ledger_add.
|
|
278
|
+
if (sel.policies.includes("preflight-before-investigation") &&
|
|
279
|
+
!mcpSet.has("grounding-mcp")) {
|
|
280
|
+
warnings.push("policy preflight-before-investigation requires a producer that writes preflight:<repo> tags to the evidence ledger. Without grounding-mcp (ledger_add) or a separate SessionStart preflight hook (not in the Custom surface), the gate stays closed forever.");
|
|
281
|
+
}
|
|
282
|
+
if (sel.policies.includes("preflight-before-push") && !mcpSet.has("grounding-mcp")) {
|
|
283
|
+
warnings.push("policy preflight-before-push requires a producer that writes preflight:<branch> tags to the evidence ledger. Without grounding-mcp (ledger_add) or a separate SessionStart preflight hook (not in the Custom surface), the gate stays closed forever.");
|
|
284
|
+
}
|
|
285
|
+
if (sel.policies.includes("dogfood-before-release") && !mcpSet.has("grounding-mcp")) {
|
|
286
|
+
warnings.push("policy dogfood-before-release requires a producer that writes dogfood:<session-id> tags to the evidence ledger. Without grounding-mcp (ledger_add) the gate stays closed forever — every npm publish / git tag v* will be blocked.");
|
|
287
|
+
}
|
|
288
|
+
if (mcpSet.has("codebase-oracle")) {
|
|
289
|
+
warnings.push("MCP codebase-oracle requires ORACLE_SCAN_ROOT (absolute path; tilde is NOT expanded) and OPENAI_API_KEY (or ORACLE_LLM_PROVIDER + the matching provider key) set in your shell or in Claude's settings.json env block before the first call. The wizard does NOT prompt for these.");
|
|
290
|
+
}
|
|
291
|
+
const manifest = {
|
|
292
|
+
version: 1,
|
|
293
|
+
grounding: {
|
|
294
|
+
session: { auto_start: true, id_format: "gs-{repo}-{rand:8}" },
|
|
295
|
+
evidence_ledger: { path: "~/.evidence-ledger/ledger.db", retention_days: 90 },
|
|
296
|
+
},
|
|
297
|
+
tools: {
|
|
298
|
+
builtin: {
|
|
299
|
+
known: ["Read", "Edit", "Write", "Bash", "Agent", "Skill", "TaskCreate", "Glob", "Grep"],
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
memory: {
|
|
303
|
+
directories: [
|
|
304
|
+
{ path: sel.memoryDir ?? "~/.claude/projects/{project}/memory", scope: "project" },
|
|
305
|
+
],
|
|
306
|
+
retention: { staleness_days: 180, broken_refs: "warn" },
|
|
307
|
+
scopes: { default: "project", allowed: ["project", "user"] },
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
// tools.mcp[] only for non-memory-router MCP picks (memory-router
|
|
311
|
+
// routes user-prompts and is structurally a different slot under
|
|
312
|
+
// memory.router; treating it as a tools.mcp[] entry would fail
|
|
313
|
+
// validation).
|
|
314
|
+
const mcpEntries = sel.mcps
|
|
315
|
+
.filter((m) => m !== "memory-router")
|
|
316
|
+
.map((k) => MCP_ENTRY[k]);
|
|
317
|
+
if (mcpEntries.length > 0) {
|
|
318
|
+
manifest.tools.mcp = mcpEntries;
|
|
319
|
+
}
|
|
320
|
+
if (mcpSet.has("memory-router")) {
|
|
321
|
+
manifest.memory.router = {
|
|
322
|
+
command: ["memory-router-user-prompt-submit"],
|
|
323
|
+
min_version: "0.3.0",
|
|
324
|
+
enabled: true,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
if (sel.policies.length > 0) {
|
|
328
|
+
// Dedup hooks by name: two-reviewers-required + review-before-merge
|
|
329
|
+
// both reference `require-review-evidence`, but the schema's
|
|
330
|
+
// superRefine rejects duplicate hook names (each hook entry must be
|
|
331
|
+
// unique). Emit each hook at most once; the same row services every
|
|
332
|
+
// referencing policy.
|
|
333
|
+
const seenHookName = new Set();
|
|
334
|
+
const hooks = [];
|
|
335
|
+
for (const p of sel.policies) {
|
|
336
|
+
const h = HOOK_FOR_POLICY[p];
|
|
337
|
+
if (seenHookName.has(h.name))
|
|
338
|
+
continue;
|
|
339
|
+
seenHookName.add(h.name);
|
|
340
|
+
hooks.push(h);
|
|
341
|
+
}
|
|
342
|
+
manifest.hooks = hooks;
|
|
343
|
+
manifest.policies = sel.policies.map((p) => POLICY[p]);
|
|
344
|
+
}
|
|
345
|
+
if (sel.packs.length > 0) {
|
|
346
|
+
manifest.policy_packs = sel.packs.map((k) => {
|
|
347
|
+
// Single-pack switch today; expand when the pack surface grows.
|
|
348
|
+
if (k === "understanding-before-execution") {
|
|
349
|
+
return {
|
|
350
|
+
name: "understanding-before-execution",
|
|
351
|
+
source: "builtin",
|
|
352
|
+
enabled: true,
|
|
353
|
+
description: "Force agents to expose their task interpretation and wait for explicit human approval before any write-capable tool fires.",
|
|
354
|
+
config: {
|
|
355
|
+
mode: "grill_me",
|
|
356
|
+
producers: [
|
|
357
|
+
{
|
|
358
|
+
kind: "ask",
|
|
359
|
+
command: "harness approve understanding",
|
|
360
|
+
description: "Bare command, no pipes or chaining. The hook recognises it via isEscapeCommand and emits permissionDecision:ask; the operator's go on that prompt IS the gate approval. Golden path.",
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
kind: "bash",
|
|
364
|
+
command: "harness approve understanding",
|
|
365
|
+
description: "Same command from any un-hooked terminal (operator only, not reachable from inside the gated session). Writes the canonical marker at harness.generated/.approvals/${SESSION_ID}.",
|
|
366
|
+
},
|
|
367
|
+
],
|
|
368
|
+
},
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
throw new Error(`composer: unknown pack ${String(k)}`);
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
const yaml = `${HEADER}\n${stringify(manifest, { lineWidth: 100 })}`;
|
|
375
|
+
return { yaml, warnings };
|
|
376
|
+
}
|
|
377
|
+
//# sourceMappingURL=composer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composer.js","sourceRoot":"","sources":["../../../src/cli/init/composer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ProfileChoice } from "./interactive.js";
|
|
2
|
+
import type { CustomSelection } from "./composer.js";
|
|
2
3
|
/**
|
|
3
4
|
* One required binary that must end up on PATH for a given profile's
|
|
4
5
|
* manifest to pass `harness doctor`. `binary` is the executable name we
|
|
@@ -7,12 +8,22 @@ import type { ProfileChoice } from "./interactive.js";
|
|
|
7
8
|
* we list them all so that a partial install still reads as "complete"
|
|
8
9
|
* for whichever binaries we depend on (e.g. understanding-gate ships
|
|
9
10
|
* three hook adapters; the manifest only wires two of them).
|
|
11
|
+
*
|
|
12
|
+
* `minVersion` is informational only today (rendered in the wizard's
|
|
13
|
+
* dependency table next to the package name) so operators see the
|
|
14
|
+
* floor a feature depends on. The wizard does NOT yet probe the
|
|
15
|
+
* installed bin's version, so a stale install proceeds silently;
|
|
16
|
+
* upgrade hint is on the operator. Adding actual enforcement is a
|
|
17
|
+
* separate task (mirrors the MCP `min_version` doctor probe pattern
|
|
18
|
+
* already wired in FULL_TEMPLATE for MCP entries).
|
|
10
19
|
*/
|
|
11
20
|
export interface ProfileDependency {
|
|
12
21
|
binary: string;
|
|
13
22
|
npmPackage: string;
|
|
14
23
|
/** Short label rendered in the wizard's dependency table. */
|
|
15
24
|
description: string;
|
|
25
|
+
/** Optional floor, displayed as `pkg@x.y.z+`. Informational only. */
|
|
26
|
+
minVersion?: string;
|
|
16
27
|
}
|
|
17
28
|
export declare const PROFILE_DEPENDENCIES: Record<Exclude<ProfileChoice, "custom">, ProfileDependency[]>;
|
|
18
29
|
/**
|
|
@@ -42,6 +53,20 @@ export interface CheckOptions {
|
|
|
42
53
|
* `npm i -g <pkg1> <pkg2>` call.
|
|
43
54
|
*/
|
|
44
55
|
export declare function checkDependencies(profile: Exclude<ProfileChoice, "custom">, opts?: CheckOptions): DependencyCheckResult;
|
|
56
|
+
/**
|
|
57
|
+
* List-based variant of `checkDependencies` for callers that compute a
|
|
58
|
+
* bespoke dep set (e.g. the Custom-profile composer in task 31d2fbb5).
|
|
59
|
+
* Same semantics: resolve each binary on PATH, return statuses +
|
|
60
|
+
* de-duped missing packages.
|
|
61
|
+
*/
|
|
62
|
+
export declare function checkDependencyList(deps: ProfileDependency[], opts?: CheckOptions): DependencyCheckResult;
|
|
63
|
+
/**
|
|
64
|
+
* Resolve the dependency list for a Custom-profile selection. Maps each
|
|
65
|
+
* checkbox key to its underlying binary requirement. Used by the
|
|
66
|
+
* interactive wizard's Custom branch so the dependency-check + install
|
|
67
|
+
* UX is identical to the named profiles.
|
|
68
|
+
*/
|
|
69
|
+
export declare function dependenciesForCustom(sel: CustomSelection): ProfileDependency[];
|
|
45
70
|
/**
|
|
46
71
|
* Render the dependency table the wizard shows to the operator. Pure
|
|
47
72
|
* function so tests can lock the surface text without spawning a
|