@vyuhlabs/dxkit 2.12.0 → 2.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +90 -0
- package/README.md +246 -287
- package/dist/allowlist/hint.d.ts +1 -1
- package/dist/allowlist/hint.d.ts.map +1 -1
- package/dist/allowlist/hint.js +6 -3
- package/dist/allowlist/hint.js.map +1 -1
- package/dist/baseline/check.d.ts +7 -0
- package/dist/baseline/check.d.ts.map +1 -1
- package/dist/baseline/check.js +3 -1
- package/dist/baseline/check.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +101 -14
- package/dist/cli.js.map +1 -1
- package/dist/dashboard/graph-tab.d.ts.map +1 -1
- package/dist/dashboard/graph-tab.js +6 -3
- package/dist/dashboard/graph-tab.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +13 -12
- package/dist/doctor.js.map +1 -1
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +8 -2
- package/dist/generator.js.map +1 -1
- package/dist/issue-cli.d.ts +1 -1
- package/dist/issue-cli.js +1 -1
- package/dist/loop/demo.d.ts +12 -0
- package/dist/loop/demo.d.ts.map +1 -0
- package/dist/loop/demo.js +331 -0
- package/dist/loop/demo.js.map +1 -0
- package/dist/loop/doctor.d.ts +37 -0
- package/dist/loop/doctor.d.ts.map +1 -0
- package/dist/loop/doctor.js +320 -0
- package/dist/loop/doctor.js.map +1 -0
- package/dist/loop/ledger-cli.d.ts +7 -0
- package/dist/loop/ledger-cli.d.ts.map +1 -0
- package/dist/loop/ledger-cli.js +95 -0
- package/dist/loop/ledger-cli.js.map +1 -0
- package/dist/loop/ledger.d.ts +95 -0
- package/dist/loop/ledger.d.ts.map +1 -0
- package/dist/loop/ledger.js +201 -0
- package/dist/loop/ledger.js.map +1 -0
- package/dist/loop/policy.d.ts +35 -0
- package/dist/loop/policy.d.ts.map +1 -0
- package/dist/loop/policy.js +151 -0
- package/dist/loop/policy.js.map +1 -0
- package/dist/loop/scaffold.d.ts +28 -0
- package/dist/loop/scaffold.d.ts.map +1 -0
- package/dist/loop/scaffold.js +224 -0
- package/dist/loop/scaffold.js.map +1 -0
- package/dist/loop/stop-gate.d.ts +71 -0
- package/dist/loop/stop-gate.d.ts.map +1 -0
- package/dist/loop/stop-gate.js +295 -0
- package/dist/loop/stop-gate.js.map +1 -0
- package/dist/self-invocation.d.ts +77 -0
- package/dist/self-invocation.d.ts.map +1 -0
- package/dist/self-invocation.js +157 -0
- package/dist/self-invocation.js.map +1 -0
- package/dist/ship-installers.d.ts.map +1 -1
- package/dist/ship-installers.js +8 -0
- package/dist/ship-installers.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +22 -5
- package/dist/update.js.map +1 -1
- package/dist/upgrade.d.ts +3 -3
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +5 -4
- package/dist/upgrade.js.map +1 -1
- package/package.json +6 -4
- package/templates/.claude/skills/dxkit-config/SKILL.md +17 -0
- package/templates/.claude/skills/dxkit-init/SKILL.md +1 -0
- package/templates/.claude/skills/dxkit-learn/SKILL.md +17 -0
- package/templates/.claude/skills/dxkit-loop/SKILL.md +114 -0
- package/templates/.claude/skills/dxkit-onboard/SKILL.md +2 -0
- package/templates/.claude/skills/dxkit-update/SKILL.md +3 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.buildLoopDoctorReport = buildLoopDoctorReport;
|
|
37
|
+
exports.runLoopDoctor = runLoopDoctor;
|
|
38
|
+
/**
|
|
39
|
+
* `vyuh-dxkit loop doctor` — preflight for an autonomous coding loop.
|
|
40
|
+
*
|
|
41
|
+
* The Stop-gate only protects a loop if three things are true before the
|
|
42
|
+
* loop starts: there is a baseline to diff against, the gate is actually
|
|
43
|
+
* wired into Claude Code (a registered Stop hook), and the guardrail can
|
|
44
|
+
* run. If any is missing the loop runs UNPROTECTED — and silently, because
|
|
45
|
+
* an unregistered hook never fires. This command makes that failure mode
|
|
46
|
+
* visible up front instead of after an unattended run shipped debt.
|
|
47
|
+
*
|
|
48
|
+
* It mirrors the structured shape of `src/doctor.ts` (label + ok + fix)
|
|
49
|
+
* so `dxkit-loop` / `dxkit-fix` can drive repairs conversationally, but it
|
|
50
|
+
* is loop-scoped: every check here is a precondition for safe unattended
|
|
51
|
+
* looping, not general install health.
|
|
52
|
+
*/
|
|
53
|
+
const fs = __importStar(require("fs"));
|
|
54
|
+
const path = __importStar(require("path"));
|
|
55
|
+
const child_process_1 = require("child_process");
|
|
56
|
+
const modes_1 = require("../baseline/modes");
|
|
57
|
+
const policy_1 = require("./policy");
|
|
58
|
+
const ledger_1 = require("./ledger");
|
|
59
|
+
const self_invocation_1 = require("../self-invocation");
|
|
60
|
+
const logger = __importStar(require("../logger"));
|
|
61
|
+
function isGitRepo(cwd) {
|
|
62
|
+
try {
|
|
63
|
+
(0, child_process_1.execFileSync)('git', ['rev-parse', '--is-inside-work-tree'], {
|
|
64
|
+
cwd,
|
|
65
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
66
|
+
});
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function refResolves(cwd, ref) {
|
|
74
|
+
try {
|
|
75
|
+
(0, child_process_1.execFileSync)('git', ['rev-parse', '--verify', '--quiet', `${ref}^{commit}`], {
|
|
76
|
+
cwd,
|
|
77
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
78
|
+
});
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Does `.claude/settings.json` register the Stop-gate hook? Reads the
|
|
87
|
+
* file defensively (absent / malformed → not registered) and looks for a
|
|
88
|
+
* Stop hook whose command invokes `hook stop-gate`. This is the check
|
|
89
|
+
* that catches the silent-failure class: a loop with no registered Stop
|
|
90
|
+
* hook runs with no gate at all.
|
|
91
|
+
*/
|
|
92
|
+
function stopHookRegistered(cwd) {
|
|
93
|
+
try {
|
|
94
|
+
const raw = fs.readFileSync(path.join(cwd, '.claude', 'settings.json'), 'utf8');
|
|
95
|
+
const parsed = JSON.parse(raw);
|
|
96
|
+
const stop = parsed.hooks?.Stop ?? [];
|
|
97
|
+
return stop.some((entry) => (entry.hooks ?? []).some((h) => typeof h.command === 'string' && /hook\s+stop-gate/.test(h.command)));
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Build the structured preflight report (pure of process I/O). */
|
|
104
|
+
function buildLoopDoctorReport(cwd) {
|
|
105
|
+
const checks = [];
|
|
106
|
+
const preset = (0, policy_1.resolveLoopPreset)(cwd);
|
|
107
|
+
// 1. Git repo — the gate diffs the working tree against a baseline.
|
|
108
|
+
const git = isGitRepo(cwd);
|
|
109
|
+
checks.push({
|
|
110
|
+
label: 'git repository',
|
|
111
|
+
status: git ? 'pass' : 'fail',
|
|
112
|
+
detail: git ? 'inside a git work tree' : 'not a git repository',
|
|
113
|
+
...(git
|
|
114
|
+
? {}
|
|
115
|
+
: { fix: { hint: 'Run the loop from inside a git repository.', command: 'git init' } }),
|
|
116
|
+
});
|
|
117
|
+
// 2. Baseline present / resolvable. Without a prior side the gate
|
|
118
|
+
// fail-closes (block-operator) on every Stop — the loop can never
|
|
119
|
+
// cleanly finish. Ref-based modes need a resolvable ref, not a file.
|
|
120
|
+
const mode = (0, modes_1.resolveBaselineMode)({ cwd });
|
|
121
|
+
if (mode.mode === 'ref-based') {
|
|
122
|
+
const ref = mode.ref ?? 'origin/main';
|
|
123
|
+
const ok = !git ? false : refResolves(cwd, ref);
|
|
124
|
+
checks.push({
|
|
125
|
+
label: `baseline (ref-based: ${ref})`,
|
|
126
|
+
status: ok ? 'pass' : 'fail',
|
|
127
|
+
detail: ok ? 'comparison ref resolves' : `comparison ref ${ref} does not resolve`,
|
|
128
|
+
...(ok
|
|
129
|
+
? {}
|
|
130
|
+
: {
|
|
131
|
+
fix: {
|
|
132
|
+
hint: `Fetch the comparison ref so the gate can recompute the prior side, or pin a reachable ref in .dxkit/policy.json.`,
|
|
133
|
+
command: `git fetch origin`,
|
|
134
|
+
skill: 'dxkit-config',
|
|
135
|
+
},
|
|
136
|
+
}),
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const baselinePath = path.join(cwd, '.dxkit', 'baselines', 'main.json');
|
|
141
|
+
const ok = fs.existsSync(baselinePath);
|
|
142
|
+
checks.push({
|
|
143
|
+
label: `baseline (.dxkit/baselines/main.json, mode: ${mode.mode})`,
|
|
144
|
+
status: ok ? 'pass' : 'fail',
|
|
145
|
+
detail: ok ? 'committed baseline present' : 'no committed baseline',
|
|
146
|
+
...(ok
|
|
147
|
+
? {}
|
|
148
|
+
: {
|
|
149
|
+
fix: {
|
|
150
|
+
hint: 'Capture the current state as the loop baseline; existing debt is locked in, only net-new findings block.',
|
|
151
|
+
command: (0, self_invocation_1.dxkitCli)('baseline create'),
|
|
152
|
+
skill: 'dxkit-init',
|
|
153
|
+
},
|
|
154
|
+
}),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
// 3. Stop hook registered. The safety guarantee is entirely contingent
|
|
158
|
+
// on this — an unregistered hook never fires, so the loop runs with no
|
|
159
|
+
// gate and no error.
|
|
160
|
+
const hook = stopHookRegistered(cwd);
|
|
161
|
+
checks.push({
|
|
162
|
+
label: 'Stop-gate hook registered',
|
|
163
|
+
status: hook ? 'pass' : 'fail',
|
|
164
|
+
detail: hook
|
|
165
|
+
? '.claude/settings.json invokes `vyuh-dxkit hook stop-gate` on Stop'
|
|
166
|
+
: 'no Stop hook invoking the gate — the loop would run UNPROTECTED',
|
|
167
|
+
...(hook
|
|
168
|
+
? {}
|
|
169
|
+
: {
|
|
170
|
+
fix: {
|
|
171
|
+
hint: 'Register the Stop-gate hook in .claude/settings.json (additive — your existing hooks are preserved).',
|
|
172
|
+
command: (0, self_invocation_1.dxkitCli)('init --claude-loop'),
|
|
173
|
+
skill: 'dxkit-loop',
|
|
174
|
+
},
|
|
175
|
+
}),
|
|
176
|
+
});
|
|
177
|
+
// 3b. Stop hook RESOLVABLE. The registered hook invokes the dxkit CLI;
|
|
178
|
+
// verify it actually resolves here. A registered-but-unresolvable hook
|
|
179
|
+
// 404s on every Stop — the failure mode of a pure-npx install whose
|
|
180
|
+
// devDependency was never provisioned (or a non-Node repo with no global
|
|
181
|
+
// dxkit). Only meaningful once a hook is registered; if it isn't, the
|
|
182
|
+
// check above already fails.
|
|
183
|
+
if (hook) {
|
|
184
|
+
const res = (0, self_invocation_1.resolveDxkitCli)(cwd);
|
|
185
|
+
checks.push({
|
|
186
|
+
label: 'Stop-gate hook resolvable',
|
|
187
|
+
status: res.ok ? 'pass' : 'fail',
|
|
188
|
+
detail: res.ok
|
|
189
|
+
? `\`vyuh-dxkit\` resolves (${res.how === 'local' ? 'project-local node_modules/.bin' : 'global install'}) — the hook can run`
|
|
190
|
+
: '`vyuh-dxkit` does not resolve — the Stop hook would fail on every Stop (dxkit is not installed here)',
|
|
191
|
+
...(res.ok
|
|
192
|
+
? {}
|
|
193
|
+
: {
|
|
194
|
+
fix: {
|
|
195
|
+
hint: 'Install dxkit so the Stop hook can run. The blessed path installs it as a devDependency; then `npm install` provisions it.',
|
|
196
|
+
command: 'npm install --save-dev @vyuhlabs/dxkit',
|
|
197
|
+
skill: 'dxkit-loop',
|
|
198
|
+
},
|
|
199
|
+
}),
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
// 4. Active preset — informational. Surfaces the posture so an operator
|
|
203
|
+
// knows what the loop will block on before trusting it unattended.
|
|
204
|
+
checks.push({
|
|
205
|
+
label: `loop preset: ${preset}`,
|
|
206
|
+
status: 'pass',
|
|
207
|
+
detail: preset === 'security-only'
|
|
208
|
+
? 'blocks net-new secrets + crit/high security + reachable dep-vulns; test-gap + quality warn only'
|
|
209
|
+
: 'blocks every net-new finding incl. test-gap + quality (can drive open-ended repair)',
|
|
210
|
+
});
|
|
211
|
+
// 5. Postflight test command — optional. When unset the gate skips the
|
|
212
|
+
// post-pass test run; that is a real reduction in coverage, so warn.
|
|
213
|
+
const testCmd = process.env.DXKIT_LOOP_TEST_COMMAND;
|
|
214
|
+
checks.push({
|
|
215
|
+
label: 'postflight test command',
|
|
216
|
+
status: testCmd && testCmd.trim() ? 'pass' : 'warn',
|
|
217
|
+
detail: testCmd && testCmd.trim()
|
|
218
|
+
? `DXKIT_LOOP_TEST_COMMAND set (${testCmd.trim().slice(0, 60)})`
|
|
219
|
+
: 'DXKIT_LOOP_TEST_COMMAND unset — the gate will not run tests after the guardrail passes',
|
|
220
|
+
...(testCmd && testCmd.trim()
|
|
221
|
+
? {}
|
|
222
|
+
: {
|
|
223
|
+
fix: {
|
|
224
|
+
hint: 'Optionally export DXKIT_LOOP_TEST_COMMAND so the gate also blocks completion on a failing test suite.',
|
|
225
|
+
},
|
|
226
|
+
}),
|
|
227
|
+
});
|
|
228
|
+
// 6. Graph freshness — only relevant when a graph is present (the
|
|
229
|
+
// feature/orientation surface). Stale is usable (fail-open), so warn.
|
|
230
|
+
const graphPath = path.join(cwd, '.dxkit', 'reports', 'graph.json');
|
|
231
|
+
if (fs.existsSync(graphPath)) {
|
|
232
|
+
const fresh = git ? graphFresh(cwd, graphPath) : true;
|
|
233
|
+
checks.push({
|
|
234
|
+
label: 'code graph freshness',
|
|
235
|
+
status: fresh ? 'pass' : 'warn',
|
|
236
|
+
detail: fresh
|
|
237
|
+
? 'graph.json is newer than the last commit'
|
|
238
|
+
: 'graph.json predates the last commit — orientation context may be stale',
|
|
239
|
+
...(fresh
|
|
240
|
+
? {}
|
|
241
|
+
: {
|
|
242
|
+
fix: {
|
|
243
|
+
hint: 'Regenerate the code graph so orientation context matches current code.',
|
|
244
|
+
command: (0, self_invocation_1.dxkitCli)('explore graph'),
|
|
245
|
+
skill: 'dxkit-feature',
|
|
246
|
+
},
|
|
247
|
+
}),
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
const ledgerExists = fs.existsSync(path.join(cwd, ledger_1.LEDGER_FILE));
|
|
251
|
+
checks.push({
|
|
252
|
+
label: 'loop ledger',
|
|
253
|
+
status: 'pass',
|
|
254
|
+
detail: ledgerExists
|
|
255
|
+
? `audit trail present (${ledger_1.LEDGER_FILE})`
|
|
256
|
+
: 'no ledger yet — created on the first Stop event',
|
|
257
|
+
});
|
|
258
|
+
const ok = !checks.some((c) => c.status === 'fail');
|
|
259
|
+
return {
|
|
260
|
+
schema: 'loop-doctor.v1',
|
|
261
|
+
generatedAt: new Date().toISOString(),
|
|
262
|
+
cwd,
|
|
263
|
+
preset,
|
|
264
|
+
checks,
|
|
265
|
+
ok,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* CLI entry for `vyuh-dxkit loop doctor`. Renders the preflight report
|
|
270
|
+
* (or JSON with `--json`) and exits non-zero when any check failed so it
|
|
271
|
+
* can gate a CI loop-setup step.
|
|
272
|
+
*/
|
|
273
|
+
async function runLoopDoctor(cwd, opts = {}) {
|
|
274
|
+
const report = buildLoopDoctorReport(cwd);
|
|
275
|
+
if (opts.json) {
|
|
276
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
277
|
+
process.exit(report.ok ? 0 : 1);
|
|
278
|
+
}
|
|
279
|
+
logger.header('vyuh-dxkit loop doctor');
|
|
280
|
+
for (const c of report.checks) {
|
|
281
|
+
const line = `${c.label} — ${c.detail}`;
|
|
282
|
+
if (c.status === 'pass')
|
|
283
|
+
logger.success(line);
|
|
284
|
+
else if (c.status === 'warn')
|
|
285
|
+
logger.warn(line);
|
|
286
|
+
else
|
|
287
|
+
logger.fail(line);
|
|
288
|
+
if (c.fix && c.status !== 'pass') {
|
|
289
|
+
logger.dim(` → ${c.fix.hint}`);
|
|
290
|
+
if (c.fix.command)
|
|
291
|
+
logger.dim(` ${c.fix.command}`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
console.log(''); // slop-ok
|
|
295
|
+
if (report.ok) {
|
|
296
|
+
logger.success('Loop preflight passed — safe to run unattended.');
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
logger.fail('Loop preflight failed — fix the items above before running unattended.');
|
|
300
|
+
}
|
|
301
|
+
process.exit(report.ok ? 0 : 1);
|
|
302
|
+
}
|
|
303
|
+
/** Graph is fresh when its mtime is at or after the last commit time. */
|
|
304
|
+
function graphFresh(cwd, graphPath) {
|
|
305
|
+
try {
|
|
306
|
+
const committedAt = (0, child_process_1.execFileSync)('git', ['log', '-1', '--format=%ct'], {
|
|
307
|
+
cwd,
|
|
308
|
+
encoding: 'utf8',
|
|
309
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
310
|
+
}).trim();
|
|
311
|
+
const commitMs = parseInt(committedAt, 10) * 1000;
|
|
312
|
+
if (!Number.isFinite(commitMs))
|
|
313
|
+
return true; // can't tell → don't cry wolf
|
|
314
|
+
return fs.statSync(graphPath).mtimeMs >= commitMs;
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/loop/doctor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsGA,sDA+KC;AAOD,sCA0BC;AAtTD;;;;;;;;;;;;;;GAcG;AACH,uCAAyB;AACzB,2CAA6B;AAC7B,iDAA6C;AAC7C,6CAAwD;AACxD,qCAA6C;AAC7C,qCAAuC;AACvC,wDAA+D;AAC/D,kDAAoC;AA+BpC,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC;QACH,IAAA,4BAAY,EAAC,KAAK,EAAE,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE;YAC1D,GAAG;YACH,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,GAAW,EAAE,GAAW;IAC3C,IAAI,CAAC;QACH,IAAA,4BAAY,EAAC,KAAK,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,GAAG,WAAW,CAAC,EAAE;YAC3E,GAAG;YACH,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,GAAW;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAE5B,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CACzB,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAC3E,CACF,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,SAAgB,qBAAqB,CAAC,GAAW;IAC/C,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,IAAA,0BAAiB,EAAC,GAAG,CAAC,CAAC;IAEtC,oEAAoE;IACpE,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC;QACV,KAAK,EAAE,gBAAgB;QACvB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;QAC7B,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,sBAAsB;QAC/D,GAAG,CAAC,GAAG;YACL,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,4CAA4C,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,CAAC;KAC1F,CAAC,CAAC;IAEH,kEAAkE;IAClE,kEAAkE;IAClE,qEAAqE;IACrE,MAAM,IAAI,GAAG,IAAA,2BAAmB,EAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,aAAa,CAAC;QACtC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAChD,MAAM,CAAC,IAAI,CAAC;YACV,KAAK,EAAE,wBAAwB,GAAG,GAAG;YACrC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YAC5B,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,kBAAkB,GAAG,mBAAmB;YACjF,GAAG,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACE,GAAG,EAAE;wBACH,IAAI,EAAE,kHAAkH;wBACxH,OAAO,EAAE,kBAAkB;wBAC3B,KAAK,EAAE,cAAc;qBACtB;iBACF,CAAC;SACP,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;QACxE,MAAM,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC;YACV,KAAK,EAAE,+CAA+C,IAAI,CAAC,IAAI,GAAG;YAClE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YAC5B,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,uBAAuB;YACnE,GAAG,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACE,GAAG,EAAE;wBACH,IAAI,EAAE,0GAA0G;wBAChH,OAAO,EAAE,IAAA,0BAAQ,EAAC,iBAAiB,CAAC;wBACpC,KAAK,EAAE,YAAY;qBACpB;iBACF,CAAC;SACP,CAAC,CAAC;IACL,CAAC;IAED,uEAAuE;IACvE,uEAAuE;IACvE,qBAAqB;IACrB,MAAM,IAAI,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,CAAC,IAAI,CAAC;QACV,KAAK,EAAE,2BAA2B;QAClC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;QAC9B,MAAM,EAAE,IAAI;YACV,CAAC,CAAC,mEAAmE;YACrE,CAAC,CAAC,iEAAiE;QACrE,GAAG,CAAC,IAAI;YACN,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,GAAG,EAAE;oBACH,IAAI,EAAE,sGAAsG;oBAC5G,OAAO,EAAE,IAAA,0BAAQ,EAAC,oBAAoB,CAAC;oBACvC,KAAK,EAAE,YAAY;iBACpB;aACF,CAAC;KACP,CAAC,CAAC;IAEH,uEAAuE;IACvE,uEAAuE;IACvE,oEAAoE;IACpE,yEAAyE;IACzE,sEAAsE;IACtE,6BAA6B;IAC7B,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,GAAG,GAAG,IAAA,iCAAe,EAAC,GAAG,CAAC,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC;YACV,KAAK,EAAE,2BAA2B;YAClC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YAChC,MAAM,EAAE,GAAG,CAAC,EAAE;gBACZ,CAAC,CAAC,4BACE,GAAG,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,gBAC5D,sBAAsB;gBACxB,CAAC,CAAC,sGAAsG;YAC1G,GAAG,CAAC,GAAG,CAAC,EAAE;gBACR,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACE,GAAG,EAAE;wBACH,IAAI,EAAE,4HAA4H;wBAClI,OAAO,EAAE,wCAAwC;wBACjD,KAAK,EAAE,YAAY;qBACpB;iBACF,CAAC;SACP,CAAC,CAAC;IACL,CAAC;IAED,wEAAwE;IACxE,mEAAmE;IACnE,MAAM,CAAC,IAAI,CAAC;QACV,KAAK,EAAE,gBAAgB,MAAM,EAAE;QAC/B,MAAM,EAAE,MAAM;QACd,MAAM,EACJ,MAAM,KAAK,eAAe;YACxB,CAAC,CAAC,iGAAiG;YACnG,CAAC,CAAC,qFAAqF;KAC5F,CAAC,CAAC;IAEH,uEAAuE;IACvE,qEAAqE;IACrE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IACpD,MAAM,CAAC,IAAI,CAAC;QACV,KAAK,EAAE,yBAAyB;QAChC,MAAM,EAAE,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;QACnD,MAAM,EACJ,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE;YACvB,CAAC,CAAC,gCAAgC,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG;YAChE,CAAC,CAAC,wFAAwF;QAC9F,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE;YAC3B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,GAAG,EAAE;oBACH,IAAI,EAAE,uGAAuG;iBAC9G;aACF,CAAC;KACP,CAAC,CAAC;IAEH,kEAAkE;IAClE,sEAAsE;IACtE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IACpE,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtD,MAAM,CAAC,IAAI,CAAC;YACV,KAAK,EAAE,sBAAsB;YAC7B,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YAC/B,MAAM,EAAE,KAAK;gBACX,CAAC,CAAC,0CAA0C;gBAC5C,CAAC,CAAC,wEAAwE;YAC5E,GAAG,CAAC,KAAK;gBACP,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACE,GAAG,EAAE;wBACH,IAAI,EAAE,wEAAwE;wBAC9E,OAAO,EAAE,IAAA,0BAAQ,EAAC,eAAe,CAAC;wBAClC,KAAK,EAAE,eAAe;qBACvB;iBACF,CAAC;SACP,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAW,CAAC,CAAC,CAAC;IAChE,MAAM,CAAC,IAAI,CAAC;QACV,KAAK,EAAE,aAAa;QACpB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,YAAY;YAClB,CAAC,CAAC,wBAAwB,oBAAW,GAAG;YACxC,CAAC,CAAC,iDAAiD;KACtD,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACpD,OAAO;QACL,MAAM,EAAE,gBAAgB;QACxB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,GAAG;QACH,MAAM;QACN,MAAM;QACN,EAAE;KACH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACI,KAAK,UAAU,aAAa,CAAC,GAAW,EAAE,OAA2B,EAAE;IAC5E,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAE1C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;QACxC,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;YAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;aACzC,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;YAC3C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACjC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAChC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO;gBAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU;IAC3B,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,MAAM,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,yEAAyE;AACzE,SAAS,UAAU,CAAC,GAAW,EAAE,SAAiB;IAChD,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAA,4BAAY,EAAC,KAAK,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE;YACrE,GAAG;YACH,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;QAClD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC,CAAC,8BAA8B;QAC3E,OAAO,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface LoopLedgerOptions {
|
|
2
|
+
readonly json?: boolean;
|
|
3
|
+
/** For `show`: cap to the last N events. */
|
|
4
|
+
readonly limit?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function runLoopLedger(cwd: string, action: string | undefined, opts: LoopLedgerOptions): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=ledger-cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger-cli.d.ts","sourceRoot":"","sources":["../../src/loop/ledger-cli.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AASD,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,IAAI,CAAC,CA4Cf"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runLoopLedger = runLoopLedger;
|
|
37
|
+
/**
|
|
38
|
+
* CLI for `vyuh-dxkit loop ledger [show | summarize | clear]`.
|
|
39
|
+
*
|
|
40
|
+
* A thin renderer over the pure ledger functions. The ledger is an
|
|
41
|
+
* audit trail ("what did the loop do?"), not a dashboard, so the output
|
|
42
|
+
* is deliberately plain text (or `--json` for tooling).
|
|
43
|
+
*/
|
|
44
|
+
const logger = __importStar(require("../logger"));
|
|
45
|
+
const ledger_1 = require("./ledger");
|
|
46
|
+
function renderEventLine(e) {
|
|
47
|
+
const verdict = e.allowed ? 'PASS ' : 'BLOCK';
|
|
48
|
+
const cont = e.stop_hook_active ? ' (continuation)' : '';
|
|
49
|
+
const nn = e.allowed ? '' : `, ${e.net_new_findings} net-new`;
|
|
50
|
+
return `${e.timestamp} ${verdict} guardrail=${e.guardrail_status}${nn}${cont}`;
|
|
51
|
+
}
|
|
52
|
+
async function runLoopLedger(cwd, action, opts) {
|
|
53
|
+
const act = action ?? 'show';
|
|
54
|
+
if (act === 'clear') {
|
|
55
|
+
const removed = (0, ledger_1.clearLedger)(cwd);
|
|
56
|
+
if (opts.json) {
|
|
57
|
+
process.stdout.write(JSON.stringify({ cleared: removed }) + '\n');
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
logger.info(removed ? 'Loop ledger cleared.' : 'No loop ledger to clear.');
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const events = (0, ledger_1.readLedger)(cwd);
|
|
65
|
+
if (act === 'summarize') {
|
|
66
|
+
const summary = (0, ledger_1.summarizeLedger)(events);
|
|
67
|
+
if (opts.json) {
|
|
68
|
+
process.stdout.write(JSON.stringify(summary, null, 2) + '\n');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
logger.header('Loop ledger summary');
|
|
72
|
+
logger.info(`Total postflights: ${summary.total}`);
|
|
73
|
+
logger.info(`Allowed (clean stop): ${summary.allowed}`);
|
|
74
|
+
logger.info(`Blocked completions: ${summary.blocked}`);
|
|
75
|
+
logger.info(`Net-new findings blocked: ${summary.netNewBlocked}`);
|
|
76
|
+
logger.info(`Repaired after block: ${summary.repairedAfterBlock}`);
|
|
77
|
+
logger.info(`Unrepaired sessions: ${summary.unrepairedSessions}`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Default: show.
|
|
81
|
+
const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;
|
|
82
|
+
const shown = limit && Number.isFinite(limit) ? events.slice(-limit) : events;
|
|
83
|
+
if (opts.json) {
|
|
84
|
+
process.stdout.write(JSON.stringify(shown, null, 2) + '\n');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (shown.length === 0) {
|
|
88
|
+
logger.info('Loop ledger is empty.');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
logger.header(`Loop ledger (${shown.length}${limit ? ` of ${events.length}` : ''} events)`);
|
|
92
|
+
for (const e of shown)
|
|
93
|
+
process.stdout.write(renderEventLine(e) + '\n');
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=ledger-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger-cli.js","sourceRoot":"","sources":["../../src/loop/ledger-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { LoopPreset } from './policy';
|
|
2
|
+
/** Bump only on a breaking change to the event shape. */
|
|
3
|
+
export declare const LEDGER_SCHEMA_VERSION = 1;
|
|
4
|
+
/** Relative location of the ledger inside a repo. */
|
|
5
|
+
export declare const LEDGER_DIR: string;
|
|
6
|
+
export declare const LEDGER_FILE: string;
|
|
7
|
+
/** Status of a deterministic check at the moment the Stop-gate ran. */
|
|
8
|
+
export type CheckStatus = 'pass' | 'fail' | 'error' | 'not_configured' | 'skipped';
|
|
9
|
+
/**
|
|
10
|
+
* One postflight event. Mirrors the schema in the loop pack spec so
|
|
11
|
+
* the ledger is stable across releases. Optional agent fields are
|
|
12
|
+
* populated when the hook payload carries them (agent teams / subagents).
|
|
13
|
+
*/
|
|
14
|
+
export interface LedgerEvent {
|
|
15
|
+
readonly schema_version: number;
|
|
16
|
+
readonly timestamp: string;
|
|
17
|
+
readonly event: 'Stop';
|
|
18
|
+
readonly session_id: string;
|
|
19
|
+
readonly agent_id?: string;
|
|
20
|
+
readonly agent_type?: string;
|
|
21
|
+
readonly cwd: string;
|
|
22
|
+
readonly branch: string;
|
|
23
|
+
readonly commit: string;
|
|
24
|
+
/** Loop posture in force when the gate ran (`security-only` /
|
|
25
|
+
* `full-debt`). Optional for forward/backward compat — absent on
|
|
26
|
+
* events written before presets existed. */
|
|
27
|
+
readonly preset?: LoopPreset;
|
|
28
|
+
/** Outcome of the dxkit guardrail check. */
|
|
29
|
+
readonly guardrail_status: CheckStatus;
|
|
30
|
+
/** Net-new findings that blocked completion (0 when guardrail passed). */
|
|
31
|
+
readonly net_new_findings: number;
|
|
32
|
+
/** Size of the prior baseline the current scan was diffed against. */
|
|
33
|
+
readonly baseline_findings: number;
|
|
34
|
+
/** Files changed relative to the baseline commit, when derivable. */
|
|
35
|
+
readonly files_changed: number;
|
|
36
|
+
/**
|
|
37
|
+
* Whether THIS event blocked the loop from stopping. A blocked event
|
|
38
|
+
* is the durable record of "the loop tried to declare done while
|
|
39
|
+
* unsafe." `allowed: true` events are clean completions (or a
|
|
40
|
+
* non-blocking allow after an un-fixable config error).
|
|
41
|
+
*/
|
|
42
|
+
readonly allowed: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* True when Claude was already continuing because a prior Stop-gate
|
|
45
|
+
* blocked this turn (the Claude Code `stop_hook_active` flag). Lets
|
|
46
|
+
* the summary distinguish "repaired on first try" from "needed N
|
|
47
|
+
* continuations."
|
|
48
|
+
*/
|
|
49
|
+
readonly stop_hook_active: boolean;
|
|
50
|
+
readonly tests_status: CheckStatus;
|
|
51
|
+
readonly lint_status: CheckStatus;
|
|
52
|
+
readonly typecheck_status: CheckStatus;
|
|
53
|
+
readonly duration_ms: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Fill in the repo-derived fields (branch, commit) and stamp the
|
|
57
|
+
* schema version + timestamp, so callers only supply the outcome.
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildLedgerEvent(cwd: string, fields: Omit<LedgerEvent, 'schema_version' | 'timestamp' | 'event' | 'branch' | 'commit'> & Partial<Pick<LedgerEvent, 'branch' | 'commit'>>): LedgerEvent;
|
|
60
|
+
/**
|
|
61
|
+
* Append one event to the ledger. Creates `.dxkit/loop/` on demand.
|
|
62
|
+
* Best-effort: a ledger write must never abort the Stop-gate (the
|
|
63
|
+
* gate's verdict matters more than its audit line), so failures are
|
|
64
|
+
* swallowed and reported via the return value.
|
|
65
|
+
*/
|
|
66
|
+
export declare function appendLedgerEvent(cwd: string, event: LedgerEvent): boolean;
|
|
67
|
+
/** Read every ledger event. Returns [] when the ledger is absent. */
|
|
68
|
+
export declare function readLedger(cwd: string): LedgerEvent[];
|
|
69
|
+
/** Remove the ledger file. Returns true when a file was deleted. */
|
|
70
|
+
export declare function clearLedger(cwd: string): boolean;
|
|
71
|
+
export interface LedgerSummary {
|
|
72
|
+
readonly total: number;
|
|
73
|
+
readonly allowed: number;
|
|
74
|
+
readonly blocked: number;
|
|
75
|
+
/** Total net-new findings across all blocked events. */
|
|
76
|
+
readonly netNewBlocked: number;
|
|
77
|
+
/**
|
|
78
|
+
* Sessions where a blocked Stop was later followed by a clean
|
|
79
|
+
* (allowed, guardrail-pass) Stop — i.e. the agent repaired the
|
|
80
|
+
* net-new findings after being blocked. The headline "repair-after-
|
|
81
|
+
* block" metric for the Loop-Safety study.
|
|
82
|
+
*/
|
|
83
|
+
readonly repairedAfterBlock: number;
|
|
84
|
+
/** Sessions that were blocked at least once and never repaired. */
|
|
85
|
+
readonly unrepairedSessions: number;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Reduce a list of events to the audit-trail summary. Repair detection
|
|
89
|
+
* is per-session: a session counts as "repaired" if it has at least one
|
|
90
|
+
* blocked event AND a strictly-later allowed event with a passing
|
|
91
|
+
* guardrail. Order is taken from event position (the ledger is
|
|
92
|
+
* append-only, so file order is chronological).
|
|
93
|
+
*/
|
|
94
|
+
export declare function summarizeLedger(events: ReadonlyArray<LedgerEvent>): LedgerSummary;
|
|
95
|
+
//# sourceMappingURL=ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../src/loop/ledger.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,yDAAyD;AACzD,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,qDAAqD;AACrD,eAAO,MAAM,UAAU,QAA8B,CAAC;AACtD,eAAO,MAAM,WAAW,QAAwC,CAAC;AAEjE,uEAAuE;AACvE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAAC;AAEnF;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;iDAE6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,4CAA4C;IAC5C,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC;IACvC,0EAA0E;IAC1E,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,qEAAqE;IACrE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC;IACvC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AA4BD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,gBAAgB,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC,GACvF,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,QAAQ,CAAC,CAAC,GAChD,WAAW,CASb;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAS1E;AAED,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,EAAE,CAqBrD;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOhD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,mEAAmE;IACnE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,aAAa,CAuCjF"}
|