@lannguyensi/harness 0.52.0 → 0.54.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 +82 -0
- package/dist/cli/delegate/index.d.ts +15 -2
- package/dist/cli/delegate/index.js +128 -4
- package/dist/cli/delegate/index.js.map +1 -1
- package/dist/cli/doctor/bypass-without-auto-approve.d.ts +38 -0
- package/dist/cli/doctor/bypass-without-auto-approve.js +95 -0
- package/dist/cli/doctor/bypass-without-auto-approve.js.map +1 -0
- package/dist/cli/doctor/format.js +7 -0
- package/dist/cli/doctor/format.js.map +1 -1
- package/dist/cli/doctor/index.js +17 -0
- package/dist/cli/doctor/index.js.map +1 -1
- package/dist/cli/doctor/types.d.ts +11 -0
- package/dist/cli/doctor/types.js.map +1 -1
- package/dist/cli/doctor/ug-auto-approvals.js +18 -43
- package/dist/cli/doctor/ug-auto-approvals.js.map +1 -1
- package/dist/cli/dry-run.js +32 -1
- package/dist/cli/dry-run.js.map +1 -1
- package/dist/cli/gc/index.d.ts +13 -2
- package/dist/cli/gc/index.js +203 -1
- package/dist/cli/gc/index.js.map +1 -1
- package/dist/cli/index.js +57 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/composer.js +9 -0
- package/dist/cli/init/composer.js.map +1 -1
- package/dist/cli/init/profiles.d.ts +2 -2
- package/dist/cli/init/profiles.js +100 -8
- package/dist/cli/init/profiles.js.map +1 -1
- package/dist/cli/init/templates.d.ts +1 -1
- package/dist/cli/init/templates.js +174 -3
- package/dist/cli/init/templates.js.map +1 -1
- package/dist/cli/pack/hook-pre-tool-use.js +219 -115
- package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/index.d.ts +1 -0
- package/dist/cli/pack/index.js +1 -0
- package/dist/cli/pack/index.js.map +1 -1
- package/dist/cli/pack/upgrade.d.ts +32 -0
- package/dist/cli/pack/upgrade.js +273 -0
- package/dist/cli/pack/upgrade.js.map +1 -0
- package/dist/cli/record/index.d.ts +8 -0
- package/dist/cli/record/index.js +55 -7
- package/dist/cli/record/index.js.map +1 -1
- package/dist/cli/validate/checks.js +61 -9
- package/dist/cli/validate/checks.js.map +1 -1
- package/dist/io/extract.d.ts +29 -0
- package/dist/io/extract.js +36 -0
- package/dist/io/extract.js.map +1 -1
- package/dist/io/read-json-dir-entries.d.ts +36 -0
- package/dist/io/read-json-dir-entries.js +38 -0
- package/dist/io/read-json-dir-entries.js.map +1 -0
- package/dist/policies/index.d.ts +1 -1
- package/dist/policies/index.js +1 -1
- package/dist/policies/index.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.d.ts +35 -0
- package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.js +86 -0
- package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.js.map +1 -0
- package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.d.ts +51 -0
- package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.js +55 -1
- package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution/index.d.ts +3 -1
- package/dist/policy-packs/builtin/understanding-before-execution/index.js +18 -1
- package/dist/policy-packs/builtin/understanding-before-execution/index.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.d.ts +71 -0
- package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.js +175 -0
- package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.js.map +1 -0
- package/dist/runtime/destructive-shell-floor.d.ts +19 -0
- package/dist/runtime/destructive-shell-floor.js +597 -0
- package/dist/runtime/destructive-shell-floor.js.map +1 -0
- package/dist/runtime/git-context.js +7 -1
- package/dist/runtime/git-context.js.map +1 -1
- package/dist/runtime/intercept.d.ts +10 -7
- package/dist/runtime/intercept.js +108 -9
- package/dist/runtime/intercept.js.map +1 -1
- package/dist/runtime/read-only-bash.d.ts +21 -0
- package/dist/runtime/read-only-bash.js +484 -0
- package/dist/runtime/read-only-bash.js.map +1 -1
- package/dist/runtime/risk-classifier.js +68 -13
- package/dist/runtime/risk-classifier.js.map +1 -1
- package/dist/runtime/when-eval.d.ts +18 -5
- package/dist/runtime/when-eval.js +64 -11
- package/dist/runtime/when-eval.js.map +1 -1
- package/dist/runtime/workflow-policies.d.ts +43 -1
- package/dist/runtime/workflow-policies.js +158 -1
- package/dist/runtime/workflow-policies.js.map +1 -1
- package/dist/schema/extract.d.ts +4 -0
- package/dist/schema/extract.js +64 -1
- package/dist/schema/extract.js.map +1 -1
- package/dist/schema/index.d.ts +13 -0
- package/dist/schema/policies.d.ts +19 -0
- package/dist/schema/policies.js +17 -1
- package/dist/schema/policies.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
// `harness pack upgrade <name>`: text-level insertion of a pack's
|
|
2
|
+
// missing default config block into an existing manifest, WITHOUT
|
|
3
|
+
// parsing and reserializing the operator's YAML (unlike `pack add` /
|
|
4
|
+
// `pack reseed`, which both mutate via the `yaml` Document API). Task
|
|
5
|
+
// 8f637efd: the one upgrade this ships is `auto_approve` for
|
|
6
|
+
// `understanding-before-execution` (D-004,
|
|
7
|
+
// docs/decisions/2026-08-27-ug-auto-mode-approval.md, "Amendment:
|
|
8
|
+
// install default").
|
|
9
|
+
//
|
|
10
|
+
// WHY TEXT-LEVEL, NOT DOCUMENT-LEVEL. The `yaml` package's Document API
|
|
11
|
+
// (`withDocument`, used by `pack reseed`) round-trips comments
|
|
12
|
+
// reasonably well for a single field REPLACEMENT, but this upgrade
|
|
13
|
+
// INSERTS a brand-new key with its own multi-line comment block into an
|
|
14
|
+
// operator manifest that may carry hand edits `pack add` / `reseed`
|
|
15
|
+
// never touch (custom producers, an extra top-level key, a reordered
|
|
16
|
+
// field). Re-serializing the whole document risks reformatting content
|
|
17
|
+
// this verb has no business touching. Insertion by line position,
|
|
18
|
+
// guided by indentation, keeps every byte outside the inserted block
|
|
19
|
+
// untouched.
|
|
20
|
+
//
|
|
21
|
+
// IDEMPOTENT. If `auto_approve:` already exists anywhere inside the
|
|
22
|
+
// pack's `config:` mapping (any indentation), this is a no-op: the
|
|
23
|
+
// output is byte-identical to the input. An operator who already
|
|
24
|
+
// hand-applied the workaround (the ADR's own "Workaround, bereits
|
|
25
|
+
// angewendet" paragraph) gets nothing rewritten out from under them.
|
|
26
|
+
//
|
|
27
|
+
// REFUSES ON AMBIGUITY. Zero or more than one
|
|
28
|
+
// `understanding-before-execution` pack block, more than one `config:`
|
|
29
|
+
// key inside it, or no `config:` key found at all, is a refusal
|
|
30
|
+
// (non-zero exit, a clear message), never a guess at where to insert.
|
|
31
|
+
import * as fs from "node:fs";
|
|
32
|
+
import * as path from "node:path";
|
|
33
|
+
import { parse as parseYaml } from "yaml";
|
|
34
|
+
import { atomicWriteFile } from "../../io/atomic-write.js";
|
|
35
|
+
import { unifiedDiff } from "../../io/patch.js";
|
|
36
|
+
import { withFileLock } from "../../io/lock.js";
|
|
37
|
+
import { formatValidationErrors, validateBeforeWrite, } from "../../io/validate-before-write.js";
|
|
38
|
+
import { resolveHomeDir } from "../../runtime/home-dir.js";
|
|
39
|
+
import { renderAutoApproveSnippet } from "../../policy-packs/builtin/understanding-before-execution-runtime.js";
|
|
40
|
+
import { EX_FAIL, EX_NOINPUT, HarnessExitError } from "../exit-codes.js";
|
|
41
|
+
const DEFAULT_BASENAME = "harness.yaml";
|
|
42
|
+
const LOCK_BASENAME = ".harness.lock";
|
|
43
|
+
function resolveTargetPath(opts) {
|
|
44
|
+
if (opts.configPath)
|
|
45
|
+
return path.resolve(opts.configPath);
|
|
46
|
+
return path.join(resolveHomeDir({ ...(opts.homeDir !== undefined ? { homeDir: opts.homeDir } : {}) }).path, DEFAULT_BASENAME);
|
|
47
|
+
}
|
|
48
|
+
function countLeadingSpaces(line) {
|
|
49
|
+
return line.length - line.trimStart().length;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Text-level insertion of the `auto_approve` default snippet into the
|
|
53
|
+
* `understanding-before-execution` pack's `config:` mapping. Pure: text
|
|
54
|
+
* in, text (+ a change flag) out, or an error string on ambiguity.
|
|
55
|
+
* Exported for direct unit testing without going through the CLI/file
|
|
56
|
+
* layer.
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* The line ending most of `text` uses, so an insertion into a CRLF
|
|
60
|
+
* manifest does not mix in bare-LF lines (task 8f637efd review round 2
|
|
61
|
+
* F6): counts `\r\n` occurrences against LF-only ones (every `\n` not
|
|
62
|
+
* part of a `\r\n` pair) and picks whichever is more common, defaulting
|
|
63
|
+
* to `\n` on a tie or an all-LF file.
|
|
64
|
+
*/
|
|
65
|
+
function detectDominantEol(text) {
|
|
66
|
+
const crlfCount = (text.match(/\r\n/g) ?? []).length;
|
|
67
|
+
const totalLf = (text.match(/\n/g) ?? []).length;
|
|
68
|
+
const lfOnlyCount = totalLf - crlfCount;
|
|
69
|
+
return crlfCount > lfOnlyCount ? "\r\n" : "\n";
|
|
70
|
+
}
|
|
71
|
+
export function applyAutoApproveUpgrade(original) {
|
|
72
|
+
const eol = detectDominantEol(original);
|
|
73
|
+
// Split on either line ending so every line in `lines` is `\r`-free
|
|
74
|
+
// (its own trailing `\r`, if any, is consumed by the delimiter, not
|
|
75
|
+
// left dangling on the line content); the array is rejoined with the
|
|
76
|
+
// detected `eol` below, so a CRLF manifest stays CRLF end to end
|
|
77
|
+
// instead of picking up bare-LF lines from the inserted snippet.
|
|
78
|
+
const lines = original.split(/\r\n|\n/);
|
|
79
|
+
// Accepts a bare, double-quoted, or single-quoted scalar for the pack
|
|
80
|
+
// name (task 8f637efd review round 2 F4): `- name: understanding-before-execution`,
|
|
81
|
+
// `- name: "understanding-before-execution"`, and
|
|
82
|
+
// `- name: 'understanding-before-execution'` are all schema-valid YAML
|
|
83
|
+
// for the same value; the bare-only form previously refused the
|
|
84
|
+
// quoted spellings with "could not find a ... entry".
|
|
85
|
+
const packNameRe = /^(\s*)-\s*name:\s*(?:"understanding-before-execution"|'understanding-before-execution'|understanding-before-execution)\s*(#.*)?$/;
|
|
86
|
+
const packMatches = [];
|
|
87
|
+
for (let i = 0; i < lines.length; i++) {
|
|
88
|
+
const m = packNameRe.exec(lines[i] ?? "");
|
|
89
|
+
if (m)
|
|
90
|
+
packMatches.push({ index: i, indent: (m[1] ?? "").length });
|
|
91
|
+
}
|
|
92
|
+
if (packMatches.length === 0) {
|
|
93
|
+
return {
|
|
94
|
+
ok: false,
|
|
95
|
+
error: "could not find a `- name: understanding-before-execution` policy_packs entry in this manifest",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (packMatches.length > 1) {
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
error: `found ${packMatches.length} \`understanding-before-execution\` policy_packs entries; refusing (ambiguous)`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const pack = packMatches[0];
|
|
105
|
+
const itemIndent = pack.indent;
|
|
106
|
+
function findBoundary(startIdx, indentThreshold) {
|
|
107
|
+
for (let i = startIdx; i < lines.length; i++) {
|
|
108
|
+
const line = lines[i] ?? "";
|
|
109
|
+
if (line.trim() === "")
|
|
110
|
+
continue;
|
|
111
|
+
if (countLeadingSpaces(line) <= indentThreshold)
|
|
112
|
+
return i;
|
|
113
|
+
}
|
|
114
|
+
return lines.length;
|
|
115
|
+
}
|
|
116
|
+
const packEnd = findBoundary(pack.index + 1, itemIndent);
|
|
117
|
+
const configIndent = itemIndent + 2;
|
|
118
|
+
const configRe = /^config:\s*(#.*)?$/;
|
|
119
|
+
let configIdx = -1;
|
|
120
|
+
for (let i = pack.index + 1; i < packEnd; i++) {
|
|
121
|
+
const line = lines[i] ?? "";
|
|
122
|
+
if (line.trim() === "")
|
|
123
|
+
continue;
|
|
124
|
+
if (countLeadingSpaces(line) === configIndent && configRe.test(line.trim())) {
|
|
125
|
+
if (configIdx !== -1) {
|
|
126
|
+
return {
|
|
127
|
+
ok: false,
|
|
128
|
+
error: "found more than one `config:` key in the understanding-before-execution pack block; refusing (ambiguous)",
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
configIdx = i;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (configIdx === -1) {
|
|
135
|
+
return {
|
|
136
|
+
ok: false,
|
|
137
|
+
error: "could not find a `config:` key in the understanding-before-execution pack block",
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
let lastContentIdx = configIdx;
|
|
141
|
+
let autoApprovePresent = false;
|
|
142
|
+
for (let i = configIdx + 1; i < packEnd; i++) {
|
|
143
|
+
const line = lines[i] ?? "";
|
|
144
|
+
const trimmed = line.trim();
|
|
145
|
+
if (trimmed === "")
|
|
146
|
+
continue;
|
|
147
|
+
const indent = countLeadingSpaces(line);
|
|
148
|
+
if (indent <= configIndent)
|
|
149
|
+
break;
|
|
150
|
+
lastContentIdx = i;
|
|
151
|
+
// Review round 3, F3: any line whose trimmed form starts with
|
|
152
|
+
// `auto_approve:` counts as "already present", not only the exact
|
|
153
|
+
// bare-key spelling `auto_approve:` with nothing else on the line.
|
|
154
|
+
// That exact-equality check missed a hand-applied flow-style value
|
|
155
|
+
// (`auto_approve: {when: [bypassPermissions], ...}`) and a bare key
|
|
156
|
+
// with a trailing comment (`auto_approve: # already configured`):
|
|
157
|
+
// both are schema-valid YAML for the same key, but neither passed
|
|
158
|
+
// `trimmed === "auto_approve:"`, so this verb would insert a SECOND
|
|
159
|
+
// `auto_approve` key and `parseYaml` below would throw "Map keys
|
|
160
|
+
// must be unique" uncaught (exit 70, a raw YAML message) instead of
|
|
161
|
+
// recognizing the upgrade as already applied.
|
|
162
|
+
// Known limit: a line starting with `auto_approve:` inside a block scalar
|
|
163
|
+
// under another key would also count as present; the verb then no-ops
|
|
164
|
+
// (fail-safe, never a corrupted manifest) rather than inserting twice.
|
|
165
|
+
if (trimmed.startsWith("auto_approve:"))
|
|
166
|
+
autoApprovePresent = true;
|
|
167
|
+
}
|
|
168
|
+
if (autoApprovePresent) {
|
|
169
|
+
return { ok: true, text: original, changed: false };
|
|
170
|
+
}
|
|
171
|
+
const snippetLines = renderAutoApproveSnippet(configIndent + 2).split("\n");
|
|
172
|
+
const insertAt = lastContentIdx + 1;
|
|
173
|
+
const next = [...lines.slice(0, insertAt), ...snippetLines, ...lines.slice(insertAt)];
|
|
174
|
+
return { ok: true, text: next.join(eol), changed: true };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* `parseYaml`, but a parse failure on the PROPOSED (post-insertion) text
|
|
178
|
+
* surfaces as this verb's own refusal (`HarnessExitError`, `EX_FAIL`,
|
|
179
|
+
* naming the pack and that the proposed text did not parse) rather than
|
|
180
|
+
* an uncaught exception (review round 3, F3: before this wrapper, a
|
|
181
|
+
* proposal `applyAutoApproveUpgrade` mis-recognized as a genuine
|
|
182
|
+
* insertion (e.g. a duplicate key under a different quoting style this
|
|
183
|
+
* heuristic does not special-case) reached the operator as a raw
|
|
184
|
+
* "Map keys must be unique" crash at exit 70 instead of a normal
|
|
185
|
+
* refusal). `original` is never passed here: it is the operator's own
|
|
186
|
+
* file, already on disk, and is not re-validated by this verb.
|
|
187
|
+
*/
|
|
188
|
+
function parseProposedYamlOrRefuse(text, name, context) {
|
|
189
|
+
try {
|
|
190
|
+
return parseYaml(text);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
throw new HarnessExitError(`harness pack upgrade: proposed manifest for pack ${JSON.stringify(name)} did not parse as YAML (${context}): ${err instanceof Error ? err.message : String(err)}`, EX_FAIL);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* `harness pack upgrade <name>` implementation. `name` is validated
|
|
198
|
+
* against the (currently one-entry) set of known upgrades before any
|
|
199
|
+
* file I/O; an unknown name refuses with `EX_FAIL` rather than silently
|
|
200
|
+
* doing nothing.
|
|
201
|
+
*/
|
|
202
|
+
export async function packUpgrade(name, opts = {}) {
|
|
203
|
+
if (name !== "understanding-before-execution") {
|
|
204
|
+
throw new HarnessExitError(`harness pack upgrade does not support ${JSON.stringify(name)} yet; only "understanding-before-execution" (auto_approve default, task 8f637efd) is wired.`, EX_FAIL);
|
|
205
|
+
}
|
|
206
|
+
const target = resolveTargetPath(opts);
|
|
207
|
+
if (!fs.existsSync(target)) {
|
|
208
|
+
throw new HarnessExitError(`harness manifest not found at ${target}; run \`harness init\` first`, EX_NOINPUT);
|
|
209
|
+
}
|
|
210
|
+
const original = fs.readFileSync(target, "utf8");
|
|
211
|
+
const result = applyAutoApproveUpgrade(original);
|
|
212
|
+
if (!result.ok) {
|
|
213
|
+
throw new HarnessExitError(`harness pack upgrade: ${result.error}`, EX_FAIL);
|
|
214
|
+
}
|
|
215
|
+
const diff = unifiedDiff({
|
|
216
|
+
fileName: path.basename(target),
|
|
217
|
+
oldText: original,
|
|
218
|
+
newText: result.text,
|
|
219
|
+
oldHeader: "current",
|
|
220
|
+
newHeader: "proposed",
|
|
221
|
+
});
|
|
222
|
+
if (!result.changed) {
|
|
223
|
+
return { path: target, name, diff, applied: false, alreadyPresent: true };
|
|
224
|
+
}
|
|
225
|
+
// Schema gate before ever touching disk, mirroring `pack add` / `pack
|
|
226
|
+
// reseed`: catches an insertion that would somehow produce an invalid
|
|
227
|
+
// manifest (e.g. a config: key this heuristic mis-located) before it
|
|
228
|
+
// reaches the operator's file.
|
|
229
|
+
const schemaResult = validateBeforeWrite(parseProposedYamlOrRefuse(result.text, name, "post-insertion validation"));
|
|
230
|
+
if (!schemaResult.ok) {
|
|
231
|
+
throw new HarnessExitError(`proposed manifest fails schema validation:\n${formatValidationErrors(schemaResult.errors)}`, EX_FAIL);
|
|
232
|
+
}
|
|
233
|
+
if (opts.dryRun) {
|
|
234
|
+
return { path: target, name, diff, applied: false, alreadyPresent: false };
|
|
235
|
+
}
|
|
236
|
+
const lockPath = path.join(path.dirname(target), LOCK_BASENAME);
|
|
237
|
+
// Review round 3, F4: whether the locked callback actually WROTE is
|
|
238
|
+
// tracked here rather than assumed. The pre-lock read above can be
|
|
239
|
+
// stale by the time the lock is acquired: if a concurrent writer
|
|
240
|
+
// already inserted the block, the callback below returns early
|
|
241
|
+
// (`recomputed.changed === false`) without writing anything, and the
|
|
242
|
+
// result reported to the caller/CLI must say so (`applied: false,
|
|
243
|
+
// alreadyPresent: true`, so `harness pack upgrade` prints the
|
|
244
|
+
// "already carries this upgrade" message) instead of the hardcoded
|
|
245
|
+
// `applied: true` this used to return unconditionally.
|
|
246
|
+
let wroteUnderLock = false;
|
|
247
|
+
await withFileLock(lockPath, () => {
|
|
248
|
+
// Re-read and recompute under the lock (mirrors `pack add`): a
|
|
249
|
+
// concurrent writer may have inserted the block (or changed the
|
|
250
|
+
// file entirely) between the pre-lock read above and now.
|
|
251
|
+
const current = fs.readFileSync(target, "utf8");
|
|
252
|
+
const recomputed = applyAutoApproveUpgrade(current);
|
|
253
|
+
if (!recomputed.ok) {
|
|
254
|
+
throw new HarnessExitError(`harness pack upgrade: ${recomputed.error}`, EX_FAIL);
|
|
255
|
+
}
|
|
256
|
+
if (!recomputed.changed)
|
|
257
|
+
return; // raced: someone else already inserted it
|
|
258
|
+
const recheck = validateBeforeWrite(parseProposedYamlOrRefuse(recomputed.text, name, "post-insertion validation after lock acquisition"));
|
|
259
|
+
if (!recheck.ok) {
|
|
260
|
+
throw new HarnessExitError(`proposed manifest fails schema validation after lock acquisition:\n${formatValidationErrors(recheck.errors)}`, EX_FAIL);
|
|
261
|
+
}
|
|
262
|
+
atomicWriteFile(target, recomputed.text);
|
|
263
|
+
wroteUnderLock = true;
|
|
264
|
+
});
|
|
265
|
+
return {
|
|
266
|
+
path: target,
|
|
267
|
+
name,
|
|
268
|
+
diff,
|
|
269
|
+
applied: wroteUnderLock,
|
|
270
|
+
alreadyPresent: !wroteUnderLock,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=upgrade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../../src/cli/pack/upgrade.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,6 +42,14 @@ export interface RecordReviewOptions extends RecordCommonOptions {
|
|
|
42
42
|
base?: string;
|
|
43
43
|
/** Explicit branch override (otherwise resolved via resolveGitContext(cwd)). */
|
|
44
44
|
branch?: string;
|
|
45
|
+
/**
|
|
46
|
+
* agent-tasks task id for the `review:<task-id>` tag the two task-scoped
|
|
47
|
+
* merge gates read (`review-before-task-merge` /
|
|
48
|
+
* `review-before-task-finish-automerge`, task 2699b476). Optional: the
|
|
49
|
+
* PR/branch/base tags are what the pull_requests_merge and `gh pr merge`
|
|
50
|
+
* gates read, and an operator on those surfaces has no task id to pass.
|
|
51
|
+
*/
|
|
52
|
+
task?: string;
|
|
45
53
|
/** Free-form review summary — required, non-empty. */
|
|
46
54
|
summary: string;
|
|
47
55
|
}
|
package/dist/cli/record/index.js
CHANGED
|
@@ -29,6 +29,11 @@ import { resolveManifestLedgerWriter } from "../../runtime/ledger-writer.js";
|
|
|
29
29
|
import { resolveReadSessionId, } from "../../runtime/session-id.js";
|
|
30
30
|
import { EX_FAIL, EX_USAGE } from "../exit-codes.js";
|
|
31
31
|
import { loadManifest } from "../loader.js";
|
|
32
|
+
// U+2014 EM DASH, written as an escape so the literal never appears in
|
|
33
|
+
// source. The emitted fact content is byte-identical to what `harness
|
|
34
|
+
// record review` has always written; every gate reads the tags before it,
|
|
35
|
+
// never this separator.
|
|
36
|
+
const TAG_SUMMARY_SEPARATOR = "\u2014";
|
|
32
37
|
const LEDGER_SOURCE_REVIEW = "harness-record-review";
|
|
33
38
|
const LEDGER_SOURCE_REVIEW_SUBAGENT = "harness-record-review-subagent";
|
|
34
39
|
const LEDGER_SOURCE_DOGFOOD = "harness-record-dogfood";
|
|
@@ -80,6 +85,20 @@ function initRecordVerb(opts, verbName) {
|
|
|
80
85
|
};
|
|
81
86
|
return { note, cwd: opts.cwd ?? process.cwd(), sessionId: resolveSession(opts) };
|
|
82
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* The one shared "this flag was misused" failure shape: warn on stderr and
|
|
90
|
+
* hand back the ready-to-`return` EX_USAGE `RecordResult`. Extracted when
|
|
91
|
+
* `optionalTagValue` (task 2699b476) grew the second copy of this
|
|
92
|
+
* five-line construction and the duplication fitness function
|
|
93
|
+
* (`scripts/check-duplication.mjs`) flagged it.
|
|
94
|
+
*/
|
|
95
|
+
function usageFailure(reason, sessionId, note) {
|
|
96
|
+
note(reason);
|
|
97
|
+
return {
|
|
98
|
+
ok: false,
|
|
99
|
+
result: { exitCode: EX_USAGE, wrote: false, content: "", sessionId, branch: "", reason },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
83
102
|
/**
|
|
84
103
|
* Trim `value` and refuse it if empty (a required flag / positional
|
|
85
104
|
* argument left blank). Returns the ready-to-`return`ed EX_USAGE
|
|
@@ -90,12 +109,25 @@ function initRecordVerb(opts, verbName) {
|
|
|
90
109
|
function requireNonEmpty(value, flagLabel, sessionId, note) {
|
|
91
110
|
const trimmed = (value ?? "").trim();
|
|
92
111
|
if (trimmed.length === 0) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
return usageFailure(`${flagLabel} must not be empty`, sessionId, note);
|
|
113
|
+
}
|
|
114
|
+
return { ok: true, value: trimmed };
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* An OPTIONAL tag value: absent stays absent, present must be a non-empty
|
|
118
|
+
* token with no internal whitespace. The shape check is deliberately loose
|
|
119
|
+
* (task 2699b476): the id only namespaces a ledger tag, so anything the
|
|
120
|
+
* gate's `${TASK_ID}` substitution can compare against is acceptable, but
|
|
121
|
+
* a value carrying whitespace would split into two tags in the fact
|
|
122
|
+
* content and silently satisfy a gate keyed on the first half.
|
|
123
|
+
*/
|
|
124
|
+
function optionalTagValue(value, flagLabel, sessionId, note) {
|
|
125
|
+
if (value === undefined)
|
|
126
|
+
return { ok: true, value: undefined };
|
|
127
|
+
const trimmed = value.trim();
|
|
128
|
+
if (trimmed.length === 0 || /\s/.test(trimmed)) {
|
|
129
|
+
return usageFailure(`${flagLabel} must be a non-empty value with no whitespace ` +
|
|
130
|
+
`(it namespaces one ledger tag); got ${JSON.stringify(value)}`, sessionId, note);
|
|
99
131
|
}
|
|
100
132
|
return { ok: true, value: trimmed };
|
|
101
133
|
}
|
|
@@ -177,8 +209,24 @@ export async function runRecordReview(opts) {
|
|
|
177
209
|
if (!branchResult.ok)
|
|
178
210
|
return branchResult.result;
|
|
179
211
|
const branch = branchResult.branch;
|
|
212
|
+
const taskResult = optionalTagValue(opts.task, "--task", sessionId, note);
|
|
213
|
+
if (!taskResult.ok)
|
|
214
|
+
return taskResult.result;
|
|
215
|
+
const task = taskResult.value;
|
|
180
216
|
const base = resolveBase(cwd, opts.base, note);
|
|
181
|
-
|
|
217
|
+
// One fact, every tag family a merge/PR gate can key on: the PR number,
|
|
218
|
+
// the working branch, the base branch, and (task 2699b476) the
|
|
219
|
+
// agent-tasks task id the two task-scoped merge gates read. Recording a
|
|
220
|
+
// review once therefore satisfies whichever surface actually fires,
|
|
221
|
+
// instead of asking the operator to predict it (docs/CLI.md, "The
|
|
222
|
+
// merge-surface trap"). TAG_SUMMARY_SEPARATOR keeps the emitted content
|
|
223
|
+
// byte-identical to what this verb has always written.
|
|
224
|
+
const tags = [`review:${pr}`, `review:${branch}`];
|
|
225
|
+
if (base !== undefined)
|
|
226
|
+
tags.push(`review:${base}`);
|
|
227
|
+
if (task !== undefined)
|
|
228
|
+
tags.push(`review:${task}`);
|
|
229
|
+
const content = `${tags.join(" ")} ${TAG_SUMMARY_SEPARATOR} ${summary}`;
|
|
182
230
|
return finishRecordWrite(opts, sessionId, branch, LEDGER_SOURCE_REVIEW, content, note);
|
|
183
231
|
}
|
|
184
232
|
export async function runRecordReviewSubagent(opts) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/record/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/record/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ import { PACK_NAME as UNDERSTANDING_BEFORE_EXECUTION_PACK_NAME } from "../../pol
|
|
|
10
10
|
import { isMeasuredPermissionModeFor, measuredPermissionModeLiteralsFor, } from "../../policy-packs/builtin/understanding-before-execution/measured-permission-modes.js";
|
|
11
11
|
import { AUTO_APPROVE_HARNESS_VALUES, DEFAULT_AUTO_APPROVE_HARNESSES, } from "../../policy-packs/builtin/understanding-before-execution/auto-approve.js";
|
|
12
12
|
import { DEFAULT_SAFE_DELETION_ROOTS } from "../../schema/risk.js";
|
|
13
|
-
import { deriveWorkflowGatePolicies, findWeakGatePolicyOverlaps, handAuthoredPolicies, MERGE_BASH_MATCH, MERGE_MCP_MATCH, REVIEW_EVIDENCE_HOOK_BASH, REVIEW_EVIDENCE_HOOK_MCP, workflowRequiresMergeGate, } from "../../runtime/workflow-policies.js";
|
|
13
|
+
import { deriveWorkflowGatePolicies, findWeakGatePolicyOverlaps, handAuthoredPolicies, MERGE_BASH_MATCH, MERGE_MCP_MATCH, REVIEW_EVIDENCE_HOOK_BASH, REVIEW_EVIDENCE_HOOK_MCP, REVIEW_EVIDENCE_HOOK_TASK_FINISH, REVIEW_EVIDENCE_HOOK_TASK_MERGE, workflowRequiresMergeGate, } from "../../runtime/workflow-policies.js";
|
|
14
14
|
const DEFAULT_RUNTIME_BUILTINS = [
|
|
15
15
|
"Read",
|
|
16
16
|
"Edit",
|
|
@@ -344,17 +344,69 @@ export function checkWorkflowGateWiring(manifest) {
|
|
|
344
344
|
if (missing.length > 0) {
|
|
345
345
|
problems.unshift(`hooks[] is missing ${missing.join(" and ")}`);
|
|
346
346
|
}
|
|
347
|
-
|
|
347
|
+
const errors = problems.length === 0
|
|
348
|
+
? []
|
|
349
|
+
: offending.map((wf) => ({
|
|
350
|
+
severity: "error",
|
|
351
|
+
path: "workflows",
|
|
352
|
+
message: `workflow "${wf.name}" declares a review_subagent step with spawn: "required" ` +
|
|
353
|
+
`followed by a merge step, but the runtime merge gate is not wired: ${problems.join("; ")}. ` +
|
|
354
|
+
"Without both hooks correctly wired, harness policy intercept never derives this " +
|
|
355
|
+
"workflow's merge-gate policy and the merge is NOT blocked (silent non-enforcement). " +
|
|
356
|
+
"See docs/for-agents.md, or src/cli/init/templates.ts's require-review-evidence / " +
|
|
357
|
+
'require-review-evidence-bash entries, or drop spawn: "required".',
|
|
358
|
+
}));
|
|
359
|
+
return [...errors, ...checkTaskVerbGateWiring(manifest, offending)];
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* MEDIUM security (review round 1, task 2699b476 round 2): a manifest can
|
|
363
|
+
* wire the ORIGINAL pair of review-evidence hooks
|
|
364
|
+
* (`require-review-evidence` / `require-review-evidence-bash`, gating
|
|
365
|
+
* `mcp__agent-tasks__pull_requests_merge` and `gh pr merge`) without ever
|
|
366
|
+
* adding the two task-scoped ones task 2699b476 introduced
|
|
367
|
+
* (`require-review-evidence-task-merge` / `require-review-evidence-task-finish`,
|
|
368
|
+
* gating `mcp__agent-tasks__task_merge` and `task_finish { autoMerge: true }`).
|
|
369
|
+
* `deriveWorkflowGatePolicies` derives the task-scoped gate ONLY when its
|
|
370
|
+
* own hook is present (same "quietly returns nothing" shape
|
|
371
|
+
* `checkWorkflowGateWiring` already guards for the original pair), so a
|
|
372
|
+
* manifest predating that task keeps the two newer verbs completely
|
|
373
|
+
* uncovered: a PR can be merged via `task_merge` or an auto-merging
|
|
374
|
+
* `task_finish` with no recorded review at all, while `harness validate`
|
|
375
|
+
* stayed silent about it. This is a `warning`, not an `error`, because the
|
|
376
|
+
* ORIGINAL surfaces (`pull_requests_merge`, `gh pr merge`) are still
|
|
377
|
+
* enforced when this fires: the gap is narrower than the fully-unwired
|
|
378
|
+
* case above, but still silent non-enforcement for the two verbs it names.
|
|
379
|
+
*/
|
|
380
|
+
function checkTaskVerbGateWiring(manifest, offending) {
|
|
381
|
+
const mcpHook = manifest.hooks.find((h) => h.name === REVIEW_EVIDENCE_HOOK_MCP);
|
|
382
|
+
const bashHook = manifest.hooks.find((h) => h.name === REVIEW_EVIDENCE_HOOK_BASH);
|
|
383
|
+
if (!mcpHook || !bashHook)
|
|
384
|
+
return [];
|
|
385
|
+
const taskMergeHook = manifest.hooks.find((h) => h.name === REVIEW_EVIDENCE_HOOK_TASK_MERGE);
|
|
386
|
+
const taskFinishHook = manifest.hooks.find((h) => h.name === REVIEW_EVIDENCE_HOOK_TASK_FINISH);
|
|
387
|
+
const uncoveredVerbs = [];
|
|
388
|
+
const missingHookNames = [];
|
|
389
|
+
if (!taskMergeHook) {
|
|
390
|
+
uncoveredVerbs.push("mcp__agent-tasks__task_merge");
|
|
391
|
+
missingHookNames.push(`"${REVIEW_EVIDENCE_HOOK_TASK_MERGE}"`);
|
|
392
|
+
}
|
|
393
|
+
if (!taskFinishHook) {
|
|
394
|
+
uncoveredVerbs.push("mcp__agent-tasks__task_finish (autoMerge: true)");
|
|
395
|
+
missingHookNames.push(`"${REVIEW_EVIDENCE_HOOK_TASK_FINISH}"`);
|
|
396
|
+
}
|
|
397
|
+
if (uncoveredVerbs.length === 0)
|
|
348
398
|
return [];
|
|
349
399
|
return offending.map((wf) => ({
|
|
350
|
-
severity: "
|
|
400
|
+
severity: "warning",
|
|
351
401
|
path: "workflows",
|
|
352
|
-
message: `workflow "${wf.name}"
|
|
353
|
-
`
|
|
354
|
-
|
|
355
|
-
"
|
|
356
|
-
"
|
|
357
|
-
|
|
402
|
+
message: `workflow "${wf.name}" wires the review-evidence gate for mcp__agent-tasks__pull_requests_merge ` +
|
|
403
|
+
`and gh pr merge, but not for ${uncoveredVerbs.join(" or ")}: ` +
|
|
404
|
+
`hooks[] is missing ${missingHookNames.join(" and ")}. ` +
|
|
405
|
+
"Without them harness policy intercept never derives the task-scoped merge gate (task 2699b476) " +
|
|
406
|
+
"and a PR can be merged through those verbs with no recorded review, even though the original " +
|
|
407
|
+
"pull_requests_merge / gh pr merge surfaces are still gated. See docs/for-agents.md, or " +
|
|
408
|
+
"src/cli/init/templates.ts's require-review-evidence-task-merge / " +
|
|
409
|
+
"require-review-evidence-task-finish entries.",
|
|
358
410
|
}));
|
|
359
411
|
}
|
|
360
412
|
/**
|