@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
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #3286 Later graduation trigger from a #3282 run summary (#3320).
|
|
3
|
+
*
|
|
4
|
+
* Named surface: eval:report prints graduate / do-not-graduate / unevaluable.
|
|
5
|
+
* A graduation or decline MUST cite an emitted share. Counts without a
|
|
6
|
+
* denominator are unevaluable — never invent a ratio.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
9
|
+
import { isAbsolute, resolve } from "node:path";
|
|
10
|
+
import { computeRitualGateShare, parseRunSummaryJsonl, } from "../run-summary/share.js";
|
|
11
|
+
import { DEFAULT_RUN_SUMMARY_BASENAME, ENV_RUN_SUMMARY_PATH } from "../run-summary/types.js";
|
|
12
|
+
/** #3286 Later trigger: graduate when ritual+gate share is at least this fraction. */
|
|
13
|
+
export const LATER_GRADUATION_SHARE_THRESHOLD = 0.25;
|
|
14
|
+
function formatPercent(value) {
|
|
15
|
+
return `${(value * 100).toFixed(1)}%`;
|
|
16
|
+
}
|
|
17
|
+
export function laterGraduationFromShare(share, threshold = LATER_GRADUATION_SHARE_THRESHOLD) {
|
|
18
|
+
if (!share.evaluable || share.share === null || share.totalToolTurns === null) {
|
|
19
|
+
return {
|
|
20
|
+
evaluable: false,
|
|
21
|
+
verdict: "unevaluable",
|
|
22
|
+
summary: "trigger unevaluable (no tool/turn denominator on run summary)",
|
|
23
|
+
ritualGateCount: share.ritualGateCount,
|
|
24
|
+
totalToolTurns: share.totalToolTurns,
|
|
25
|
+
share: null,
|
|
26
|
+
threshold,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const graduate = share.share >= threshold;
|
|
30
|
+
const verdict = graduate ? "graduate" : "do-not-graduate";
|
|
31
|
+
return {
|
|
32
|
+
evaluable: true,
|
|
33
|
+
verdict,
|
|
34
|
+
summary: `ritual+gate share ${formatPercent(share.share)} (${share.ritualGateCount}/${share.totalToolTurns}) — ${verdict} (threshold ${formatPercent(threshold)})`,
|
|
35
|
+
ritualGateCount: share.ritualGateCount,
|
|
36
|
+
totalToolTurns: share.totalToolTurns,
|
|
37
|
+
share: share.share,
|
|
38
|
+
threshold,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve a readable run-summary path. Unset env + missing default file → null
|
|
43
|
+
* (fail-open / unevaluable). stdout dest (`-`) is not a file.
|
|
44
|
+
*/
|
|
45
|
+
export function resolveRunSummaryReadPath(projectRoot, options = {}) {
|
|
46
|
+
if (options.runSummaryPath !== undefined && options.runSummaryPath.trim().length > 0) {
|
|
47
|
+
return resolve(options.runSummaryPath.trim());
|
|
48
|
+
}
|
|
49
|
+
const env = options.env ?? process.env;
|
|
50
|
+
const raw = env[ENV_RUN_SUMMARY_PATH];
|
|
51
|
+
if (raw !== undefined && raw.trim() === "-") {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
if (raw !== undefined && raw.trim().length > 0) {
|
|
55
|
+
const trimmed = raw.trim();
|
|
56
|
+
return isAbsolute(trimmed) ? resolve(trimmed) : resolve(projectRoot, trimmed);
|
|
57
|
+
}
|
|
58
|
+
const fallback = resolve(projectRoot, DEFAULT_RUN_SUMMARY_BASENAME);
|
|
59
|
+
return existsSync(fallback) ? fallback : null;
|
|
60
|
+
}
|
|
61
|
+
function readSummaryText(path) {
|
|
62
|
+
try {
|
|
63
|
+
if (!existsSync(path)) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return readFileSync(path, "utf8");
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Evaluate #3286 Later from the run-summary file (or unevaluable). */
|
|
73
|
+
export function evaluateLaterGraduationTrigger(options) {
|
|
74
|
+
const threshold = options.threshold ?? LATER_GRADUATION_SHARE_THRESHOLD;
|
|
75
|
+
const path = resolveRunSummaryReadPath(options.projectRoot, {
|
|
76
|
+
runSummaryPath: options.runSummaryPath,
|
|
77
|
+
env: options.env,
|
|
78
|
+
});
|
|
79
|
+
if (path === null) {
|
|
80
|
+
return laterGraduationFromShare({ evaluable: false, ritualGateCount: 0, totalToolTurns: null, share: null }, threshold);
|
|
81
|
+
}
|
|
82
|
+
const text = readSummaryText(path);
|
|
83
|
+
if (text === null) {
|
|
84
|
+
return laterGraduationFromShare({ evaluable: false, ritualGateCount: 0, totalToolTurns: null, share: null }, threshold);
|
|
85
|
+
}
|
|
86
|
+
return laterGraduationFromShare(computeRitualGateShare(parseRunSummaryJsonl(text)), threshold);
|
|
87
|
+
}
|
|
88
|
+
export function formatLaterGraduationLine(trigger) {
|
|
89
|
+
return `#3286 Later: ${trigger.summary}`;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=later-graduation.js.map
|
package/dist/eval/report.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type LaterGraduationTrigger } from "./later-graduation.js";
|
|
1
2
|
import { type GoldenRunRecord } from "./run.js";
|
|
2
3
|
import { type CellVersionPurity, type MixedVersionPolicy } from "./version-pin.js";
|
|
3
4
|
export declare const REPORT_SCHEMA_VERSION: 1;
|
|
@@ -39,6 +40,8 @@ export interface GoldenEvalReport {
|
|
|
39
40
|
readonly holdoutTripwire: HoldoutTripwire;
|
|
40
41
|
/** Cell-level framework version purity for the reported model (#3215). */
|
|
41
42
|
readonly versionPurity: VersionPurityEvidence;
|
|
43
|
+
/** #3286 Later graduation trigger from the run-summary denominator (#3320). */
|
|
44
|
+
readonly laterGraduation: LaterGraduationTrigger;
|
|
42
45
|
}
|
|
43
46
|
export interface ReportGoldenEvalOptions {
|
|
44
47
|
readonly projectRoot?: string;
|
|
@@ -50,6 +53,9 @@ export interface ReportGoldenEvalOptions {
|
|
|
50
53
|
* ledger runs for this model disagree on framework version within a treatment.
|
|
51
54
|
*/
|
|
52
55
|
readonly mixedVersionPolicy?: MixedVersionPolicy;
|
|
56
|
+
/** Override run-summary JSONL path (#3320). Default: DEFT_RUN_SUMMARY_PATH or repo default. */
|
|
57
|
+
readonly runSummaryPath?: string;
|
|
58
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
53
59
|
}
|
|
54
60
|
export interface ReportGoldenEvalResult {
|
|
55
61
|
readonly code: 0 | 1 | 2;
|
package/dist/eval/report.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { resolveEvalPath } from "../layout/resolve.js";
|
|
3
|
+
import { evaluateLaterGraduationTrigger, formatLaterGraduationLine, } from "./later-graduation.js";
|
|
3
4
|
import { GOLDEN_RUNS_HISTORY_REL } from "./run.js";
|
|
4
5
|
import { aggregateCellWithVersionPurity, evaluateLedgerVersionPurity, } from "./version-pin.js";
|
|
5
6
|
export const REPORT_SCHEMA_VERSION = 1;
|
|
@@ -107,17 +108,33 @@ export function goldenRunToVersionedRun(record) {
|
|
|
107
108
|
}
|
|
108
109
|
/** Diff two directive versions with metric deltas and significance (#1703 Tier 2). */
|
|
109
110
|
export function reportGoldenEval(options) {
|
|
110
|
-
|
|
111
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
112
|
+
const laterGraduation = evaluateLaterGraduationTrigger({
|
|
113
|
+
projectRoot,
|
|
114
|
+
runSummaryPath: options.runSummaryPath,
|
|
115
|
+
env: options.env,
|
|
116
|
+
});
|
|
117
|
+
const laterLine = formatLaterGraduationLine(laterGraduation);
|
|
118
|
+
const championMissing = !options.championVersion.trim();
|
|
119
|
+
const challengerMissing = !options.challengerVersion.trim();
|
|
120
|
+
const modelMissing = !options.model.trim();
|
|
121
|
+
if (championMissing && challengerMissing && modelMissing) {
|
|
122
|
+
return {
|
|
123
|
+
code: 0,
|
|
124
|
+
report: null,
|
|
125
|
+
message: `eval:report ${laterLine}`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (championMissing || challengerMissing) {
|
|
111
129
|
return {
|
|
112
130
|
code: 2,
|
|
113
131
|
report: null,
|
|
114
|
-
message:
|
|
132
|
+
message: `eval:report: --champion and --challenger are required\n ${laterLine}`,
|
|
115
133
|
};
|
|
116
134
|
}
|
|
117
|
-
if (
|
|
118
|
-
return { code: 2, report: null, message:
|
|
135
|
+
if (modelMissing) {
|
|
136
|
+
return { code: 2, report: null, message: `eval:report: --model is required\n ${laterLine}` };
|
|
119
137
|
}
|
|
120
|
-
const projectRoot = options.projectRoot ?? process.cwd();
|
|
121
138
|
const policy = options.mixedVersionPolicy ?? "refuse";
|
|
122
139
|
const records = readGoldenRuns(projectRoot);
|
|
123
140
|
const modelRecords = records.filter((r) => r.model === options.model);
|
|
@@ -157,7 +174,7 @@ export function reportGoldenEval(options) {
|
|
|
157
174
|
return {
|
|
158
175
|
code: 1,
|
|
159
176
|
report: null,
|
|
160
|
-
message: `eval:report: mixed framework versions in treatment cell(s) — aggregation refused (#3215)\n ${versionPurity.summary}`,
|
|
177
|
+
message: `eval:report: mixed framework versions in treatment cell(s) — aggregation refused (#3215)\n ${versionPurity.summary}\n ${laterLine}`,
|
|
161
178
|
};
|
|
162
179
|
}
|
|
163
180
|
const champion = findLatestGoldenRun(records, options.championVersion, options.model);
|
|
@@ -166,14 +183,14 @@ export function reportGoldenEval(options) {
|
|
|
166
183
|
return {
|
|
167
184
|
code: 1,
|
|
168
185
|
report: null,
|
|
169
|
-
message: `eval:report: no golden run found for champion v${options.championVersion} model=${options.model}`,
|
|
186
|
+
message: `eval:report: no golden run found for champion v${options.championVersion} model=${options.model}\n ${laterLine}`,
|
|
170
187
|
};
|
|
171
188
|
}
|
|
172
189
|
if (challenger === null) {
|
|
173
190
|
return {
|
|
174
191
|
code: 1,
|
|
175
192
|
report: null,
|
|
176
|
-
message: `eval:report: no golden run found for challenger v${options.challengerVersion} model=${options.model}`,
|
|
193
|
+
message: `eval:report: no golden run found for challenger v${options.challengerVersion} model=${options.model}\n ${laterLine}`,
|
|
177
194
|
};
|
|
178
195
|
}
|
|
179
196
|
const championPrimary = champion.results.filter((r) => !r.holdout);
|
|
@@ -208,6 +225,7 @@ export function reportGoldenEval(options) {
|
|
|
208
225
|
deltas,
|
|
209
226
|
holdoutTripwire,
|
|
210
227
|
versionPurity,
|
|
228
|
+
laterGraduation,
|
|
211
229
|
};
|
|
212
230
|
const lines = [
|
|
213
231
|
`eval:report champion=v${options.championVersion} challenger=v${options.challengerVersion} model=${options.model}`,
|
|
@@ -223,6 +241,7 @@ export function reportGoldenEval(options) {
|
|
|
223
241
|
` version purity: ${versionPurity.pure ? "ok" : "mixed"} — ${versionPurity.summary}`,
|
|
224
242
|
` champion cell pin: v${champion.frameworkVersionPin?.frameworkVersion ?? champion.directiveVersion}`,
|
|
225
243
|
` challenger cell pin: v${challenger.frameworkVersionPin?.frameworkVersion ?? challenger.directiveVersion}`,
|
|
244
|
+
` ${laterLine}`,
|
|
226
245
|
];
|
|
227
246
|
const code = holdoutTripwire.triggered ? 1 : 0;
|
|
228
247
|
return { code, report, message: lines.join("\n") };
|
package/dist/index.d.ts
CHANGED
|
@@ -74,6 +74,7 @@ export * as vbriefBuild from "./vbrief-build/index.js";
|
|
|
74
74
|
export * as vbriefReconcile from "./vbrief-reconcile/index.js";
|
|
75
75
|
export * as vbriefValidate from "./vbrief-validate/index.js";
|
|
76
76
|
export * as vbriefValidation from "./vbrief-validation/index.js";
|
|
77
|
+
export * as verifyAc from "./verify-ac/index.js";
|
|
77
78
|
export * as verifyEnv from "./verify-env/index.js";
|
|
78
79
|
export * as verifySource from "./verify-source/index.js";
|
|
79
80
|
export * as wipCap from "./wip-cap/index.js";
|
package/dist/index.js
CHANGED
|
@@ -75,6 +75,7 @@ export * as vbriefBuild from "./vbrief-build/index.js";
|
|
|
75
75
|
export * as vbriefReconcile from "./vbrief-reconcile/index.js";
|
|
76
76
|
export * as vbriefValidate from "./vbrief-validate/index.js";
|
|
77
77
|
export * as vbriefValidation from "./vbrief-validation/index.js";
|
|
78
|
+
export * as verifyAc from "./verify-ac/index.js";
|
|
78
79
|
export * as verifyEnv from "./verify-env/index.js";
|
|
79
80
|
export * as verifySource from "./verify-source/index.js";
|
|
80
81
|
export * as wipCap from "./wip-cap/index.js";
|
|
@@ -42,7 +42,13 @@ export declare function installerManagedMatchers(): InstallerManagedMatcher[];
|
|
|
42
42
|
* so an unlisted `xbrief/active/another-scope.xbrief.json` matcher still fails.
|
|
43
43
|
*/
|
|
44
44
|
export declare function assertInstallerAllowlistHonors1430(matchers?: readonly InstallerManagedMatcher[]): void;
|
|
45
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Individual POSIX ERE patterns for the deposited deft-core-guard allowlist.
|
|
47
|
+
* One pattern per line in the workflow heredoc (#3345) — joined form is still
|
|
48
|
+
* available via {@link installerManagedGuardEre} for tests and classifiers.
|
|
49
|
+
*/
|
|
50
|
+
export declare function installerManagedGuardErePatterns(): string[];
|
|
51
|
+
/** POSIX ERE alternation (joined) for tests / tooling that want a single pattern. */
|
|
46
52
|
export declare function installerManagedGuardEre(): string;
|
|
47
53
|
export declare function isInstallerManagedPath(path: string): boolean;
|
|
48
54
|
export interface MixedCoreAndAppClassification {
|
|
@@ -174,12 +174,20 @@ export function assertInstallerAllowlistHonors1430(matchers = installerManagedMa
|
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
|
-
/**
|
|
178
|
-
|
|
177
|
+
/**
|
|
178
|
+
* Individual POSIX ERE patterns for the deposited deft-core-guard allowlist.
|
|
179
|
+
* One pattern per line in the workflow heredoc (#3345) — joined form is still
|
|
180
|
+
* available via {@link installerManagedGuardEre} for tests and classifiers.
|
|
181
|
+
*/
|
|
182
|
+
export function installerManagedGuardErePatterns() {
|
|
179
183
|
const matchers = installerManagedMatchers();
|
|
180
184
|
// Refuse to emit a guard workflow that would exempt consumer denylist paths.
|
|
181
185
|
assertInstallerAllowlistHonors1430(matchers);
|
|
182
|
-
return matchers.map((matcher) => matcherToEre(matcher))
|
|
186
|
+
return matchers.map((matcher) => matcherToEre(matcher));
|
|
187
|
+
}
|
|
188
|
+
/** POSIX ERE alternation (joined) for tests / tooling that want a single pattern. */
|
|
189
|
+
export function installerManagedGuardEre() {
|
|
190
|
+
return installerManagedGuardErePatterns().join("|");
|
|
183
191
|
}
|
|
184
192
|
export function isInstallerManagedPath(path) {
|
|
185
193
|
return matchesInstallerManaged(path, installerManagedMatchers());
|
|
@@ -82,6 +82,18 @@ export declare function coreGuardCheckoutUsesLine(sha?: string, tag?: string): s
|
|
|
82
82
|
* the managed guard script / allowlist body (#1672 option 1).
|
|
83
83
|
*/
|
|
84
84
|
export declare function mergeCoreGuardWorkflowRefresh(existing: string, desired: string): string;
|
|
85
|
+
/**
|
|
86
|
+
* Soft max line length for deposited core-guard workflow YAML (#3345).
|
|
87
|
+
* Mega-line allowlist EREs previously sat near ~5k chars; keep well below.
|
|
88
|
+
* Enforced by {@link assertCoreGuardWorkflowLoadable} before deposit write.
|
|
89
|
+
*/
|
|
90
|
+
export declare const CORE_GUARD_WORKFLOW_MAX_LINE = 500;
|
|
91
|
+
/**
|
|
92
|
+
* Fail closed if a rendered deft-core-guard workflow would not load in GHA
|
|
93
|
+
* (#3345): any `run: |` content line less indented than the block base, or a
|
|
94
|
+
* line longer than {@link CORE_GUARD_WORKFLOW_MAX_LINE}.
|
|
95
|
+
*/
|
|
96
|
+
export declare function assertCoreGuardWorkflowLoadable(content: string): void;
|
|
85
97
|
export declare function ensureGitattributes(projectDir: string, io: InitDepositIo): boolean;
|
|
86
98
|
export declare function ensureGreptileIgnore(projectDir: string, io: InitDepositIo): boolean;
|
|
87
99
|
export declare function ensureCodeqlPathsIgnore(projectDir: string, io: InitDepositIo): boolean;
|
|
@@ -14,7 +14,7 @@ import { assertDestinationNotSymlink, ProjectionContainmentError, } from "../fs/
|
|
|
14
14
|
import { agentsRefreshPlan } from "../platform/agents-md.js";
|
|
15
15
|
import { MIGRATED_ARTIFACT_DIR } from "../xbrief-migrate/constants.js";
|
|
16
16
|
import { CANONICAL_INSTALL_ROOT } from "./constants.js";
|
|
17
|
-
import { assertInstallerAllowlistHonors1430,
|
|
17
|
+
import { assertInstallerAllowlistHonors1430, installerManagedGuardErePatterns } from "./hygiene.js";
|
|
18
18
|
import { writeAgentsSkillsFromInventory } from "./skill-discovery-deposit.js";
|
|
19
19
|
import { syncConsumerXbriefSchemas } from "./xbrief-projections.js";
|
|
20
20
|
export { CANONICAL_INSTALL_ROOT };
|
|
@@ -501,16 +501,66 @@ export function mergeCoreGuardWorkflowRefresh(existing, desired) {
|
|
|
501
501
|
return desired;
|
|
502
502
|
return desired.slice(0, idx) + existingCheckout + desired.slice(idx + desiredCheckout.length);
|
|
503
503
|
}
|
|
504
|
+
/**
|
|
505
|
+
* Indent for shell lines inside the deposited workflow `run: |` block.
|
|
506
|
+
* YAML literal blocks end at any line less indented than this; the #3193
|
|
507
|
+
* Python body must stay at this column so GHA can load the workflow (#3345).
|
|
508
|
+
*/
|
|
509
|
+
const CORE_GUARD_RUN_INDENT = " ";
|
|
510
|
+
/**
|
|
511
|
+
* Soft max line length for deposited core-guard workflow YAML (#3345).
|
|
512
|
+
* Mega-line allowlist EREs previously sat near ~5k chars; keep well below.
|
|
513
|
+
* Enforced by {@link assertCoreGuardWorkflowLoadable} before deposit write.
|
|
514
|
+
*/
|
|
515
|
+
export const CORE_GUARD_WORKFLOW_MAX_LINE = 500;
|
|
516
|
+
/**
|
|
517
|
+
* Fail closed if a rendered deft-core-guard workflow would not load in GHA
|
|
518
|
+
* (#3345): any `run: |` content line less indented than the block base, or a
|
|
519
|
+
* line longer than {@link CORE_GUARD_WORKFLOW_MAX_LINE}.
|
|
520
|
+
*/
|
|
521
|
+
export function assertCoreGuardWorkflowLoadable(content) {
|
|
522
|
+
if (!content.startsWith("name: deft-core-guard\n") &&
|
|
523
|
+
!content.startsWith("name: deft-core-guard\r\n")) {
|
|
524
|
+
throw new Error("deft-core-guard workflow must start with name: deft-core-guard (#3345)");
|
|
525
|
+
}
|
|
526
|
+
let inRun = false;
|
|
527
|
+
let baseIndent = null;
|
|
528
|
+
for (const [index, line] of content.split("\n").entries()) {
|
|
529
|
+
if (line.length > CORE_GUARD_WORKFLOW_MAX_LINE) {
|
|
530
|
+
throw new Error(`deft-core-guard workflow line ${index + 1} is ${line.length} chars ` +
|
|
531
|
+
`(max ${CORE_GUARD_WORKFLOW_MAX_LINE}; #3345 loadable YAML)`);
|
|
532
|
+
}
|
|
533
|
+
if (line.trim() === "run: |") {
|
|
534
|
+
inRun = true;
|
|
535
|
+
baseIndent = null;
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
if (!inRun || line.trim() === "")
|
|
539
|
+
continue;
|
|
540
|
+
const lead = line.match(/^( *)/)?.[1]?.length ?? 0;
|
|
541
|
+
if (baseIndent === null) {
|
|
542
|
+
baseIndent = lead;
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
if (lead < baseIndent) {
|
|
546
|
+
throw new Error(`deft-core-guard workflow line ${index + 1} dedents below run-block base ` +
|
|
547
|
+
`(indent ${lead} < ${baseIndent}; #3345 YAML load failure class)`);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
504
551
|
/**
|
|
505
552
|
* Embedded python3 content check for package.json / lockfiles when co-travelling
|
|
506
553
|
* with .deft/core/** (#3193). Mirrors TS `isUpgradePinPathContentAllowed`.
|
|
507
554
|
* Uses a single-quoted heredoc so GHA does not interpolate shell variables
|
|
508
555
|
* inside the Python source (BASE/HEAD are argv).
|
|
556
|
+
*
|
|
557
|
+
* Every emitted line is indented to {@link CORE_GUARD_RUN_INDENT} so the YAML
|
|
558
|
+
* `run: |` block stays intact (#3345). After GHA strips the common indent, the
|
|
559
|
+
* shell heredoc body reaches python3 with correct relative indentation.
|
|
509
560
|
*/
|
|
510
561
|
function coreGuardPinContentPython() {
|
|
511
562
|
// Keep this compact: deposited into every consumer workflow on init/update.
|
|
512
|
-
|
|
513
|
-
' python3 - "$BASE_SHA" "$HEAD_SHA" <<\'PY\'',
|
|
563
|
+
const pyBody = [
|
|
514
564
|
"import json, re, subprocess, sys",
|
|
515
565
|
"base_sha, head_sha = sys.argv[1], sys.argv[2]",
|
|
516
566
|
"def git_show(sha, path):",
|
|
@@ -766,7 +816,31 @@ function coreGuardPinContentPython() {
|
|
|
766
816
|
" print('\\n'.join(bad))",
|
|
767
817
|
" sys.exit(1)",
|
|
768
818
|
"print('OK: package/lock content is Directive pin unit (#3193).')",
|
|
769
|
-
|
|
819
|
+
];
|
|
820
|
+
const run = CORE_GUARD_RUN_INDENT;
|
|
821
|
+
return [
|
|
822
|
+
`${run}python3 - "$BASE_SHA" "$HEAD_SHA" <<'PY'`,
|
|
823
|
+
...pyBody.map((line) => `${run}${line}`),
|
|
824
|
+
`${run}PY`,
|
|
825
|
+
].join("\n");
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Shell that materializes the installer-managed allowlist as one ERE per line
|
|
829
|
+
* and filters "app" paths with `grep -vE -f` (#3345 — avoids a ~5k-char line
|
|
830
|
+
* that contributed to invalid workflow load). Semantics match the prior
|
|
831
|
+
* single-alternation ERE (OR of all matchers).
|
|
832
|
+
*/
|
|
833
|
+
function coreGuardAllowlistShell() {
|
|
834
|
+
const run = CORE_GUARD_RUN_INDENT;
|
|
835
|
+
const patterns = installerManagedGuardErePatterns();
|
|
836
|
+
return [
|
|
837
|
+
`${run}# Installer-managed allowlist — one ERE per line (#3345 loadable YAML)`,
|
|
838
|
+
`${run}allowlist=$(mktemp)`,
|
|
839
|
+
`${run}trap 'rm -f "$allowlist"' EXIT`,
|
|
840
|
+
`${run}cat > "$allowlist" <<'ALLOW'`,
|
|
841
|
+
...patterns.map((p) => `${run}${p}`),
|
|
842
|
+
`${run}ALLOW`,
|
|
843
|
+
`${run}app=$(printf '%s\\n' "$changed" | grep -vE '^\\.deft/core/' | grep -vE -f "$allowlist" | grep -v '^$' || true)`,
|
|
770
844
|
].join("\n");
|
|
771
845
|
}
|
|
772
846
|
function coreGuardWorkflowContent() {
|
|
@@ -775,7 +849,7 @@ function coreGuardWorkflowContent() {
|
|
|
775
849
|
const baseSha = githubActionsExpr("github.event.pull_request.base.sha");
|
|
776
850
|
const headSha = githubActionsExpr("github.event.pull_request.head.sha");
|
|
777
851
|
return ("name: deft-core-guard\n\n" +
|
|
778
|
-
"# Deft framework guard (#1430 / #3127 / #3193): a single PR should not mix changes to the\n" +
|
|
852
|
+
"# Deft framework guard (#1430 / #3127 / #3193 / #3345): a single PR should not mix changes to the\n" +
|
|
779
853
|
"# vendored framework payload (.deft/core/**) with true application/product files.\n" +
|
|
780
854
|
"# One upgrade PR MAY include deposit + installer-managed paths + package.json pin/lock\n" +
|
|
781
855
|
"# + .deft/GENERATION.json when package.json is @deftai/directive* dependency-key pin-only\n" +
|
|
@@ -803,9 +877,7 @@ function coreGuardWorkflowContent() {
|
|
|
803
877
|
' echo "Changed files:"\n' +
|
|
804
878
|
' echo "$changed"\n' +
|
|
805
879
|
" core=$(printf '%s\\n' \"$changed\" | grep -E '^\\.deft/core/' || true)\n" +
|
|
806
|
-
|
|
807
|
-
installerManagedGuardEre() +
|
|
808
|
-
"' | grep -v '^$' || true)\n" +
|
|
880
|
+
`${coreGuardAllowlistShell()}\n` +
|
|
809
881
|
' if [ -n "$core" ] && [ -n "$app" ]; then\n' +
|
|
810
882
|
' echo "::error title=deft-core guard (#1430)::This PR changes the vendored framework payload (.deft/core/**) AND non-framework files. Split the framework update into its own PR."\n' +
|
|
811
883
|
' echo "--- framework (.deft/core/**) changes ---"; printf \'%s\\n\' "$core"\n' +
|
|
@@ -951,6 +1023,7 @@ export function ensureCodeqlPathsIgnore(projectDir, io) {
|
|
|
951
1023
|
export function ensureCoreGuardWorkflow(projectDir, io) {
|
|
952
1024
|
const path = projectionTarget(projectDir, CORE_GUARD_WORKFLOW_REL);
|
|
953
1025
|
const desired = coreGuardWorkflowContent();
|
|
1026
|
+
assertCoreGuardWorkflowLoadable(desired);
|
|
954
1027
|
if (existsSync(path)) {
|
|
955
1028
|
const existing = readFileSync(path, "utf8");
|
|
956
1029
|
if (!existing.includes("name: deft-core-guard")) {
|
|
@@ -6,12 +6,14 @@ import { assertWriteTargetSafe, ProjectionContainmentError } from "../fs/project
|
|
|
6
6
|
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
7
7
|
import { captureAndAttachLiteralAcceptance } from "../literal-acceptance/index.js";
|
|
8
8
|
import { stampAcceptanceFromLiteralCapture } from "../product-first-done-gate/index.js";
|
|
9
|
+
import { ENV_RUN_SUMMARY_PATH, RunSummaryEmitter } from "../run-summary/index.js";
|
|
9
10
|
import { call } from "../scm/call.js";
|
|
10
11
|
import { resolveProjectRoot } from "../scope/project-context.js";
|
|
11
12
|
import { resolveProjectRepo } from "../slice/project-context.js";
|
|
12
13
|
import { countMaintainerCurrentShapeComments, mapIssueCommentEntry, RAW_ISSUE_COMMENTS_KEY, selectCurrentShapeComment, } from "../umbrella-current-shape/index.js";
|
|
13
14
|
import { slugify, TODAY } from "../vbrief-build/build.js";
|
|
14
15
|
import { EMITTED_VBRIEF_VERSION } from "../vbrief-build/constants.js";
|
|
16
|
+
import { stampDerivedClausesOnAcceptance } from "../verify-ac/clauses.js";
|
|
15
17
|
import { LEGACY_ARTIFACT_SUFFIX, LEGACY_INFO_ROOT_KEY, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY, VBRIEF_VERSION, } from "../xbrief-migrate/constants.js";
|
|
16
18
|
import { findAcHeading, parseCheckboxItems, parseListItems, sliceAcSection, stripCodeBlocks, stripFencedCodeBlocks, } from "./markdown-scanners.js";
|
|
17
19
|
import { detectRepo, extractReferencesFromVbrief, fetchOpenIssues, GITHUB_ISSUE_REF_TYPES, LIFECYCLE_FOLDERS, parseIssueNumber, } from "./reconcile-issues.js";
|
|
@@ -475,6 +477,9 @@ export function buildIssueVbrief(issue, status, repoUrl, options = {}) {
|
|
|
475
477
|
Object.assign(plan, attached.plan);
|
|
476
478
|
// #3284: stamp plan.acceptance from captured literals (stated or none_stated floor).
|
|
477
479
|
Object.assign(plan, stampAcceptanceFromLiteralCapture(plan));
|
|
480
|
+
// #3323: when no commands were stated, derive numbered clauses before product edit.
|
|
481
|
+
const derived = stampDerivedClausesOnAcceptance(plan, [title, overviewSource].filter((s) => s.length > 0).join("\n\n"));
|
|
482
|
+
Object.assign(plan, derived.plan);
|
|
478
483
|
}
|
|
479
484
|
else {
|
|
480
485
|
// No body: still record none_stated acceptance so absence is a decision.
|
|
@@ -718,8 +723,45 @@ export function ingestOne(issue, options) {
|
|
|
718
723
|
assertWriteTargetSafe(projectRoot, target);
|
|
719
724
|
mkdirSync(folderPath, { recursive: true });
|
|
720
725
|
writeFileSync(target, `${JSON.stringify(vbrief, null, 2)}\n`, "utf8");
|
|
726
|
+
emitIntakeAcceptanceStamp(projectRoot, vbrief.plan);
|
|
721
727
|
return ["created", target, `CREATED ${folder}/${filename}`];
|
|
722
728
|
}
|
|
729
|
+
function emitIntakeAcceptanceStamp(projectRoot, plan) {
|
|
730
|
+
const rec = plan !== null && typeof plan === "object" && !Array.isArray(plan)
|
|
731
|
+
? plan
|
|
732
|
+
: null;
|
|
733
|
+
if (rec === null) {
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
const acceptance = rec.acceptance !== null && typeof rec.acceptance === "object" && !Array.isArray(rec.acceptance)
|
|
737
|
+
? rec.acceptance
|
|
738
|
+
: null;
|
|
739
|
+
if (acceptance === null) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
const env = process.env;
|
|
743
|
+
const dest = env[ENV_RUN_SUMMARY_PATH];
|
|
744
|
+
if (dest === undefined || dest.trim().length === 0) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
try {
|
|
748
|
+
const sessionId = typeof env.DEFT_SESSION_ID === "string" && env.DEFT_SESSION_ID.trim().length > 0
|
|
749
|
+
? env.DEFT_SESSION_ID.trim()
|
|
750
|
+
: "issue-ingest";
|
|
751
|
+
const emitter = new RunSummaryEmitter({ projectRoot, sessionId, env });
|
|
752
|
+
const commands = Array.isArray(acceptance.commands) ? acceptance.commands.length : 0;
|
|
753
|
+
const clauses = Array.isArray(acceptance.clauses) ? acceptance.clauses.length : 0;
|
|
754
|
+
emitter.emitAcceptanceStamp({
|
|
755
|
+
rung: typeof acceptance.source_rung === "string" ? acceptance.source_rung : "project_floor",
|
|
756
|
+
none_stated: acceptance.none_stated === true,
|
|
757
|
+
command_count: commands,
|
|
758
|
+
clause_count: clauses,
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
catch {
|
|
762
|
+
// fail-open
|
|
763
|
+
}
|
|
764
|
+
}
|
|
723
765
|
export function ingestBulk(issues, options) {
|
|
724
766
|
let filtered = issues;
|
|
725
767
|
if (options.label !== undefined && options.label !== null) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ceremony-dial escalation evaluation + start-tier provenance (#3319).
|
|
3
|
+
*
|
|
4
|
+
* Observability only: does not change escalate-on-evidence thresholds or the
|
|
5
|
+
* default start tier. A declined evaluation is distinct from never-evaluated.
|
|
6
|
+
*/
|
|
7
|
+
import type { DialEscalationEvaluationOutcome } from "../run-summary/types.js";
|
|
8
|
+
import { type CeremonyDepth, type CeremonyDialInputs, type CeremonyDialSelection, type CeremonyModelTier } from "./ceremony-dial.js";
|
|
9
|
+
export declare const CEREMONY_START_TIER_PROVENANCES: readonly ["cold-start", "external-pin", "operator"];
|
|
10
|
+
export type CeremonyStartTierProvenance = (typeof CEREMONY_START_TIER_PROVENANCES)[number];
|
|
11
|
+
export declare const CEREMONY_DEPTH_RANK: Readonly<Record<CeremonyDepth, number>>;
|
|
12
|
+
export interface ResolveCeremonyStartTierProvenanceInput {
|
|
13
|
+
readonly selection: CeremonyDialSelection;
|
|
14
|
+
/** True when session:start received a pre-resolved selection (CLI/harness). */
|
|
15
|
+
readonly injectedSelection: boolean;
|
|
16
|
+
readonly hint?: CeremonyStartTierProvenance;
|
|
17
|
+
}
|
|
18
|
+
export declare function resolveCeremonyStartTierProvenance(input: ResolveCeremonyStartTierProvenanceInput): CeremonyStartTierProvenance;
|
|
19
|
+
export declare function isCeremonyStartTierPinned(provenance: CeremonyStartTierProvenance): boolean;
|
|
20
|
+
/** Session-start fail-closed line when a pin bypasses #3274 cold-start selection. */
|
|
21
|
+
export declare function formatCeremonyDialPinBypassLine(provenance: CeremonyStartTierProvenance): string | null;
|
|
22
|
+
export interface CeremonyDialEscalationEvaluation {
|
|
23
|
+
readonly tier: CeremonyDepth;
|
|
24
|
+
readonly outcome: DialEscalationEvaluationOutcome;
|
|
25
|
+
readonly reason: string;
|
|
26
|
+
readonly from: CeremonyDepth;
|
|
27
|
+
readonly to: CeremonyDepth;
|
|
28
|
+
}
|
|
29
|
+
export interface EvaluateCeremonyDialEscalationInput {
|
|
30
|
+
readonly from: CeremonyDepth;
|
|
31
|
+
readonly to: CeremonyDepth;
|
|
32
|
+
readonly inputs?: CeremonyDialInputs;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Pure escalate-on-evidence evaluation. `to > from` → escalated; else declined.
|
|
36
|
+
* Does not persist a transition.
|
|
37
|
+
*/
|
|
38
|
+
export declare function evaluateCeremonyDialEscalation(input: EvaluateCeremonyDialEscalationInput): CeremonyDialEscalationEvaluation;
|
|
39
|
+
/** Cold-start vs selected depth at session:start (unpinned path only). */
|
|
40
|
+
export declare function evaluateSessionStartCeremonyDialEscalation(input: {
|
|
41
|
+
readonly selection: CeremonyDialSelection;
|
|
42
|
+
readonly modelTier?: CeremonyModelTier | null;
|
|
43
|
+
}): CeremonyDialEscalationEvaluation;
|
|
44
|
+
export interface EmitCeremonyDialEscalationEvaluationOptions {
|
|
45
|
+
readonly projectRoot: string;
|
|
46
|
+
readonly sessionId: string;
|
|
47
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
48
|
+
readonly evaluation: CeremonyDialEscalationEvaluation;
|
|
49
|
+
}
|
|
50
|
+
/** Fail-open emit of a #3319 evaluation event. */
|
|
51
|
+
export declare function emitCeremonyDialEscalationEvaluation(options: EmitCeremonyDialEscalationEvaluationOptions): void;
|
|
52
|
+
//# sourceMappingURL=ceremony-dial-escalation.d.ts.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ceremony-dial escalation evaluation + start-tier provenance (#3319).
|
|
3
|
+
*
|
|
4
|
+
* Observability only: does not change escalate-on-evidence thresholds or the
|
|
5
|
+
* default start tier. A declined evaluation is distinct from never-evaluated.
|
|
6
|
+
*/
|
|
7
|
+
import { RunSummaryEmitter } from "../run-summary/emit.js";
|
|
8
|
+
import { selectCeremonyColdStartDepth, } from "./ceremony-dial.js";
|
|
9
|
+
export const CEREMONY_START_TIER_PROVENANCES = ["cold-start", "external-pin", "operator"];
|
|
10
|
+
export const CEREMONY_DEPTH_RANK = {
|
|
11
|
+
minimal: 0,
|
|
12
|
+
rapid: 1,
|
|
13
|
+
standard: 2,
|
|
14
|
+
elevated: 3,
|
|
15
|
+
};
|
|
16
|
+
export function resolveCeremonyStartTierProvenance(input) {
|
|
17
|
+
if (input.hint !== undefined) {
|
|
18
|
+
return input.hint;
|
|
19
|
+
}
|
|
20
|
+
if (input.selection.source === "override") {
|
|
21
|
+
return input.injectedSelection ? "external-pin" : "operator";
|
|
22
|
+
}
|
|
23
|
+
return "cold-start";
|
|
24
|
+
}
|
|
25
|
+
export function isCeremonyStartTierPinned(provenance) {
|
|
26
|
+
return provenance === "external-pin" || provenance === "operator";
|
|
27
|
+
}
|
|
28
|
+
/** Session-start fail-closed line when a pin bypasses #3274 cold-start selection. */
|
|
29
|
+
export function formatCeremonyDialPinBypassLine(provenance) {
|
|
30
|
+
if (!isCeremonyStartTierPinned(provenance)) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const pinLabel = provenance === "external-pin" ? "external-pin" : "operator pin";
|
|
34
|
+
return (`[deft ceremony-dial] #3274 cold-start selection is bypassed (${pinLabel}). ` +
|
|
35
|
+
"Unset the pin (--ceremony-depth or plan.policy.ceremonyDial.override) to exercise #3274.");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Pure escalate-on-evidence evaluation. `to > from` → escalated; else declined.
|
|
39
|
+
* Does not persist a transition.
|
|
40
|
+
*/
|
|
41
|
+
export function evaluateCeremonyDialEscalation(input) {
|
|
42
|
+
const size = input.inputs?.taskSize ?? null;
|
|
43
|
+
const modelTier = input.inputs?.modelTier ?? null;
|
|
44
|
+
const evidence = `size=${size ?? "-"} modelTier=${modelTier ?? "-"}`;
|
|
45
|
+
const raised = CEREMONY_DEPTH_RANK[input.to] > CEREMONY_DEPTH_RANK[input.from];
|
|
46
|
+
if (raised) {
|
|
47
|
+
return {
|
|
48
|
+
tier: input.to,
|
|
49
|
+
outcome: "escalated",
|
|
50
|
+
reason: `evidence raised ${input.from} -> ${input.to} (${evidence})`,
|
|
51
|
+
from: input.from,
|
|
52
|
+
to: input.to,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
tier: input.from,
|
|
57
|
+
outcome: "declined",
|
|
58
|
+
reason: `insufficient evidence to raise above ${input.from} (${evidence})`,
|
|
59
|
+
from: input.from,
|
|
60
|
+
to: input.to,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Cold-start vs selected depth at session:start (unpinned path only). */
|
|
64
|
+
export function evaluateSessionStartCeremonyDialEscalation(input) {
|
|
65
|
+
const modelTier = input.modelTier ?? input.selection.inputs.modelTier;
|
|
66
|
+
const from = selectCeremonyColdStartDepth(modelTier);
|
|
67
|
+
return evaluateCeremonyDialEscalation({
|
|
68
|
+
from,
|
|
69
|
+
to: input.selection.depth,
|
|
70
|
+
inputs: input.selection.inputs,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** Fail-open emit of a #3319 evaluation event. */
|
|
74
|
+
export function emitCeremonyDialEscalationEvaluation(options) {
|
|
75
|
+
try {
|
|
76
|
+
const emitter = new RunSummaryEmitter({
|
|
77
|
+
projectRoot: options.projectRoot,
|
|
78
|
+
sessionId: options.sessionId,
|
|
79
|
+
env: options.env,
|
|
80
|
+
});
|
|
81
|
+
emitter.emitDialEscalationEvaluation({
|
|
82
|
+
tier: options.evaluation.tier,
|
|
83
|
+
outcome: options.evaluation.outcome,
|
|
84
|
+
reason: options.evaluation.reason,
|
|
85
|
+
});
|
|
86
|
+
emitter.emitKnownToolTurnDenominator();
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// fail-open
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=ceremony-dial-escalation.js.map
|
|
@@ -161,7 +161,9 @@ export interface ResolveCeremonyDialOptions {
|
|
|
161
161
|
*/
|
|
162
162
|
export declare function resolveCeremonyDial(projectRoot: string, options?: ResolveCeremonyDialOptions): CeremonyDialSelection;
|
|
163
163
|
/** Human-readable status line for session:start / policy:show. */
|
|
164
|
-
export declare function formatCeremonyDialStatusLine(selection: CeremonyDialSelection
|
|
164
|
+
export declare function formatCeremonyDialStatusLine(selection: CeremonyDialSelection, extras?: {
|
|
165
|
+
readonly startTierProvenance?: string;
|
|
166
|
+
}): string;
|
|
165
167
|
/** JSON-serializable dial snapshot for ritual-state / session payload. */
|
|
166
168
|
export declare function ceremonyDialToDict(selection: CeremonyDialSelection): Record<string, unknown>;
|
|
167
169
|
export interface CeremonyDialPolicyField {
|