@kenkaiiii/ggcoder 5.44.3 → 5.46.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 (56) hide show
  1. package/README.md +3 -1
  2. package/assets/skills/durable/SKILL.md +111 -0
  3. package/assets/skills/durable/references/backups-and-runtime.md +86 -0
  4. package/assets/skills/durable/references/migrations-and-schema.md +79 -0
  5. package/assets/skills/lean/SKILL.md +110 -0
  6. package/assets/skills/lean/references/memory-and-processes.md +97 -0
  7. package/assets/skills/lean/references/playbooks.md +107 -0
  8. package/dist/core/agent-session-verification-gate.test.d.ts +2 -0
  9. package/dist/core/agent-session-verification-gate.test.d.ts.map +1 -0
  10. package/dist/core/agent-session-verification-gate.test.js +135 -0
  11. package/dist/core/agent-session-verification-gate.test.js.map +1 -0
  12. package/dist/core/agent-session.d.ts +2 -0
  13. package/dist/core/agent-session.d.ts.map +1 -1
  14. package/dist/core/agent-session.js +41 -0
  15. package/dist/core/agent-session.js.map +1 -1
  16. package/dist/core/process-manager-wake.test.d.ts +2 -0
  17. package/dist/core/process-manager-wake.test.d.ts.map +1 -0
  18. package/dist/core/process-manager-wake.test.js +96 -0
  19. package/dist/core/process-manager-wake.test.js.map +1 -0
  20. package/dist/core/process-manager.d.ts +39 -1
  21. package/dist/core/process-manager.d.ts.map +1 -1
  22. package/dist/core/process-manager.js +146 -2
  23. package/dist/core/process-manager.js.map +1 -1
  24. package/dist/core/settings-manager.d.ts +1 -0
  25. package/dist/core/settings-manager.d.ts.map +1 -1
  26. package/dist/core/settings-manager.js +5 -0
  27. package/dist/core/settings-manager.js.map +1 -1
  28. package/dist/core/skills.js +1 -1
  29. package/dist/core/skills.js.map +1 -1
  30. package/dist/core/verification-gate.d.ts +55 -0
  31. package/dist/core/verification-gate.d.ts.map +1 -0
  32. package/dist/core/verification-gate.js +188 -0
  33. package/dist/core/verification-gate.js.map +1 -0
  34. package/dist/core/verification-gate.test.d.ts +2 -0
  35. package/dist/core/verification-gate.test.d.ts.map +1 -0
  36. package/dist/core/verification-gate.test.js +102 -0
  37. package/dist/core/verification-gate.test.js.map +1 -0
  38. package/dist/tools/bash.d.ts +4 -0
  39. package/dist/tools/bash.d.ts.map +1 -1
  40. package/dist/tools/bash.js +57 -3
  41. package/dist/tools/bash.js.map +1 -1
  42. package/dist/tools/bash.test.js +37 -0
  43. package/dist/tools/bash.test.js.map +1 -1
  44. package/dist/tools/read-only-bash.d.ts +6 -0
  45. package/dist/tools/read-only-bash.d.ts.map +1 -1
  46. package/dist/tools/read-only-bash.js +168 -9
  47. package/dist/tools/read-only-bash.js.map +1 -1
  48. package/dist/tools/read-only-bash.test.js +49 -0
  49. package/dist/tools/read-only-bash.test.js.map +1 -1
  50. package/dist/tools/skill.js +1 -0
  51. package/dist/tools/skill.js.map +1 -1
  52. package/dist/ui/App.d.ts +3 -0
  53. package/dist/ui/App.d.ts.map +1 -1
  54. package/dist/ui/App.js +35 -1
  55. package/dist/ui/App.js.map +1 -1
  56. package/package.json +4 -4
@@ -5,6 +5,12 @@
5
5
  * blocked), false positives are not (a mutating command would slip through).
6
6
  * Plan mode gates bash on `isReadOnlyCommand`; anything this function cannot
7
7
  * prove is read-only falls back to the existing plan-mode block.
