zelari-code 2.46.1 → 2.48.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 +3 -3
- package/dist/cli/automations/browser/cookieDisk.js +56 -0
- package/dist/cli/automations/browser/cookieDisk.js.map +1 -0
- package/dist/cli/automations/browser/pageAdapter.js +130 -0
- package/dist/cli/automations/browser/pageAdapter.js.map +1 -0
- package/dist/cli/automations/browser/selectors.js +178 -0
- package/dist/cli/automations/browser/selectors.js.map +1 -0
- package/dist/cli/automations/browser/session.js +243 -0
- package/dist/cli/automations/browser/session.js.map +1 -0
- package/dist/cli/budget/budgetRuntime.js +9 -13
- package/dist/cli/budget/budgetRuntime.js.map +1 -1
- package/dist/cli/budget/essentialBashConfig.js +118 -0
- package/dist/cli/budget/essentialBashConfig.js.map +1 -0
- package/dist/cli/headless/runOneTurn.js +36 -6
- package/dist/cli/headless/runOneTurn.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +30 -7
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/keyStore.js +2 -0
- package/dist/cli/keyStore.js.map +1 -1
- package/dist/cli/kraken/candidateRegistry.js +13 -0
- package/dist/cli/kraken/candidateRegistry.js.map +1 -1
- package/dist/cli/kraken/executor.js +200 -22
- package/dist/cli/kraken/executor.js.map +1 -1
- package/dist/cli/kraken/narrativeFloor.js +23 -0
- package/dist/cli/kraken/narrativeFloor.js.map +1 -0
- package/dist/cli/kraken/planner.js +27 -0
- package/dist/cli/kraken/planner.js.map +1 -1
- package/dist/cli/kraken/strictWaiver.js +22 -0
- package/dist/cli/kraken/strictWaiver.js.map +1 -0
- package/dist/cli/kraken/unresolvedGate.js +32 -0
- package/dist/cli/kraken/unresolvedGate.js.map +1 -0
- package/dist/cli/kraken/verificationBridge.js +67 -8
- package/dist/cli/kraken/verificationBridge.js.map +1 -1
- package/dist/cli/kraken/verifyHonestVerdict.js +30 -0
- package/dist/cli/kraken/verifyHonestVerdict.js.map +1 -0
- package/dist/cli/kraken/worktreeMergeRollback.js +277 -0
- package/dist/cli/kraken/worktreeMergeRollback.js.map +1 -0
- package/dist/cli/kraken/worktreeScheduling.js +11 -0
- package/dist/cli/kraken/worktreeScheduling.js.map +1 -1
- package/dist/cli/main.bundled.js +3278 -1483
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +1 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/modelDiscovery.js +5 -1
- package/dist/cli/modelDiscovery.js.map +1 -1
- package/dist/cli/museOAuth.js +384 -0
- package/dist/cli/museOAuth.js.map +1 -0
- package/dist/cli/oauthDesktop.js +18 -1
- package/dist/cli/oauthDesktop.js.map +1 -1
- package/dist/cli/provider/openai-compatible.js +1 -0
- package/dist/cli/provider/openai-compatible.js.map +1 -1
- package/dist/cli/provider/resolveStream.js +2 -0
- package/dist/cli/provider/resolveStream.js.map +1 -1
- package/dist/cli/providerConfig.js +2 -0
- package/dist/cli/providerConfig.js.map +1 -1
- package/dist/cli/refreshRegistry.js +6 -0
- package/dist/cli/refreshRegistry.js.map +1 -1
- package/dist/cli/runHeadless.js +184 -100
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/slashCommands.js +6 -6
- package/dist/cli/slashCommands.js.map +1 -1
- package/dist/cli/slashHandlers/krakenGraph.js +25 -7
- package/dist/cli/slashHandlers/krakenGraph.js.map +1 -1
- package/dist/cli/slashHandlers/provider.js +14 -4
- package/dist/cli/slashHandlers/provider.js.map +1 -1
- package/dist/cli/thinking.js +1 -0
- package/dist/cli/thinking.js.map +1 -1
- package/dist/cli/thinkingCapability.js +2 -0
- package/dist/cli/thinkingCapability.js.map +1 -1
- package/dist/cli/toolRegistry.js +22 -3
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/bashWriteWatch.js +195 -0
- package/dist/cli/tools/bashWriteWatch.js.map +1 -0
- package/dist/cli/tools/krakenModel.js +50 -0
- package/dist/cli/tools/krakenModel.js.map +1 -1
- package/dist/cli/tools/krakenRadio.js +50 -5
- package/dist/cli/tools/krakenRadio.js.map +1 -1
- package/dist/cli/tools/krakenWorktree.js +35 -6
- package/dist/cli/tools/krakenWorktree.js.map +1 -1
- package/dist/cli/tools/taskTool.js +328 -34
- package/dist/cli/tools/taskTool.js.map +1 -1
- package/dist/cli/tools/verifyDebtSpine.js +117 -0
- package/dist/cli/tools/verifyDebtSpine.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* automations/browser/session.ts — persistent-profile browser sessions (F3.1).
|
|
3
|
+
*
|
|
4
|
+
* Manual HUMAN login; cookies live under
|
|
5
|
+
* <os.homedir()>/.zelari-code/browser-profiles/<channel>/
|
|
6
|
+
* - openLoginSession: headed window → user logs in → close/timeout → headless confirm.
|
|
7
|
+
* - checkLogin: headless → is this profile currently logged in?
|
|
8
|
+
*
|
|
9
|
+
* Playwright is loaded lazily via the existing browser_check loader, so it stays
|
|
10
|
+
* an OPTIONAL dependency (no static import, no new dep). All access goes through
|
|
11
|
+
* the minimal seams in ./pageAdapter.ts, so the orchestration is unit-testable
|
|
12
|
+
* with a fake browser (tests never launch Chromium). The page/context seams are
|
|
13
|
+
* re-exported here for back-compat with existing importers.
|
|
14
|
+
*/
|
|
15
|
+
import { mkdir } from 'node:fs/promises';
|
|
16
|
+
import { homedir } from 'node:os';
|
|
17
|
+
import path from 'node:path';
|
|
18
|
+
import { loadPlaywright } from '../../browser/driver.js';
|
|
19
|
+
import { probeSessionCookiesOnDisk } from './cookieDisk.js';
|
|
20
|
+
import { isSupportedChannel, loadSelectors, SUPPORTED_CHANNELS } from './selectors.js';
|
|
21
|
+
import { adaptContext, } from './pageAdapter.js';
|
|
22
|
+
export { SELECTOR_TIMEOUT_MS, } from './pageAdapter.js';
|
|
23
|
+
/** Navigation timeout for a login-state check (short on purpose). */
|
|
24
|
+
export const NAV_TIMEOUT_MS = 15_000;
|
|
25
|
+
/** Default window for the manual login before we give up (seconds). */
|
|
26
|
+
export const DEFAULT_LOGIN_TIMEOUT_SEC = 300;
|
|
27
|
+
/** Shown verbatim when Playwright is absent — same UX as the browser_check gate. */
|
|
28
|
+
export const PLAYWRIGHT_UNAVAILABLE_HINT = 'browser automation unavailable — Playwright is not installed in this workspace. ' +
|
|
29
|
+
'Install it with: `zelari-code --plugins-install playwright --cwd .` ' +
|
|
30
|
+
'(or Desktop banner “Install”, or CLI `/plugins install playwright`, or ' +
|
|
31
|
+
'`npm i -D playwright && npx playwright install chromium`).';
|
|
32
|
+
/** `<os.homedir()>/.zelari-code/browser-profiles/<channel>/`. Throws if unknown. */
|
|
33
|
+
export function profileDir(channel) {
|
|
34
|
+
if (!isSupportedChannel(channel)) {
|
|
35
|
+
throw new Error(`unknown social channel: ${channel} (supported: ${SUPPORTED_CHANNELS.join(', ')})`);
|
|
36
|
+
}
|
|
37
|
+
return path.join(homedir(), '.zelari-code', 'browser-profiles', channel);
|
|
38
|
+
}
|
|
39
|
+
const nowIso = () => new Date().toISOString();
|
|
40
|
+
/** True when Playwright resolves in the given tree (never throws). */
|
|
41
|
+
export async function playwrightAvailable(cwd) {
|
|
42
|
+
try {
|
|
43
|
+
return (await loadPlaywright(cwd ?? process.cwd())) !== null;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Default opener: real Playwright persistent context on the channel profile. */
|
|
50
|
+
export const defaultContextOpener = async ({ channel, headless, cwd }) => {
|
|
51
|
+
const pw = (await loadPlaywright(cwd ?? process.cwd()));
|
|
52
|
+
if (!pw?.chromium || typeof pw.chromium.launchPersistentContext !== 'function')
|
|
53
|
+
return null;
|
|
54
|
+
const dir = profileDir(channel);
|
|
55
|
+
await mkdir(dir, { recursive: true });
|
|
56
|
+
// A headed login launched from a background process (Desktop IPC, OS
|
|
57
|
+
// scheduler) can open BEHIND the active window — Windows foreground lock.
|
|
58
|
+
// An explicit on-screen position/size makes the window impossible to miss.
|
|
59
|
+
const launchOpts = headless
|
|
60
|
+
? { headless }
|
|
61
|
+
: { headless, args: ['--window-position=100,80', '--window-size=1180,880'] };
|
|
62
|
+
return adaptContext(await pw.chromium.launchPersistentContext(dir, launchOpts));
|
|
63
|
+
};
|
|
64
|
+
/** First entry of `entries` whose selector is present on `page` (or undefined). */
|
|
65
|
+
async function firstMatch(page, entries) {
|
|
66
|
+
for (const e of entries) {
|
|
67
|
+
if (await page.hasSelector(e.selector))
|
|
68
|
+
return e.label;
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Headless login-state check against the on-disk profile. Returns a
|
|
74
|
+
* HealthReport; a technical failure (Playwright missing, launch/navigation
|
|
75
|
+
* error) THROWS — so "not logged in" is never confused with "could not check".
|
|
76
|
+
*/
|
|
77
|
+
export async function checkLogin(channel, deps = {}) {
|
|
78
|
+
if (!isSupportedChannel(channel)) {
|
|
79
|
+
throw new Error(`unknown social channel: ${channel} (supported: ${SUPPORTED_CHANNELS.join(', ')})`);
|
|
80
|
+
}
|
|
81
|
+
const sel = await loadSelectors(channel);
|
|
82
|
+
const wanted = sel.sessionCookies ?? [];
|
|
83
|
+
// Skip the default disk probe when a test injects `opener` (otherwise we'd
|
|
84
|
+
// read the real user profile). An explicit `diskProbe` always runs first.
|
|
85
|
+
const probe = deps.diskProbe ?? (deps.opener ? undefined : probeSessionCookiesOnDisk);
|
|
86
|
+
if (probe && wanted.length > 0) {
|
|
87
|
+
const disk = await probe(profileDir(channel), wanted);
|
|
88
|
+
if (disk === 'present') {
|
|
89
|
+
return { channel, loggedIn: true, matched: `cookies:disk:${wanted.join('+')}`, checkedAt: nowIso() };
|
|
90
|
+
}
|
|
91
|
+
if (disk === 'locked') {
|
|
92
|
+
// Chromium already has the profile — not logged-out. Don't fight it.
|
|
93
|
+
return { channel, loggedIn: true, matched: 'profile-in-use', checkedAt: nowIso() };
|
|
94
|
+
}
|
|
95
|
+
if (disk === 'missing') {
|
|
96
|
+
return { channel, loggedIn: false, matched: 'cookies:missing-on-disk', checkedAt: nowIso() };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const ctx = await (deps.opener ?? defaultContextOpener)({ channel, headless: true, cwd: deps.cwd });
|
|
100
|
+
if (!ctx)
|
|
101
|
+
throw new Error(PLAYWRIGHT_UNAVAILABLE_HINT);
|
|
102
|
+
try {
|
|
103
|
+
const page = ctx.pages()[0] ?? (await ctx.newPage());
|
|
104
|
+
await page.goto(sel.loginUrl, {
|
|
105
|
+
timeout: deps.navTimeoutMs ?? NAV_TIMEOUT_MS,
|
|
106
|
+
waitUntil: 'domcontentloaded',
|
|
107
|
+
});
|
|
108
|
+
// PRIMARY signal — session cookies (locale-proof, A/B-proof). A profile
|
|
109
|
+
// holding ALL the channel's auth cookies IS logged in, whatever the
|
|
110
|
+
// (translated, shuffled) DOM renders. DOM chains remain the fallback for
|
|
111
|
+
// channels without sessionCookies or contexts without cookie access.
|
|
112
|
+
const wanted = sel.sessionCookies ?? [];
|
|
113
|
+
if (wanted.length > 0 && typeof ctx.cookies === 'function') {
|
|
114
|
+
const names = new Set((await ctx.cookies()).map((c) => c.name));
|
|
115
|
+
if (wanted.every((n) => names.has(n))) {
|
|
116
|
+
return {
|
|
117
|
+
channel,
|
|
118
|
+
loggedIn: true,
|
|
119
|
+
matched: `cookies:${wanted.join('+')}`,
|
|
120
|
+
checkedAt: nowIso(),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const missing = wanted.filter((n) => !names.has(n));
|
|
124
|
+
return {
|
|
125
|
+
channel,
|
|
126
|
+
loggedIn: false,
|
|
127
|
+
matched: `cookies:missing ${missing.join('+')}`,
|
|
128
|
+
checkedAt: nowIso(),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const inHit = await firstMatch(page, sel.loggedIn);
|
|
132
|
+
if (inHit)
|
|
133
|
+
return { channel, loggedIn: true, matched: inHit, checkedAt: nowIso() };
|
|
134
|
+
const outHit = await firstMatch(page, sel.loggedOut);
|
|
135
|
+
return { channel, loggedIn: false, matched: outHit, checkedAt: nowIso() };
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
await ctx.close().catch(() => undefined);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Resolve as soon as the profile gains ALL wanted cookies (login detected —
|
|
143
|
+
* the caller then closes the window), the context closes, or `timeoutMs`
|
|
144
|
+
* elapses — whichever comes first.
|
|
145
|
+
*/
|
|
146
|
+
function waitForLoginCloseOrTimeout(ctx, timeoutMs, loginDetected, pollMs = 2_500) {
|
|
147
|
+
return new Promise((resolve) => {
|
|
148
|
+
let settled = false;
|
|
149
|
+
let timer;
|
|
150
|
+
let poller;
|
|
151
|
+
const done = (r) => {
|
|
152
|
+
if (settled)
|
|
153
|
+
return;
|
|
154
|
+
settled = true;
|
|
155
|
+
if (timer)
|
|
156
|
+
clearTimeout(timer);
|
|
157
|
+
if (poller)
|
|
158
|
+
clearInterval(poller);
|
|
159
|
+
resolve(r);
|
|
160
|
+
};
|
|
161
|
+
timer = setTimeout(() => done('timeout'), timeoutMs);
|
|
162
|
+
ctx.onClose(() => done('closed'));
|
|
163
|
+
poller = setInterval(() => {
|
|
164
|
+
void loginDetected()
|
|
165
|
+
.then((hit) => {
|
|
166
|
+
if (hit)
|
|
167
|
+
done('login');
|
|
168
|
+
})
|
|
169
|
+
.catch(() => undefined);
|
|
170
|
+
}, pollMs);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Open a HEADED window on the persistent profile for a manual login, then
|
|
175
|
+
* confirm headlessly. Returns { ok:false } (never throws) when the window closed
|
|
176
|
+
* without a logged-in state — that is "unproven" (exit 4), not a technical error.
|
|
177
|
+
*/
|
|
178
|
+
export async function openLoginSession(channel, opts = {}) {
|
|
179
|
+
if (!isSupportedChannel(channel)) {
|
|
180
|
+
throw new Error(`unknown social channel: ${channel} (supported: ${SUPPORTED_CHANNELS.join(', ')})`);
|
|
181
|
+
}
|
|
182
|
+
const sel = await loadSelectors(channel);
|
|
183
|
+
const log = opts.log ?? ((line) => process.stdout.write(`${line}\n`));
|
|
184
|
+
const opener = opts.opener ?? defaultContextOpener;
|
|
185
|
+
const timeoutSec = opts.timeoutSec && opts.timeoutSec > 0 ? opts.timeoutSec : DEFAULT_LOGIN_TIMEOUT_SEC;
|
|
186
|
+
const ctx = await opener({ channel, headless: false, cwd: opts.cwd });
|
|
187
|
+
if (!ctx)
|
|
188
|
+
throw new Error(PLAYWRIGHT_UNAVAILABLE_HINT);
|
|
189
|
+
try {
|
|
190
|
+
const page = ctx.pages()[0] ?? (await ctx.newPage());
|
|
191
|
+
log(`Opening ${sel.loginUrl} …`);
|
|
192
|
+
log(`Log in to ${channel} manually, then close the window — or wait up to ${timeoutSec}s. ` +
|
|
193
|
+
`The profile is saved under ${profileDir(channel)}. ` +
|
|
194
|
+
`If you do not see the window, look for Chromium in the taskbar.`);
|
|
195
|
+
try {
|
|
196
|
+
await page.goto(sel.loginUrl, {
|
|
197
|
+
timeout: opts.navTimeoutMs ?? NAV_TIMEOUT_MS,
|
|
198
|
+
waitUntil: 'domcontentloaded',
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
log(`Could not navigate to ${sel.loginUrl} (${err instanceof Error ? err.message : String(err)}) — ` +
|
|
203
|
+
'if the window stays blank, type the address in it manually.');
|
|
204
|
+
}
|
|
205
|
+
// Best-effort foreground: raise the login window above the app that spawned
|
|
206
|
+
// us (e.g. the Desktop Automations tab). Noop on pages without the method.
|
|
207
|
+
if (typeof page.bringToFront === 'function') {
|
|
208
|
+
await page.bringToFront().catch(() => undefined);
|
|
209
|
+
}
|
|
210
|
+
// Poll the profile cookies WHILE the window is open: the moment all the
|
|
211
|
+
// channel's auth cookies land, the login is detected and the window closes
|
|
212
|
+
// itself — no guessing about when the user is done.
|
|
213
|
+
const wanted = sel.sessionCookies ?? [];
|
|
214
|
+
const cookieCheck = async () => {
|
|
215
|
+
if (wanted.length === 0 || typeof ctx.cookies !== 'function')
|
|
216
|
+
return false;
|
|
217
|
+
const names = new Set((await ctx.cookies()).map((c) => c.name));
|
|
218
|
+
return wanted.every((n) => names.has(n));
|
|
219
|
+
};
|
|
220
|
+
const outcome = await waitForLoginCloseOrTimeout(ctx, timeoutSec * 1000, cookieCheck, opts.loginPollMs);
|
|
221
|
+
if (outcome === 'login') {
|
|
222
|
+
log('Login detected (session cookies present) — closing the window…');
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
log(outcome === 'closed' ? 'Window closed — verifying login…' : 'Timed out — verifying login…');
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
await ctx.close().catch(() => undefined);
|
|
230
|
+
}
|
|
231
|
+
const health = await checkLogin(channel, { opener, cwd: opts.cwd, navTimeoutMs: opts.navTimeoutMs });
|
|
232
|
+
if (health.loggedIn)
|
|
233
|
+
return { ok: true, loginUrl: sel.loginUrl, loggedIn: true };
|
|
234
|
+
return {
|
|
235
|
+
ok: false,
|
|
236
|
+
loggedIn: false,
|
|
237
|
+
loginUrl: sel.loginUrl,
|
|
238
|
+
reason: `no logged-in state detected — the profile lacks ${sel.sessionCookies?.join('+') ?? 'a login'}` +
|
|
239
|
+
(health.matched ? ` (${health.matched})` : '') +
|
|
240
|
+
` — re-run \`automation login ${channel}\` and complete the login in the window`,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../../src/cli/automations/browser/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
import { computeBudget, defaultResourcePolicy } from '@zelari/core';
|
|
26
26
|
import { ResourceLedger, rebuildLedgerFromEvents } from './resourceLedger.js';
|
|
27
|
+
import { loadEssentialBashPatterns } from './essentialBashConfig.js';
|
|
27
28
|
import { buildResourceSnapshot, shouldEmitSnapshot, withResourceSnapshotContext, } from './resourceSnapshot.js';
|
|
28
29
|
/**
|
|
29
30
|
* §11.3 verification-essential tools: test/typecheck/build/diff/read
|
|
@@ -46,17 +47,6 @@ const DEFAULT_ESSENTIAL_TOOLS = [
|
|
|
46
47
|
const ADVISORY_NOTICE = 'Resource advisory: verification reserve reached. Prioritize test/typecheck/build/diff and targeted repair; avoid broad exploration or delegation.';
|
|
47
48
|
const PROTECTED_DENIAL = 'Resource protected: remaining tool calls are reserved for verification and targeted repair. Run the required checks (test/typecheck/build), read the failure, apply a minimal fix, retest — or report BLOCKED with the evidence you have.';
|
|
48
49
|
const HARD_LIMIT_DENIAL = 'Resource exhausted: this turn\'s execution budget (maxToolCalls) is spent. No further billable tool calls are allowed in this turn — summarize what was verified and report BLOCKED/resource-exhausted with the evidence already collected. A later user turn starts a fresh execution budget.';
|
|
49
|
-
/** bash commands that count as verification-essential (plan §13). */
|
|
50
|
-
const ESSENTIAL_BASH = [
|
|
51
|
-
/\b(npm|pnpm|yarn|bun)\s+(run\s+)?(test|vitest|jest)\b/,
|
|
52
|
-
/\b(npm|pnpm|yarn|bun)\s+run\s+[\w:-]*(typecheck|lint|build)\b/,
|
|
53
|
-
/\bnpx\s+(vitest|tsc|typescript|eslint)\b/,
|
|
54
|
-
/\b(npx\s+)?tsc\b/,
|
|
55
|
-
/\bvitest\b/,
|
|
56
|
-
/\bjest\b/,
|
|
57
|
-
/\bnode\s+--run\b/,
|
|
58
|
-
/\bgit\s+(diff|status|log|show)\b/,
|
|
59
|
-
];
|
|
60
50
|
/** Phase selector — advisory by default (§11.4), protected via env (Phase 3). */
|
|
61
51
|
export function resolveResourceEnforcement(env = process.env) {
|
|
62
52
|
return env.ZELARI_RESOURCE_ENFORCEMENT === 'protected' ? 'protected' : 'advisory';
|
|
@@ -77,13 +67,19 @@ function bashCommand(args) {
|
|
|
77
67
|
* Essential = test/typecheck/build/lint, git diff/status, targeted
|
|
78
68
|
* read/grep/repair. NOT essential = arbitrary bash, repo-wide speculative
|
|
79
69
|
* grep, dependency install, delegation.
|
|
70
|
+
*
|
|
71
|
+
* K2.5 (F21): the bash matchers are now the built-in set ∪ repo-configured
|
|
72
|
+
* extras (`.zelari/zelari.config.json` → `essentialBash`) ∪ declared
|
|
73
|
+
* package.json scripts (`<pm> run <script>`), so cargo/pytest/mvn repos can
|
|
74
|
+
* run their own verification commands in protected mode. `root` defaults to
|
|
75
|
+
* the process cwd (the CLI project root) — see loadEssentialBashPatterns.
|
|
80
76
|
*/
|
|
81
|
-
export function isVerificationEssential(toolName, args, _stage = 'implement') {
|
|
77
|
+
export function isVerificationEssential(toolName, args, _stage = 'implement', root = process.cwd()) {
|
|
82
78
|
if (toolName === 'bash') {
|
|
83
79
|
const cmd = bashCommand(args);
|
|
84
80
|
if (!cmd)
|
|
85
81
|
return false;
|
|
86
|
-
return
|
|
82
|
+
return loadEssentialBashPatterns(root).some((re) => re.test(cmd));
|
|
87
83
|
}
|
|
88
84
|
if (toolName === 'grep_content') {
|
|
89
85
|
// Targeted grep: bounded by an explicit path/pattern scope is essential;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budgetRuntime.js","sourceRoot":"","sources":["../../../src/cli/budget/budgetRuntime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAA2C,MAAM,cAAc,CAAC;AAE7G,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAElB,2BAA2B,GAC5B,MAAM,uBAAuB,CAAC;AAI/B;;;;;GAKG;AACH,MAAM,uBAAuB,GAAsB;IACjD,WAAW;IACX,MAAM;IACN,YAAY;IACZ,4EAA4E;IAC5E,2EAA2E;IAC3E,WAAW;IACX,YAAY;IACZ,cAAc;IACd,YAAY;IACZ,WAAW;CACZ,CAAC;AAEF,MAAM,eAAe,GACnB,mJAAmJ,CAAC;AAEtJ,MAAM,gBAAgB,GACpB,2OAA2O,CAAC;AAE9O,MAAM,iBAAiB,GACrB,gSAAgS,CAAC;AAEnS,
|
|
1
|
+
{"version":3,"file":"budgetRuntime.js","sourceRoot":"","sources":["../../../src/cli/budget/budgetRuntime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAA2C,MAAM,cAAc,CAAC;AAE7G,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAElB,2BAA2B,GAC5B,MAAM,uBAAuB,CAAC;AAI/B;;;;;GAKG;AACH,MAAM,uBAAuB,GAAsB;IACjD,WAAW;IACX,MAAM;IACN,YAAY;IACZ,4EAA4E;IAC5E,2EAA2E;IAC3E,WAAW;IACX,YAAY;IACZ,cAAc;IACd,YAAY;IACZ,WAAW;CACZ,CAAC;AAEF,MAAM,eAAe,GACnB,mJAAmJ,CAAC;AAEtJ,MAAM,gBAAgB,GACpB,2OAA2O,CAAC;AAE9O,MAAM,iBAAiB,GACrB,gSAAgS,CAAC;AAEnS,iFAAiF;AACjF,MAAM,UAAU,0BAA0B,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7E,OAAO,GAAG,CAAC,2BAA2B,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC;AACpF,CAAC;AAED,oEAAoE;AACpE,SAAS,WAAW,CAAC,IAAa;IAChC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACjD,MAAM,GAAG,GAAG,IAA+B,CAAC;IAC5C,KAAK,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC/C,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,GAAG,CAAW,CAAC;IAC9D,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAAgB,EAChB,IAAa,EACb,SAAwB,WAAW,EACnC,OAAe,OAAO,CAAC,GAAG,EAAE;IAE5B,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG;YAAE,OAAO,KAAK,CAAC;QACvB,OAAO,yBAAyB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;QAChC,yEAAyE;QACzE,yEAAyE;QACzE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACnD,MAAM,GAAG,GAAG,IAA+B,CAAC;QAC5C,MAAM,QAAQ,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC;QACvF,OAAO,QAAQ,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC;IACrD,CAAC;IACD,OAAO,uBAAuB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACpD,CAAC;AAsCD,MAAM,OAAO,aAAa;IACf,MAAM,CAAiB;IACvB,WAAW,CAAsB;IACzB,MAAM,CAAiB;IACvB,SAAS,CAAsB;IAC/B,YAAY,CAAgB;IACrC,KAAK,CAAgB;IACrB,KAAK,GAAG,CAAC,CAAC;IACV,iBAAiB,GAAG,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;IACnE,WAAW,CAA2B;IACtC,kBAAkB,GAAG,KAAK,CAAC;IAEnC,YAAY,SAAiB,EAAE,OAA6B,EAAE;QAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,qBAAqB,CAAC,SAAS,CAAC,CAAC;QACnE,2EAA2E;QAC3E,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC5E,IAAI,CAAC,MAAM;YACT,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;QAChG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,UAAU,CAAC;QAClD,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,cAAc,IAAI,uBAAuB,CAAC,CAAC;QACzE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,IAAI,WAAW,CAAC;QAC9C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;IACrC,CAAC;IAED;;;OAGG;IACH,SAAS;QACP,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7C,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC;QAC/B,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;QAChC,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+DAA+D;IAC/D,YAAY;QACV,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,eAAe;QACb,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,IAAI,SAAS,GAA0B,IAAI,CAAC;QAC5C,MAAM,IAAI,GAAG;YACX,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,aAAa;YACxB,KAAK,EAAE,IAAI,CAAC,cAAc;YAC1B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;SAChD,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,kBAAkB,IAAI,CAAC,EAAE,CAAC;YAC7D,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;YAC/B,SAAS,GAAG,EAAE,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,CAAC;QACvD,CAAC;aAAM,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;YAC5B,SAAS,GAAG,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;QACjD,CAAC;QACD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACvG,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACjC,CAAC;IAED,4EAA4E;IAC5E,qBAAqB;QACnB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,0BAA0B;IAC1B,eAAe;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,+DAA+D;IAC/D,QAAQ,CAAC,KAAoB;QAC3B,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACtC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC;IAED,+DAA+D;IAC/D,cAAc;QACZ,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACvC,OAAO,aAAa,CAClB,IAAI,CAAC,MAAM,EACX;YACE,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC;YAC3F,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;YACzE,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC;SACnF,EACD,IAAI,CAAC,KAAK,CACX,CAAC;IACJ,CAAC;IAED,2CAA2C;IAC3C,OAAO;QACL,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACvC,OAAO,2BAA2B,CAAC,qBAAqB,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;YAC5F,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,oBAAoB,EAAE,UAAU,CAAC,aAAa;SAC/C,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,eAA2C;QACtD,MAAM,KAAK,GACT,OAAO,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC;QACxF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAChC,iEAAiE;QACjE,8DAA8D;QAC9D,IAAI,QAAQ,CAAC,kBAAkB,IAAI,CAAC,EAAE,CAAC;YACrC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACnG,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,gBAAgB;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;QACpF,IAAI,IAAI,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;YACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC;QAC9E,CAAC;QACD,MAAM,SAAS,GACb,KAAK,CAAC,QAAQ,KAAK,MAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,cAAc;YAC5D,CAAC,CAAC,uBAAuB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;YAChF,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC;QAC9E,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC;IACjF,CAAC;IAED,2EAA2E;IAC3E,qBAAqB,CAAC,MAAuC;QAC3D,MAAM,OAAO,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxC,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC;QACpB,IAAI,iBAAiB,GAAG,CAAC,CAAC,CAAC;QAC3B,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;YACzB,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc;gBAAE,iBAAiB,GAAG,CAAC,CAAC;YACzD,IAAI,KAAK,CAAC,IAAI,KAAK,wBAAwB,EAAE,CAAC;gBAC5C,UAAU,GAAG,CAAC,CAAC;gBACf,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;gBAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,aAAa,EAAE,CAAC;oBAClF,aAAa,GAAG,KAAK,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,WAAW,GAAG,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,iBAAiB,CAAC;QACrE,IAAI,CAAC,iBAAiB;YACpB,WAAW,IAAI,CAAC;gBACd,CAAC,CAAC,uBAAuB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE;gBACnE,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;QACrD,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,kBAAkB,GAAG,GAAG,CAAC,kBAAkB,IAAI,CAAC,CAAC;IACxD,CAAC;IAED,sEAAsE;IACtE,aAAa;QACX,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAEO,SAAS;QACf,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,IAAI,kBAAkB,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* essentialBashConfig — extensible verification-essential bash classifier
|
|
3
|
+
* (plan K2.5, hardening F21).
|
|
4
|
+
*
|
|
5
|
+
* `isVerificationEssential` (budgetRuntime.ts) originally recognised only a
|
|
6
|
+
* hardcoded npm/tsc/vitest/git set, so a protected-mode run on a
|
|
7
|
+
* cargo/pytest/mvn repo could not execute its own verification commands — a
|
|
8
|
+
* forced BLOCKED. This module loads EXTRA matchers and merges them with the
|
|
9
|
+
* built-in list:
|
|
10
|
+
*
|
|
11
|
+
* 1. built-ins (BUILTIN_ESSENTIAL_BASH, plan §13) — always present;
|
|
12
|
+
* 2. `<root>/.zelari/zelari.config.json` → top-level `essentialBash` (an
|
|
13
|
+
* array of RegExp SOURCE strings). This is the project settings file
|
|
14
|
+
* userSettings.ts documents (`SETTINGS_FILE_NAME`); the key is read
|
|
15
|
+
* directly here because it only feeds the budget classifier;
|
|
16
|
+
* 3. `<root>/package.json` `scripts` — any `<pm> run <script>` whose
|
|
17
|
+
* `<script>` is declared is essential (repo-native verification entry
|
|
18
|
+
* points, e.g. a `native-test` script that shells out to cargo/pytest).
|
|
19
|
+
*
|
|
20
|
+
* Fail-open by contract: a missing/unreadable/corrupt config contributes
|
|
21
|
+
* nothing; an invalid user RegExp is IGNORED (warned once) and never breaks
|
|
22
|
+
* the built-in list. Loading is lazy + cached per resolved root; tests reset
|
|
23
|
+
* the cache with resetEssentialBashCache().
|
|
24
|
+
*/
|
|
25
|
+
import { readFileSync } from 'node:fs';
|
|
26
|
+
import path from 'node:path';
|
|
27
|
+
import { SETTINGS_FILE_NAME } from '../userSettings.js';
|
|
28
|
+
/** bash commands that count as verification-essential out of the box (plan §13). */
|
|
29
|
+
export const BUILTIN_ESSENTIAL_BASH = [
|
|
30
|
+
/\b(npm|pnpm|yarn|bun)\s+(run\s+)?(test|vitest|jest)\b/,
|
|
31
|
+
/\b(npm|pnpm|yarn|bun)\s+run\s+[\w:-]*(typecheck|lint|build)\b/,
|
|
32
|
+
/\bnpx\s+(vitest|tsc|typescript|eslint)\b/,
|
|
33
|
+
/\b(npx\s+)?tsc\b/,
|
|
34
|
+
/\bvitest\b/,
|
|
35
|
+
/\bjest\b/,
|
|
36
|
+
/\bnode\s+--run\b/,
|
|
37
|
+
/\bgit\s+(diff|status|log|show)\b/,
|
|
38
|
+
];
|
|
39
|
+
const PACKAGE_MANAGERS = 'npm|pnpm|yarn|bun';
|
|
40
|
+
/** Per-resolved-root memo of the merged list (never keyed by relative path). */
|
|
41
|
+
const cache = new Map();
|
|
42
|
+
let warnedInvalidRegex = false;
|
|
43
|
+
/** Drop the memo (tests, or a config edit mid-process). */
|
|
44
|
+
export function resetEssentialBashCache() {
|
|
45
|
+
cache.clear();
|
|
46
|
+
warnedInvalidRegex = false;
|
|
47
|
+
}
|
|
48
|
+
/** Best-effort JSON object read; absent/unreadable/corrupt → null (fail-open). */
|
|
49
|
+
function readJsonObject(file) {
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
52
|
+
return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
53
|
+
? parsed
|
|
54
|
+
: null;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** RegExp-source strings from `<root>/.zelari/zelari.config.json` (project scope). */
|
|
61
|
+
function settingsExtraSources(root) {
|
|
62
|
+
const settings = readJsonObject(path.join(root, '.zelari', SETTINGS_FILE_NAME));
|
|
63
|
+
const raw = settings?.['essentialBash'];
|
|
64
|
+
if (!Array.isArray(raw))
|
|
65
|
+
return [];
|
|
66
|
+
return raw.filter((v) => typeof v === 'string' && v.trim() !== '');
|
|
67
|
+
}
|
|
68
|
+
/** Compile user RegExp sources; an invalid one is ignored (warned once). */
|
|
69
|
+
function compileUserSources(sources) {
|
|
70
|
+
const out = [];
|
|
71
|
+
for (const source of sources) {
|
|
72
|
+
try {
|
|
73
|
+
out.push(new RegExp(source));
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
if (!warnedInvalidRegex) {
|
|
77
|
+
warnedInvalidRegex = true;
|
|
78
|
+
console.warn(`[essential-bash] ignoring invalid regex in ${SETTINGS_FILE_NAME}.essentialBash: ${JSON.stringify(source)}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
function escapeRegExp(literal) {
|
|
85
|
+
return literal.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
86
|
+
}
|
|
87
|
+
/** `<pm> run <script>` matchers for every declared package.json script. */
|
|
88
|
+
function scriptPatterns(root) {
|
|
89
|
+
const pkg = readJsonObject(path.join(root, 'package.json'));
|
|
90
|
+
const scripts = pkg?.['scripts'];
|
|
91
|
+
if (scripts === null || typeof scripts !== 'object' || Array.isArray(scripts))
|
|
92
|
+
return [];
|
|
93
|
+
const out = [];
|
|
94
|
+
for (const [name, body] of Object.entries(scripts)) {
|
|
95
|
+
if (typeof body !== 'string' || body === '')
|
|
96
|
+
continue;
|
|
97
|
+
out.push(new RegExp(`\\b(${PACKAGE_MANAGERS})\\s+run\\s+${escapeRegExp(name)}\\b`));
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Merged essential-bash matchers for `root`: built-ins ∪ settings extras ∪
|
|
103
|
+
* package.json scripts. Lazy + cached per resolved root. Never throws.
|
|
104
|
+
*/
|
|
105
|
+
export function loadEssentialBashPatterns(root = process.cwd()) {
|
|
106
|
+
const key = path.resolve(root);
|
|
107
|
+
const cached = cache.get(key);
|
|
108
|
+
if (cached)
|
|
109
|
+
return cached;
|
|
110
|
+
const merged = [
|
|
111
|
+
...BUILTIN_ESSENTIAL_BASH,
|
|
112
|
+
...compileUserSources(settingsExtraSources(key)),
|
|
113
|
+
...scriptPatterns(key),
|
|
114
|
+
];
|
|
115
|
+
cache.set(key, merged);
|
|
116
|
+
return merged;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=essentialBashConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"essentialBashConfig.js","sourceRoot":"","sources":["../../../src/cli/budget/essentialBashConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,8 +34,10 @@ import { createStreamScrubber } from '../utils/streamScrub.js';
|
|
|
34
34
|
import { promises as fs } from 'node:fs';
|
|
35
35
|
import path from 'node:path';
|
|
36
36
|
import { evaluateStrictBuildGate, repairExcerptsFromEvaluation, strictEnvOverlay, strictGateEventPayload, strictGateExitCode, STRICT_DONE_EXIT_CODE, strictDoneEnabled } from '../kraken/verificationBridge.js';
|
|
37
|
+
import { honestUnevaluatedPayload } from '../kraken/verifyHonestVerdict.js';
|
|
37
38
|
// t78 (ADR-0033 slice): runtime general⇒verify obligation on the task tool path.
|
|
38
|
-
import { outcomeMemoryAllowed, taskVerifyObligation } from '../tools/taskTool.js';
|
|
39
|
+
import { hydrateTaskVerifyDebtFromSpine, outcomeMemoryAllowed, taskVerifyObligation } from '../tools/taskTool.js';
|
|
40
|
+
import { bindVerifyDebtSpineEmit, flushVerifyDebtSpine, formatHeadlessVerifyDebtNotice } from '../tools/verifyDebtSpine.js';
|
|
39
41
|
import { writeCompletionProofDetailed } from '../kraken/completionProof.js';
|
|
40
42
|
import { enforceRequiredProofPersistence } from '../kraken/completionProofPersist.js';
|
|
41
43
|
import { promoteOpsKnowledgeSafe, skippedOpsKnowledgeResult } from '../memory/opsKnowledge.js';
|
|
@@ -312,6 +314,17 @@ export async function runOneTurn(opts, provider, model, providerStream, extras)
|
|
|
312
314
|
// 2.6.1 (plan §7): deep specs from THIS run’s registry.
|
|
313
315
|
toolSpecs: typeof toolRegistry.fingerprints === 'function' ? toolRegistry.fingerprints() : undefined,
|
|
314
316
|
});
|
|
317
|
+
// K1.5 / F5: bind debt emit to this turn's spine, then merge un-cleared
|
|
318
|
+
// opens from the log (do not wipe — callers/tests may have seeded debt).
|
|
319
|
+
bindVerifyDebtSpineEmit(async (input) => ({ seq: await spine.appendEvent(input) }));
|
|
320
|
+
// Fresh sessions have no prior debt; only `--resume` must replay the log
|
|
321
|
+
// (and must not race the just-opened writer on win32).
|
|
322
|
+
if (opts.resumeSessionId) {
|
|
323
|
+
await hydrateTaskVerifyDebtFromSpine({
|
|
324
|
+
sessionsDir: spine.spine.sessionsDir,
|
|
325
|
+
sessionId: spine.sessionId,
|
|
326
|
+
}).catch(() => 0);
|
|
327
|
+
}
|
|
315
328
|
// W2: bind the memory telemetry sink to the now-open spine.
|
|
316
329
|
spineHolder.current = spine;
|
|
317
330
|
// T4-S3: drain pre-bind buffered memory events (cap 32) onto the spine.
|
|
@@ -717,7 +730,10 @@ export async function runOneTurn(opts, provider, model, providerStream, extras)
|
|
|
717
730
|
// payload and as its own spine event. Never fails the parent run.
|
|
718
731
|
await runAdvisoryVerifierReview(strictGate, verifierReviewDeps).catch(() => undefined);
|
|
719
732
|
const gate = strictGate.gate;
|
|
720
|
-
|
|
733
|
+
// K1.7: strict-off evaluations are UNEVALUATED, never a silent/fake PASS.
|
|
734
|
+
const verificationPayload = strictGate.strict
|
|
735
|
+
? strictGateEventPayload(strictGate)
|
|
736
|
+
: honestUnevaluatedPayload('kraken');
|
|
721
737
|
spine.verificationRun(verificationPayload);
|
|
722
738
|
if (opts.output === 'json') {
|
|
723
739
|
emitEvent({ type: 'verification_run', ...verificationPayload });
|
|
@@ -758,7 +774,9 @@ export async function runOneTurn(opts, provider, model, providerStream, extras)
|
|
|
758
774
|
};
|
|
759
775
|
const after = await evaluateStrictBuildGate('build', { emit: async (input) => ({ seq: await spine.appendEvent(input) }), cwd, env: strictEnv });
|
|
760
776
|
await runAdvisoryVerifierReview(after, verifierReviewDeps).catch(() => undefined);
|
|
761
|
-
const afterPayload =
|
|
777
|
+
const afterPayload = after.strict
|
|
778
|
+
? strictGateEventPayload(after)
|
|
779
|
+
: honestUnevaluatedPayload('kraken');
|
|
762
780
|
spine.verificationRun(afterPayload);
|
|
763
781
|
if (opts.output === 'json') {
|
|
764
782
|
emitEvent({ type: 'verification_run', ...afterPayload });
|
|
@@ -781,11 +799,25 @@ export async function runOneTurn(opts, provider, model, providerStream, extras)
|
|
|
781
799
|
}
|
|
782
800
|
}
|
|
783
801
|
}
|
|
802
|
+
else if (pass.finalReason === 'completed' &&
|
|
803
|
+
pass.exitCode === 0 &&
|
|
804
|
+
isKrakenMode(opts.mode) &&
|
|
805
|
+
!planModeFromOpts(opts)) {
|
|
806
|
+
// K1.7: no selection/pack → the gate above never ran. Silence would be
|
|
807
|
+
// indistinguishable from "never verified" on --resume / TUI replay.
|
|
808
|
+
const honest = honestUnevaluatedPayload('kraken');
|
|
809
|
+
spine.verificationRun(honest);
|
|
810
|
+
if (opts.output === 'json') {
|
|
811
|
+
emitEvent({ type: 'verification_run', ...honest });
|
|
812
|
+
}
|
|
813
|
+
}
|
|
784
814
|
// t78 (ADR-0033 slice): a `task agent=general` that finished this turn
|
|
785
815
|
// without a passing verify — the tool's auto-spawned verify reported FAIL
|
|
786
816
|
// after the rework budget, produced no parseable verdict, or could not run —
|
|
787
817
|
// must NOT close as success. Strict done is blocked ⇒ dedicated exit code.
|
|
788
818
|
// `ZELARI_STRICT_DONE=0` remains the only opt-out (no new env flag).
|
|
819
|
+
await flushVerifyDebtSpine();
|
|
820
|
+
bindVerifyDebtSpineEmit(undefined);
|
|
789
821
|
const verifyDebt = taskVerifyObligation();
|
|
790
822
|
if (strictExit === 0 &&
|
|
791
823
|
pass.finalReason === 'completed' &&
|
|
@@ -795,9 +827,7 @@ export async function runOneTurn(opts, provider, model, providerStream, extras)
|
|
|
795
827
|
verifyDebt !== null &&
|
|
796
828
|
strictDoneEnabled('kraken', strictEnv)) {
|
|
797
829
|
strictExit = STRICT_DONE_EXIT_CODE;
|
|
798
|
-
const debtMsg =
|
|
799
|
-
`passing verify — strict done blocked (exit ${STRICT_DONE_EXIT_CODE}): ` +
|
|
800
|
-
`${verifyDebt.detail ?? 'unverified work'}`;
|
|
830
|
+
const debtMsg = formatHeadlessVerifyDebtNotice(verifyDebt, STRICT_DONE_EXIT_CODE);
|
|
801
831
|
if (opts.output === 'json')
|
|
802
832
|
emitEvent({ type: 'log', message: debtMsg });
|
|
803
833
|
else
|