iterate-plugin 3.5.6 → 3.6.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/README.md +64 -20
- package/README.zh-CN.md +53 -17
- package/dist/approval-gate.js +143 -23
- package/dist/atomic-fs.js +148 -17
- package/dist/config-loader.js +509 -34
- package/dist/config-write.js +83 -22
- package/dist/evidence.js +141 -87
- package/dist/file-lock.js +165 -0
- package/dist/index.js +54 -28
- package/dist/jobs.js +56 -11
- package/dist/live.js +52 -13
- package/dist/meta-review.js +132 -28
- package/dist/method-scope.js +31 -8
- package/dist/review-scope.js +32 -9
- package/dist/review.js +96 -17
- package/dist/session-hooks.js +55 -13
- package/dist/skill-prompt.js +417 -67
- package/dist/tools/checkpoint.js +85 -19
- package/dist/tools/config.js +44 -2
- package/dist/tools/context.js +22 -5
- package/dist/tools/decision-log.js +122 -27
- package/dist/tools/defense-events.js +90 -31
- package/dist/tools/defense-store.js +28 -3
- package/dist/tools/experience-bank.js +108 -43
- package/dist/tools/experience-store.js +54 -4
- package/dist/tools/fix.js +347 -119
- package/dist/tools/history.js +68 -14
- package/dist/tools/present.js +80 -0
- package/dist/tools/prune.js +156 -53
- package/dist/tools/quality-gate.js +52 -2
- package/dist/tools/quality-store.js +17 -1
- package/dist/tools/review.js +158 -7
- package/dist/tools/transcript.js +173 -36
- package/dist/tools/triage.js +67 -12
- package/dist/tools/validate.js +115 -24
- package/dist/transcript.js +267 -4
- package/lib/client.js +945 -181
- package/lib/parse.js +760 -57
- package/package.json +15 -12
- package/src/approval-gate.ts +160 -23
- package/src/atomic-fs.ts +152 -17
- package/src/client/index.ts +600 -129
- package/src/config-loader.ts +542 -35
- package/src/config-write.ts +108 -26
- package/src/evidence.ts +194 -92
- package/src/file-lock.ts +184 -0
- package/src/index.ts +53 -29
- package/src/jobs.ts +63 -12
- package/src/live.ts +48 -11
- package/src/meta-review.ts +151 -34
- package/src/method-scope.ts +31 -8
- package/src/review-scope.ts +33 -10
- package/src/review.ts +96 -17
- package/src/session-hooks.ts +54 -12
- package/src/skill-prompt.ts +417 -67
- package/src/tools/checkpoint.ts +81 -19
- package/src/tools/config.ts +44 -2
- package/src/tools/context.ts +25 -5
- package/src/tools/decision-log.ts +127 -22
- package/src/tools/defense-events.ts +87 -31
- package/src/tools/defense-store.ts +30 -3
- package/src/tools/experience-bank.ts +112 -44
- package/src/tools/experience-store.ts +54 -5
- package/src/tools/fix.ts +258 -20
- package/src/tools/history.ts +74 -15
- package/src/tools/present.ts +89 -0
- package/src/tools/prune.ts +160 -51
- package/src/tools/quality-gate.ts +57 -2
- package/src/tools/quality-store.ts +18 -1
- package/src/tools/review.ts +155 -6
- package/src/tools/transcript.ts +178 -36
- package/src/tools/triage.ts +70 -13
- package/src/tools/validate.ts +138 -32
- package/src/transcript.ts +279 -4
- package/src/types.ts +29 -1
package/src/session-hooks.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Wires the {@link decideApproval} policy gate to dsh's `tools/pre-execute`
|
|
5
5
|
* waterfall. This is the AUTHORITATIVE approval seam for destructive iterate
|
|
6
|
-
* tools (`iterate_fix` / `iterate_rollback` / `iterate_prune` with dryRun:false
|
|
6
|
+
* tools (`iterate_fix` / `iterate_rollback` / `iterate_prune` with dryRun:false
|
|
7
|
+
* / `iterate_config` with operation:"write"):
|
|
7
8
|
*
|
|
8
9
|
* - `allow` policy → the call runs.
|
|
9
10
|
* - `deny` policy → the call is refused (fail-closed), surfaced as an
|
|
@@ -13,11 +14,19 @@
|
|
|
13
14
|
* plus the human-readable reason) so durable
|
|
14
15
|
* projections can route it distinctly from a normal
|
|
15
16
|
* tool failure.
|
|
16
|
-
* - `ask` policy → return `{ kind: 'ask', reason }`;
|
|
17
|
-
* scheduler routes it through the
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* on the
|
|
17
|
+
* - `ask` policy → return `{ kind: 'ask', reason, displayReason }`;
|
|
18
|
+
* dsh's own scheduler routes it through the
|
|
19
|
+
* `approval` service (see
|
|
20
|
+
* `@deepseek-ai/dsh-user-approval`), which prompts
|
|
21
|
+
* the human and audits an approve/deny pair on the
|
|
22
|
+
* session. `reason` is the audited English summary;
|
|
23
|
+
* `displayReason` (dsh 0.2.x) is the localized
|
|
24
|
+
* prompt text. LANGUAGE RULE: human-facing text
|
|
25
|
+
* follows the project `language` (zh|en); every
|
|
26
|
+
* structured/durable field (deny reason,
|
|
27
|
+
* `info.reason`, decision-log entries, console
|
|
28
|
+
* logs) stays English so machine matchers never
|
|
29
|
+
* depend on a locale.
|
|
21
30
|
* - canceled → if the caller aborted the invocation before
|
|
22
31
|
* dispatch, return `{ kind: 'cancel' }` (the
|
|
23
32
|
* canonical 0.1.6-alpha.1 cancellation result) so a
|
|
@@ -31,7 +40,15 @@
|
|
|
31
40
|
*
|
|
32
41
|
* Safety properties:
|
|
33
42
|
* - Read-only tools and non-iterate tools are always allowed (the gate only
|
|
34
|
-
* inspects the
|
|
43
|
+
* inspects the four gated iterate toolnames, and of those only prune
|
|
44
|
+
* `dryRun:false` and `iterate_config` `operation:"write"` — a config read
|
|
45
|
+
* or a dry-run prune short-circuits to allow inside the policy gate).
|
|
46
|
+
* - The approval policy is read from the SESSION workspace whenever a
|
|
47
|
+
* session cwd is known — the model-controlled `path` argument can never
|
|
48
|
+
* choose where the human's policy comes from (it is only consulted when
|
|
49
|
+
* there is no session cwd at all). Otherwise `path:` could point at an
|
|
50
|
+
* `approval: allow` directory to self-grant, or dodge a `deny` in the
|
|
51
|
+
* workspace.
|
|
35
52
|
* - If the project root / observatory config cannot be resolved, the policy
|
|
36
53
|
* degrades to `ask` (fail-safe: destructive writes always require consent).
|
|
37
54
|
*/
|
|
@@ -81,8 +98,14 @@ export function gateDecision(exec: ToolExecution): PreToolDecision {
|
|
|
81
98
|
return { kind: 'cancel' }
|
|
82
99
|
}
|
|
83
100
|
|
|
84
|
-
// Resolve the project root
|
|
85
|
-
//
|
|
101
|
+
// Resolve the project root whose observatory policy governs this call.
|
|
102
|
+
// SECURITY: the policy source must NOT be model-controlled. `path` is a
|
|
103
|
+
// model argument, so reading the policy from the path-resolved root let a
|
|
104
|
+
// call point `path:` at a directory with `approval: allow` (self-grant) or
|
|
105
|
+
// dodge a human's `deny` in the session workspace. When the session cwd is
|
|
106
|
+
// known, the SESSION workspace's config is authoritative and `path` is
|
|
107
|
+
// ignored; the path-resolved root is only the fallback when there is no
|
|
108
|
+
// session cwd at all (headless/tests). The `ask` default stays fail-closed.
|
|
86
109
|
let argPath: string | undefined
|
|
87
110
|
let sessionCwd: string | undefined
|
|
88
111
|
try {
|
|
@@ -95,17 +118,25 @@ export function gateDecision(exec: ToolExecution): PreToolDecision {
|
|
|
95
118
|
} catch {
|
|
96
119
|
// hostile/proxied exec — fall through with both undefined (defaults to ask)
|
|
97
120
|
}
|
|
98
|
-
|
|
121
|
+
// Passing sessionCwd as BOTH the input and the anchor makes the root the
|
|
122
|
+
// session cwd itself (no server-cwd fallback can sneak in), anchored there.
|
|
123
|
+
const resolved = sessionCwd
|
|
124
|
+
? resolveProjectRoot(sessionCwd, sessionCwd)
|
|
125
|
+
: resolveProjectRoot(argPath, sessionCwd)
|
|
99
126
|
let policy: 'ask' | 'deny' | 'allow' = 'ask'
|
|
127
|
+
// Project language for the HUMAN-FACING ask prompt only (see the header's
|
|
128
|
+
// language rule: structured deny/audit text stays English).
|
|
129
|
+
let language: 'zh' | 'en' = 'en'
|
|
100
130
|
if (resolved.ok) {
|
|
101
131
|
const { config } = loadEffectiveConfig(resolved.root)
|
|
102
132
|
const p = config.observatory?.approval
|
|
103
133
|
if (p === 'deny') policy = 'deny'
|
|
104
134
|
else if (p === 'allow') policy = 'allow'
|
|
105
135
|
// anything else (including a corrupt/missing `ask`) → 'ask'
|
|
136
|
+
if (config.language === 'zh') language = 'zh'
|
|
106
137
|
}
|
|
107
138
|
|
|
108
|
-
const decision = decideApproval(exec, policy)
|
|
139
|
+
const decision = decideApproval(exec, policy, language)
|
|
109
140
|
if (decision.kind === 'deny') {
|
|
110
141
|
return {
|
|
111
142
|
kind: 'deny',
|
|
@@ -114,11 +145,19 @@ export function gateDecision(exec: ToolExecution): PreToolDecision {
|
|
|
114
145
|
...DENY_INFO,
|
|
115
146
|
// ToolErrorInfo.reason (0.1.6-alpha.1): raw user-facing detail kept in
|
|
116
147
|
// durable state; the model-facing text still only sees `reason` above.
|
|
148
|
+
// Deliberately the ENGLISH structured reason, never the localized
|
|
149
|
+
// prompt — durable projections must match on a stable string.
|
|
117
150
|
reason: decision.reason,
|
|
118
151
|
},
|
|
119
152
|
}
|
|
120
153
|
}
|
|
121
|
-
|
|
154
|
+
// dsh 0.2.x: `displayReason` is the localized prompt text (en + the
|
|
155
|
+
// configured locale); `reason` stays the audited English summary. Both are
|
|
156
|
+
// forwarded so the approval UI can show the full localized explanation
|
|
157
|
+
// (including the WARNING line for gate-disabling config writes).
|
|
158
|
+
if (decision.kind === 'ask') {
|
|
159
|
+
return { kind: 'ask', reason: decision.reason, displayReason: decision.displayReason }
|
|
160
|
+
}
|
|
122
161
|
return { kind: 'allow' }
|
|
123
162
|
}
|
|
124
163
|
|
|
@@ -139,6 +178,9 @@ export function registerSessionHooks(ctx: Context): void {
|
|
|
139
178
|
return Promise.resolve({
|
|
140
179
|
kind: 'ask',
|
|
141
180
|
reason: 'iterate approval gate unavailable — require consent',
|
|
181
|
+
// Fail-safe path: no config was read, so the localized prompt falls
|
|
182
|
+
// back to English (displayReason requires at least an `en` entry).
|
|
183
|
+
displayReason: { en: 'iterate approval gate unavailable — require consent' },
|
|
142
184
|
})
|
|
143
185
|
}
|
|
144
186
|
if (decision.kind === 'ask') {
|