@lannguyensi/harness 0.40.0 → 0.42.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.
Files changed (189) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +9 -0
  3. package/dist/cli/adopt/derive.d.ts +15 -0
  4. package/dist/cli/adopt/derive.js +34 -7
  5. package/dist/cli/adopt/derive.js.map +1 -1
  6. package/dist/cli/adopt/index.d.ts +30 -0
  7. package/dist/cli/adopt/index.js +23 -3
  8. package/dist/cli/adopt/index.js.map +1 -1
  9. package/dist/cli/apply/generate-settings.d.ts +14 -1
  10. package/dist/cli/apply/generate-settings.js +7 -3
  11. package/dist/cli/apply/generate-settings.js.map +1 -1
  12. package/dist/cli/approve/stdin-report.js +2 -0
  13. package/dist/cli/approve/stdin-report.js.map +1 -1
  14. package/dist/cli/approve/understanding.js +28 -0
  15. package/dist/cli/approve/understanding.js.map +1 -1
  16. package/dist/cli/doctor/claude-mcp.d.ts +50 -0
  17. package/dist/cli/doctor/claude-mcp.js +170 -0
  18. package/dist/cli/doctor/claude-mcp.js.map +1 -0
  19. package/dist/cli/doctor/codex.d.ts +8 -0
  20. package/dist/cli/doctor/codex.js +8 -1
  21. package/dist/cli/doctor/codex.js.map +1 -1
  22. package/dist/cli/doctor/format.js +60 -11
  23. package/dist/cli/doctor/format.js.map +1 -1
  24. package/dist/cli/doctor/index.d.ts +46 -0
  25. package/dist/cli/doctor/index.js +155 -29
  26. package/dist/cli/doctor/index.js.map +1 -1
  27. package/dist/cli/doctor/npm-bin-path.js +42 -0
  28. package/dist/cli/doctor/npm-bin-path.js.map +1 -1
  29. package/dist/cli/doctor/types.d.ts +37 -0
  30. package/dist/cli/doctor/types.js.map +1 -1
  31. package/dist/cli/dry-run.js +5 -0
  32. package/dist/cli/dry-run.js.map +1 -1
  33. package/dist/cli/explain.js +16 -3
  34. package/dist/cli/explain.js.map +1 -1
  35. package/dist/cli/index.js +328 -11
  36. package/dist/cli/index.js.map +1 -1
  37. package/dist/cli/init/agent-tasks-auth.js +32 -0
  38. package/dist/cli/init/agent-tasks-auth.js.map +1 -1
  39. package/dist/cli/init/composer.js +13 -40
  40. package/dist/cli/init/composer.js.map +1 -1
  41. package/dist/cli/init/dependencies.js +21 -0
  42. package/dist/cli/init/dependencies.js.map +1 -1
  43. package/dist/cli/init/detect.d.ts +20 -3
  44. package/dist/cli/init/detect.js +34 -36
  45. package/dist/cli/init/detect.js.map +1 -1
  46. package/dist/cli/init/index.d.ts +18 -0
  47. package/dist/cli/init/index.js +28 -2
  48. package/dist/cli/init/index.js.map +1 -1
  49. package/dist/cli/init/interactive.d.ts +41 -0
  50. package/dist/cli/init/interactive.js +421 -6
  51. package/dist/cli/init/interactive.js.map +1 -1
  52. package/dist/cli/init/profiles.d.ts +2 -2
  53. package/dist/cli/init/profiles.js +10 -1
  54. package/dist/cli/init/profiles.js.map +1 -1
  55. package/dist/cli/init/templates.d.ts +1 -1
  56. package/dist/cli/init/templates.js +217 -8
  57. package/dist/cli/init/templates.js.map +1 -1
  58. package/dist/cli/list.js +3 -1
  59. package/dist/cli/list.js.map +1 -1
  60. package/dist/cli/main.js +10 -0
  61. package/dist/cli/main.js.map +1 -1
  62. package/dist/cli/pack/hook-bootstrap.d.ts +24 -0
  63. package/dist/cli/pack/hook-bootstrap.js +47 -1
  64. package/dist/cli/pack/hook-bootstrap.js.map +1 -1
  65. package/dist/cli/pack/hook-branch-protection.js +9 -1
  66. package/dist/cli/pack/hook-branch-protection.js.map +1 -1
  67. package/dist/cli/pack/hook-codex-post-tool-use.d.ts +25 -0
  68. package/dist/cli/pack/hook-codex-post-tool-use.js +160 -0
  69. package/dist/cli/pack/hook-codex-post-tool-use.js.map +1 -0
  70. package/dist/cli/pack/hook-codex-pre-tool-use.d.ts +1 -0
  71. package/dist/cli/pack/hook-codex-pre-tool-use.js +43 -10
  72. package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -1
  73. package/dist/cli/pack/hook-codex-stop.js +1 -8
  74. package/dist/cli/pack/hook-codex-stop.js.map +1 -1
  75. package/dist/cli/pack/hook-post-merge-gate-record.d.ts +30 -0
  76. package/dist/cli/pack/hook-post-merge-gate-record.js +153 -0
  77. package/dist/cli/pack/hook-post-merge-gate-record.js.map +1 -0
  78. package/dist/cli/pack/hook-post-merge-gate.d.ts +28 -0
  79. package/dist/cli/pack/hook-post-merge-gate.js +244 -0
  80. package/dist/cli/pack/hook-post-merge-gate.js.map +1 -0
  81. package/dist/cli/pack/hook-post-tool-use.js +16 -131
  82. package/dist/cli/pack/hook-post-tool-use.js.map +1 -1
  83. package/dist/cli/pack/hook-pre-tool-use.js +54 -2
  84. package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
  85. package/dist/cli/pack/hook-solution-acceptance-writeguard.js +148 -2
  86. package/dist/cli/pack/hook-solution-acceptance-writeguard.js.map +1 -1
  87. package/dist/cli/pack/hook-stay-in-scope.js +63 -20
  88. package/dist/cli/pack/hook-stay-in-scope.js.map +1 -1
  89. package/dist/cli/pack/hook-track-active-claim.js +33 -9
  90. package/dist/cli/pack/hook-track-active-claim.js.map +1 -1
  91. package/dist/cli/pack/index.d.ts +2 -1
  92. package/dist/cli/pack/index.js +2 -1
  93. package/dist/cli/pack/index.js.map +1 -1
  94. package/dist/cli/pack/mutate.d.ts +19 -0
  95. package/dist/cli/pack/mutate.js +38 -0
  96. package/dist/cli/pack/mutate.js.map +1 -1
  97. package/dist/cli/pack/reseed.d.ts +19 -0
  98. package/dist/cli/pack/reseed.js +118 -0
  99. package/dist/cli/pack/reseed.js.map +1 -0
  100. package/dist/cli/pack/understanding-report-schema-hint.js +1 -1
  101. package/dist/cli/pack/understanding-report-schema-hint.js.map +1 -1
  102. package/dist/cli/pause/index.js +12 -3
  103. package/dist/cli/pause/index.js.map +1 -1
  104. package/dist/cli/record/index.d.ts +64 -0
  105. package/dist/cli/record/index.js +211 -0
  106. package/dist/cli/record/index.js.map +1 -0
  107. package/dist/cli/session-start/index.d.ts +21 -0
  108. package/dist/cli/session-start/index.js +160 -25
  109. package/dist/cli/session-start/index.js.map +1 -1
  110. package/dist/cli/session-start/toolchain-parity.d.ts +149 -0
  111. package/dist/cli/session-start/toolchain-parity.js +618 -0
  112. package/dist/cli/session-start/toolchain-parity.js.map +1 -0
  113. package/dist/cli/uninstall/index.d.ts +73 -1
  114. package/dist/cli/uninstall/index.js +134 -2
  115. package/dist/cli/uninstall/index.js.map +1 -1
  116. package/dist/cli/validate/checks.js +8 -0
  117. package/dist/cli/validate/checks.js.map +1 -1
  118. package/dist/io/claude-mcp.d.ts +258 -0
  119. package/dist/io/claude-mcp.js +544 -0
  120. package/dist/io/claude-mcp.js.map +1 -0
  121. package/dist/policies/ledger-client.d.ts +34 -1
  122. package/dist/policies/ledger-client.js +21 -16
  123. package/dist/policies/ledger-client.js.map +1 -1
  124. package/dist/policy-packs/builtin/branch-protection-runtime.d.ts +4 -2
  125. package/dist/policy-packs/builtin/branch-protection-runtime.js +4 -2
  126. package/dist/policy-packs/builtin/branch-protection-runtime.js.map +1 -1
  127. package/dist/policy-packs/builtin/branch-protection.d.ts +10 -1
  128. package/dist/policy-packs/builtin/branch-protection.js +17 -0
  129. package/dist/policy-packs/builtin/branch-protection.js.map +1 -1
  130. package/dist/policy-packs/builtin/post-merge-gate-runtime.d.ts +195 -0
  131. package/dist/policy-packs/builtin/post-merge-gate-runtime.js +290 -0
  132. package/dist/policy-packs/builtin/post-merge-gate-runtime.js.map +1 -0
  133. package/dist/policy-packs/builtin/post-merge-gate.d.ts +56 -0
  134. package/dist/policy-packs/builtin/post-merge-gate.js +291 -0
  135. package/dist/policy-packs/builtin/post-merge-gate.js.map +1 -0
  136. package/dist/policy-packs/builtin/solution-acceptance-runtime.js +28 -13
  137. package/dist/policy-packs/builtin/solution-acceptance-runtime.js.map +1 -1
  138. package/dist/policy-packs/builtin/understanding-before-execution-runtime.d.ts +197 -24
  139. package/dist/policy-packs/builtin/understanding-before-execution-runtime.js +342 -40
  140. package/dist/policy-packs/builtin/understanding-before-execution-runtime.js.map +1 -1
  141. package/dist/policy-packs/builtin/understanding-before-execution.d.ts +26 -1
  142. package/dist/policy-packs/builtin/understanding-before-execution.js +302 -17
  143. package/dist/policy-packs/builtin/understanding-before-execution.js.map +1 -1
  144. package/dist/policy-packs/registry.d.ts +23 -2
  145. package/dist/policy-packs/registry.js +31 -2
  146. package/dist/policy-packs/registry.js.map +1 -1
  147. package/dist/policy-packs/ux-compare.d.ts +14 -0
  148. package/dist/policy-packs/ux-compare.js +58 -0
  149. package/dist/policy-packs/ux-compare.js.map +1 -0
  150. package/dist/policy-packs/ux-drift-check.d.ts +27 -0
  151. package/dist/policy-packs/ux-drift-check.js +78 -0
  152. package/dist/policy-packs/ux-drift-check.js.map +1 -0
  153. package/dist/probes/mcp.d.ts +13 -0
  154. package/dist/probes/mcp.js +57 -0
  155. package/dist/probes/mcp.js.map +1 -1
  156. package/dist/runtime/approval-signing.d.ts +82 -0
  157. package/dist/runtime/approval-signing.js +275 -0
  158. package/dist/runtime/approval-signing.js.map +1 -0
  159. package/dist/runtime/git-context.d.ts +50 -0
  160. package/dist/runtime/git-context.js +108 -1
  161. package/dist/runtime/git-context.js.map +1 -1
  162. package/dist/runtime/hermetic-spawn-guard.d.ts +25 -0
  163. package/dist/runtime/hermetic-spawn-guard.js +136 -0
  164. package/dist/runtime/hermetic-spawn-guard.js.map +1 -0
  165. package/dist/runtime/intercept.js +62 -5
  166. package/dist/runtime/intercept.js.map +1 -1
  167. package/dist/runtime/ledger-writer.d.ts +27 -0
  168. package/dist/runtime/ledger-writer.js +46 -0
  169. package/dist/runtime/ledger-writer.js.map +1 -0
  170. package/dist/runtime/pause-sentinel.js +14 -3
  171. package/dist/runtime/pause-sentinel.js.map +1 -1
  172. package/dist/runtime/read-only-bash.js +118 -0
  173. package/dist/runtime/read-only-bash.js.map +1 -1
  174. package/dist/runtime/recovery-git-commit.d.ts +22 -0
  175. package/dist/runtime/recovery-git-commit.js +284 -0
  176. package/dist/runtime/recovery-git-commit.js.map +1 -0
  177. package/dist/runtime/tool-name-aliases.d.ts +1 -0
  178. package/dist/runtime/tool-name-aliases.js +7 -1
  179. package/dist/runtime/tool-name-aliases.js.map +1 -1
  180. package/dist/schema/index.d.ts +94 -42
  181. package/dist/schema/index.js +5 -0
  182. package/dist/schema/index.js.map +1 -1
  183. package/dist/schema/policies.d.ts +56 -44
  184. package/dist/schema/policies.js +79 -9
  185. package/dist/schema/policies.js.map +1 -1
  186. package/dist/schema/toolchain-parity.d.ts +18 -0
  187. package/dist/schema/toolchain-parity.js +35 -0
  188. package/dist/schema/toolchain-parity.js.map +1 -0
  189. package/package.json +4 -2
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Classify a Bash/shell command string as the narrow "recovery commit"
3
+ * shape: a bare, unchained `git commit` invocation carrying only
4
+ * `-a`/`--all`/`--allow-empty` and one or more `-m`/`--message`/`-am`
5
+ * message flags. `true` means the understanding-gate PreToolUse hooks
6
+ * may admit this ONE call without a fresh Understanding Report, provided
7
+ * the caller has already established that this session/task had a real
8
+ * (now-expired) operator approval — see module header for the full
9
+ * safety argument and why that precondition is load-bearing.
10
+ *
11
+ * A properly single- or double-quoted `-m`/`--message` value may contain
12
+ * ANY text, including characters like `<`/`>`/`;`/`&`/`|` that would be
13
+ * dangerous unquoted — that is what lets a real trailer such as
14
+ * `Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>` through (see
15
+ * `hasUnsafeMetachar`'s doc for the exact quote-aware rule). Anything
16
+ * outside this narrow shape — `--amend`, `--no-verify`, `-C <dir>`
17
+ * (rejected implicitly: it does not appear directly after `git commit`),
18
+ * a pathspec, UNQUOTED chaining/redirection, command substitution that
19
+ * is live where it appears, an unrecognised flag — fails closed
20
+ * (`false`) and the caller falls through to the ordinary hard block.
21
+ */
22
+ export declare function isRecoveryGitCommit(command: string): boolean;
@@ -0,0 +1,284 @@
1
+ // Recovery git-commit exemption for the understanding-gate PreToolUse
2
+ // hooks (task 6e888423).
3
+ //
4
+ // The problem: `approval_lifecycle.max_age` (default 4h, see
5
+ // src/cli/init/templates.ts) expires the operator-approval MARKER
6
+ // independently of any task-completion boundary. That is by design for
7
+ // genuinely new work — a session idle for hours should re-justify itself
8
+ // before its next Edit/Write/Bash. But it also fires mid-task, e.g. while
9
+ // an agent is deep in a reviewer-amendment loop (apply fixes, wait on CI,
10
+ // iterate again) that outlives the window. When the marker ages out at
11
+ // exactly the moment the agent needs to run the recovery `git commit`
12
+ // that consolidates already-approved Edit/Write output into a new HEAD
13
+ // (so `preflight` / solution-acceptance can re-pin their verdict there),
14
+ // the gate hard-blocks that Bash call — including the recovery commit
15
+ // itself — and only the operator can unblock it (agent-grounding
16
+ // frictions #2/#9/#58/#71).
17
+ //
18
+ // The fix is narrow on purpose. A `git commit` records whatever is
19
+ // ALREADY sitting in the working tree; it introduces no new file
20
+ // content. Every byte in that working tree was necessarily produced by
21
+ // an Edit/Write/Bash call that was itself gated at the time it ran, so
22
+ // letting a bare, unchained `git commit` through does not let unreviewed
23
+ // content sneak past the Understanding Gate — it only lets the agent
24
+ // finish recording work that was already approved once. This is
25
+ // deliberately NOT a blanket "any Bash whitelist" or "ignore
26
+ // max_age" fix:
27
+ // - The caller (hook-pre-tool-use.ts / hook-codex-pre-tool-use.ts)
28
+ // gates this classifier behind `expired === true` from
29
+ // `checkOperatorApprovalMarkers` — i.e. a real operator-written
30
+ // marker for THIS session/task existed and simply aged past
31
+ // max_age. A session that was NEVER approved (marker absent) gets
32
+ // no exemption: `isRecoveryGitCommit` alone is not a bypass, it
33
+ // only matters once the caller has already proven prior approval.
34
+ // - A marker CLEARED by a task-completion boundary tool
35
+ // (`task_finish`, `pull_requests_merge`, ...) reads as "missing",
36
+ // not "expired" (`clearApprovalMarker` deletes the file rather than
37
+ // leaving a stale one behind). The exemption therefore does not
38
+ // fire for a fresh task's first commit — the gate still re-arms
39
+ // exactly as `approval_lifecycle` intends.
40
+ // - Edit / Write and every other Bash shape stay hard-gated
41
+ // regardless of this exemption; only the exact `git commit`
42
+ // invocation classified below is admitted.
43
+ // - The matcher refuses chaining (`;`, `&`, `|`, `&&`, `||`) and
44
+ // redirection (`<`, `>`) that appear OUTSIDE a quoted span, and
45
+ // command substitution (backtick, `$(...)`) that appears outside a
46
+ // quote OR inside a DOUBLE-quoted span (both are still expanded by
47
+ // bash there) — so a compound command cannot ride a legitimate
48
+ // commit past the gate. `;`/`&`/`|`/`<`/`>` are treated as literal
49
+ // when they appear inside a quoted span (single OR double), exactly
50
+ // as bash treats them: this is what lets a real commit-message
51
+ // trailer like `Co-Authored-By: Claude Fable 5
52
+ // <noreply@anthropic.com>` (this very repo's own commit convention)
53
+ // through a quoted `-m` value without opening a metachar hole,
54
+ // because git only ever sees the trailer as inert message text, not
55
+ // as shell syntax. A backtick or `$(` inside a SINGLE-quoted span is
56
+ // also literal (single quotes suppress all expansion) and therefore
57
+ // safe to admit. Newlines are rejected unconditionally regardless of
58
+ // quoting (see `isRecoveryGitCommit`): multiple `-m` flags are the
59
+ // supported shape for a multi-paragraph message, so no caller needs
60
+ // an embedded newline inside one quoted token. The matcher also
61
+ // fails closed on any flag it does not recognise, in particular
62
+ // `--amend` (rewrites a commit that may have been approved under an
63
+ // entirely different, unrelated window) and `--no-verify` (skips
64
+ // local hooks, which this exemption has no mandate to waive — see
65
+ // AGENTS.md "no workarounds").
66
+ // - ANY backslash in the command rejects the whole thing outright, in
67
+ // `isRecoveryGitCommit` before the quote-aware scan even runs. The
68
+ // quote-toggling in `hasUnsafeMetachar`/`tokenize` has no concept of
69
+ // backslash-escaping, so a payload like `git commit -am a\" ; echo
70
+ // INJECTED ; \"` was, for one commit on this branch, misclassified
71
+ // as a single safely-quoted message — the classifier "entered" a
72
+ // phantom quote span at the escaped `"` and read the live `;` inside
73
+ // it as literal text, while bash itself never entered a quote at all
74
+ // and executed `echo INJECTED` as a separate command (confirmed
75
+ // end-to-end for `;`, `||`, and `|`). Rejecting every backslash
76
+ // up front closes the whole escape-based attack surface: without a
77
+ // backslash present, naive quote-toggling matches bash's real
78
+ // quoting exactly. A hand-rolled bash-accurate escape state machine
79
+ // is deliberately NOT built here — too risky for a security boundary
80
+ // to get subtly wrong twice.
81
+ /** Flags that take no following value. */
82
+ const FLAG_ONLY_TOKENS = new Set(["-a", "--all", "--allow-empty"]);
83
+ /**
84
+ * Flags that consume the NEXT token as their value. `-am` is the common
85
+ * combined `-a -m` shorthand — the LAST flag in a short-option cluster is
86
+ * the one that takes an argument, so `-am <value>` clusters to `-a` (no
87
+ * value) followed by `-m <value>` exactly like a real shell/getopt would
88
+ * parse it. `-ma` is deliberately NOT included: there `-m` is NOT last in
89
+ * the cluster, so getopt takes the cluster's OWN remainder ("a") as `-m`'s
90
+ * value and the flag `-a` is never set at all — the next token (the
91
+ * agent's intended message) would be consumed by git as a pathspec
92
+ * instead, silently restricting the commit to files matching that
93
+ * pathspec. Admitting `-ma` here would therefore misclassify a command
94
+ * whose ACTUAL git semantics differ from what this exemption assumes.
95
+ * Multiple `-m`/`--message` occurrences are allowed (git concatenates
96
+ * them as separate paragraphs — the idiomatic way to express a subject
97
+ * line, a body, and a trailer such as `Co-Authored-By:` without embedding
98
+ * a literal newline in one token).
99
+ */
100
+ const MESSAGE_FLAG_TOKENS = new Set(["-m", "--message", "-am"]);
101
+ /**
102
+ * Quote-aware scan for shell metacharacters that are unsafe given WHERE
103
+ * they appear. Unlike a flat regex, this walks the string tracking
104
+ * whether we are inside a single-quoted span, a double-quoted span, or
105
+ * neither:
106
+ * - Outside any quote: `;`, `&`, `|`, `<`, `>`, backtick, and `$(` are
107
+ * all live shell syntax — any of them is unsafe.
108
+ * - Inside a single-quoted span: everything is inert (bash disables
109
+ * ALL expansion inside single quotes, including backtick and `$(`),
110
+ * so nothing here is unsafe.
111
+ * - Inside a double-quoted span: `;`, `&`, `|`, `<`, `>` are literal
112
+ * characters (bash does NOT treat them specially inside double
113
+ * quotes) and therefore safe, but backtick and `$(` are STILL
114
+ * expanded by bash inside double quotes and therefore still unsafe.
115
+ * An unterminated quote (the scan ends still "inside" one) is itself
116
+ * unsafe: the caller's tokenizer performs the authoritative parse and
117
+ * would also reject it, but this scan must not silently pass through
118
+ * content it could not fully account for.
119
+ */
120
+ function hasUnsafeMetachar(command) {
121
+ let quote = null;
122
+ for (let i = 0; i < command.length; i += 1) {
123
+ const ch = command[i];
124
+ if (quote === "'") {
125
+ if (ch === "'")
126
+ quote = null;
127
+ continue; // single-quoted: fully inert, including ` and $(
128
+ }
129
+ if (quote === '"') {
130
+ if (ch === '"') {
131
+ quote = null;
132
+ continue;
133
+ }
134
+ if (ch === "`")
135
+ return true;
136
+ if (ch === "$" && command[i + 1] === "(")
137
+ return true;
138
+ continue; // ; & | < > are literal inside double quotes
139
+ }
140
+ // Outside any quote: every metacharacter is live.
141
+ if (ch === '"' || ch === "'") {
142
+ quote = ch;
143
+ continue;
144
+ }
145
+ if (ch === ";" || ch === "&" || ch === "|" || ch === "<" || ch === ">")
146
+ return true;
147
+ if (ch === "`")
148
+ return true;
149
+ if (ch === "$" && command[i + 1] === "(")
150
+ return true;
151
+ }
152
+ return quote !== null; // unterminated quote: unsafe/unparseable
153
+ }
154
+ /**
155
+ * Quote-aware tokenizer for the residual argv after `git commit`, mimicking
156
+ * plain shell word-splitting: a "word" runs until unquoted whitespace, and a
157
+ * quoted region (single OR double quotes) within a word contributes its
158
+ * literal contents to that same word, quotes stripped. This is what lets
159
+ * both the standalone-token shape (`-m "a message"`) and the glued shape
160
+ * (`--message="a message"`, where the shell concatenates the flag prefix
161
+ * and the quoted value into ONE argv word) tokenize the same way a real
162
+ * shell would. An unterminated quote fails the parse (`null`); the caller
163
+ * treats that as "not a recognised recovery commit" and falls through to
164
+ * the ordinary gate block rather than guessing at the intended word.
165
+ */
166
+ function tokenize(rest) {
167
+ const tokens = [];
168
+ const n = rest.length;
169
+ let i = 0;
170
+ while (i < n) {
171
+ while (i < n && /\s/.test(rest[i]))
172
+ i += 1;
173
+ if (i >= n)
174
+ break;
175
+ let token = "";
176
+ while (i < n && !/\s/.test(rest[i])) {
177
+ const ch = rest[i];
178
+ if (ch === '"' || ch === "'") {
179
+ const close = rest.indexOf(ch, i + 1);
180
+ if (close === -1)
181
+ return null;
182
+ token += rest.slice(i + 1, close);
183
+ i = close + 1;
184
+ continue;
185
+ }
186
+ token += ch;
187
+ i += 1;
188
+ }
189
+ tokens.push(token);
190
+ }
191
+ return tokens;
192
+ }
193
+ /**
194
+ * Classify a Bash/shell command string as the narrow "recovery commit"
195
+ * shape: a bare, unchained `git commit` invocation carrying only
196
+ * `-a`/`--all`/`--allow-empty` and one or more `-m`/`--message`/`-am`
197
+ * message flags. `true` means the understanding-gate PreToolUse hooks
198
+ * may admit this ONE call without a fresh Understanding Report, provided
199
+ * the caller has already established that this session/task had a real
200
+ * (now-expired) operator approval — see module header for the full
201
+ * safety argument and why that precondition is load-bearing.
202
+ *
203
+ * A properly single- or double-quoted `-m`/`--message` value may contain
204
+ * ANY text, including characters like `<`/`>`/`;`/`&`/`|` that would be
205
+ * dangerous unquoted — that is what lets a real trailer such as
206
+ * `Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>` through (see
207
+ * `hasUnsafeMetachar`'s doc for the exact quote-aware rule). Anything
208
+ * outside this narrow shape — `--amend`, `--no-verify`, `-C <dir>`
209
+ * (rejected implicitly: it does not appear directly after `git commit`),
210
+ * a pathspec, UNQUOTED chaining/redirection, command substitution that
211
+ * is live where it appears, an unrecognised flag — fails closed
212
+ * (`false`) and the caller falls through to the ordinary hard block.
213
+ */
214
+ export function isRecoveryGitCommit(command) {
215
+ const trimmed = command.trim();
216
+ if (trimmed === "")
217
+ return false;
218
+ if (trimmed.includes("\n") || trimmed.includes("\r"))
219
+ return false;
220
+ // CRITICAL (found on re-review of the quote-aware rewrite): reject ANY
221
+ // backslash before doing anything else. `hasUnsafeMetachar` and
222
+ // `tokenize` both toggle quote state on every `"`/`'` character with no
223
+ // concept of backslash-escaping, but bash does: `\"` outside a quote is
224
+ // a LITERAL `"` that does NOT open a quote context. Without this
225
+ // check, a payload like `git commit -am a\" ; echo INJECTED ; \"` gets
226
+ // classified as one big safely-quoted message (the classifier "enters"
227
+ // a phantom quote span at the escaped `"` and treats the live `;`
228
+ // inside it as literal), while bash itself never entered a quote at
229
+ // all and executes `echo INJECTED` as a separate command — confirmed
230
+ // end-to-end (classifier ADMIT + a live shell actually running the
231
+ // injected command) for `;`, `||`, and `|` riding this exact shape.
232
+ // Same bug class the 0.40.0 CHANGELOG already documents once for the
233
+ // `harness approve` heredoc matcher (a backslash-escaped redirect
234
+ // smuggled past a quote-blind check there too).
235
+ //
236
+ // The fix is deliberately blunt rather than a full escape-aware state
237
+ // machine: modeling bash's actual backslash rules (live outside
238
+ // quotes and inside double quotes for a few characters, entirely inert
239
+ // inside single quotes, `$'...'` ANSI-C quoting has its own escape
240
+ // grammar again) is exactly the kind of bash-parser-in-miniature this
241
+ // module's design explicitly avoids building for a security boundary.
242
+ // Without any backslash present, the naive quote-toggling in
243
+ // `hasUnsafeMetachar`/`tokenize` matches bash's real quoting exactly,
244
+ // so rejecting every backslash closes the whole escape-based attack
245
+ // surface at the cost of not admitting messages that happen to contain
246
+ // one — an acceptable narrowing (the documented main case, this repo's
247
+ // own `Co-Authored-By: ... <noreply@anthropic.com>` trailer, has no
248
+ // backslash) for a fail-closed exemption gate.
249
+ if (trimmed.includes("\\"))
250
+ return false;
251
+ if (hasUnsafeMetachar(trimmed))
252
+ return false;
253
+ const m = /^git\s+commit\b/.exec(trimmed);
254
+ if (!m)
255
+ return false;
256
+ const rest = trimmed.slice(m[0].length);
257
+ const tokens = tokenize(rest);
258
+ if (tokens === null)
259
+ return false;
260
+ let i = 0;
261
+ while (i < tokens.length) {
262
+ const t = tokens[i];
263
+ if (FLAG_ONLY_TOKENS.has(t)) {
264
+ i += 1;
265
+ continue;
266
+ }
267
+ if (MESSAGE_FLAG_TOKENS.has(t)) {
268
+ i += 1;
269
+ if (i >= tokens.length)
270
+ return false; // dangling flag, no message value
271
+ i += 1; // consume the message token (already quote-aware metachar-screened above)
272
+ continue;
273
+ }
274
+ if (/^--message=.+/.test(t)) {
275
+ i += 1;
276
+ continue;
277
+ }
278
+ // Unrecognised token (e.g. --amend, --no-verify, a pathspec, an
279
+ // unknown flag): fail closed.
280
+ return false;
281
+ }
282
+ return true;
283
+ }
284
+ //# sourceMappingURL=recovery-git-commit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-git-commit.js","sourceRoot":"","sources":["../../src/runtime/recovery-git-commit.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,yBAAyB;AACzB,EAAE;AACF,6DAA6D;AAC7D,kEAAkE;AAClE,uEAAuE;AACvE,yEAAyE;AACzE,0EAA0E;AAC1E,0EAA0E;AAC1E,uEAAuE;AACvE,sEAAsE;AACtE,uEAAuE;AACvE,yEAAyE;AACzE,sEAAsE;AACtE,iEAAiE;AACjE,4BAA4B;AAC5B,EAAE;AACF,mEAAmE;AACnE,iEAAiE;AACjE,uEAAuE;AACvE,uEAAuE;AACvE,yEAAyE;AACzE,qEAAqE;AACrE,gEAAgE;AAChE,6DAA6D;AAC7D,gBAAgB;AAChB,qEAAqE;AACrE,2DAA2D;AAC3D,oEAAoE;AACpE,gEAAgE;AAChE,sEAAsE;AACtE,oEAAoE;AACpE,sEAAsE;AACtE,0DAA0D;AAC1D,sEAAsE;AACtE,wEAAwE;AACxE,oEAAoE;AACpE,oEAAoE;AACpE,+CAA+C;AAC/C,8DAA8D;AAC9D,gEAAgE;AAChE,+CAA+C;AAC/C,mEAAmE;AACnE,oEAAoE;AACpE,uEAAuE;AACvE,uEAAuE;AACvE,mEAAmE;AACnE,uEAAuE;AACvE,wEAAwE;AACxE,mEAAmE;AACnE,mDAAmD;AACnD,wEAAwE;AACxE,mEAAmE;AACnE,wEAAwE;AACxE,yEAAyE;AACzE,wEAAwE;AACxE,yEAAyE;AACzE,uEAAuE;AACvE,wEAAwE;AACxE,oEAAoE;AACpE,oEAAoE;AACpE,wEAAwE;AACxE,qEAAqE;AACrE,sEAAsE;AACtE,mCAAmC;AACnC,wEAAwE;AACxE,uEAAuE;AACvE,yEAAyE;AACzE,uEAAuE;AACvE,uEAAuE;AACvE,qEAAqE;AACrE,yEAAyE;AACzE,yEAAyE;AACzE,oEAAoE;AACpE,oEAAoE;AACpE,uEAAuE;AACvE,kEAAkE;AAClE,wEAAwE;AACxE,yEAAyE;AACzE,iCAAiC;AAEjC,0CAA0C;AAC1C,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;AAExF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;AAErF;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,iBAAiB,CAAC,OAAe;IACxC,IAAI,KAAK,GAAqB,IAAI,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;QACvB,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAClB,IAAI,EAAE,KAAK,GAAG;gBAAE,KAAK,GAAG,IAAI,CAAC;YAC7B,SAAS,CAAC,iDAAiD;QAC7D,CAAC;QACD,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAClB,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBACf,KAAK,GAAG,IAAI,CAAC;gBACb,SAAS;YACX,CAAC;YACD,IAAI,EAAE,KAAK,GAAG;gBAAE,OAAO,IAAI,CAAC;YAC5B,IAAI,EAAE,KAAK,GAAG,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG;gBAAE,OAAO,IAAI,CAAC;YACtD,SAAS,CAAC,6CAA6C;QACzD,CAAC;QACD,kDAAkD;QAClD,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAC7B,KAAK,GAAG,EAAE,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACpF,IAAI,EAAE,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAC5B,IAAI,EAAE,KAAK,GAAG,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;IACxD,CAAC;IACD,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,yCAAyC;AAClE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IACtB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC;YAAE,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC;YAAE,MAAM;QAClB,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;YACrC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;YACpB,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;gBACtC,IAAI,KAAK,KAAK,CAAC,CAAC;oBAAE,OAAO,IAAI,CAAC;gBAC9B,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;gBAClC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;gBACd,SAAS;YACX,CAAC;YACD,KAAK,IAAI,EAAE,CAAC;YACZ,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IACjC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACnE,uEAAuE;IACvE,gEAAgE;IAChE,wEAAwE;IACxE,wEAAwE;IACxE,iEAAiE;IACjE,uEAAuE;IACvE,uEAAuE;IACvE,kEAAkE;IAClE,oEAAoE;IACpE,qEAAqE;IACrE,mEAAmE;IACnE,oEAAoE;IACpE,qEAAqE;IACrE,kEAAkE;IAClE,gDAAgD;IAChD,EAAE;IACF,sEAAsE;IACtE,gEAAgE;IAChE,uEAAuE;IACvE,mEAAmE;IACnE,sEAAsE;IACtE,sEAAsE;IACtE,6DAA6D;IAC7D,sEAAsE;IACtE,oEAAoE;IACpE,uEAAuE;IACvE,uEAAuE;IACvE,oEAAoE;IACpE,+CAA+C;IAC/C,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,iBAAiB,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAE7C,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrB,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAElC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACrB,IAAI,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5B,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,CAAC,IAAI,CAAC,CAAC;YACP,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM;gBAAE,OAAO,KAAK,CAAC,CAAC,kCAAkC;YACxE,CAAC,IAAI,CAAC,CAAC,CAAC,0EAA0E;YAClF,SAAS;QACX,CAAC;QACD,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5B,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,gEAAgE;QAChE,8BAA8B;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,3 +1,4 @@
1
+ export declare const SHELL_ALIASES: readonly ["Bash", "shell", "exec_command", "functions.exec_command"];
1
2
  export declare function expandToolNameAliases(toolName: string): string[];
2
3
  export declare function expandCodexHookMatchPattern(match: string): string;
3
4
  export declare function extractShellCommand(event: {
@@ -1,4 +1,10 @@
1
- const SHELL_ALIASES = [
1
+ // Canonical shell-tool alias set: Claude Code's single "Bash" tool plus
2
+ // the Codex shell-tool names current runtimes emit. Exported so callers
3
+ // elsewhere in the layering (e.g. policy-packs/builtin, which may import
4
+ // from runtime/ but not from cli/) can derive their own shell-alias
5
+ // lists from this one definition instead of hand-copying the literal
6
+ // array (task bea04a03 review finding).
7
+ export const SHELL_ALIASES = [
2
8
  "Bash",
3
9
  "shell",
4
10
  "exec_command",
@@ -1 +1 @@
1
- {"version":3,"file":"tool-name-aliases.js","sourceRoot":"","sources":["../../src/runtime/tool-name-aliases.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool-name-aliases.js","sourceRoot":"","sources":["../../src/runtime/tool-name-aliases.ts"],"names":[],"mappings":"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"}