8
+ *
9
+ * A command-name allowlist alone is not proof: several allowlisted utilities
10
+ * mutate through flags (`git branch -D`, `find -delete`, `date -s`,
11
+ * `sort -o file`), take create-shaped operands (`git tag v1`), or execute
12
+ * repo-configured code (`git diff --ext-diff`). Each carries a per-flag
13
+ * policy below.
8
14
  */
9
15
  /** Read-only utilities allowed as the leading command word of every segment. */
10
16
  const READ_ONLY_COMMANDS = new Set([
@@ -48,7 +54,9 @@ const READ_ONLY_COMMANDS = new Set([
48
54
  "readlink",
49
55
  "jq",
50
56
  "yq",
51
- "awk",
57
+ // No awk: its `system()` built-in is arbitrary shell execution and cannot
58
+ // be screened by flags. Deny-by-default costs a blocked read-only call at
59
+ // worst; allowing it costs plan mode running `rm`.
52
60
  ]);
53
61
  /** Read-only git subcommands. Everything else (commit, push, …) is rejected. */
54
62
  const READ_ONLY_GIT_SUBCOMMANDS = new Set([
@@ -99,9 +107,74 @@ function leadingWord(segment) {
99
107
  function tokens(segment) {
100
108
  return segment.split(/\s+/).filter((token) => token.length > 0);
101
109
  }
110
+ /** True if any token equals `flag` or is `flag=value`. */
111
+ function hasFlag(parts, ...flags) {
112
+ return parts.some((part) => flags.some((flag) => part === flag || part.startsWith(`${flag}=`)));
113
+ }
114
+ /** Non-flag tokens of `parts`. */
115
+ function positionals(parts) {
116
+ return parts.filter((part) => !part.startsWith("-"));
117
+ }
118
+ /**
119
+ * True if any token is a cluster of short flags containing one of `letters`
120
+ * (`-df` = `-d -f`; GNU getopt and git parse-options both accept clusters, so
121
+ * exact-token flag checks alone can be bypassed with `sort -ro`, `date -su`,
122
+ * `git branch -df`). Long flags (`--…`) never match: two leading dashes fail
123
+ * the letter run.
124
+ */
125
+ function hasClusteredShortFlag(parts, letters) {
126
+ return parts.some((part) => {
127
+ const match = /^-([a-zA-Z]+)\d*$/.exec(part);
128
+ return match !== null && [...match[1]].some((ch) => letters.has(ch));
129
+ });
130
+ }
131
+ // --- git subcommand flag policies -------------------------------------------
132
+ /** Listing flags that make `git branch`/`git tag` operands filters rather
133
+ * than create/delete targets. Without one, a positional operand creates. */
134
+ const GIT_LIST_FLAGS = ["--list", "-l"];
135
+ /** Short-flag letters that make `git branch` mutate or execute (d/D delete, m/M
136
+ * move, c/C copy, f force, u upstream). `a`/`v` listing letters excluded. */
137
+ const GIT_BRANCH_DANGEROUS_LETTERS = new Set(["d", "D", "m", "M", "c", "C", "f", "u"]);
138
+ /** Same for `git tag` (d/D delete, f force, a annotate, s sign, u local-user,
139
+ * m message, e edit). `n`/`l` listing letters excluded. */
140
+ const GIT_TAG_DANGEROUS_LETTERS = new Set(["d", "D", "f", "a", "s", "u", "m", "e"]);
141
+ function isReadOnlyGitBranch(rest) {
142
+ if (hasFlag(rest, "-d", "-D", "--delete", "-m", "-M", "--move", "-c", "-C", "--copy", "-f", "--force", "-u", "--set-upstream-to", "--unset-upstream", "--edit-description") ||
143
+ hasClusteredShortFlag(rest, GIT_BRANCH_DANGEROUS_LETTERS)) {
144
+ return false;
145
+ }
146
+ return positionals(rest).length === 0 || hasFlag(rest, ...GIT_LIST_FLAGS);
147
+ }
148
+ function isReadOnlyGitTag(rest) {
149
+ if (hasFlag(rest, "-d", "--delete", "-f", "--force", "-a", "--annotate", "-s", "--sign", "-u", "--local-user", "-m", "--message", "-e", "--edit") ||
150
+ hasClusteredShortFlag(rest, GIT_TAG_DANGEROUS_LETTERS)) {
151
+ return false;
152
+ }
153
+ return positionals(rest).length === 0 || hasFlag(rest, ...GIT_LIST_FLAGS);
154
+ }
155
+ function isReadOnlyGitRemote(rest) {
156
+ const operands = positionals(rest);
157
+ if (operands.length === 0)
158
+ return true; // bare `git remote [-v]` lists
159
+ const sub = operands[0];
160
+ if (sub === "get-url")
161
+ return true;
162
+ // `git remote show` contacts the remote (network, askpass helpers);
163
+ // read-only only with --no-query.
164
+ if (sub === "show")
165
+ return hasFlag(rest, "-n", "--no-query");
166
+ return false; // add, rename, remove, set-url, set-head, prune, update …
167
+ }
168
+ function isReadOnlyGitReflog(rest) {
169
+ // `expire` and `delete` rewrite reflog history.
170
+ const sub = positionals(rest)[0];
171
+ return sub !== "expire" && sub !== "delete";
172
+ }
102
173
  function isReadOnlyGit(segment) {
103
174
  const parts = tokens(segment);
104
- // parts[0] === "git"; find the first non-flag token as the subcommand.
175
+ // parts[0] === "git"; find the first non-flag token as the subcommand. A
176
+ // global flag with a value (`git -C /tmp branch`) puts the value here and
177
+ // denies — fail-closed, and `-C` escapes the workspace anyway.
105
178
  let subcommand = "";
106
179
  for (let i = 1; i < parts.length; i += 1) {
107
180
  const part = parts[i];
@@ -112,17 +185,102 @@ function isReadOnlyGit(segment) {
112
185
  }
113
186
  if (!READ_ONLY_GIT_SUBCOMMANDS.has(subcommand))
114
187
  return false;
115
- // `git config` is read-only only with --get (or --list / --get-all).
188
+ const rest = parts.slice(parts.indexOf(subcommand) + 1);
116
189
  if (subcommand === "config") {
117
- const hasReadFlag = parts.some((part) => part === "--get" || part === "--get-all" || part === "--list" || part === "-l");
118
- return hasReadFlag;
190
+ // `git config` is read-only only with --get (or --list / --get-all).
191
+ return hasFlag(rest, "--get", "--get-all", "--list", "-l");
192
+ }
193
+ // log/show/diff can execute repo-configured external diff/textconv
194
+ // drivers. The --no- forms (which disable them) stay allowed: exact match.
195
+ if (subcommand === "log" || subcommand === "show" || subcommand === "diff") {
196
+ if (rest.includes("--ext-diff") || rest.includes("--textconv"))
197
+ return false;
119
198
  }
199
+ if (subcommand === "branch")
200
+ return isReadOnlyGitBranch(rest);
201
+ if (subcommand === "tag")
202
+ return isReadOnlyGitTag(rest);
203
+ if (subcommand === "remote")
204
+ return isReadOnlyGitRemote(rest);
205
+ if (subcommand === "reflog")
206
+ return isReadOnlyGitReflog(rest);
120
207
  return true;
121
208
  }
209
+ /**
210
+ * sed script text that could execute a command or write a file: GNU's `e`
211
+ * command (`e cmd`, `1e`, `/re/e`, `{ e ...`), the `s///...e` exec flag, or
212
+ * the `w`/`W` write commands. Applied to ALL candidate script text - every
213
+ * non-flag token joined plus long-flag `=values` - so quoting or splitting a
214
+ * script across whitespace cannot hide the command from it. False positives
215
+ * (a filename shaped like `1e`) merely block a read-only call.
216
+ */
217
+ function sedScriptUnsafe(text) {
218
+ // `e`/`w`/`W` at a command position: script start, after `;` `{` `}`/`)`, or
219
+ // directly after an address (`1e`, `$e`, `/re/e`, `2w out`).
220
+ if (/(^|[\s;{}()])([0-9,$~/\\][^\s;{}]*)?[ewW](\s|$|\\)/.test(text))
221
+ return true;
222
+ // Exec flag on a substitution, any delimiter: `s/x/y/e`, `s#x#y#ge`.
223
+ if (/s(.).*\1[0-9A-Za-z]*e/.test(text))
224
+ return true;
225
+ return false;
226
+ }
122
227
  function isReadOnlySed(segment) {
123
- // sed is read-only only when it does not edit in place.
124
- const parts = tokens(segment);
125
- return !parts.some((part) => part === "-i" || part === "--in-place" || part.startsWith("--in-place="));
228
+ const rest = tokens(segment).slice(1);
229
+ // In-place edit (`-i`, `-i.bak`, `--in-place`) or a script read from a file
230
+ // (`-f`, `--file`) - the file's contents cannot be inspected here.
231
+ if (rest.some((part) => part.startsWith("-i") ||
232
+ part.startsWith("--in-place") ||
233
+ part.startsWith("-f") ||
234
+ part.startsWith("--file"))) {
235
+ return false;
236
+ }
237
+ // A short-flag cluster longer than two characters carries an attached value
238
+ // that cannot be attributed (`-es/a/b/`, `-i.bak`, even the pure `-nE`);
239
+ // only single-letter flags pass. Long `--flags` are words, not clusters.
240
+ if (rest.some((part) => /^-[a-zA-Z]./.test(part)))
241
+ return false;
242
+ // Fail closed on compound scripts: `;`/`{`/`}` chain commands across token
243
+ // boundaries (`sed 's/a/b/; e x' f`), so compound scripts are never provably
244
+ // read-only here.
245
+ const scriptText = rest
246
+ .filter((part) => !part.startsWith("-"))
247
+ .map((part) => part.replace(/^['"]|['"]$/g, ""))
248
+ .join(" ");
249
+ const flagValues = rest
250
+ .filter((part) => part.startsWith("--") && part.includes("="))
251
+ .map((part) => part.slice(part.indexOf("=") + 1).replace(/^['"]|['"]$/g, ""))
252
+ .join(" ");
253
+ const all = `${scriptText} ${flagValues}`;
254
+ if (/;|\{|\}/.test(all))
255
+ return false;
256
+ return !sedScriptUnsafe(all);
257
+ }
258
+ // --- plain-utility flag policies --------------------------------------------
259
+ function isReadOnlyUtility(command, parts) {
260
+ const rest = parts.slice(1);
261
+ switch (command) {
262
+ case "date":
263
+ // `-s`/`--set` sets the system clock, also when clustered (`-su`).
264
+ return !hasFlag(rest, "-s", "--set") && !hasClusteredShortFlag(rest, new Set(["s"]));
265
+ case "find":
266
+ // -exec/-ok (and their -dir variants) run arbitrary commands; the rest
267
+ // write files.
268
+ return !rest.some((part) => part === "-delete" ||
269
+ part.startsWith("-exec") ||
270
+ part.startsWith("-ok") ||
271
+ part.startsWith("-fprint") ||
272
+ part === "-fls");
273
+ case "sort":
274
+ // `-o` writes a file, also when clustered (`-ro`).
275
+ return !hasFlag(rest, "-o", "--output") && !hasClusteredShortFlag(rest, new Set(["o"]));
276
+ case "tree":
277
+ return !hasFlag(rest, "-o", "--output-file") && !hasClusteredShortFlag(rest, new Set(["o"]));
278
+ case "yq":
279
+ // -i edits in place; --split-exp/-s write one file per document.
280
+ return !hasFlag(rest, "-i", "--in-place", "-s", "--split-exp");
281
+ default:
282
+ return true;
283
+ }
126
284
  }
127
285
  export function hasUnsafeShellSyntax(segment) {
128
286
  return DANGEROUS_TOKENS.some((token) => segment.includes(token)) || /&\s*$/.test(segment);
@@ -131,12 +289,13 @@ function isReadOnlySegment(segment) {
131
289
  // Keep shell-syntax policy shared with semantic verification classification.
132
290
  if (hasUnsafeShellSyntax(segment))
133
291
  return false;
292
+ const parts = tokens(segment);
134
293
  const command = leadingWord(segment);
135
294
  if (command === "git")
136
295
  return isReadOnlyGit(segment);
137
296
  if (command === "sed")
138
297
  return isReadOnlySed(segment);
139
- return READ_ONLY_COMMANDS.has(command);
298
+ return READ_ONLY_COMMANDS.has(command) && isReadOnlyUtility(command, parts);
140
299
  }
141
300
  /**
142
301
  * Returns true only when every segment of the command is provably read-only.
@@ -1 +1 @@
1
- {"version":3,"file":"read-only-bash.js","sourceRoot":"","sources":["../../src/tools/read-only-bash.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"read-only-bash.js","sourceRoot":"","sources":["../../src/tools/read-only-bash.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,23 @@ describe("isReadOnlyCommand", () => {
15
15
  ["echo", "echo hi"],
16
16
  ["multi read pipe", "git log | head -20 | wc -l"],
17
17
  ["rg search", "rg -n pattern src"],
18
+ ["git branch list", "git branch -a"],
19
+ ["git branch list pattern", "git branch --list feat-*"],
20
+ ["git tag list", "git tag -l"],
21
+ ["git remote verbose", "git remote -v"],
22
+ ["git remote get-url", "git remote get-url origin"],
23
+ ["git remote show no-query", "git remote show -n origin"],
24
+ ["git reflog", "git reflog -5"],
25
+ ["find by name", "find . -name '*.ts' -maxdepth 2"],
26
+ ["date read", "date"],
27
+ ["date format read", "date '+%Y-%m-%d'"],
28
+ ["sort read", "sort file.txt"],
29
+ ["tree read", "tree src"],
30
+ ["yq read", "yq '.a.b' config.yaml"],
31
+ ["git log no-ext-diff", "git log --no-ext-diff"],
32
+ ["git branch cluster listing", "git branch -av"],
33
+ ["sort key read", "sort -k2,2 file.txt"],
34
+ ["git tag numeric list", "git tag -n5"],
18
35
  ];
19
36
  const blocked = [
20
37
  ["rm", "rm -rf x"],
@@ -36,6 +53,38 @@ describe("isReadOnlyCommand", () => {
36
53
  ["empty", ""],
37
54
  ["unknown command", "mytool --do-stuff"],
38
55
  ["awk write", "awk '{print > \"out\"}' f"],
56
+ ["awk exec", "awk 'BEGIN { system(\"rm -rf x\") }' f"],
57
+ ["git branch delete", "git branch -D main"],
58
+ ["git branch move", "git branch -m old new"],
59
+ ["git branch create", "git branch feature-x"],
60
+ ["git tag delete", "git tag -d v1"],
61
+ ["git tag create", "git tag v1.0"],
62
+ ["git remote set-url", "git remote set-url origin https://evil.example"],
63
+ ["git remote add", "git remote add upstream ../x"],
64
+ ["git remote show queries", "git remote show origin"],
65
+ ["git reflog expire", "git reflog expire --expire=now --all"],
66
+ ["git diff ext-diff", "git diff --ext-diff"],
67
+ ["git show textconv", "git show --textconv HEAD"],
68
+ ["date set clock", "date -s '12:00:00'"],
69
+ ["find delete", "find . -name '*.ts' -delete"],
70
+ ["find exec", "find . -type f -exec rm {} +"],
71
+ ["find fprint", "find . -fprintf /tmp/x '%p'"],
72
+ ["sort output file", "sort -o out.txt in.txt"],
73
+ ["tree output file", "tree -o tree.txt"],
74
+ ["yq in place", "yq -i '.a = 1' config.yaml"],
75
+ ["yq split", "yq '.[]' -s 'doc-~.yaml' in.yaml"],
76
+ ["sed exec command", "sed '1e date' f"],
77
+ ["sed exec flag", "sed 's/x/y/e' f"],
78
+ ["sed compound exec", "sed 's/a/b/; e touch /tmp/pwn' f"],
79
+ ["sed expression flag exec", "sed --expression='e date' f"],
80
+ ["sed e as next token", "sed -e 'e date' f"],
81
+ ["sed script from file", "sed -f transform.sed input.txt"],
82
+ ["sed in-place with backup suffix", "sed -i.bak s/a/b/ f"],
83
+ ["sed write command", "sed '2w /tmp/out' f"],
84
+ ["sed attached value flag", "sed -es/a/b/ f"],
85
+ ["git branch cluster delete", "git branch -df main"],
86
+ ["sort cluster output", "sort -ro out.txt in.txt"],
87
+ ["date cluster set", "date -su 12:00"],
39
88
  ];
40
89
  it.each(allowed)("allows %s", (_label, command) => {
41
90
  expect(isReadOnlyCommand(command)).toBe(true);
@@ -1 +1 @@
1
- {"version":3,"file":"read-only-bash.test.js","sourceRoot":"","sources":["../../src/tools/read-only-bash.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,MAAM,OAAO,GAAoC;QAC/C,CAAC,YAAY,EAAE,YAAY,CAAC;QAC5B,CAAC,iBAAiB,EAAE,sBAAsB,CAAC;QAC3C,CAAC,YAAY,EAAE,eAAe,CAAC;QAC/B,CAAC,YAAY,EAAE,gBAAgB,CAAC;QAChC,CAAC,kBAAkB,EAAE,6BAA6B,CAAC;QACnD,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;QACvC,CAAC,YAAY,EAAE,YAAY,CAAC;QAC5B,CAAC,UAAU,EAAE,iBAAiB,CAAC;QAC/B,CAAC,gBAAgB,EAAE,4BAA4B,CAAC;QAChD,CAAC,IAAI,EAAE,QAAQ,CAAC;QAChB,CAAC,MAAM,EAAE,SAAS,CAAC;QACnB,CAAC,iBAAiB,EAAE,4BAA4B,CAAC;QACjD,CAAC,WAAW,EAAE,mBAAmB,CAAC;KACnC,CAAC;IAEF,MAAM,OAAO,GAAoC;QAC/C,CAAC,IAAI,EAAE,UAAU,CAAC;QAClB,CAAC,gBAAgB,EAAE,aAAa,CAAC;QACjC,CAAC,iBAAiB,EAAE,cAAc,CAAC;QACnC,CAAC,YAAY,EAAE,eAAe,CAAC;QAC/B,CAAC,YAAY,EAAE,iBAAiB,CAAC;QACjC,CAAC,UAAU,EAAE,sBAAsB,CAAC;QACpC,CAAC,cAAc,EAAE,mBAAmB,CAAC;QACrC,CAAC,gBAAgB,EAAE,0BAA0B,CAAC;QAC9C,CAAC,cAAc,EAAE,iBAAiB,CAAC;QACnC,CAAC,MAAM,EAAE,gBAAgB,CAAC;QAC1B,CAAC,YAAY,EAAE,eAAe,CAAC;QAC/B,CAAC,sBAAsB,EAAE,4BAA4B,CAAC;QACtD,CAAC,uBAAuB,EAAE,eAAe,CAAC;QAC1C,CAAC,sBAAsB,EAAE,kBAAkB,CAAC;QAC5C,CAAC,YAAY,EAAE,WAAW,CAAC;QAC3B,CAAC,OAAO,EAAE,mBAAmB,CAAC;QAC9B,CAAC,OAAO,EAAE,EAAE,CAAC;QACb,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;QACxC,CAAC,WAAW,EAAE,2BAA2B,CAAC;KAC3C,CAAC;IAEF,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QAChD,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QAChD,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"read-only-bash.test.js","sourceRoot":"","sources":["../../src/tools/read-only-bash.test.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,7 @@ function generateSkillDescription(skills) {
38
38
  .join("\n");
39
39
  return (`Invoke a skill by name to get specialized instructions for a task. ` +
40
40
  `Before acting, invoke a skill when the request matches its scope and respect explicit exclusions. ` +
41
+ `Invoke as soon as the work enters a skill's scope — while building or when checking — not only for reviews. ` +
41
42
  `Match the work rather than the topic, skip it for routine or narrow changes, and do not re-invoke a skill already loaded in this conversation.\n\n` +
42
43
  `Available skills:\n${list}`);
43
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/tools/skill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAC7D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;CACpF,CAAC,CAAC;AAEH,MAAM,UAAU,eAAe,CAAC,MAAe;IAC7C,uEAAuE;IACvE,qEAAqE;IACrE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvE,OAAO;QACL,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,wBAAwB,CAAC,MAAM,CAAC;QAC7C,UAAU;QACV,KAAK,CAAC,OAAO,CAAC,KAAK;YACjB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;YACtD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvD,OAAO,iBAAiB,KAAK,CAAC,KAAK,kCAAkC,SAAS,IAAI,MAAM,EAAE,CAAC;YAC7F,CAAC;YAED,MAAM,KAAK,GAAG,CAAC,wBAAwB,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;YACvD,IAAI,KAAK,CAAC,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,yBAAyB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAClE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;YAC9C,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,mBAAmB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC9C,CAAC;YACD,KAAK,CAAC,IAAI,CACR,yLAAyL,CAC1L,CAAC;YACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,MAAe;IAC/C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,4DAA4D,CAAC;IACtE,CAAC;IAED,MAAM,IAAI,GAAG,MAAM;SAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,WAAW,IAAI,gBAAgB,EAAE,CAAC;SACnE,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,CACL,qEAAqE;QACrE,oGAAoG;QACpG,oJAAoJ;QACpJ,sBAAsB,IAAI,EAAE,CAC7B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/tools/skill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAC7D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;CACpF,CAAC,CAAC;AAEH,MAAM,UAAU,eAAe,CAAC,MAAe;IAC7C,uEAAuE;IACvE,qEAAqE;IACrE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvE,OAAO;QACL,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,wBAAwB,CAAC,MAAM,CAAC;QAC7C,UAAU;QACV,KAAK,CAAC,OAAO,CAAC,KAAK;YACjB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;YACtD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvD,OAAO,iBAAiB,KAAK,CAAC,KAAK,kCAAkC,SAAS,IAAI,MAAM,EAAE,CAAC;YAC7F,CAAC;YAED,MAAM,KAAK,GAAG,CAAC,wBAAwB,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;YACvD,IAAI,KAAK,CAAC,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,yBAAyB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAClE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;YAC9C,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,mBAAmB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC9C,CAAC;YACD,KAAK,CAAC,IAAI,CACR,yLAAyL,CAC1L,CAAC;YACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,MAAe;IAC/C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,4DAA4D,CAAC;IACtE,CAAC;IAED,MAAM,IAAI,GAAG,MAAM;SAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,WAAW,IAAI,gBAAgB,EAAE,CAAC;SACnE,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,CACL,qEAAqE;QACrE,oGAAoG;QACpG,8GAA8G;QAC9G,oJAAoJ;QACpJ,sBAAsB,IAAI,EAAE,CAC7B,CAAC;AACJ,CAAC"}
package/dist/ui/App.d.ts CHANGED
@@ -36,6 +36,8 @@ export interface AppProps {
36
36
  version: string;
37
37
  showTokenUsage?: boolean;
38
38
  idealReviewEnabled?: boolean;
39
+ /** Kill switch for the pre-stop verification gate (default on). */
40
+ verificationGateEnabled?: boolean;
39
41
  onSlashCommand?: (input: string) => Promise<string | null>;
40
42
  loggedInProviders?: Provider[];
41
43
  credentialsByProvider?: Record<string, {
@@ -165,6 +167,7 @@ export interface AppProps {
165
167
  planMode?: boolean;
166
168
  sessionStats?: SessionStats;
167
169
  idealReviewEnabled?: boolean;
170
+ verificationGateEnabled?: boolean;
168
171
  };
169
172
  }
170
173
  export declare function App(props: AppProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"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"}
package/dist/ui/App.js CHANGED
@@ -14,6 +14,7 @@ import {} from "@kenkaiiii/gg-ai";
14
14
  import { downscaleForPreview, extractMediaPaths } from "../utils/image.js";
15
15
  import { buildSubAgentCompletionFollowUp, } from "../core/subagent-manager.js";
16
16
  import { buildProcessCompletionFollowUp } from "../core/process-gate.js";
17
+ import { VerificationGate, isCodeFilePath, isVerificationCommand, } from "../core/verification-gate.js";
17
18
  import { useAgentLoop } from "./hooks/useAgentLoop.js";
18
19
  import { useTranscriptHistory } from "./hooks/useTranscriptHistory.js";
19
20
  import { createWebSearchTool } from "../tools/web-search.js";
@@ -253,6 +254,9 @@ export function App(props) {
253
254
  createSessionStats({ sessionId: props.sessionStore?.sessionId ?? props.sessionId }));
254
255
  const [idealReviewEnabled, setIdealReviewEnabled] = useState(props.sessionStore?.idealReviewEnabled ?? props.idealReviewEnabled ?? true);
255
256
  const idealReviewEnabledRef = useRef(idealReviewEnabled);
257
+ /** Pre-stop verification gate: code edited this run, nothing proved it since. */
258
+ const verificationGateRef = useRef(new VerificationGate());
259
+ const verificationGateEnabledRef = useRef(props.sessionStore?.verificationGateEnabled ?? props.verificationGateEnabled ?? true);
256
260
  /**
257
261
  * Languages whose style packs are currently injected into the system prompt.
258
262
  * Grown by `maybeInjectLanguagePacks` after `write`/`bash` tool results when
@@ -929,7 +933,28 @@ export function App(props) {
929
933
  return next;
930
934
  });
931
935
  }, []),
932
- onToolEnd: useCallback((toolCallId, name, result, isError, durationMs, details) => {
936
+ onToolEnd: useCallback((toolCallId, name, result, isError, durationMs, details, args) => {
937
+ // Verification-gate bookkeeping, mirroring AgentSession.trackHookEvent:
938
+ // successful code mutations vs completed foreground verification runs.
939
+ if (!isError && args) {
940
+ const filePath = String(args.file_path ?? "");
941
+ if ((name === "edit" || name === "write") && isCodeFilePath(filePath)) {
942
+ verificationGateRef.current.recordMutation(filePath);
943
+ }
944
+ if (name === "bash" &&
945
+ !args.run_in_background &&
946
+ isVerificationCommand(String(args.command ?? ""))) {
947
+ verificationGateRef.current.recordVerification();
948
+ }
949
+ // Reading the final output of an EXITED background verification run
950
+ // counts as verification — mirrors AgentSession.trackHookEvent.
951
+ if (name === "task_output") {
952
+ const proc = props.processManager?.list().find((p) => p.id === args.id);
953
+ if (proc && proc.exitCode !== null && isVerificationCommand(proc.command)) {
954
+ verificationGateRef.current.recordVerification();
955
+ }
956
+ }
957
+ }
933
958
  recordToolEnd(sessionStatsRef.current, name, isError, durationMs);
934
959
  setLiveToolFeed((prev) => prev.map((entry) => entry.id === toolCallId
935
960
  ? { ...entry, status: "done", isError, result, details }
@@ -1339,12 +1364,21 @@ export function App(props) {
1339
1364
  if (gate.runStartedAt !== runStartedAt) {
1340
1365
  gate.runStartedAt = runStartedAt;
1341
1366
  gate.injected = 0;
1367
+ verificationGateRef.current.reset();
1342
1368
  }
1343
1369
  const processFollowUp = buildProcessCompletionFollowUp(props.processManager?.list() ?? [], runStartedAt, gate.injected);
1344
1370
  if (processFollowUp) {
1345
1371
  gate.injected += 1;
1346
1372
  return processFollowUp;
1347
1373
  }
1374
+ // Verification gate: code was edited but no test/typecheck/lint/build
1375
+ // completed since the last edit — block "done" until it runs (or the
1376
+ // budget escalates to an honest unverified statement).
1377
+ if (verificationGateEnabledRef.current) {
1378
+ const verificationFollowUp = verificationGateRef.current.followUp();
1379
+ if (verificationFollowUp)
1380
+ return verificationFollowUp;
1381
+ }
1348
1382
  const steps = planStepsRef.current;
1349
1383
  if (steps.length === 0 || !approvedPlanPathRef.current)
1350
1384
  return null;