@deftai/directive 0.98.0 → 0.99.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/cli-router/route-argv.js +4 -0
- package/dist/dispatch.d.ts +2 -2
- package/dist/dispatch.js +21 -0
- package/dist/policy.d.ts +6 -1
- package/dist/policy.js +83 -11
- package/dist/scope-record-approved-scope.d.ts +22 -0
- package/dist/scope-record-approved-scope.js +253 -0
- package/dist/session-start.d.ts +8 -0
- package/dist/session-start.js +140 -0
- package/package.json +3 -3
|
@@ -83,6 +83,7 @@ export const SUBCOMMAND_ROUTES = {
|
|
|
83
83
|
"policy:allow-direct-commits": ["policy", "allow-direct-commits"],
|
|
84
84
|
"policy:allow-bot-merge": ["policy", "allow-bot-merge"],
|
|
85
85
|
"policy:enable-value-feedback": ["policy", "enable-value-feedback"],
|
|
86
|
+
"policy:set-ceremony-dial": ["policy", "set-ceremony-dial"],
|
|
86
87
|
"policy:coverage-check-resume-preset": ["policy", "coverage-check-resume-preset"],
|
|
87
88
|
"policy:coverage-check-resume-dismiss": ["policy", "coverage-check-resume-dismiss"],
|
|
88
89
|
"policy:coverage-check-resume-later": ["policy", "coverage-check-resume-later"],
|
|
@@ -188,6 +189,9 @@ function routeNamespaceVerb(ns, verb, rest) {
|
|
|
188
189
|
return { kind: "dispatch", argv: ["scope-decompose", ...rest] };
|
|
189
190
|
if (verb === "undo")
|
|
190
191
|
return { kind: "dispatch", argv: ["scope-undo", ...rest] };
|
|
192
|
+
if (verb === "record-approved-scope") {
|
|
193
|
+
return { kind: "dispatch", argv: ["scope-record-approved-scope", ...rest] };
|
|
194
|
+
}
|
|
191
195
|
}
|
|
192
196
|
if (ns === "verify") {
|
|
193
197
|
const verifyStem = VERIFY_VERB_MAP[verb];
|
package/dist/dispatch.d.ts
CHANGED
|
@@ -10,9 +10,9 @@ export interface DispatchIo {
|
|
|
10
10
|
writeErr: (text: string) => void;
|
|
11
11
|
}
|
|
12
12
|
/** CLI modules in packages/cli/src (excluding parity harnesses and bin/index). */
|
|
13
|
-
export declare const CLI_MODULE_VERBS: readonly ["agents-refresh", "cache", "check", "capacity-backfill", "capacity-show", "codebase-default-extractor", "codebase-map", "codebase-map-fresh", "codebase-projection-registry", "codebase-provider", "doctor", "install-upgrade", "install-uninstall", "migrate-preflight", "migrate-xbrief", "migrate-category-b", "framework-check-updates", "hook-dispatch", "umbrella-current-shape", "changelog-check", "change-init", "commit-lint", "coverage-hotspots", "policy", "authz", "escalation-cli", "pr-closing-keywords", "pr-merge-readiness", "pr-monitor", "pr-protected-issues", "pr-wait-mergeable", "pr-watch", "pr-finish-loop", "directive-finish-loop", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "scope-lifecycle", "lifecycle-event", "lifecycle-stats", "session-start", "session-ready", "plan-sequence", "slice", "subagent-monitor", "toolchain-check", "triage-actions", "triage-bootstrap", "triage-bulk", "triage-classify", "triage-help", "triage-queue", "triage-reconcile", "triage-refresh", "triage-scope", "triage-scope-drift", "triage-smoketest", "triage-subscribe", "triage-summary", "triage-welcome", "ts-check-lane", "vbrief-activate", "vbrief-build", "vbrief-preflight", "vbrief-reconcile", "vbrief-validate", "vbrief-validation", "xbrief-create", "xbrief-verify", "verify-branch", "verify-encoding", "verify-forward-coverage", "verify-test-boundary", "verify-scope-provenance", "verify-consumer-check-contract", "verify-hooks-installed", "verify-investigation", "verify-judgment-gates", "verify-no-task-runtime", "validate-links", "validate-strategy-output", "verify-biome-config", "verify-bridge-drift", "verify-capacity", "verify-contained-writes", "verify-content-manifest", "verify-skill-external-fetch-gate", "verify-contract-drift", "verify-cursor-tier1", "verify-openclaw-tier1", "verify-go-freeze", "verify-scm-boundary", "verify-session-ritual", "verify-plan-sequence", "verify-stubs", "verify-xbrief-drift", "rule-ownership-lint", "verify-story-ready", "verify-review-monitor", "verify-l4-owner", "verify-subagent-alive", "review-monitor-register", "review-monitor-release", "verify-tools", "verify-wip-cap", "verify-orphan-active", "verify-agents-md-budget", "verify-agents-md-advisory", "verify-eval-health-relocation", "verify-eval-triggers-relocation", "eval-health", "eval-run", "eval-report", "eval-triggers"];
|
|
13
|
+
export declare const CLI_MODULE_VERBS: readonly ["agents-refresh", "cache", "check", "capacity-backfill", "capacity-show", "codebase-default-extractor", "codebase-map", "codebase-map-fresh", "codebase-projection-registry", "codebase-provider", "doctor", "install-upgrade", "install-uninstall", "migrate-preflight", "migrate-xbrief", "migrate-category-b", "framework-check-updates", "hook-dispatch", "umbrella-current-shape", "changelog-check", "change-init", "commit-lint", "coverage-hotspots", "policy", "authz", "escalation-cli", "pr-closing-keywords", "pr-merge-readiness", "pr-monitor", "pr-protected-issues", "pr-wait-mergeable", "pr-watch", "pr-finish-loop", "directive-finish-loop", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "scope-lifecycle", "scope-record-approved-scope", "lifecycle-event", "lifecycle-stats", "session-start", "session-ready", "plan-sequence", "slice", "subagent-monitor", "toolchain-check", "triage-actions", "triage-bootstrap", "triage-bulk", "triage-classify", "triage-help", "triage-queue", "triage-reconcile", "triage-refresh", "triage-scope", "triage-scope-drift", "triage-smoketest", "triage-subscribe", "triage-summary", "triage-welcome", "ts-check-lane", "vbrief-activate", "vbrief-build", "vbrief-preflight", "vbrief-reconcile", "vbrief-validate", "vbrief-validation", "xbrief-create", "xbrief-verify", "verify-branch", "verify-encoding", "verify-forward-coverage", "verify-test-boundary", "verify-scope-provenance", "verify-consumer-check-contract", "verify-hooks-installed", "verify-investigation", "verify-judgment-gates", "verify-no-task-runtime", "validate-links", "validate-strategy-output", "verify-biome-config", "verify-bridge-drift", "verify-capacity", "verify-contained-writes", "verify-content-manifest", "verify-skill-external-fetch-gate", "verify-contract-drift", "verify-cursor-tier1", "verify-openclaw-tier1", "verify-go-freeze", "verify-scm-boundary", "verify-session-ritual", "verify-plan-sequence", "verify-stubs", "verify-xbrief-drift", "rule-ownership-lint", "verify-story-ready", "verify-review-monitor", "verify-l4-owner", "verify-subagent-alive", "review-monitor-register", "review-monitor-release", "verify-tools", "verify-wip-cap", "verify-orphan-active", "verify-agents-md-budget", "verify-agents-md-advisory", "verify-eval-health-relocation", "verify-eval-triggers-relocation", "eval-health", "eval-run", "eval-report", "eval-triggers"];
|
|
14
14
|
/** Core-only CLI entrypoints without a packages/cli wrapper. */
|
|
15
|
-
export declare const CORE_MODULE_VERBS: readonly ["scm", "scm-readiness", "github-auth-modes", "github-body", "issue-emit", "issue-ingest", "issue-sync-from-xbrief", "reconcile-issues", "swarm-launch", "swarm-complete-cohort", "swarm-finalize-cohort", "swarm-readiness", "swarm-routing-verify", "swarm-routing-set", "swarm-verify-review-clean", "swarm-worktrees", "framework-commands", "pack-render", "packs-slice", "prd-render", "export-spec", "project-render", "roadmap-render", "rule-map", "spec-render", "spec-validate", "code-structure-validate", "pack-migrate-skills", "pack-migrate-rules", "pack-migrate-strategies", "pack-migrate-patterns", "pack-migrate-swarm-spec", "policy-set", "setup-ghx", "scope-undo", "scope-demote", "scope-decompose", "changelog-resolve-unreleased", "architecture-preflight-sor", "feedback-file", "value-readback", "product-signal", "freshness-report"];
|
|
15
|
+
export declare const CORE_MODULE_VERBS: readonly ["scm", "scm-readiness", "github-auth-modes", "github-body", "issue-emit", "issue-ingest", "issue-sync-from-xbrief", "reconcile-issues", "swarm-launch", "swarm-complete-cohort", "swarm-finalize-cohort", "swarm-pre-dispatch", "swarm-readiness", "swarm-routing-verify", "swarm-routing-set", "swarm-verify-review-clean", "swarm-worktrees", "framework-commands", "pack-render", "packs-slice", "prd-render", "export-spec", "project-render", "roadmap-render", "rule-map", "spec-render", "spec-validate", "code-structure-validate", "pack-migrate-skills", "pack-migrate-rules", "pack-migrate-strategies", "pack-migrate-patterns", "pack-migrate-swarm-spec", "policy-set", "setup-ghx", "scope-undo", "scope-demote", "scope-decompose", "changelog-resolve-unreleased", "architecture-preflight-sor", "feedback-file", "value-readback", "product-signal", "freshness-report", "decision-write", "decision-list"];
|
|
16
16
|
/** Colon aliases for triage-actions (mirrors cli-router SUBCOMMAND_ROUTES). */
|
|
17
17
|
export declare const TRIAGE_ACTION_ALIAS_SUBCOMMANDS: Readonly<Record<string, string>>;
|
|
18
18
|
/** Colon aliases for policy subcommands (mirrors cli-router SUBCOMMAND_ROUTES). */
|
package/dist/dispatch.js
CHANGED
|
@@ -68,6 +68,7 @@ export const CLI_MODULE_VERBS = [
|
|
|
68
68
|
"release-publish",
|
|
69
69
|
"release-rollback",
|
|
70
70
|
"scope-lifecycle",
|
|
71
|
+
"scope-record-approved-scope",
|
|
71
72
|
"lifecycle-event",
|
|
72
73
|
"lifecycle-stats",
|
|
73
74
|
"session-start",
|
|
@@ -158,6 +159,7 @@ export const CORE_MODULE_VERBS = [
|
|
|
158
159
|
"swarm-launch",
|
|
159
160
|
"swarm-complete-cohort",
|
|
160
161
|
"swarm-finalize-cohort",
|
|
162
|
+
"swarm-pre-dispatch",
|
|
161
163
|
"swarm-readiness",
|
|
162
164
|
"swarm-routing-verify",
|
|
163
165
|
"swarm-routing-set",
|
|
@@ -190,6 +192,8 @@ export const CORE_MODULE_VERBS = [
|
|
|
190
192
|
"value-readback",
|
|
191
193
|
"product-signal",
|
|
192
194
|
"freshness-report",
|
|
195
|
+
"decision-write",
|
|
196
|
+
"decision-list",
|
|
193
197
|
];
|
|
194
198
|
/** Colon aliases for triage-actions (mirrors cli-router SUBCOMMAND_ROUTES). */
|
|
195
199
|
export const TRIAGE_ACTION_ALIAS_SUBCOMMANDS = {
|
|
@@ -210,6 +214,7 @@ export const POLICY_ACTION_ALIAS_SUBCOMMANDS = {
|
|
|
210
214
|
"policy:allow-direct-commits": "allow-direct-commits",
|
|
211
215
|
"policy:allow-bot-merge": "allow-bot-merge",
|
|
212
216
|
"policy:enable-value-feedback": "enable-value-feedback",
|
|
217
|
+
"policy:set-ceremony-dial": "set-ceremony-dial",
|
|
213
218
|
"policy:clear-value-feedback": "clear-value-feedback",
|
|
214
219
|
"policy:coverage-check-resume-preset": "coverage-check-resume-preset",
|
|
215
220
|
"policy:coverage-check-resume-dismiss": "coverage-check-resume-dismiss",
|
|
@@ -267,6 +272,7 @@ export const VERB_ALIASES = {
|
|
|
267
272
|
"verify:forward-coverage": "verify-forward-coverage",
|
|
268
273
|
"verify:test-boundary": "verify-test-boundary",
|
|
269
274
|
"verify:scope-provenance": "verify-scope-provenance",
|
|
275
|
+
"scope:record-approved-scope": "scope-record-approved-scope",
|
|
270
276
|
"verify:consumer-check-contract": "verify-consumer-check-contract",
|
|
271
277
|
"coverage:hotspots": "coverage-hotspots",
|
|
272
278
|
"verify:branch": "verify-branch",
|
|
@@ -358,6 +364,8 @@ export const VERB_ALIASES = {
|
|
|
358
364
|
"feedback:file": "feedback-file",
|
|
359
365
|
"value:show": "value-readback",
|
|
360
366
|
"triage:metrics": "value-readback",
|
|
367
|
+
"decision:write": "decision-write",
|
|
368
|
+
"decision:list": "decision-list",
|
|
361
369
|
"eval:run": "eval-run",
|
|
362
370
|
"eval:triggers": "eval-triggers",
|
|
363
371
|
"eval:report": "eval-report",
|
|
@@ -2338,6 +2346,10 @@ async function loadCoreModuleHandler(verb, io) {
|
|
|
2338
2346
|
const { finalizeCohortMain } = await import("@deftai/directive-core/dist/swarm/finalize-cohort-cli.js");
|
|
2339
2347
|
return finalizeCohortMain;
|
|
2340
2348
|
}
|
|
2349
|
+
case "swarm-pre-dispatch": {
|
|
2350
|
+
const { preDispatchMain } = await import("@deftai/directive-core/dist/swarm/pre-dispatch-cli.js");
|
|
2351
|
+
return preDispatchMain;
|
|
2352
|
+
}
|
|
2341
2353
|
case "swarm-readiness": {
|
|
2342
2354
|
const { readinessMain } = await import("@deftai/directive-core/dist/swarm/readiness-cli.js");
|
|
2343
2355
|
return readinessMain;
|
|
@@ -2468,6 +2480,14 @@ async function loadCoreModuleHandler(verb, io) {
|
|
|
2468
2480
|
const { mainEntry } = await import("@deftai/directive-core/dist/freshness/cli.js");
|
|
2469
2481
|
return mainEntry;
|
|
2470
2482
|
}
|
|
2483
|
+
case "decision-write": {
|
|
2484
|
+
const { writeMainEntry } = await import("@deftai/directive-core/dist/decision/index.js");
|
|
2485
|
+
return writeMainEntry;
|
|
2486
|
+
}
|
|
2487
|
+
case "decision-list": {
|
|
2488
|
+
const { listMainEntry } = await import("@deftai/directive-core/dist/decision/index.js");
|
|
2489
|
+
return listMainEntry;
|
|
2490
|
+
}
|
|
2471
2491
|
default:
|
|
2472
2492
|
throw new Error(`unknown core verb: ${verb}`);
|
|
2473
2493
|
}
|
|
@@ -2529,6 +2549,7 @@ const SCOPE_COMMAND_NAMES = [
|
|
|
2529
2549
|
"scope:complete",
|
|
2530
2550
|
"scope:demote",
|
|
2531
2551
|
"scope:undo",
|
|
2552
|
+
"scope:record-approved-scope",
|
|
2532
2553
|
];
|
|
2533
2554
|
/**
|
|
2534
2555
|
* Deduplicated command names for `directive commands`, preferring colon-style
|
package/dist/policy.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { type CeremonyDepth } from "@deftai/directive-core/policy";
|
|
2
3
|
interface ShowArgs {
|
|
3
4
|
format: "text" | "json";
|
|
4
5
|
changedOnly: boolean;
|
|
@@ -7,7 +8,7 @@ interface ShowArgs {
|
|
|
7
8
|
error?: string;
|
|
8
9
|
}
|
|
9
10
|
interface SetArgs {
|
|
10
|
-
cmd: "show" | "enforce-branches" | "allow-direct-commits" | "allow-bot-merge" | "enable-value-feedback" | "clear-value-feedback" | "coverage-check-resume-preset" | "coverage-check-resume-dismiss" | "coverage-check-resume-later" | "disable-directive" | "enable-directive" | "resolve";
|
|
11
|
+
cmd: "show" | "enforce-branches" | "allow-direct-commits" | "allow-bot-merge" | "enable-value-feedback" | "clear-value-feedback" | "set-ceremony-dial" | "coverage-check-resume-preset" | "coverage-check-resume-dismiss" | "coverage-check-resume-later" | "disable-directive" | "enable-directive" | "resolve";
|
|
11
12
|
confirm: boolean;
|
|
12
13
|
actor: string;
|
|
13
14
|
note: string;
|
|
@@ -18,6 +19,10 @@ interface SetArgs {
|
|
|
18
19
|
/** Strict | hatch-aware for coverage-check-resume-preset; reason for dismiss. */
|
|
19
20
|
preset?: string;
|
|
20
21
|
reason?: string;
|
|
22
|
+
/** #3214 ceremony dial override depth for set-ceremony-dial. */
|
|
23
|
+
ceremonyOverride?: CeremonyDepth | null;
|
|
24
|
+
/** #3214 ceremony dial enabled flag for set-ceremony-dial. */
|
|
25
|
+
ceremonyEnabled?: boolean;
|
|
21
26
|
error?: string;
|
|
22
27
|
}
|
|
23
28
|
/** Parse policy:show flags (mirrors _policy_show_cli.py). */
|
package/dist/policy.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { resolve as pathResolve, relative } from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
|
-
import { ALLOW_BOT_MERGE_CAPABILITY_COST, applyHatchAwareCoverageCheckResumePreset, applyLaterCoverageCheckResumeSkip, applyStrictCoverageCheckResumePreset, clearValueFeedback, createNoDeftDirectiveFlag, describeShadowedPlanExtension, detectNoDeftDirective, detectShadowedPlanExtensions, disclosureLine, dismissCoverageCheckResume, enableValueFeedback, FIELD_VALUE_FEEDBACK, FIELD_VALUE_FEEDBACK_CLI_ALIAS, formatValueFeedbackStatusLine, humanMergeDisclosureLine, inspectAllPolicies, inspectOnePolicy, loadProjectDefinition, NO_DEFT_DIRECTIVE_DISABLED_MESSAGE, NO_DEFT_DIRECTIVE_FLAG_NAME, NO_DEFT_DIRECTIVE_INCONSISTENT_MESSAGE, policyColonInvocation, projectDefinitionPath, pythonListRepr, pythonStringRepr, registeredPolicyNames, removeNoDeftDirectiveFlag, renderJson, renderText, resolveHumanMergePolicy, resolvePolicy, resolveValueFeedback, setPolicy, setRequireHumanMerge, } from "@deftai/directive-core/policy";
|
|
9
|
+
import { ALLOW_BOT_MERGE_CAPABILITY_COST, applyHatchAwareCoverageCheckResumePreset, applyLaterCoverageCheckResumeSkip, applyStrictCoverageCheckResumePreset, CEREMONY_DEPTHS, clearValueFeedback, createNoDeftDirectiveFlag, describeShadowedPlanExtension, detectNoDeftDirective, detectShadowedPlanExtensions, disclosureLine, dismissCoverageCheckResume, enableValueFeedback, FIELD_VALUE_FEEDBACK, FIELD_VALUE_FEEDBACK_CLI_ALIAS, formatValueFeedbackStatusLine, humanMergeDisclosureLine, inspectAllPolicies, inspectOnePolicy, loadProjectDefinition, NO_DEFT_DIRECTIVE_DISABLED_MESSAGE, NO_DEFT_DIRECTIVE_FLAG_NAME, NO_DEFT_DIRECTIVE_INCONSISTENT_MESSAGE, policyColonInvocation, projectDefinitionPath, pythonListRepr, pythonStringRepr, registeredPolicyNames, removeNoDeftDirectiveFlag, renderJson, renderText, resolveHumanMergePolicy, resolvePolicy, resolveValueFeedback, setCeremonyDial, setPolicy, setRequireHumanMerge, } from "@deftai/directive-core/policy";
|
|
10
10
|
const CAPABILITY_COST_DISCLOSURE = "\u26a0 Capability-cost disclosure -- enabling direct commits to the default " +
|
|
11
11
|
"branch turns OFF the deft branch-protection policy.\n" +
|
|
12
12
|
" \u2022 Pre-commit + pre-push hooks will no longer block default-branch " +
|
|
@@ -114,7 +114,7 @@ export function parseShowArgs(argv) {
|
|
|
114
114
|
/** Parse argv for the policy CLI (show + set subcommands). */
|
|
115
115
|
export function parseArgs(argv) {
|
|
116
116
|
if (argv.length === 0) {
|
|
117
|
-
const usage = "usage: policy [show|enforce-branches|allow-direct-commits|allow-bot-merge|enable-value-feedback|clear-value-feedback|coverage-check-resume-preset|coverage-check-resume-dismiss|coverage-check-resume-later|disable-directive|enable-directive|resolve] ...";
|
|
117
|
+
const usage = "usage: policy [show|enforce-branches|allow-direct-commits|allow-bot-merge|enable-value-feedback|clear-value-feedback|set-ceremony-dial|coverage-check-resume-preset|coverage-check-resume-dismiss|coverage-check-resume-later|disable-directive|enable-directive|resolve] ...";
|
|
118
118
|
return makeSetError(usage);
|
|
119
119
|
}
|
|
120
120
|
const cmd = argv[0];
|
|
@@ -151,6 +151,7 @@ export function parseArgs(argv) {
|
|
|
151
151
|
cmd === "allow-bot-merge" ||
|
|
152
152
|
cmd === "enable-value-feedback" ||
|
|
153
153
|
cmd === "clear-value-feedback" ||
|
|
154
|
+
cmd === "set-ceremony-dial" ||
|
|
154
155
|
cmd === "coverage-check-resume-preset" ||
|
|
155
156
|
cmd === "coverage-check-resume-dismiss" ||
|
|
156
157
|
cmd === "coverage-check-resume-later" ||
|
|
@@ -167,19 +168,23 @@ export function parseArgs(argv) {
|
|
|
167
168
|
? policyColonInvocation("enable-value-feedback")
|
|
168
169
|
: cmd === "clear-value-feedback"
|
|
169
170
|
? policyColonInvocation("clear-value-feedback")
|
|
170
|
-
: cmd === "
|
|
171
|
-
? policyColonInvocation("
|
|
172
|
-
: cmd === "coverage-check-resume-
|
|
173
|
-
? policyColonInvocation("coverage-check-resume-
|
|
174
|
-
: cmd === "coverage-check-resume-
|
|
175
|
-
? policyColonInvocation("coverage-check-resume-
|
|
176
|
-
: cmd === "
|
|
177
|
-
? policyColonInvocation("
|
|
178
|
-
:
|
|
171
|
+
: cmd === "set-ceremony-dial"
|
|
172
|
+
? policyColonInvocation("set-ceremony-dial")
|
|
173
|
+
: cmd === "coverage-check-resume-preset"
|
|
174
|
+
? policyColonInvocation("coverage-check-resume-preset")
|
|
175
|
+
: cmd === "coverage-check-resume-dismiss"
|
|
176
|
+
? policyColonInvocation("coverage-check-resume-dismiss")
|
|
177
|
+
: cmd === "coverage-check-resume-later"
|
|
178
|
+
? policyColonInvocation("coverage-check-resume-later")
|
|
179
|
+
: cmd === "disable-directive"
|
|
180
|
+
? policyColonInvocation("disable-directive")
|
|
181
|
+
: policyColonInvocation("enable-directive");
|
|
179
182
|
let note = "";
|
|
180
183
|
let projectRoot = ".";
|
|
181
184
|
let preset = "";
|
|
182
185
|
let reason = "";
|
|
186
|
+
let ceremonyOverride;
|
|
187
|
+
let ceremonyEnabled;
|
|
183
188
|
for (let i = 1; i < argv.length; i += 1) {
|
|
184
189
|
const arg = argv[i];
|
|
185
190
|
if (arg === "--confirm") {
|
|
@@ -239,6 +244,50 @@ export function parseArgs(argv) {
|
|
|
239
244
|
(arg === "strict" || arg === "hatch-aware")) {
|
|
240
245
|
preset = arg;
|
|
241
246
|
}
|
|
247
|
+
else if (cmd === "set-ceremony-dial" && (arg === "--override" || arg === "--depth")) {
|
|
248
|
+
const v = argv[i + 1];
|
|
249
|
+
if (v === undefined) {
|
|
250
|
+
return makeSetError(`argument ${arg}: expected one argument (minimal|rapid|standard|elevated|null)`);
|
|
251
|
+
}
|
|
252
|
+
if (v === "null" || v === "none" || v === "clear") {
|
|
253
|
+
ceremonyOverride = null;
|
|
254
|
+
}
|
|
255
|
+
else if (CEREMONY_DEPTHS.includes(v)) {
|
|
256
|
+
ceremonyOverride = v;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
return makeSetError(`argument ${arg}: expected minimal|rapid|standard|elevated|null, got ${JSON.stringify(v)}`);
|
|
260
|
+
}
|
|
261
|
+
i += 1;
|
|
262
|
+
}
|
|
263
|
+
else if (cmd === "set-ceremony-dial" &&
|
|
264
|
+
(arg?.startsWith("--override=") || arg?.startsWith("--depth="))) {
|
|
265
|
+
const v = arg.slice(arg.indexOf("=") + 1);
|
|
266
|
+
if (v === "null" || v === "none" || v === "clear") {
|
|
267
|
+
ceremonyOverride = null;
|
|
268
|
+
}
|
|
269
|
+
else if (CEREMONY_DEPTHS.includes(v)) {
|
|
270
|
+
ceremonyOverride = v;
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
return makeSetError(`argument --override: expected minimal|rapid|standard|elevated|null, got ${JSON.stringify(v)}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else if (cmd === "set-ceremony-dial" && arg === "--enabled") {
|
|
277
|
+
const v = argv[i + 1];
|
|
278
|
+
if (v === undefined || (v !== "true" && v !== "false")) {
|
|
279
|
+
return makeSetError("argument --enabled: expected true|false");
|
|
280
|
+
}
|
|
281
|
+
ceremonyEnabled = v === "true";
|
|
282
|
+
i += 1;
|
|
283
|
+
}
|
|
284
|
+
else if (cmd === "set-ceremony-dial" && arg?.startsWith("--enabled=")) {
|
|
285
|
+
const v = arg.slice("--enabled=".length);
|
|
286
|
+
if (v !== "true" && v !== "false") {
|
|
287
|
+
return makeSetError("argument --enabled: expected true|false");
|
|
288
|
+
}
|
|
289
|
+
ceremonyEnabled = v === "true";
|
|
290
|
+
}
|
|
242
291
|
else {
|
|
243
292
|
return makeSetError(`unrecognized argument: ${arg}`);
|
|
244
293
|
}
|
|
@@ -254,6 +303,8 @@ export function parseArgs(argv) {
|
|
|
254
303
|
field: null,
|
|
255
304
|
preset,
|
|
256
305
|
reason,
|
|
306
|
+
ceremonyOverride,
|
|
307
|
+
ceremonyEnabled,
|
|
257
308
|
};
|
|
258
309
|
}
|
|
259
310
|
return makeSetError(`unknown subcommand: ${cmd}`);
|
|
@@ -493,6 +544,9 @@ export function run(argv) {
|
|
|
493
544
|
if (args.cmd === "clear-value-feedback") {
|
|
494
545
|
return runClearValueFeedback(args);
|
|
495
546
|
}
|
|
547
|
+
if (args.cmd === "set-ceremony-dial") {
|
|
548
|
+
return runSetCeremonyDial(args);
|
|
549
|
+
}
|
|
496
550
|
if (args.cmd === "coverage-check-resume-preset") {
|
|
497
551
|
return runCoverageCheckResumePreset(args);
|
|
498
552
|
}
|
|
@@ -546,6 +600,24 @@ function runCoverageCheckResumeLater() {
|
|
|
546
600
|
process.stdout.write(result.stdout);
|
|
547
601
|
return result.exitCode;
|
|
548
602
|
}
|
|
603
|
+
/** Persist plan.policy.ceremonyDial override/enabled (#3214). */
|
|
604
|
+
function runSetCeremonyDial(args) {
|
|
605
|
+
const root = pathResolve(args.projectRoot);
|
|
606
|
+
if (args.ceremonyOverride === undefined && args.ceremonyEnabled === undefined) {
|
|
607
|
+
process.stdout.write("usage: policy set-ceremony-dial -- --confirm [--override minimal|rapid|standard|elevated|null] [--enabled true|false] [--project-root PATH]\n" +
|
|
608
|
+
` Inspect: ${policyColonInvocation("show", " --field=ceremonyDial")}\n`);
|
|
609
|
+
return 1;
|
|
610
|
+
}
|
|
611
|
+
const result = setCeremonyDial(root, {
|
|
612
|
+
confirm: args.confirm,
|
|
613
|
+
actor: args.actor,
|
|
614
|
+
note: args.note,
|
|
615
|
+
...(args.ceremonyOverride !== undefined ? { override: args.ceremonyOverride } : {}),
|
|
616
|
+
...(args.ceremonyEnabled !== undefined ? { enabled: args.ceremonyEnabled } : {}),
|
|
617
|
+
});
|
|
618
|
+
process.stdout.write(result.stdout);
|
|
619
|
+
return result.exitCode;
|
|
620
|
+
}
|
|
549
621
|
if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
550
622
|
process.exit(run(process.argv.slice(2)));
|
|
551
623
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** True when `candidate` is the same as or a descendant of `root` after realpath. */
|
|
3
|
+
export declare function isPathInsideRoot(root: string, candidate: string): boolean;
|
|
4
|
+
export interface ParsedArgs {
|
|
5
|
+
projectRoot: string;
|
|
6
|
+
xbriefPath: string;
|
|
7
|
+
actor: string;
|
|
8
|
+
kind: string;
|
|
9
|
+
/** Optional override for recorded xbriefRelPath (defaults: pending→active map). */
|
|
10
|
+
xbriefRelPath: string;
|
|
11
|
+
quiet: boolean;
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Map pending/ → active/ for path-bound approval records.
|
|
16
|
+
* Returns null when the source cannot be expressed as a repo-relative path under projectRoot
|
|
17
|
+
* (absolute outside-root paths must not be stamped into xbriefRelPath — #3205 Greptile).
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveApprovalXbriefRelPath(sourceRelOrAbs: string, projectRoot: string, override?: string): string | null;
|
|
20
|
+
export declare function parseArgs(argv: string[]): ParsedArgs;
|
|
21
|
+
export declare function run(argv: string[]): number;
|
|
22
|
+
//# sourceMappingURL=scope-record-approved-scope.d.ts.map
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI for scope:record-approved-scope (#3205).
|
|
4
|
+
*
|
|
5
|
+
* Deposits a human-origin approved-scope digest under
|
|
6
|
+
* `.deft/approved-scope/<plan-id>.json` so verify:scope-provenance can
|
|
7
|
+
* authorize pending→active and operator-approved expansion without same-PR
|
|
8
|
+
* self-authorization.
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, lstatSync, readFileSync, realpathSync } from "node:fs";
|
|
11
|
+
import { basename, join, relative, resolve, sep } from "node:path";
|
|
12
|
+
import { scopeProvenance } from "@deftai/directive-core";
|
|
13
|
+
import { isDirectEntrypoint } from "./entrypoint.js";
|
|
14
|
+
/** True when `candidate` is the same as or a descendant of `root` after realpath. */
|
|
15
|
+
export function isPathInsideRoot(root, candidate) {
|
|
16
|
+
let rootReal;
|
|
17
|
+
let candReal;
|
|
18
|
+
try {
|
|
19
|
+
rootReal = realpathSync(root);
|
|
20
|
+
// realpathSync fails if path does not exist; fall back to resolve for missing targets
|
|
21
|
+
candReal = existsSync(candidate) ? realpathSync(candidate) : resolve(candidate);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const rel = relative(rootReal, candReal);
|
|
27
|
+
if (rel === "")
|
|
28
|
+
return true;
|
|
29
|
+
if (rel.startsWith(`..${sep}`) ||
|
|
30
|
+
rel === ".." ||
|
|
31
|
+
rel.startsWith("../") ||
|
|
32
|
+
rel.startsWith("..\\")) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
// Absolute relative() means different drive/root (win32)
|
|
36
|
+
if (resolve(rel) === rel && rel.includes(":"))
|
|
37
|
+
return false;
|
|
38
|
+
return !rel.startsWith("..");
|
|
39
|
+
}
|
|
40
|
+
const { buildApprovedScopeRecord, isHumanApprovalStamp, writeApprovedScopeRecord } = scopeProvenance;
|
|
41
|
+
function usage() {
|
|
42
|
+
return ("usage: scope:record-approved-scope -- <xbrief-path> --actor <name> " +
|
|
43
|
+
"[--kind operator] [--project-root <dir>] [--xbrief-rel-path <posix>] [--quiet]\n" +
|
|
44
|
+
" Writes .deft/approved-scope/<plan-id>.json with a humanApproval stamp (#3205).\n" +
|
|
45
|
+
" Agent-shaped stamps are refused. Path-binds to xbrief/active/ by default when " +
|
|
46
|
+
"the source is under pending/ or active/.");
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Map pending/ → active/ for path-bound approval records.
|
|
50
|
+
* Returns null when the source cannot be expressed as a repo-relative path under projectRoot
|
|
51
|
+
* (absolute outside-root paths must not be stamped into xbriefRelPath — #3205 Greptile).
|
|
52
|
+
*/
|
|
53
|
+
export function resolveApprovalXbriefRelPath(sourceRelOrAbs, projectRoot, override) {
|
|
54
|
+
if (override !== undefined && override.trim().length > 0) {
|
|
55
|
+
const o = override.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
56
|
+
if (o.startsWith("/") || /^[A-Za-z]:\//.test(o))
|
|
57
|
+
return null;
|
|
58
|
+
return o;
|
|
59
|
+
}
|
|
60
|
+
const root = resolve(projectRoot);
|
|
61
|
+
const abs = resolve(sourceRelOrAbs.includes(":") ||
|
|
62
|
+
sourceRelOrAbs.startsWith("/") ||
|
|
63
|
+
sourceRelOrAbs.startsWith("\\")
|
|
64
|
+
? sourceRelOrAbs
|
|
65
|
+
: join(root, sourceRelOrAbs));
|
|
66
|
+
// Lexical + realpath containment (symlink to outside root must fail closed — #3205 Greptile).
|
|
67
|
+
if (!isPathInsideRoot(root, abs)) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
let rel = relative(root, abs).replace(/\\/g, "/");
|
|
71
|
+
if (rel.length === 0 || rel.startsWith("../") || rel === "..") {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
if (existsSync(abs) && lstatSync(abs).isSymbolicLink() && !isPathInsideRoot(root, abs)) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
// Normalize pending → active for future-active binding (issue #3205 multi-PR).
|
|
83
|
+
if (rel.startsWith("xbrief/pending/")) {
|
|
84
|
+
rel = `xbrief/active/${basename(rel)}`;
|
|
85
|
+
}
|
|
86
|
+
else if (rel.startsWith("vbrief/pending/")) {
|
|
87
|
+
rel = `vbrief/active/${basename(rel)}`;
|
|
88
|
+
}
|
|
89
|
+
return rel;
|
|
90
|
+
}
|
|
91
|
+
export function parseArgs(argv) {
|
|
92
|
+
const parsed = {
|
|
93
|
+
projectRoot: ".",
|
|
94
|
+
xbriefPath: "",
|
|
95
|
+
actor: "",
|
|
96
|
+
kind: "operator",
|
|
97
|
+
xbriefRelPath: "",
|
|
98
|
+
quiet: false,
|
|
99
|
+
};
|
|
100
|
+
const positionals = [];
|
|
101
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
102
|
+
const arg = argv[i];
|
|
103
|
+
if (arg === "--help" || arg === "-h") {
|
|
104
|
+
return { ...parsed, error: usage() };
|
|
105
|
+
}
|
|
106
|
+
if (arg === "--quiet") {
|
|
107
|
+
parsed.quiet = true;
|
|
108
|
+
}
|
|
109
|
+
else if (arg === "--project-root") {
|
|
110
|
+
const value = argv[i + 1];
|
|
111
|
+
if (value === undefined) {
|
|
112
|
+
return { ...parsed, error: "argument --project-root: expected one argument" };
|
|
113
|
+
}
|
|
114
|
+
parsed.projectRoot = value;
|
|
115
|
+
i += 1;
|
|
116
|
+
}
|
|
117
|
+
else if (arg?.startsWith("--project-root=")) {
|
|
118
|
+
parsed.projectRoot = arg.slice("--project-root=".length);
|
|
119
|
+
}
|
|
120
|
+
else if (arg === "--actor") {
|
|
121
|
+
const value = argv[i + 1];
|
|
122
|
+
if (value === undefined) {
|
|
123
|
+
return { ...parsed, error: "argument --actor: expected one argument" };
|
|
124
|
+
}
|
|
125
|
+
parsed.actor = value;
|
|
126
|
+
i += 1;
|
|
127
|
+
}
|
|
128
|
+
else if (arg?.startsWith("--actor=")) {
|
|
129
|
+
parsed.actor = arg.slice("--actor=".length);
|
|
130
|
+
}
|
|
131
|
+
else if (arg === "--kind") {
|
|
132
|
+
const value = argv[i + 1];
|
|
133
|
+
if (value === undefined) {
|
|
134
|
+
return { ...parsed, error: "argument --kind: expected one argument" };
|
|
135
|
+
}
|
|
136
|
+
parsed.kind = value;
|
|
137
|
+
i += 1;
|
|
138
|
+
}
|
|
139
|
+
else if (arg?.startsWith("--kind=")) {
|
|
140
|
+
parsed.kind = arg.slice("--kind=".length);
|
|
141
|
+
}
|
|
142
|
+
else if (arg === "--xbrief-rel-path") {
|
|
143
|
+
const value = argv[i + 1];
|
|
144
|
+
if (value === undefined) {
|
|
145
|
+
return { ...parsed, error: "argument --xbrief-rel-path: expected one argument" };
|
|
146
|
+
}
|
|
147
|
+
parsed.xbriefRelPath = value;
|
|
148
|
+
i += 1;
|
|
149
|
+
}
|
|
150
|
+
else if (arg?.startsWith("--xbrief-rel-path=")) {
|
|
151
|
+
parsed.xbriefRelPath = arg.slice("--xbrief-rel-path=".length);
|
|
152
|
+
}
|
|
153
|
+
else if (arg?.startsWith("-")) {
|
|
154
|
+
return { ...parsed, error: `unrecognized argument: ${arg}` };
|
|
155
|
+
}
|
|
156
|
+
else if (arg !== undefined) {
|
|
157
|
+
positionals.push(arg);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (positionals.length === 0) {
|
|
161
|
+
return { ...parsed, error: `missing xBRIEF path\n${usage()}` };
|
|
162
|
+
}
|
|
163
|
+
if (positionals.length > 1) {
|
|
164
|
+
return { ...parsed, error: `unexpected extra args: ${positionals.slice(1).join(" ")}` };
|
|
165
|
+
}
|
|
166
|
+
parsed.xbriefPath = positionals[0] ?? "";
|
|
167
|
+
if (parsed.actor.trim().length === 0) {
|
|
168
|
+
return {
|
|
169
|
+
...parsed,
|
|
170
|
+
error: `argument --actor is required (human operator identity)\n${usage()}`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return parsed;
|
|
174
|
+
}
|
|
175
|
+
export function run(argv) {
|
|
176
|
+
const args = parseArgs(argv);
|
|
177
|
+
if (args.error !== undefined) {
|
|
178
|
+
process.stderr.write(`scope_record_approved_scope: ${args.error}\n`);
|
|
179
|
+
return 2;
|
|
180
|
+
}
|
|
181
|
+
const projectRoot = resolve(args.projectRoot);
|
|
182
|
+
const xbriefAbs = resolve(projectRoot, args.xbriefPath);
|
|
183
|
+
if (!existsSync(xbriefAbs)) {
|
|
184
|
+
// Also try absolute path as given
|
|
185
|
+
const alt = resolve(args.xbriefPath);
|
|
186
|
+
if (!existsSync(alt)) {
|
|
187
|
+
process.stderr.write(`scope_record_approved_scope: xBRIEF not found: ${args.xbriefPath}\n`);
|
|
188
|
+
return 2;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const fullPath = existsSync(xbriefAbs) ? xbriefAbs : resolve(args.xbriefPath);
|
|
192
|
+
if (!isPathInsideRoot(projectRoot, fullPath)) {
|
|
193
|
+
process.stderr.write("scope_record_approved_scope: xBRIEF path escapes --project-root " +
|
|
194
|
+
"(symlink or absolute outside-root targets refused) (#3205).\n");
|
|
195
|
+
return 2;
|
|
196
|
+
}
|
|
197
|
+
let raw;
|
|
198
|
+
try {
|
|
199
|
+
raw = readFileSync(fullPath, "utf8");
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
process.stderr.write(`scope_record_approved_scope: failed to read xBRIEF: ${String(err)}\n`);
|
|
203
|
+
return 2;
|
|
204
|
+
}
|
|
205
|
+
let payload;
|
|
206
|
+
try {
|
|
207
|
+
payload = JSON.parse(raw);
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
process.stderr.write("scope_record_approved_scope: xBRIEF is not valid JSON\n");
|
|
211
|
+
return 2;
|
|
212
|
+
}
|
|
213
|
+
const stamp = {
|
|
214
|
+
kind: args.kind.trim(),
|
|
215
|
+
actor: args.actor.trim(),
|
|
216
|
+
mintedAt: new Date().toISOString().replace(/\.\d{3}Z$/, "Z"),
|
|
217
|
+
mintedVia: "scope:record-approved-scope",
|
|
218
|
+
};
|
|
219
|
+
if (!isHumanApprovalStamp(stamp)) {
|
|
220
|
+
process.stderr.write("scope_record_approved_scope: refused agent/non-human stamp " +
|
|
221
|
+
`(kind=${stamp.kind}, actor=${stamp.actor}). Use a human operator actor ` +
|
|
222
|
+
"and kind in {operator,human,user,cli,github-user,interactive,renewed-approval} (#3205).\n");
|
|
223
|
+
return 1;
|
|
224
|
+
}
|
|
225
|
+
const xbriefRelPath = resolveApprovalXbriefRelPath(fullPath, projectRoot, args.xbriefRelPath.length > 0 ? args.xbriefRelPath : undefined);
|
|
226
|
+
if (xbriefRelPath === null) {
|
|
227
|
+
process.stderr.write("scope_record_approved_scope: xBRIEF path must resolve under --project-root " +
|
|
228
|
+
"(repo-relative path required for approval binding) (#3205).\n");
|
|
229
|
+
return 2;
|
|
230
|
+
}
|
|
231
|
+
const record = buildApprovedScopeRecord({
|
|
232
|
+
xbriefRelPath,
|
|
233
|
+
payload,
|
|
234
|
+
humanApproval: stamp,
|
|
235
|
+
xbriefRawText: raw,
|
|
236
|
+
});
|
|
237
|
+
const outPath = writeApprovedScopeRecord(projectRoot, record);
|
|
238
|
+
if (!args.quiet) {
|
|
239
|
+
process.stdout.write(`scope_record_approved_scope: wrote ${outPath}\n` +
|
|
240
|
+
` planId: ${record.planId}\n` +
|
|
241
|
+
` xbriefRelPath: ${record.xbriefRelPath}\n` +
|
|
242
|
+
` fileScopeDigest: ${record.fileScopeDigest}\n` +
|
|
243
|
+
` paths: ${record.fileScope.length}\n` +
|
|
244
|
+
` humanApproval: ${stamp.kind}/${stamp.actor}\n` +
|
|
245
|
+
" Next: commit this file on the merge base (or a prior PR) before " +
|
|
246
|
+
"activation/expansion in the implementation change set (#3205).\n");
|
|
247
|
+
}
|
|
248
|
+
return 0;
|
|
249
|
+
}
|
|
250
|
+
if (isDirectEntrypoint(import.meta.url)) {
|
|
251
|
+
process.exit(run(process.argv.slice(2)));
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=scope-record-approved-scope.js.map
|
package/dist/session-start.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { type CeremonyDepth, type CeremonyDialInputs } from "@deftai/directive-core/policy";
|
|
2
3
|
import { type SessionCeremonyTier } from "@deftai/directive-core/session";
|
|
3
4
|
export interface ParsedSessionStartArgs {
|
|
4
5
|
projectRoot: string;
|
|
@@ -10,6 +11,13 @@ export interface ParsedSessionStartArgs {
|
|
|
10
11
|
withNetwork: boolean;
|
|
11
12
|
/** #2992: cold (full) vs rearm (clock/HEAD refresh without fat path). */
|
|
12
13
|
ceremonyTier: SessionCeremonyTier;
|
|
14
|
+
/** #3214: optional dial inputs for ritual-depth selection. */
|
|
15
|
+
ceremonyDialInputs: CeremonyDialInputs;
|
|
16
|
+
/**
|
|
17
|
+
* #3214: force depth for this session only (does not persist policy).
|
|
18
|
+
* Applied as resolve inputs via a one-shot config override in run().
|
|
19
|
+
*/
|
|
20
|
+
ceremonyDepthOverride: CeremonyDepth | null;
|
|
13
21
|
error?: string;
|
|
14
22
|
}
|
|
15
23
|
/** Parse session:start CLI args, mirroring scripts/session_start.py. */
|
package/dist/session-start.js
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { CEREMONY_DEPTHS, normalizeCeremonyModelTier, normalizeCeremonyProjectShape, normalizeCeremonyTaskSize, selectCeremonyDepth, } from "@deftai/directive-core/policy";
|
|
4
5
|
import { COLD_CEREMONY_TIER, parseDeferrals, READ_ONLY_POSTURE, REARM_CEREMONY_TIER, ritualStatePath, runSessionStart, SESSION_CEREMONY_TIERS, } from "@deftai/directive-core/session";
|
|
6
|
+
function parseCeremonyDepth(raw) {
|
|
7
|
+
const value = raw.trim().toLowerCase();
|
|
8
|
+
if (CEREMONY_DEPTHS.includes(value)) {
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
5
13
|
function parseCeremonyTier(raw) {
|
|
6
14
|
const value = raw.trim().toLowerCase();
|
|
7
15
|
if (SESSION_CEREMONY_TIERS.includes(value)) {
|
|
@@ -19,7 +27,10 @@ export function parseArgs(argv) {
|
|
|
19
27
|
readOnly: false,
|
|
20
28
|
withNetwork: false,
|
|
21
29
|
ceremonyTier: COLD_CEREMONY_TIER,
|
|
30
|
+
ceremonyDialInputs: {},
|
|
31
|
+
ceremonyDepthOverride: null,
|
|
22
32
|
};
|
|
33
|
+
const dialInputs = {};
|
|
23
34
|
for (let i = 0; i < argv.length; i += 1) {
|
|
24
35
|
const arg = argv[i];
|
|
25
36
|
if (arg === "--json") {
|
|
@@ -86,10 +97,129 @@ export function parseArgs(argv) {
|
|
|
86
97
|
else if (arg?.startsWith("--defer=")) {
|
|
87
98
|
parsed.deferValues.push(arg.slice("--defer=".length));
|
|
88
99
|
}
|
|
100
|
+
else if (arg === "--task-size" || arg === "--ceremony-task-size") {
|
|
101
|
+
const value = argv[i + 1];
|
|
102
|
+
if (value === undefined) {
|
|
103
|
+
return { ...parsed, error: `argument ${arg}: expected one argument (S|M|L|XL)` };
|
|
104
|
+
}
|
|
105
|
+
const size = normalizeCeremonyTaskSize(value);
|
|
106
|
+
if (size === null) {
|
|
107
|
+
return {
|
|
108
|
+
...parsed,
|
|
109
|
+
error: `argument ${arg}: expected S|M|L|XL (or small|medium|large), got ${JSON.stringify(value)}`,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
dialInputs.taskSize = size;
|
|
113
|
+
i += 1;
|
|
114
|
+
}
|
|
115
|
+
else if (arg?.startsWith("--task-size=") || arg?.startsWith("--ceremony-task-size=")) {
|
|
116
|
+
const value = arg.slice(arg.indexOf("=") + 1);
|
|
117
|
+
const size = normalizeCeremonyTaskSize(value);
|
|
118
|
+
if (size === null) {
|
|
119
|
+
return {
|
|
120
|
+
...parsed,
|
|
121
|
+
error: `argument --task-size: expected S|M|L|XL, got ${JSON.stringify(value)}`,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
dialInputs.taskSize = size;
|
|
125
|
+
}
|
|
126
|
+
else if (arg === "--model-tier" || arg === "--ceremony-model-tier") {
|
|
127
|
+
const value = argv[i + 1];
|
|
128
|
+
if (value === undefined) {
|
|
129
|
+
return {
|
|
130
|
+
...parsed,
|
|
131
|
+
error: `argument ${arg}: expected one argument (frontier|mid|low)`,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const tier = normalizeCeremonyModelTier(value);
|
|
135
|
+
if (tier === null) {
|
|
136
|
+
return {
|
|
137
|
+
...parsed,
|
|
138
|
+
error: `argument ${arg}: expected frontier|mid|low, got ${JSON.stringify(value)}`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
dialInputs.modelTier = tier;
|
|
142
|
+
i += 1;
|
|
143
|
+
}
|
|
144
|
+
else if (arg?.startsWith("--model-tier=") || arg?.startsWith("--ceremony-model-tier=")) {
|
|
145
|
+
const value = arg.slice(arg.indexOf("=") + 1);
|
|
146
|
+
const tier = normalizeCeremonyModelTier(value);
|
|
147
|
+
if (tier === null) {
|
|
148
|
+
return {
|
|
149
|
+
...parsed,
|
|
150
|
+
error: `argument --model-tier: expected frontier|mid|low, got ${JSON.stringify(value)}`,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
dialInputs.modelTier = tier;
|
|
154
|
+
}
|
|
155
|
+
else if (arg === "--project-shape" || arg === "--ceremony-project-shape") {
|
|
156
|
+
const value = argv[i + 1];
|
|
157
|
+
if (value === undefined) {
|
|
158
|
+
return {
|
|
159
|
+
...parsed,
|
|
160
|
+
error: `argument ${arg}: expected one argument (project|non-project)`,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const shape = normalizeCeremonyProjectShape(value);
|
|
164
|
+
if (shape === null) {
|
|
165
|
+
return {
|
|
166
|
+
...parsed,
|
|
167
|
+
error: `argument ${arg}: expected project|non-project, got ${JSON.stringify(value)}`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
dialInputs.projectShape = shape;
|
|
171
|
+
i += 1;
|
|
172
|
+
}
|
|
173
|
+
else if (arg?.startsWith("--project-shape=") ||
|
|
174
|
+
arg?.startsWith("--ceremony-project-shape=")) {
|
|
175
|
+
const value = arg.slice(arg.indexOf("=") + 1);
|
|
176
|
+
const shape = normalizeCeremonyProjectShape(value);
|
|
177
|
+
if (shape === null) {
|
|
178
|
+
return {
|
|
179
|
+
...parsed,
|
|
180
|
+
error: `argument --project-shape: expected project|non-project, got ${JSON.stringify(value)}`,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
dialInputs.projectShape = shape;
|
|
184
|
+
}
|
|
185
|
+
else if (arg === "--ceremony-depth") {
|
|
186
|
+
const value = argv[i + 1];
|
|
187
|
+
if (value === undefined) {
|
|
188
|
+
return {
|
|
189
|
+
...parsed,
|
|
190
|
+
error: "argument --ceremony-depth: expected one argument (minimal|rapid|standard|elevated)",
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const depth = parseCeremonyDepth(value);
|
|
194
|
+
if (depth === null) {
|
|
195
|
+
return {
|
|
196
|
+
...parsed,
|
|
197
|
+
error: `argument --ceremony-depth: expected minimal|rapid|standard|elevated, got ${JSON.stringify(value)}`,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
parsed.ceremonyDepthOverride = depth;
|
|
201
|
+
i += 1;
|
|
202
|
+
}
|
|
203
|
+
else if (arg?.startsWith("--ceremony-depth=")) {
|
|
204
|
+
const value = arg.slice("--ceremony-depth=".length);
|
|
205
|
+
const depth = parseCeremonyDepth(value);
|
|
206
|
+
if (depth === null) {
|
|
207
|
+
return {
|
|
208
|
+
...parsed,
|
|
209
|
+
error: `argument --ceremony-depth: expected minimal|rapid|standard|elevated, got ${JSON.stringify(value)}`,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
parsed.ceremonyDepthOverride = depth;
|
|
213
|
+
}
|
|
89
214
|
else {
|
|
90
215
|
return { ...parsed, error: `unrecognized argument: ${arg}` };
|
|
91
216
|
}
|
|
92
217
|
}
|
|
218
|
+
parsed.ceremonyDialInputs = {
|
|
219
|
+
taskSize: dialInputs.taskSize ?? null,
|
|
220
|
+
modelTier: dialInputs.modelTier ?? null,
|
|
221
|
+
projectShape: dialInputs.projectShape ?? null,
|
|
222
|
+
};
|
|
93
223
|
return parsed;
|
|
94
224
|
}
|
|
95
225
|
/** Native session:start handler (#2032 — replaces framework-commands Python bridge). */
|
|
@@ -119,12 +249,22 @@ export function run(argv) {
|
|
|
119
249
|
});
|
|
120
250
|
let result;
|
|
121
251
|
try {
|
|
252
|
+
// #3214: --ceremony-depth forces this session only (not persisted to policy).
|
|
122
253
|
result = runSessionStart(projectRoot, {
|
|
123
254
|
deferrals,
|
|
124
255
|
writeHistory: !args.noHistory,
|
|
125
256
|
posture: args.readOnly ? READ_ONLY_POSTURE : undefined,
|
|
126
257
|
allowOptionalNetwork: args.withNetwork ? true : undefined,
|
|
127
258
|
ceremonyTier: args.ceremonyTier,
|
|
259
|
+
ceremonyDialInputs: args.ceremonyDialInputs,
|
|
260
|
+
...(args.ceremonyDepthOverride !== null
|
|
261
|
+
? {
|
|
262
|
+
ceremonyDial: selectCeremonyDepth({
|
|
263
|
+
config: { enabled: true, override: args.ceremonyDepthOverride },
|
|
264
|
+
inputs: args.ceremonyDialInputs,
|
|
265
|
+
}),
|
|
266
|
+
}
|
|
267
|
+
: {}),
|
|
128
268
|
});
|
|
129
269
|
}
|
|
130
270
|
finally {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deftai/directive",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.99.0",
|
|
4
4
|
"description": "Directive CLI — npm install path for the Deft Directive framework.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://deftai.github.io/directive/",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"provenance": true
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@deftai/directive-core": "^0.
|
|
38
|
-
"@deftai/directive-content": "^0.
|
|
37
|
+
"@deftai/directive-core": "^0.99.0",
|
|
38
|
+
"@deftai/directive-content": "^0.99.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsc -b"
|