@deftai/directive-core 0.101.0 → 0.103.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/dist/authz/classify.js +97 -8
- package/dist/check/cached-orchestrator.d.ts +4 -0
- package/dist/check/cached-orchestrator.js +70 -5
- package/dist/check/cli-native-gates.d.ts +43 -0
- package/dist/check/cli-native-gates.js +84 -0
- package/dist/check/index.d.ts +1 -0
- package/dist/check/index.js +1 -0
- package/dist/check/named-cause.js +10 -0
- package/dist/doctor/checks.d.ts +5 -6
- package/dist/doctor/checks.js +13 -56
- package/dist/eval/later-graduation.d.ts +39 -0
- package/dist/eval/later-graduation.js +91 -0
- package/dist/eval/report.d.ts +6 -0
- package/dist/eval/report.js +27 -8
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/init-deposit/hygiene.d.ts +7 -1
- package/dist/init-deposit/hygiene.js +11 -3
- package/dist/init-deposit/scaffold.d.ts +12 -0
- package/dist/init-deposit/scaffold.js +81 -8
- package/dist/intake/issue-ingest.js +42 -0
- package/dist/policy/ceremony-dial-escalation.d.ts +52 -0
- package/dist/policy/ceremony-dial-escalation.js +92 -0
- package/dist/policy/ceremony-dial.d.ts +3 -1
- package/dist/policy/ceremony-dial.js +52 -1
- package/dist/policy/check-resume.d.ts +9 -38
- package/dist/policy/check-resume.js +18 -156
- package/dist/policy/coverage-debt.d.ts +18 -37
- package/dist/policy/coverage-debt.js +38 -147
- package/dist/policy/index.d.ts +1 -1
- package/dist/policy/index.js +1 -1
- package/dist/product-first-done-gate/acceptance.js +22 -0
- package/dist/product-first-done-gate/empty-resolution.d.ts +26 -0
- package/dist/product-first-done-gate/empty-resolution.js +38 -0
- package/dist/product-first-done-gate/evaluate.d.ts +40 -2
- package/dist/product-first-done-gate/evaluate.js +253 -61
- package/dist/product-first-done-gate/index.d.ts +2 -1
- package/dist/product-first-done-gate/index.js +2 -1
- package/dist/product-first-done-gate/types.d.ts +3 -0
- package/dist/product-first-done-gate/types.js +0 -7
- package/dist/run-summary/emit.d.ts +11 -1
- package/dist/run-summary/emit.js +48 -2
- package/dist/run-summary/index.d.ts +2 -1
- package/dist/run-summary/index.js +2 -1
- package/dist/run-summary/path.d.ts +1 -1
- package/dist/run-summary/path.js +1 -1
- package/dist/run-summary/share.d.ts +25 -0
- package/dist/run-summary/share.js +106 -0
- package/dist/run-summary/types.d.ts +60 -2
- package/dist/run-summary/types.js +7 -0
- package/dist/scope/acceptance-activate-gate.d.ts +23 -0
- package/dist/scope/acceptance-activate-gate.js +70 -0
- package/dist/scope/index.d.ts +1 -0
- package/dist/scope/index.js +1 -0
- package/dist/scope/transition.js +5 -0
- package/dist/session/index.d.ts +0 -1
- package/dist/session/index.js +0 -1
- package/dist/session/orientation-compression.js +19 -9
- package/dist/session/session-start.d.ts +6 -0
- package/dist/session/session-start.js +44 -22
- package/dist/session/toolchain-preflight.d.ts +15 -0
- package/dist/session/toolchain-preflight.js +65 -5
- package/dist/verify-ac/clauses.d.ts +51 -0
- package/dist/verify-ac/clauses.js +490 -0
- package/dist/verify-ac/evaluate.d.ts +73 -0
- package/dist/verify-ac/evaluate.js +167 -0
- package/dist/verify-ac/flag.d.ts +35 -0
- package/dist/verify-ac/flag.js +104 -0
- package/dist/verify-ac/index.d.ts +10 -0
- package/dist/verify-ac/index.js +10 -0
- package/package.json +7 -3
- package/dist/policy/coverage-check-resume-presets.d.ts +0 -46
- package/dist/policy/coverage-check-resume-presets.js +0 -228
- package/dist/session/coverage-check-resume-nudge.d.ts +0 -34
- package/dist/session/coverage-check-resume-nudge.js +0 -66
|
@@ -3,14 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Runs plan.acceptance.commands (or #3267 literal ledger) via the shared
|
|
5
5
|
* literal-acceptance runner. Records source_rung in the result message.
|
|
6
|
-
* Project floor with empty commands is a soft pass
|
|
7
|
-
* inside full `task check`)
|
|
6
|
+
* Project floor with empty commands is a soft pass only when a suite floor
|
|
7
|
+
* exists (suite gates own the floor inside full `task check`). With no suite
|
|
8
|
+
* floor, empty resolution is soft_empty — not a green run (#3334).
|
|
8
9
|
*/
|
|
9
10
|
import { existsSync, readFileSync } from "node:fs";
|
|
10
|
-
import { basename, resolve } from "node:path";
|
|
11
|
+
import { basename, isAbsolute, relative, resolve } from "node:path";
|
|
11
12
|
import { evaluateLiteralAcceptanceFromPlan, runLiteralAcceptanceCommands, } from "../literal-acceptance/index.js";
|
|
13
|
+
import { ENV_RUN_SUMMARY_PATH, RunSummaryEmitter, } from "../run-summary/index.js";
|
|
12
14
|
import { maybeBankOnAcPass } from "../session/ac-pass-banking.js";
|
|
15
|
+
import { formatClauseWalkMessage, walkAcceptanceClauses, } from "../verify-ac/clauses.js";
|
|
16
|
+
import { emitVerifyAcAttempts, evaluateProductOracleIntegrity, mergeOracleVerdict, } from "../verify-ac/evaluate.js";
|
|
13
17
|
import { readPlanAcceptance, validatePlanAcceptance } from "./acceptance.js";
|
|
18
|
+
import { formatSoftEmptyMessage, isEmptyAcResolution, projectHasSuiteFloor, } from "./empty-resolution.js";
|
|
14
19
|
function asRecord(value) {
|
|
15
20
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
16
21
|
return value;
|
|
@@ -21,11 +26,16 @@ function asRecord(value) {
|
|
|
21
26
|
* Evaluate product AC from an in-memory plan.
|
|
22
27
|
*/
|
|
23
28
|
export function evaluateVerifyAcFromPlan(plan, options = {}) {
|
|
29
|
+
const planId = typeof plan.id === "string" && plan.id.trim() ? plan.id.trim() : null;
|
|
30
|
+
const optionsWithScope = {
|
|
31
|
+
...options,
|
|
32
|
+
oracleScopeKey: options.oracleScopeKey?.trim() || planId || null,
|
|
33
|
+
};
|
|
24
34
|
const acceptance = readPlanAcceptance(plan);
|
|
25
35
|
const schemaErrors = validatePlanAcceptance(plan.acceptance ?? acceptance);
|
|
26
36
|
// Only hard-fail schema when an explicit plan.acceptance object exists.
|
|
27
37
|
if (plan.acceptance !== undefined && schemaErrors.length > 0) {
|
|
28
|
-
return {
|
|
38
|
+
return applyOracle({
|
|
29
39
|
ok: false,
|
|
30
40
|
code: 2,
|
|
31
41
|
message: `verify:ac config error (#3284): ${schemaErrors.join("; ")}`,
|
|
@@ -34,9 +44,11 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
|
|
|
34
44
|
sourceRung: acceptance.source_rung,
|
|
35
45
|
noneStated: acceptance.none_stated,
|
|
36
46
|
acceptance,
|
|
37
|
-
|
|
47
|
+
resolution: "config",
|
|
48
|
+
resolvedCommandCount: 0,
|
|
49
|
+
}, optionsWithScope);
|
|
38
50
|
}
|
|
39
|
-
const projectRoot = resolve(
|
|
51
|
+
const projectRoot = resolve(optionsWithScope.projectRoot ?? process.cwd());
|
|
40
52
|
// Prefer shared literal-acceptance path so safety / promotion rules stay one place.
|
|
41
53
|
// Empty plan.acceptance.commands still consults the #3267 rejected ledger
|
|
42
54
|
// (Greptile P1: rejected stated AC must never soft-pass).
|
|
@@ -44,9 +56,13 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
|
|
|
44
56
|
// if the literal ledger is empty of executables.
|
|
45
57
|
const base = evaluateLiteralAcceptanceFromPlan(plan, {
|
|
46
58
|
projectRoot,
|
|
47
|
-
runner:
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
runner: optionsWithScope.runner,
|
|
60
|
+
// Check composition uses the stamped ledger only. Re-scanning issue prose
|
|
61
|
+
// during `task check` re-captures backtick `verify:ac` lines as rejected
|
|
62
|
+
// and deadlocks the graph (#3323 / #3284 check-integrated).
|
|
63
|
+
captureFromNarratives: optionsWithScope.captureFromNarratives ??
|
|
64
|
+
(optionsWithScope.checkIntegrated === true ? false : undefined),
|
|
65
|
+
quiet: optionsWithScope.quiet,
|
|
50
66
|
});
|
|
51
67
|
// When literal path had nothing executable but plan.acceptance has derived commands,
|
|
52
68
|
// run them directly with source=explicit semantics.
|
|
@@ -54,7 +70,7 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
|
|
|
54
70
|
base.runs.length === 0 &&
|
|
55
71
|
acceptance.commands.length > 0 &&
|
|
56
72
|
(acceptance.source_rung === "derived" || acceptance.source_rung === "project_floor")) {
|
|
57
|
-
const runner =
|
|
73
|
+
const runner = optionsWithScope.runner;
|
|
58
74
|
const direct = runLiteralAcceptanceCommands(acceptance.commands.map((c) => ({
|
|
59
75
|
command: c.command,
|
|
60
76
|
cwd: c.cwd ?? null,
|
|
@@ -62,25 +78,29 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
|
|
|
62
78
|
expectedExitCode: c.expectedExitCode ?? 0,
|
|
63
79
|
source: "explicit",
|
|
64
80
|
sourceSpan: "plan.acceptance.commands",
|
|
65
|
-
})), {
|
|
66
|
-
|
|
81
|
+
})), {
|
|
82
|
+
projectRoot,
|
|
83
|
+
runner,
|
|
84
|
+
allowTaskStatement: optionsWithScope.allowTaskStatement,
|
|
85
|
+
});
|
|
86
|
+
return applyOracle(annotate(direct, acceptance, optionsWithScope.quiet), optionsWithScope);
|
|
67
87
|
}
|
|
68
88
|
// Check composition: mid-story unpromoted capture-only may soft-pass so the
|
|
69
89
|
// framework graph is not deadlocked before agents promote peers.
|
|
70
90
|
// Greptile P1 #3284: safety-rejected stated commands NEVER soft-pass — they
|
|
71
91
|
// block product verification until a safe alternative is promoted.
|
|
72
|
-
if (
|
|
92
|
+
if (optionsWithScope.checkIntegrated === true && !base.ok && base.runs.length === 0) {
|
|
73
93
|
const hasRejected = (base.rejected?.length ?? 0) > 0;
|
|
74
94
|
if (hasRejected) {
|
|
75
|
-
return annotate(base, acceptance,
|
|
95
|
+
return applyOracle(annotate(base, acceptance, optionsWithScope.quiet), optionsWithScope);
|
|
76
96
|
}
|
|
77
97
|
const unpromoted = /capture-only|task_statement|no matching agent-promoted/i.test(base.message) ||
|
|
78
98
|
(base.commands.length > 0 && base.commands.every((c) => c.source === "task_statement"));
|
|
79
99
|
if (unpromoted || base.commands.length === 0) {
|
|
80
|
-
return {
|
|
100
|
+
return applyOracle({
|
|
81
101
|
ok: true,
|
|
82
102
|
code: 0,
|
|
83
|
-
message:
|
|
103
|
+
message: optionsWithScope.quiet
|
|
84
104
|
? ""
|
|
85
105
|
: `verify:ac advisory (#3284 check-integrated): no executable AC peers yet ` +
|
|
86
106
|
`(capture-only / empty). Done-gate standalone verify:ac still requires promotion. ` +
|
|
@@ -92,10 +112,165 @@ export function evaluateVerifyAcFromPlan(plan, options = {}) {
|
|
|
92
112
|
sourceRung: acceptance.source_rung,
|
|
93
113
|
noneStated: acceptance.none_stated,
|
|
94
114
|
acceptance,
|
|
95
|
-
|
|
115
|
+
resolution: classifyResolution({
|
|
116
|
+
ok: true,
|
|
117
|
+
code: 0,
|
|
118
|
+
runsLength: 0,
|
|
119
|
+
commandCount: base.commands.length,
|
|
120
|
+
rejectedCount: base.rejected?.length ?? 0,
|
|
121
|
+
}),
|
|
122
|
+
resolvedCommandCount: base.commands.length,
|
|
123
|
+
}, optionsWithScope);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return applyOracle(annotate(base, acceptance, optionsWithScope.quiet), optionsWithScope);
|
|
127
|
+
}
|
|
128
|
+
function classifyResolution(input) {
|
|
129
|
+
if (input.resolution !== undefined) {
|
|
130
|
+
return input.resolution;
|
|
131
|
+
}
|
|
132
|
+
if (input.code === 2) {
|
|
133
|
+
return "config";
|
|
134
|
+
}
|
|
135
|
+
if (!input.ok) {
|
|
136
|
+
return "fail";
|
|
137
|
+
}
|
|
138
|
+
if (input.runsLength > 0) {
|
|
139
|
+
return "verified-pass";
|
|
140
|
+
}
|
|
141
|
+
if (isEmptyAcResolution(input)) {
|
|
142
|
+
return "empty-pass";
|
|
143
|
+
}
|
|
144
|
+
return "empty-pass";
|
|
145
|
+
}
|
|
146
|
+
function applyEmptyFloorPolicy(result, options) {
|
|
147
|
+
if (!isEmptyAcResolution({
|
|
148
|
+
ok: result.ok,
|
|
149
|
+
code: result.code,
|
|
150
|
+
runsLength: result.runs.length,
|
|
151
|
+
commandCount: Math.max(result.commands.length, result.acceptance.commands.length),
|
|
152
|
+
rejectedCount: result.rejected?.length ?? 0,
|
|
153
|
+
resolution: result.resolution,
|
|
154
|
+
})) {
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
const projectRoot = resolve(options.projectRoot ?? process.cwd());
|
|
158
|
+
const suiteFloor = options.hasSuiteFloor ?? projectHasSuiteFloor(projectRoot);
|
|
159
|
+
if (suiteFloor) {
|
|
160
|
+
return {
|
|
161
|
+
...result,
|
|
162
|
+
resolution: "empty-pass",
|
|
163
|
+
resolvedCommandCount: 0,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
...result,
|
|
168
|
+
ok: false,
|
|
169
|
+
code: 1,
|
|
170
|
+
message: formatSoftEmptyMessage(result.acceptance),
|
|
171
|
+
resolution: "soft_empty",
|
|
172
|
+
resolvedCommandCount: 0,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function acceptanceOutcomeOf(result) {
|
|
176
|
+
if (result.resolution === "verified-pass")
|
|
177
|
+
return "verified-pass";
|
|
178
|
+
if (result.resolution === "empty-pass")
|
|
179
|
+
return "empty-pass";
|
|
180
|
+
if (result.resolution === "soft_empty")
|
|
181
|
+
return "soft_empty";
|
|
182
|
+
if (result.resolution === "fail")
|
|
183
|
+
return "fail";
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
function emitAcceptanceOutcome(result, options, projectRoot) {
|
|
187
|
+
if (options.env === undefined) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const dest = options.env[ENV_RUN_SUMMARY_PATH];
|
|
191
|
+
if (dest === undefined || dest.trim().length === 0) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const outcome = acceptanceOutcomeOf(result);
|
|
195
|
+
if (outcome === null) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
const emitter = new RunSummaryEmitter({
|
|
200
|
+
projectRoot,
|
|
201
|
+
sessionId: (typeof options.env.DEFT_SESSION_ID === "string" && options.env.DEFT_SESSION_ID.trim()) ||
|
|
202
|
+
"verify-ac",
|
|
203
|
+
env: options.env,
|
|
204
|
+
});
|
|
205
|
+
emitter.emitAcceptance({
|
|
206
|
+
resolved_command_count: result.resolvedCommandCount,
|
|
207
|
+
outcome,
|
|
208
|
+
source_rung: result.sourceRung,
|
|
209
|
+
none_stated: result.noneStated,
|
|
210
|
+
clause_count: result.clauseOutcomes?.length,
|
|
211
|
+
clause_outcomes: result.clauseOutcomes?.map((row) => ({
|
|
212
|
+
id: row.id,
|
|
213
|
+
outcome: row.outcome,
|
|
214
|
+
})),
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// fail-open
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function applyClauseWalk(result, options) {
|
|
222
|
+
const clauses = result.acceptance.clauses ?? [];
|
|
223
|
+
if (clauses.length === 0 || result.resolution === "config" || result.resolution === "skipped") {
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
const projectRoot = resolve(options.projectRoot ?? process.cwd());
|
|
227
|
+
const report = walkAcceptanceClauses(clauses, projectRoot);
|
|
228
|
+
const message = options.quiet ? result.message : formatClauseWalkMessage(report, result.message);
|
|
229
|
+
const ok = result.ok && report.ok;
|
|
230
|
+
return {
|
|
231
|
+
...result,
|
|
232
|
+
ok,
|
|
233
|
+
code: ok ? result.code : result.code === 2 ? 2 : 1,
|
|
234
|
+
message,
|
|
235
|
+
resolution: ok
|
|
236
|
+
? result.resolution === "empty-pass"
|
|
237
|
+
? "verified-pass"
|
|
238
|
+
: result.resolution
|
|
239
|
+
: "fail",
|
|
240
|
+
clauseOutcomes: report.clauses,
|
|
241
|
+
clauseWalked: true,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function applyOracle(result, options) {
|
|
245
|
+
const projectRoot = resolve(options.projectRoot ?? process.cwd());
|
|
246
|
+
const walked = applyClauseWalk(result, options);
|
|
247
|
+
const gated = walked.clauseWalked === true ? walked : applyEmptyFloorPolicy(walked, options);
|
|
248
|
+
// Emit/read disk only when the caller supplied env (CLI passes process.env).
|
|
249
|
+
// Tests stay isolated unless they opt in with env or runSummaryText.
|
|
250
|
+
if (options.env !== undefined) {
|
|
251
|
+
emitVerifyAcAttempts({
|
|
252
|
+
projectRoot,
|
|
253
|
+
runs: gated.runs,
|
|
254
|
+
env: options.env,
|
|
255
|
+
scopeKey: options.oracleScopeKey,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
let next = gated;
|
|
259
|
+
if (options.applyOracleIntegrity !== false) {
|
|
260
|
+
const verdict = evaluateProductOracleIntegrity({
|
|
261
|
+
projectRoot,
|
|
262
|
+
runSummaryText: options.runSummaryText,
|
|
263
|
+
env: options.env,
|
|
264
|
+
});
|
|
265
|
+
next = mergeOracleVerdict(gated, verdict);
|
|
266
|
+
if (!verdict.ok && next.resolution !== "soft_empty" && next.resolution !== "config") {
|
|
267
|
+
next = { ...next, resolution: "fail" };
|
|
96
268
|
}
|
|
97
269
|
}
|
|
98
|
-
|
|
270
|
+
if (options.skipAcceptanceEmit !== true) {
|
|
271
|
+
emitAcceptanceOutcome(next, options, projectRoot);
|
|
272
|
+
}
|
|
273
|
+
return next;
|
|
99
274
|
}
|
|
100
275
|
function annotate(result, acceptance, quiet) {
|
|
101
276
|
const prefix = result.ok
|
|
@@ -116,12 +291,21 @@ function annotate(result, acceptance, quiet) {
|
|
|
116
291
|
else if (result.ok) {
|
|
117
292
|
message = "";
|
|
118
293
|
}
|
|
294
|
+
const commandCount = Math.max(result.commands.length, acceptance.commands.length);
|
|
119
295
|
return {
|
|
120
296
|
...result,
|
|
121
297
|
message,
|
|
122
298
|
sourceRung: acceptance.source_rung,
|
|
123
299
|
noneStated: acceptance.none_stated,
|
|
124
300
|
acceptance,
|
|
301
|
+
resolution: classifyResolution({
|
|
302
|
+
ok: result.ok,
|
|
303
|
+
code: result.code,
|
|
304
|
+
runsLength: result.runs.length,
|
|
305
|
+
commandCount,
|
|
306
|
+
rejectedCount: result.rejected?.length ?? 0,
|
|
307
|
+
}),
|
|
308
|
+
resolvedCommandCount: result.runs.length > 0 ? result.runs.length : commandCount,
|
|
125
309
|
};
|
|
126
310
|
}
|
|
127
311
|
/**
|
|
@@ -131,18 +315,9 @@ export function evaluateVerifyAcFromPath(xbriefPath, options = {}) {
|
|
|
131
315
|
const abs = resolve(xbriefPath);
|
|
132
316
|
if (!existsSync(abs)) {
|
|
133
317
|
if (options.softMissingXbrief) {
|
|
134
|
-
return softSkip(`xBRIEF not found: ${abs}`, options.quiet);
|
|
318
|
+
return applyOracle(softSkip(`xBRIEF not found: ${abs}`, options.quiet), options);
|
|
135
319
|
}
|
|
136
|
-
return {
|
|
137
|
-
ok: false,
|
|
138
|
-
code: 2,
|
|
139
|
-
message: `verify:ac: xBRIEF not found: ${abs}`,
|
|
140
|
-
commands: [],
|
|
141
|
-
runs: [],
|
|
142
|
-
sourceRung: "project_floor",
|
|
143
|
-
noneStated: true,
|
|
144
|
-
acceptance: { commands: [], none_stated: true, source_rung: "project_floor" },
|
|
145
|
-
};
|
|
320
|
+
return applyOracle(configResult(`verify:ac: xBRIEF not found: ${abs}`), options);
|
|
146
321
|
}
|
|
147
322
|
let parsed;
|
|
148
323
|
try {
|
|
@@ -150,45 +325,45 @@ export function evaluateVerifyAcFromPath(xbriefPath, options = {}) {
|
|
|
150
325
|
}
|
|
151
326
|
catch (err) {
|
|
152
327
|
const msg = err instanceof Error ? err.message : String(err);
|
|
153
|
-
return {
|
|
154
|
-
ok: false,
|
|
155
|
-
code: 2,
|
|
156
|
-
message: `verify:ac: unreadable xBRIEF (${msg}): ${abs}`,
|
|
157
|
-
commands: [],
|
|
158
|
-
runs: [],
|
|
159
|
-
sourceRung: "project_floor",
|
|
160
|
-
noneStated: true,
|
|
161
|
-
acceptance: { commands: [], none_stated: true, source_rung: "project_floor" },
|
|
162
|
-
};
|
|
328
|
+
return applyOracle(configResult(`verify:ac: unreadable xBRIEF (${msg}): ${abs}`), options);
|
|
163
329
|
}
|
|
164
330
|
const data = asRecord(parsed);
|
|
165
331
|
if (data === null) {
|
|
166
|
-
return {
|
|
167
|
-
ok: false,
|
|
168
|
-
code: 2,
|
|
169
|
-
message: `verify:ac: xBRIEF top-level is not an object: ${abs}`,
|
|
170
|
-
commands: [],
|
|
171
|
-
runs: [],
|
|
172
|
-
sourceRung: "project_floor",
|
|
173
|
-
noneStated: true,
|
|
174
|
-
acceptance: { commands: [], none_stated: true, source_rung: "project_floor" },
|
|
175
|
-
};
|
|
332
|
+
return applyOracle(configResult(`verify:ac: xBRIEF top-level is not an object: ${abs}`), options);
|
|
176
333
|
}
|
|
177
334
|
const plan = asRecord(data.plan);
|
|
178
335
|
if (plan === null) {
|
|
179
|
-
return {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
336
|
+
return applyOracle(configResult(`verify:ac: xBRIEF missing plan object: ${abs}`), options);
|
|
337
|
+
}
|
|
338
|
+
const projectRoot = resolve(options.projectRoot ?? process.cwd());
|
|
339
|
+
// Path-relative keys stay unique across xbrief/ vs vbrief/ and duplicate plan.id (#3337 Greptile).
|
|
340
|
+
const oracleScopeKey = options.oracleScopeKey?.trim() || resolveOracleScopeKey(plan, abs, projectRoot);
|
|
341
|
+
const result = evaluateVerifyAcFromPlan(plan, {
|
|
342
|
+
...options,
|
|
343
|
+
skipAcceptanceEmit: true,
|
|
344
|
+
oracleScopeKey,
|
|
345
|
+
});
|
|
346
|
+
const banked = maybeAttachAcPassBank(result, plan, abs, options);
|
|
347
|
+
emitAcceptanceOutcome(banked, options, projectRoot);
|
|
348
|
+
return banked;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Unique product-oracle scope key for one active xBRIEF path (#3337).
|
|
352
|
+
* Relative path is always unique across active roots; plan.id alone is not
|
|
353
|
+
* (duplicate ids / same stem in xbrief+vbrief). Prefer `id@relPath` when both exist.
|
|
354
|
+
*/
|
|
355
|
+
export function resolveOracleScopeKey(plan, xbriefPath, projectRoot) {
|
|
356
|
+
const abs = resolve(xbriefPath);
|
|
357
|
+
const root = resolve(projectRoot);
|
|
358
|
+
let rel = relative(root, abs).replace(/\\/g, "/");
|
|
359
|
+
if (rel.length === 0 || rel.startsWith("..") || isAbsolute(rel)) {
|
|
360
|
+
rel = basename(abs);
|
|
361
|
+
}
|
|
362
|
+
const planId = typeof plan.id === "string" && plan.id.trim() ? plan.id.trim() : null;
|
|
363
|
+
if (planId !== null) {
|
|
364
|
+
return `${planId}@${rel}`;
|
|
189
365
|
}
|
|
190
|
-
|
|
191
|
-
return maybeAttachAcPassBank(result, plan, abs, options);
|
|
366
|
+
return rel;
|
|
192
367
|
}
|
|
193
368
|
/**
|
|
194
369
|
* After executable AC pass, FINALIZE the banking checkpoint (#3285).
|
|
@@ -231,11 +406,26 @@ function maybeAttachAcPassBank(result, plan, xbriefPath, options) {
|
|
|
231
406
|
...result,
|
|
232
407
|
ok: false,
|
|
233
408
|
code: 1,
|
|
409
|
+
resolution: "fail",
|
|
234
410
|
message: `verify:ac bank checkpoint failed (#3285): ${msg}` +
|
|
235
411
|
(result.message ? `\n${result.message}` : ""),
|
|
236
412
|
};
|
|
237
413
|
}
|
|
238
414
|
}
|
|
415
|
+
function configResult(message) {
|
|
416
|
+
return {
|
|
417
|
+
ok: false,
|
|
418
|
+
code: 2,
|
|
419
|
+
message,
|
|
420
|
+
commands: [],
|
|
421
|
+
runs: [],
|
|
422
|
+
sourceRung: "project_floor",
|
|
423
|
+
noneStated: true,
|
|
424
|
+
acceptance: { commands: [], none_stated: true, source_rung: "project_floor" },
|
|
425
|
+
resolution: "config",
|
|
426
|
+
resolvedCommandCount: 0,
|
|
427
|
+
};
|
|
428
|
+
}
|
|
239
429
|
function softSkip(detail, quiet) {
|
|
240
430
|
return {
|
|
241
431
|
ok: true,
|
|
@@ -246,6 +436,8 @@ function softSkip(detail, quiet) {
|
|
|
246
436
|
sourceRung: "project_floor",
|
|
247
437
|
noneStated: true,
|
|
248
438
|
acceptance: { commands: [], none_stated: true, source_rung: "project_floor" },
|
|
439
|
+
resolution: "skipped",
|
|
440
|
+
resolvedCommandCount: 0,
|
|
249
441
|
};
|
|
250
442
|
}
|
|
251
443
|
/** Pure: product AC is required at every ceremony depth (#3284 / #3267 / #3156). */
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { attachPlanAcceptance, buildAcceptanceFromIntakeCapture, readPlanAcceptance, stampAcceptanceFromLiteralCapture, validatePlanAcceptance, } from "./acceptance.js";
|
|
8
8
|
export { applyProductFirstGateMode, isHygieneGate, isProductAcGate, type ProductFirstCheckModeResolution, type ResolveProductFirstCheckModeInput, resolveProductFirstCheckMode, } from "./check-mode.js";
|
|
9
|
-
export {
|
|
9
|
+
export { EMPTY_AC_CAUSE, EMPTY_AC_OUTCOME, EMPTY_AC_REMEDY, formatSoftEmptyMessage, isEmptyAcResolution, isSoftEmptyAcText, projectHasSuiteFloor, type VerifyAcResolution, } from "./empty-resolution.js";
|
|
10
|
+
export { type EvaluateVerifyAcOptions, evaluateVerifyAcFromPath, evaluateVerifyAcFromPlan, isVerifyAcRequiredAtCeremonyDepth, resolveOracleScopeKey, type VerifyAcResult, } from "./evaluate.js";
|
|
10
11
|
export { type AcceptanceCommand, type AcSourceRung, ENV_CHECK_AC_ONLY, ENV_CHECK_MODE, ENV_HYGIENE_ADVISORY, HYGIENE_GATE_ID_PREFIXES, PLAN_ACCEPTANCE_KEY, type PlanAcceptance, PRODUCT_AC_GATE_ID, type ProductFirstCheckMode, } from "./types.js";
|
|
11
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { attachPlanAcceptance, buildAcceptanceFromIntakeCapture, readPlanAcceptance, stampAcceptanceFromLiteralCapture, validatePlanAcceptance, } from "./acceptance.js";
|
|
8
8
|
export { applyProductFirstGateMode, isHygieneGate, isProductAcGate, resolveProductFirstCheckMode, } from "./check-mode.js";
|
|
9
|
-
export {
|
|
9
|
+
export { EMPTY_AC_CAUSE, EMPTY_AC_OUTCOME, EMPTY_AC_REMEDY, formatSoftEmptyMessage, isEmptyAcResolution, isSoftEmptyAcText, projectHasSuiteFloor, } from "./empty-resolution.js";
|
|
10
|
+
export { evaluateVerifyAcFromPath, evaluateVerifyAcFromPlan, isVerifyAcRequiredAtCeremonyDepth, resolveOracleScopeKey, } from "./evaluate.js";
|
|
10
11
|
export { ENV_CHECK_AC_ONLY, ENV_CHECK_MODE, ENV_HYGIENE_ADVISORY, HYGIENE_GATE_ID_PREFIXES, PLAN_ACCEPTANCE_KEY, PRODUCT_AC_GATE_ID, } from "./types.js";
|
|
11
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AcceptanceClause } from "../verify-ac/clauses.js";
|
|
1
2
|
/**
|
|
2
3
|
* Product-first done-gate (#3284): stated acceptance criteria run FIRST and are
|
|
3
4
|
* never skippable; hygiene gates run second and may degrade under pressure.
|
|
@@ -31,6 +32,8 @@ export interface PlanAcceptance {
|
|
|
31
32
|
readonly source_rung: AcSourceRung;
|
|
32
33
|
/** Why derived/floor was chosen (required for derived when recorded). */
|
|
33
34
|
readonly derived_reason?: string | null;
|
|
35
|
+
/** Rung-2 independently testable clauses (#3323). Parallel to commands[]. */
|
|
36
|
+
readonly clauses?: readonly AcceptanceClause[];
|
|
34
37
|
}
|
|
35
38
|
/** How `task check` composes product vs hygiene gates under pressure (#3284). */
|
|
36
39
|
export type ProductFirstCheckMode =
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Product-first done-gate (#3284): stated acceptance criteria run FIRST and are
|
|
3
|
-
* never skippable; hygiene gates run second and may degrade under pressure.
|
|
4
|
-
*
|
|
5
|
-
* Architecture for #3267 (literal acceptance-command mechanism). Composes
|
|
6
|
-
* #3214 ceremony dial (rapid = AC-only) and #3266 bank-the-pass.
|
|
7
|
-
*/
|
|
8
1
|
/** Canonical product AC gate id used in check gate lists. */
|
|
9
2
|
export const PRODUCT_AC_GATE_ID = "verify:ac";
|
|
10
3
|
/** plan.acceptance object key on the plan root. */
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Symlink destinations are refused (no-follow / containment) — fail-open.
|
|
7
7
|
*/
|
|
8
8
|
import { type ResolveRunSummaryDestinationOptions } from "./path.js";
|
|
9
|
-
import { type CheckInvocationRunSummaryPayload, type DialTransitionRunSummaryPayload, type RunSummaryDestination, type RunSummaryEventKind, type RunSummaryLine, type RunSummaryPayload, type SessionStartRunSummaryPayload } from "./types.js";
|
|
9
|
+
import { type AcceptanceRunSummaryPayload, type AcceptanceStampRunSummaryPayload, type CheckInvocationRunSummaryPayload, type DialEscalationEvaluationRunSummaryPayload, type DialTransitionRunSummaryPayload, type RunSummaryDestination, type RunSummaryEventKind, type RunSummaryLine, type RunSummaryPayload, type SessionStartRunSummaryPayload, type ToolTurnDenominatorRunSummaryPayload, type VerificationRunSummaryPayload } from "./types.js";
|
|
10
10
|
export interface RunSummaryEmitterOptions extends ResolveRunSummaryDestinationOptions {
|
|
11
11
|
readonly projectRoot: string;
|
|
12
12
|
readonly sessionId: string;
|
|
@@ -36,6 +36,7 @@ export declare class RunSummaryEmitter {
|
|
|
36
36
|
private readonly frameworkVersion;
|
|
37
37
|
private readonly now;
|
|
38
38
|
private readonly destination;
|
|
39
|
+
private readonly env;
|
|
39
40
|
private readonly writeStdout;
|
|
40
41
|
private readonly writeStderr;
|
|
41
42
|
constructor(options: RunSummaryEmitterOptions);
|
|
@@ -43,8 +44,17 @@ export declare class RunSummaryEmitter {
|
|
|
43
44
|
emit(event: RunSummaryEventKind, payload: RunSummaryPayload): EmitRunSummaryResult;
|
|
44
45
|
emitSessionStart(payload: SessionStartRunSummaryPayload): EmitRunSummaryResult;
|
|
45
46
|
emitDialTransition(payload: DialTransitionRunSummaryPayload): EmitRunSummaryResult;
|
|
47
|
+
emitDialEscalationEvaluation(payload: DialEscalationEvaluationRunSummaryPayload): EmitRunSummaryResult;
|
|
46
48
|
emitCheckInvocation(payload: CheckInvocationRunSummaryPayload): EmitRunSummaryResult;
|
|
49
|
+
emitToolTurnDenominator(payload: ToolTurnDenominatorRunSummaryPayload): EmitRunSummaryResult;
|
|
50
|
+
emitVerification(payload: VerificationRunSummaryPayload): EmitRunSummaryResult;
|
|
51
|
+
emitAcceptance(payload: AcceptanceRunSummaryPayload): EmitRunSummaryResult;
|
|
52
|
+
emitAcceptanceStamp(payload: AcceptanceStampRunSummaryPayload): EmitRunSummaryResult;
|
|
53
|
+
/** Emit the harness-supplied denominator when DEFT_TOTAL_TOOL_TURNS is set. */
|
|
54
|
+
emitKnownToolTurnDenominator(): EmitRunSummaryResult;
|
|
47
55
|
}
|
|
56
|
+
/** Parse harness-supplied DEFT_TOTAL_TOOL_TURNS (integer > 0). Invalid/unset → omit. */
|
|
57
|
+
export declare function readEnvToolTurnDenominator(env: NodeJS.ProcessEnv): number | undefined;
|
|
48
58
|
/**
|
|
49
59
|
* One-shot helper for call sites that do not hold an emitter (e.g. dial escalate).
|
|
50
60
|
* Still fail-open; creates a fresh seq=1 emitter unless `seqSeed` is passed via reuse.
|
package/dist/run-summary/emit.js
CHANGED
|
@@ -11,7 +11,7 @@ import { readCorePackageVersion } from "../engine-version.js";
|
|
|
11
11
|
import { containedWrite } from "../fs/contained-write.js";
|
|
12
12
|
import { assertWriteTargetSafe } from "../fs/projection-containment.js";
|
|
13
13
|
import { resolveRunSummaryDestination } from "./path.js";
|
|
14
|
-
import { RUN_SUMMARY_SCHEMA_VERSION, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, } from "./types.js";
|
|
14
|
+
import { ENV_TOTAL_TOOL_TURNS, RUN_SUMMARY_SCHEMA_VERSION, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, } from "./types.js";
|
|
15
15
|
function sortKeysDeep(value) {
|
|
16
16
|
if (Array.isArray(value)) {
|
|
17
17
|
return value.map(sortKeysDeep);
|
|
@@ -90,6 +90,7 @@ export class RunSummaryEmitter {
|
|
|
90
90
|
frameworkVersion;
|
|
91
91
|
now;
|
|
92
92
|
destination;
|
|
93
|
+
env;
|
|
93
94
|
writeStdout;
|
|
94
95
|
writeStderr;
|
|
95
96
|
constructor(options) {
|
|
@@ -97,10 +98,11 @@ export class RunSummaryEmitter {
|
|
|
97
98
|
this.sessionId = options.sessionId;
|
|
98
99
|
this.frameworkVersion = options.frameworkVersion ?? readCorePackageVersion();
|
|
99
100
|
this.now = options.now ?? (() => new Date());
|
|
101
|
+
this.env = options.env ?? process.env;
|
|
100
102
|
this.destination =
|
|
101
103
|
options.destination ??
|
|
102
104
|
resolveRunSummaryDestination(options.projectRoot, {
|
|
103
|
-
env:
|
|
105
|
+
env: this.env,
|
|
104
106
|
gitignoreCovers: options.gitignoreCovers,
|
|
105
107
|
});
|
|
106
108
|
this.writeStdout = options.writeStdout ?? ((line) => process.stdout.write(`${line}\n`));
|
|
@@ -115,6 +117,7 @@ export class RunSummaryEmitter {
|
|
|
115
117
|
return { emitted: false, destination: this.destination, line: null, warning: false };
|
|
116
118
|
}
|
|
117
119
|
this.seq += 1;
|
|
120
|
+
const denominator = readPayloadToolTurnDenominator(payload) ?? readEnvToolTurnDenominator(this.env);
|
|
118
121
|
const line = {
|
|
119
122
|
schema_version: RUN_SUMMARY_SCHEMA_VERSION,
|
|
120
123
|
session_id: this.sessionId,
|
|
@@ -123,6 +126,7 @@ export class RunSummaryEmitter {
|
|
|
123
126
|
ts: this.now().toISOString(),
|
|
124
127
|
event,
|
|
125
128
|
payload,
|
|
129
|
+
...(denominator !== undefined ? { total_tool_turns: denominator } : {}),
|
|
126
130
|
};
|
|
127
131
|
const text = lineToJson(line);
|
|
128
132
|
if (this.destination.kind === "stdout") {
|
|
@@ -156,9 +160,51 @@ export class RunSummaryEmitter {
|
|
|
156
160
|
emitDialTransition(payload) {
|
|
157
161
|
return this.emit("dial_transition", payload);
|
|
158
162
|
}
|
|
163
|
+
emitDialEscalationEvaluation(payload) {
|
|
164
|
+
return this.emit("dial_escalation_evaluation", payload);
|
|
165
|
+
}
|
|
159
166
|
emitCheckInvocation(payload) {
|
|
160
167
|
return this.emit("check_invocation", payload);
|
|
161
168
|
}
|
|
169
|
+
emitToolTurnDenominator(payload) {
|
|
170
|
+
return this.emit("tool_turn_denominator", payload);
|
|
171
|
+
}
|
|
172
|
+
emitVerification(payload) {
|
|
173
|
+
return this.emit("verification", payload);
|
|
174
|
+
}
|
|
175
|
+
emitAcceptance(payload) {
|
|
176
|
+
return this.emit("acceptance", payload);
|
|
177
|
+
}
|
|
178
|
+
emitAcceptanceStamp(payload) {
|
|
179
|
+
return this.emit("acceptance_stamp", payload);
|
|
180
|
+
}
|
|
181
|
+
/** Emit the harness-supplied denominator when DEFT_TOTAL_TOOL_TURNS is set. */
|
|
182
|
+
emitKnownToolTurnDenominator() {
|
|
183
|
+
const n = readEnvToolTurnDenominator(this.env);
|
|
184
|
+
if (n === undefined) {
|
|
185
|
+
return { emitted: false, destination: this.destination, line: null, warning: false };
|
|
186
|
+
}
|
|
187
|
+
return this.emitToolTurnDenominator({ total_tool_turns: n });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function readPayloadToolTurnDenominator(payload) {
|
|
191
|
+
if (!("total_tool_turns" in payload)) {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
const value = payload.total_tool_turns;
|
|
195
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
196
|
+
}
|
|
197
|
+
/** Parse harness-supplied DEFT_TOTAL_TOOL_TURNS (integer > 0). Invalid/unset → omit. */
|
|
198
|
+
export function readEnvToolTurnDenominator(env) {
|
|
199
|
+
const raw = env[ENV_TOTAL_TOOL_TURNS];
|
|
200
|
+
if (raw === undefined || raw.trim().length === 0) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
const n = Number(raw.trim());
|
|
204
|
+
if (!Number.isInteger(n) || !Number.isFinite(n) || n <= 0) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
return n;
|
|
162
208
|
}
|
|
163
209
|
/**
|
|
164
210
|
* One-shot helper for call sites that do not hold an emitter (e.g. dial escalate).
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { type EmitRunSummaryResult, emitRunSummaryEvent, RunSummaryEmitter, type RunSummaryEmitterOptions, } from "./emit.js";
|
|
2
2
|
export { gitignoreCoversRunSummary, type ResolveRunSummaryDestinationOptions, resolveRunSummaryDestination, } from "./path.js";
|
|
3
|
-
export {
|
|
3
|
+
export { computeRitualGateShare, parseRunSummaryJsonl, type RitualGateShare, readToolTurnDenominator, } from "./share.js";
|
|
4
|
+
export { type AcceptanceClauseOutcomeRow, type AcceptanceRunSummaryOutcome, type AcceptanceRunSummaryPayload, type AcceptanceStampRunSummaryPayload, type CheckGateOutcome, type CheckInvocationRunSummaryPayload, DEFAULT_RUN_SUMMARY_BASENAME, type DialEscalationEvaluationOutcome, type DialEscalationEvaluationRunSummaryPayload, type DialTransitionRunSummaryPayload, ENV_RUN_SUMMARY_PATH, ENV_TOTAL_TOOL_TURNS, RUN_SUMMARY_EVENT_KINDS, RUN_SUMMARY_SCHEMA_VERSION, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, type RunSummaryBaseFields, type RunSummaryDestination, type RunSummaryEventKind, type RunSummaryLine, type RunSummaryPayload, type SessionStartRunSummaryPayload, type ToolTurnDenominatorRunSummaryPayload, type VerificationOutcome, type VerificationRunSummaryPayload, } from "./types.js";
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { emitRunSummaryEvent, RunSummaryEmitter, } from "./emit.js";
|
|
2
2
|
export { gitignoreCoversRunSummary, resolveRunSummaryDestination, } from "./path.js";
|
|
3
|
-
export {
|
|
3
|
+
export { computeRitualGateShare, parseRunSummaryJsonl, readToolTurnDenominator, } from "./share.js";
|
|
4
|
+
export { DEFAULT_RUN_SUMMARY_BASENAME, ENV_RUN_SUMMARY_PATH, ENV_TOTAL_TOOL_TURNS, RUN_SUMMARY_EVENT_KINDS, RUN_SUMMARY_SCHEMA_VERSION, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, } from "./types.js";
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - unset → repo-root `.deft-run-summary.json` only when .gitignore covers it; else silent
|
|
7
7
|
*/
|
|
8
8
|
import { type RunSummaryDestination } from "./types.js";
|
|
9
|
-
export { DEFAULT_RUN_SUMMARY_BASENAME, ENV_RUN_SUMMARY_PATH, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, } from "./types.js";
|
|
9
|
+
export { DEFAULT_RUN_SUMMARY_BASENAME, ENV_RUN_SUMMARY_PATH, ENV_TOTAL_TOOL_TURNS, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, } from "./types.js";
|
|
10
10
|
/**
|
|
11
11
|
* True when a .gitignore line covers the default run-summary basename.
|
|
12
12
|
* Matches exact line or trailing slash variants; ignores comments.
|
package/dist/run-summary/path.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { existsSync, readFileSync } from "node:fs";
|
|
9
9
|
import { isAbsolute, join, resolve } from "node:path";
|
|
10
10
|
import { DEFAULT_RUN_SUMMARY_BASENAME, ENV_RUN_SUMMARY_PATH, } from "./types.js";
|
|
11
|
-
export { DEFAULT_RUN_SUMMARY_BASENAME, ENV_RUN_SUMMARY_PATH, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, } from "./types.js";
|
|
11
|
+
export { DEFAULT_RUN_SUMMARY_BASENAME, ENV_RUN_SUMMARY_PATH, ENV_TOTAL_TOOL_TURNS, RUN_SUMMARY_STDOUT_PREFIX, RUN_SUMMARY_WRITE_WARNING, } from "./types.js";
|
|
12
12
|
/**
|
|
13
13
|
* True when a .gitignore line covers the default run-summary basename.
|
|
14
14
|
* Matches exact line or trailing slash variants; ignores comments.
|