@deftai/directive 0.124.0 → 0.125.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authz.js +88 -3
- package/dist/cli-router/route-argv.d.ts +8 -0
- package/dist/cli-router/route-argv.js +41 -0
- package/dist/dispatch.d.ts +8 -5
- package/dist/dispatch.js +93 -14
- package/dist/preflight-gh.d.ts +2 -0
- package/dist/preflight-gh.js +14 -1
- package/package.json +3 -3
package/dist/authz.js
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
* deft authz:grant -- --template release-publish --target 0.30.0 [--confirm]
|
|
12
12
|
* deft authz:grant -- --template finish-loop [--confirm]
|
|
13
13
|
* deft authz:grant -- --template spec-drift-override --target <baseline> --plan-ref <scopeId> --story-ids <ids> [--confirm]
|
|
14
|
+
* deft authz:grant -- --template gate-override --target <refuseCode> --plan-ref <attemptId> \\
|
|
15
|
+
* --base-sha <sha> --head-sha <sha> --tree-hash <hash> [--confirm]
|
|
14
16
|
* deft authz:grant -- --parent <parent.xbrief.json> --draft <draft.json> [--repo owner/name] [--confirm]
|
|
15
17
|
* deft authz:revoke -- <grant-id> [--confirm]
|
|
16
18
|
*
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
import { existsSync } from "node:fs";
|
|
28
30
|
import { isAbsolute, resolve } from "node:path";
|
|
29
31
|
import { onePrUnit } from "@deftai/directive-core";
|
|
30
|
-
import { AFK_TEMPLATE_NAMES, AUTHZ_OPERATIONS, CLOSED_VERB_TEMPLATE_NAMES, FINISH_LOOP_TEMPLATE_NAME, formatDecomposeStructuralMintCommand, isAfkTemplateName, isClosedVerbTemplateName, isFinishLoopTemplateName, mintAfkTemplateGrant, mintDecomposeStructuralApplyGrant, mintHumanOriginGrant, revokeGrant, showAuthzSnapshot, startUatLease, suspendUatLease, toProjectRelativePosix, } from "@deftai/directive-core/authz";
|
|
32
|
+
import { AFK_TEMPLATE_NAMES, AUTHZ_OPERATIONS, CLOSED_VERB_TEMPLATE_NAMES, FINISH_LOOP_TEMPLATE_NAME, formatDecomposeStructuralMintCommand, GATE_OVERRIDE_TEMPLATE_NAME, isAfkTemplateName, isClosedVerbTemplateName, isFinishLoopTemplateName, isGateOverrideTemplateName, mintAfkTemplateGrant, mintDecomposeStructuralApplyGrant, mintGateOverrideTemplateGrant, mintHumanOriginGrant, revokeGrant, showAuthzSnapshot, startUatLease, suspendUatLease, toProjectRelativePosix, } from "@deftai/directive-core/authz";
|
|
31
33
|
import { uatCampaignEndSeal } from "@deftai/directive-core/authz/campaign-end-seal";
|
|
32
34
|
import { isSpecDriftOverrideTemplateName, mintSpecDriftOverrideTemplateGrant, SPEC_DRIFT_OVERRIDE_TEMPLATE_NAME, } from "@deftai/directive-core/policy";
|
|
33
35
|
import { refuseMintWhileUatActive, refuseNonInteractiveMint, resolveHumanPresenceMintSeams, } from "./human-presence-mint.js";
|
|
@@ -68,6 +70,11 @@ function parseArgv(argv) {
|
|
|
68
70
|
target: null,
|
|
69
71
|
parent: null,
|
|
70
72
|
draft: null,
|
|
73
|
+
baseSha: null,
|
|
74
|
+
headSha: null,
|
|
75
|
+
treeHash: null,
|
|
76
|
+
worktree: null,
|
|
77
|
+
evaluatorId: null,
|
|
71
78
|
format: "text",
|
|
72
79
|
confirm: false,
|
|
73
80
|
};
|
|
@@ -196,6 +203,26 @@ function parseArgv(argv) {
|
|
|
196
203
|
base.draft = args[++i] ?? null;
|
|
197
204
|
continue;
|
|
198
205
|
}
|
|
206
|
+
if (a === "--base-sha" || a === "--baseSha") {
|
|
207
|
+
base.baseSha = args[++i] ?? null;
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (a === "--head-sha" || a === "--headSha") {
|
|
211
|
+
base.headSha = args[++i] ?? null;
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (a === "--tree-hash" || a === "--treeHash") {
|
|
215
|
+
base.treeHash = args[++i] ?? null;
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (a === "--worktree") {
|
|
219
|
+
base.worktree = args[++i] ?? null;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (a === "--evaluator-id" || a === "--evaluatorId") {
|
|
223
|
+
base.evaluatorId = args[++i] ?? null;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
199
226
|
if (a === "--confirm") {
|
|
200
227
|
base.confirm = true;
|
|
201
228
|
continue;
|
|
@@ -255,6 +282,11 @@ function helpText() {
|
|
|
255
282
|
` Finish-loop (#871): ${FINISH_LOOP_TEMPLATE_NAME} — edit/push/pr/merge (no release ops)`,
|
|
256
283
|
" Templates call mintHumanOriginGrant only — no second session-auth mint engine.",
|
|
257
284
|
" Env bypass for a single shell: DEFT_ALLOW_RELEASE_PUBLISH=1 / DEFT_ALLOW_FINISH_LOOP=1.",
|
|
285
|
+
"",
|
|
286
|
+
`Gate-override (#5542): ${GATE_OVERRIDE_TEMPLATE_NAME}`,
|
|
287
|
+
" deft authz:grant -- --template gate-override --target <refuseCode> --plan-ref <attemptId> \\",
|
|
288
|
+
" --base-sha <sha> --head-sha <sha> --tree-hash <hash> [--worktree <id>] [--evaluator-id <id>] [--confirm]",
|
|
289
|
+
" operator-cli human-presence only; waived ≠ passed; no independent push/merge.",
|
|
258
290
|
].join("\n");
|
|
259
291
|
}
|
|
260
292
|
export function main(argv = process.argv.slice(2), seams = {}) {
|
|
@@ -481,6 +513,59 @@ export function main(argv = process.argv.slice(2), seams = {}) {
|
|
|
481
513
|
process.stdout.write(` origins=${claim.origins.map((o) => `${o.repo}#${o.issueId}`).join(",")}\n`);
|
|
482
514
|
return 0;
|
|
483
515
|
}
|
|
516
|
+
// Gate-override hatch (#5542 Prefer-A Bound): coverage-applicability refuse waiver.
|
|
517
|
+
if (args.template !== null && isGateOverrideTemplateName(args.template)) {
|
|
518
|
+
if (args.target === null || args.target.trim().length === 0) {
|
|
519
|
+
process.stderr.write("authz:grant --template gate-override requires --target <refuseCode>\n");
|
|
520
|
+
return 2;
|
|
521
|
+
}
|
|
522
|
+
if (args.planRef === null || args.planRef.trim().length === 0) {
|
|
523
|
+
process.stderr.write("authz:grant --template gate-override requires --plan-ref <attemptId>\n");
|
|
524
|
+
return 2;
|
|
525
|
+
}
|
|
526
|
+
if (args.baseSha === null ||
|
|
527
|
+
args.baseSha.trim().length === 0 ||
|
|
528
|
+
args.headSha === null ||
|
|
529
|
+
args.headSha.trim().length === 0 ||
|
|
530
|
+
args.treeHash === null ||
|
|
531
|
+
args.treeHash.trim().length === 0) {
|
|
532
|
+
process.stderr.write("authz:grant --template gate-override requires --base-sha --head-sha --tree-hash\n");
|
|
533
|
+
return 2;
|
|
534
|
+
}
|
|
535
|
+
const blockedGate = gateConfirm();
|
|
536
|
+
if (blockedGate !== null)
|
|
537
|
+
return blockedGate;
|
|
538
|
+
const mintedGate = mintGateOverrideTemplateGrant({
|
|
539
|
+
projectRoot: args.projectRoot,
|
|
540
|
+
target: args.target,
|
|
541
|
+
planRef: args.planRef,
|
|
542
|
+
baseSha: args.baseSha,
|
|
543
|
+
headSha: args.headSha,
|
|
544
|
+
treeHash: args.treeHash,
|
|
545
|
+
actor: args.actor,
|
|
546
|
+
expiresAt: args.expiresAt,
|
|
547
|
+
// gate-override template is always single-use (#5542 Greptile P2).
|
|
548
|
+
singleUse: true,
|
|
549
|
+
repo: args.repo,
|
|
550
|
+
branch: args.branch,
|
|
551
|
+
worktree: args.worktree,
|
|
552
|
+
evaluatorId: args.evaluatorId,
|
|
553
|
+
failedGateEvidence: args.note,
|
|
554
|
+
});
|
|
555
|
+
if (!mintedGate.ok) {
|
|
556
|
+
process.stderr.write(`authz:grant: ${mintedGate.reason}\n`);
|
|
557
|
+
return 2;
|
|
558
|
+
}
|
|
559
|
+
const gateGrant = mintedGate.grant;
|
|
560
|
+
process.stdout.write(`✓ human-origin grant minted id=${gateGrant.id} origin=${gateGrant.origin.kind} ` +
|
|
561
|
+
`template=${GATE_OVERRIDE_TEMPLATE_NAME}\n`);
|
|
562
|
+
process.stdout.write(` ops=[${gateGrant.scope.operations.join(",")}] attempt=${gateGrant.scope.planRef} ` +
|
|
563
|
+
`surfaces=${gateGrant.scope.surfaces.join(", ")}\n`);
|
|
564
|
+
process.stdout.write(" Hatch: waives coverage-applicability refuse for bound attempt/tree only; " +
|
|
565
|
+
"waived ≠ passed; reviewObligation=pre-merge-human-review-required.\n");
|
|
566
|
+
process.stdout.write(" Authorization SoT: Wave 1 grant store (.deft/authz/grants) — not session-auth / chat.\n");
|
|
567
|
+
return 0;
|
|
568
|
+
}
|
|
484
569
|
// Spec-drift override hatch (#5350): policy module, not authz/** (class 4).
|
|
485
570
|
if (args.template !== null && isSpecDriftOverrideTemplateName(args.template)) {
|
|
486
571
|
if (args.target === null || args.target.trim().length === 0) {
|
|
@@ -525,7 +610,7 @@ export function main(argv = process.argv.slice(2), seams = {}) {
|
|
|
525
610
|
// AFK template path (#1095 / #871): presets only — still mintHumanOriginGrant.
|
|
526
611
|
if (args.template !== null && args.template.trim().length > 0) {
|
|
527
612
|
if (!isAfkTemplateName(args.template)) {
|
|
528
|
-
process.stderr.write(`authz:grant unknown --template '${args.template}'; expected one of: ${AFK_TEMPLATE_NAMES.join(", ")}, ${SPEC_DRIFT_OVERRIDE_TEMPLATE_NAME}\n`);
|
|
613
|
+
process.stderr.write(`authz:grant unknown --template '${args.template}'; expected one of: ${AFK_TEMPLATE_NAMES.join(", ")}, ${SPEC_DRIFT_OVERRIDE_TEMPLATE_NAME}, ${GATE_OVERRIDE_TEMPLATE_NAME}\n`);
|
|
529
614
|
return 2;
|
|
530
615
|
}
|
|
531
616
|
if (isClosedVerbTemplateName(args.template) &&
|
|
@@ -569,7 +654,7 @@ export function main(argv = process.argv.slice(2), seams = {}) {
|
|
|
569
654
|
return 0;
|
|
570
655
|
}
|
|
571
656
|
if (args.operations.length === 0) {
|
|
572
|
-
process.stderr.write("authz:grant requires --operations <edit,push,...>, --template <finish-loop|release-*|spec-drift-override>, " +
|
|
657
|
+
process.stderr.write("authz:grant requires --operations <edit,push,...>, --template <finish-loop|release-*|spec-drift-override|gate-override>, " +
|
|
573
658
|
"or --parent + --draft (structural scope:decompose apply)\n");
|
|
574
659
|
return 2;
|
|
575
660
|
}
|
|
@@ -16,6 +16,14 @@ export declare const PR_VERB_MAP: Readonly<Record<string, string>>;
|
|
|
16
16
|
export declare const VERIFY_VERB_MAP: Readonly<Record<string, string>>;
|
|
17
17
|
/** Namespace handlers that require a subcommand token after the handler stem. */
|
|
18
18
|
export declare const SUBCOMMAND_ROUTES: Readonly<Record<string, readonly [string, string]>>;
|
|
19
|
+
/** Eight scm:body:* dual-invoke names (#5521); keep in sync with SUBCOMMAND_ROUTES above. */
|
|
20
|
+
export declare const SCM_BODY_COLON_VERBS: readonly ["scm:body:issue:create", "scm:body:issue:edit", "scm:body:issue:fetch", "scm:body:issue:lint", "scm:body:comment:create", "scm:body:comment:edit", "scm:body:pr:edit", "scm:body:pr:lint"];
|
|
21
|
+
/**
|
|
22
|
+
* Colon forms handled by explicit `routeNamespaceVerb` branches (not SUBCOMMAND_ROUTES /
|
|
23
|
+
* PR_VERB_MAP / VERIFY_VERB_MAP / SCOPE_LIFECYCLE_VERBS). Scraped by rule-to-verb parity
|
|
24
|
+
* so valid citations like `deft framework:doctor` pass (#5521).
|
|
25
|
+
*/
|
|
26
|
+
export declare const ROUTER_BRANCH_COLON_VERBS: readonly ["framework:doctor", "agents:refresh", "scope:demote", "scope:decompose", "scope:undo", "scope:record-approved-scope", "scope:record-observable-scope", "scope:record-intent-constraint", "scm:issue:design-critique-chip", "scm:issue:design-critique-stale-ready", "scm:issue:work-claim", "issue:ingest", "issue:emit", "issue:sync-from-xbrief"];
|
|
19
27
|
export type RouteKind = "dispatch" | "stub";
|
|
20
28
|
export interface RoutedArgv {
|
|
21
29
|
kind: RouteKind;
|
|
@@ -118,11 +118,52 @@ export const SUBCOMMAND_ROUTES = {
|
|
|
118
118
|
"github-body:comment-edit": ["github-body", "comment-edit"],
|
|
119
119
|
"github-body:pr-edit": ["github-body", "pr-edit"],
|
|
120
120
|
"github-body:pr-lint": ["github-body", "pr-lint"],
|
|
121
|
+
// #5521: pinned AGENTS scm:body:* colon aliases → github-body engine (argv inserts subcommand)
|
|
122
|
+
"scm:body:issue:create": ["github-body", "issue-create"],
|
|
123
|
+
"scm:body:issue:edit": ["github-body", "issue-edit"],
|
|
124
|
+
"scm:body:issue:fetch": ["github-body", "issue-fetch"],
|
|
125
|
+
"scm:body:issue:lint": ["github-body", "issue-lint"],
|
|
126
|
+
"scm:body:comment:create": ["github-body", "comment-create"],
|
|
127
|
+
"scm:body:comment:edit": ["github-body", "comment-edit"],
|
|
128
|
+
"scm:body:pr:edit": ["github-body", "pr-edit"],
|
|
129
|
+
"scm:body:pr:lint": ["github-body", "pr-lint"],
|
|
121
130
|
"plan-sequence:set": ["plan-sequence", "set"],
|
|
122
131
|
"plan-sequence:current": ["plan-sequence", "current"],
|
|
123
132
|
"plan-sequence:clear": ["plan-sequence", "clear"],
|
|
124
133
|
"plan-sequence:advance": ["plan-sequence", "advance"],
|
|
125
134
|
};
|
|
135
|
+
/** Eight scm:body:* dual-invoke names (#5521); keep in sync with SUBCOMMAND_ROUTES above. */
|
|
136
|
+
export const SCM_BODY_COLON_VERBS = [
|
|
137
|
+
"scm:body:issue:create",
|
|
138
|
+
"scm:body:issue:edit",
|
|
139
|
+
"scm:body:issue:fetch",
|
|
140
|
+
"scm:body:issue:lint",
|
|
141
|
+
"scm:body:comment:create",
|
|
142
|
+
"scm:body:comment:edit",
|
|
143
|
+
"scm:body:pr:edit",
|
|
144
|
+
"scm:body:pr:lint",
|
|
145
|
+
];
|
|
146
|
+
/**
|
|
147
|
+
* Colon forms handled by explicit `routeNamespaceVerb` branches (not SUBCOMMAND_ROUTES /
|
|
148
|
+
* PR_VERB_MAP / VERIFY_VERB_MAP / SCOPE_LIFECYCLE_VERBS). Scraped by rule-to-verb parity
|
|
149
|
+
* so valid citations like `deft framework:doctor` pass (#5521).
|
|
150
|
+
*/
|
|
151
|
+
export const ROUTER_BRANCH_COLON_VERBS = [
|
|
152
|
+
"framework:doctor",
|
|
153
|
+
"agents:refresh",
|
|
154
|
+
"scope:demote",
|
|
155
|
+
"scope:decompose",
|
|
156
|
+
"scope:undo",
|
|
157
|
+
"scope:record-approved-scope",
|
|
158
|
+
"scope:record-observable-scope",
|
|
159
|
+
"scope:record-intent-constraint",
|
|
160
|
+
"scm:issue:design-critique-chip",
|
|
161
|
+
"scm:issue:design-critique-stale-ready",
|
|
162
|
+
"scm:issue:work-claim",
|
|
163
|
+
"issue:ingest",
|
|
164
|
+
"issue:emit",
|
|
165
|
+
"issue:sync-from-xbrief",
|
|
166
|
+
];
|
|
126
167
|
function isMetaVerb(token) {
|
|
127
168
|
return token === "--help" || token === "-h" || token === "--version" || token === "-V";
|
|
128
169
|
}
|
package/dist/dispatch.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export interface DispatchIo {
|
|
|
12
12
|
/** CLI modules in packages/cli/src (excluding parity harnesses and bin/index). */
|
|
13
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", "ownership-doctor", "ownership-fix", "verify-ownership", "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", "pre-pr-run", "preflight-cache", "preflight-gh", "probe-session", "release", "release-e2e", "release-publish", "release-rollback", "release-wait-npm", "scope-lifecycle", "scope-record-approved-scope", "scope-record-observable-scope", "scope-record-intent-constraint", "scm-sync-default", "lifecycle-event", "lifecycle-stats", "session-start", "session-ready", "occupancy-steal", "occupancy-release", "occupancy-heartbeat", "occupancy-grant", "plan-sequence", "slice", "subagent-monitor", "toolchain-check", "triage-actions", "triage-bootstrap", "triage-bulk", "triage-classify", "triage-strip-withdrawn", "triage-evaluate", "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", "xbrief-adopt-stored-plan-id", "verify-branch", "verify-encoding", "verify-forward-coverage", "verify-test-boundary", "verify-class-checks", "verify-presentation-coverage", "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-telemetry-coverage", "verify-content-manifest", "verify-deposit-closure", "verify-consumer-hard-stops", "verify-closing-keywords", "verify-skill-external-fetch-gate", "verify-semantic-single-source", "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", "verify-spec-prd-fresh", "verify-spec-drift", "rule-ownership-lint", "verify-story-ready", "verify-review-monitor", "verify-cohort-review-monitors", "verify-l4-owner", "verify-subagent-alive", "verify-subagent-steer", "subagent-pre-cancel", "subagent-steer-write", "design-critique-spend-resolve", "review-monitor-register", "review-monitor-release", "verify-tools", "verify-wip-cap", "verify-orphan-active", "verify-pr-closeout-attestable", "verify-lifecycle-visible", "verify-completed-tracked", "verify-completed-write-guard", "verify-literal-ac", "verify-ac", "verify-agents-md-budget", "verify-consumer-header-placeholder", "verify-agents-md-advisory", "verify-persisted-planning-narratives", "verify-eval-health-relocation", "verify-eval-triggers-relocation", "verify-evaluator-surface", "verify-observable-scope", "verify-operator-scope-limit", "verify-presentation-ceiling", "verify-intent-constraint", "verify-durable-effect-acquisition", "verify-consumer-test-lane", "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-finalize-owed", "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", "project-write-narratives", "roadmap-render", "rule-map", "spec-render", "spec-reconstruct", "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", "docs-impact", "migrate-clause-ids", "migrate-confidence"];
|
|
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-finalize-owed", "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", "project-write-narratives", "roadmap-render", "rule-map", "spec-render", "spec-reconstruct", "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", "docs-impact", "tutorial", "migrate-clause-ids", "migrate-confidence", "rule-to-verb-parity"];
|
|
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). */
|
|
@@ -23,6 +23,8 @@ export declare const AUTHZ_ACTION_ALIAS_SUBCOMMANDS: Readonly<Record<string, str
|
|
|
23
23
|
export declare const ESCALATION_ACTION_ALIAS_SUBCOMMANDS: Readonly<Record<string, string>>;
|
|
24
24
|
/** Colon aliases for plan-sequence subcommands (#2402). */
|
|
25
25
|
export declare const PLAN_SEQUENCE_ALIAS_SUBCOMMANDS: Readonly<Record<string, string>>;
|
|
26
|
+
/** Colon aliases for the Directive Tutorial (#4981). */
|
|
27
|
+
export declare const TUTORIAL_ALIAS_SUBCOMMANDS: Readonly<Record<string, string>>;
|
|
26
28
|
/** Colon aliases for product-signal subcommands (#2693). */
|
|
27
29
|
export declare const PRODUCT_SIGNAL_ALIAS_SUBCOMMANDS: Readonly<Record<string, string>>;
|
|
28
30
|
/** Colon aliases for freshness subcommands (#3117). */
|
|
@@ -177,12 +179,13 @@ export declare function printCommandsList(io?: DispatchIo): void;
|
|
|
177
179
|
* (#2172). Preserves the init/update/doctor first-run guidance from #2273.
|
|
178
180
|
*/
|
|
179
181
|
export declare function printHelp(io?: DispatchIo): void;
|
|
182
|
+
export type UnknownColonHintContext = "framework" | "include-only" | "no-taskfile" | "unknown";
|
|
180
183
|
/**
|
|
181
|
-
* Unknown-colon-verb remediation (#3439 / #2652).
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
+
* Unknown-colon-verb remediation (#3439 / #2652 / #5521).
|
|
185
|
+
* Never re-suggest the failing `deft <verb>` spelling. Prefer Taskfile
|
|
186
|
+
* dual-invoke forms when known; demote hyphen stems; no `task --list` shell-out.
|
|
184
187
|
*/
|
|
185
|
-
export declare function unknownColonVerbHint(verb: string): string;
|
|
188
|
+
export declare function unknownColonVerbHint(verb: string, context?: UnknownColonHintContext): string;
|
|
186
189
|
/** Dispatch argv to a registered verb; returns the handler exit code. */
|
|
187
190
|
export declare function dispatch(argv: string[], io?: DispatchIo): Promise<number>;
|
|
188
191
|
/** Test seam: reset lazy handler cache between cases. */
|
package/dist/dispatch.js
CHANGED
|
@@ -243,8 +243,10 @@ export const CORE_MODULE_VERBS = [
|
|
|
243
243
|
"decision-write",
|
|
244
244
|
"decision-list",
|
|
245
245
|
"docs-impact",
|
|
246
|
+
"tutorial",
|
|
246
247
|
"migrate-clause-ids",
|
|
247
248
|
"migrate-confidence",
|
|
249
|
+
"rule-to-verb-parity",
|
|
248
250
|
];
|
|
249
251
|
/** Colon aliases for triage-actions (mirrors cli-router SUBCOMMAND_ROUTES). */
|
|
250
252
|
export const TRIAGE_ACTION_ALIAS_SUBCOMMANDS = {
|
|
@@ -300,6 +302,20 @@ export const PLAN_SEQUENCE_ALIAS_SUBCOMMANDS = {
|
|
|
300
302
|
"plan-sequence:advance": "advance",
|
|
301
303
|
};
|
|
302
304
|
const PLAN_SEQUENCE_COLON_ALIASES = Object.fromEntries(Object.keys(PLAN_SEQUENCE_ALIAS_SUBCOMMANDS).map((alias) => [alias, "plan-sequence"]));
|
|
305
|
+
/** Colon aliases for the Directive Tutorial (#4981). */
|
|
306
|
+
export const TUTORIAL_ALIAS_SUBCOMMANDS = {
|
|
307
|
+
"tutorial:offer": "offer",
|
|
308
|
+
"tutorial:start": "start",
|
|
309
|
+
"tutorial:inspect": "inspect",
|
|
310
|
+
"tutorial:advance": "advance",
|
|
311
|
+
"tutorial:resume": "resume",
|
|
312
|
+
"tutorial:skip": "skip",
|
|
313
|
+
"tutorial:leave": "leave",
|
|
314
|
+
"tutorial:reset": "reset",
|
|
315
|
+
"tutorial:decline": "decline",
|
|
316
|
+
"tutorial:defer": "defer",
|
|
317
|
+
};
|
|
318
|
+
const TUTORIAL_COLON_ALIASES = Object.fromEntries(Object.keys(TUTORIAL_ALIAS_SUBCOMMANDS).map((alias) => [alias, "tutorial"]));
|
|
303
319
|
/** Colon aliases for product-signal subcommands (#2693). */
|
|
304
320
|
export const PRODUCT_SIGNAL_ALIAS_SUBCOMMANDS = {
|
|
305
321
|
"product-signal:status": "status",
|
|
@@ -391,6 +407,7 @@ export const VERB_ALIASES = {
|
|
|
391
407
|
"validate:links": "validate-links",
|
|
392
408
|
"verify:rule-ownership": "rule-ownership-lint",
|
|
393
409
|
"rule:ownership-lint": "rule-ownership-lint",
|
|
410
|
+
"verify:rule-to-verb-parity": "rule-to-verb-parity",
|
|
394
411
|
"verify:biome-config": "verify-biome-config",
|
|
395
412
|
"verify:contained-writes": "verify-contained-writes",
|
|
396
413
|
"verify:telemetry-coverage": "verify-telemetry-coverage",
|
|
@@ -414,6 +431,7 @@ export const VERB_ALIASES = {
|
|
|
414
431
|
"verify:session-ritual": "verify-session-ritual",
|
|
415
432
|
"verify:plan-sequence": "verify-plan-sequence",
|
|
416
433
|
...PLAN_SEQUENCE_COLON_ALIASES,
|
|
434
|
+
...TUTORIAL_COLON_ALIASES,
|
|
417
435
|
"verify-strategy-output": "validate-strategy-output",
|
|
418
436
|
"validate:strategy-output": "validate-strategy-output",
|
|
419
437
|
"verify:codebase-map-fresh": "codebase-map-fresh",
|
|
@@ -2469,6 +2487,10 @@ async function loadCoreModuleHandler(verb, io) {
|
|
|
2469
2487
|
const { mainEntry } = await import("@deftai/directive-core/dist/intake/github-body-cli.js");
|
|
2470
2488
|
return mainEntry;
|
|
2471
2489
|
}
|
|
2490
|
+
case "rule-to-verb-parity": {
|
|
2491
|
+
const { mainEntry } = await import("@deftai/directive-core/dist/check/rule-to-verb-parity.js");
|
|
2492
|
+
return mainEntry;
|
|
2493
|
+
}
|
|
2472
2494
|
case "issue-emit": {
|
|
2473
2495
|
const { mainEntry } = await import("@deftai/directive-core/dist/intake/issue-emit-cli.js");
|
|
2474
2496
|
return mainEntry;
|
|
@@ -2656,6 +2678,10 @@ async function loadCoreModuleHandler(verb, io) {
|
|
|
2656
2678
|
const { docsImpactMain } = await import("@deftai/directive-core/dist/docs/docs-impact.js");
|
|
2657
2679
|
return (argv) => docsImpactMain(argv);
|
|
2658
2680
|
}
|
|
2681
|
+
case "tutorial": {
|
|
2682
|
+
const { tutorialMain } = await import("@deftai/directive-core/dist/tutorial/cli.js");
|
|
2683
|
+
return tutorialMain;
|
|
2684
|
+
}
|
|
2659
2685
|
case "migrate-clause-ids": {
|
|
2660
2686
|
const { mainEntry } = await import("@deftai/directive-core/dist/xbrief-migrate/clause-ids.js");
|
|
2661
2687
|
return (argv) => mainEntry(argv);
|
|
@@ -2729,6 +2755,21 @@ const SCOPE_COMMAND_NAMES = [
|
|
|
2729
2755
|
"scope:record-observable-scope",
|
|
2730
2756
|
"scope:record-intent-constraint",
|
|
2731
2757
|
];
|
|
2758
|
+
/**
|
|
2759
|
+
* Static dual-invoke set for scm:body:* (#5521). Mirror of
|
|
2760
|
+
* packages/cli/src/cli-router/route-argv.ts SCM_BODY_COLON_VERBS — kept here
|
|
2761
|
+
* so dispatch does not import route-argv (route-argv already imports dispatch).
|
|
2762
|
+
*/
|
|
2763
|
+
const SCM_BODY_DUAL_INVOKE_VERBS = new Set([
|
|
2764
|
+
"scm:body:issue:create",
|
|
2765
|
+
"scm:body:issue:edit",
|
|
2766
|
+
"scm:body:issue:fetch",
|
|
2767
|
+
"scm:body:issue:lint",
|
|
2768
|
+
"scm:body:comment:create",
|
|
2769
|
+
"scm:body:comment:edit",
|
|
2770
|
+
"scm:body:pr:edit",
|
|
2771
|
+
"scm:body:pr:lint",
|
|
2772
|
+
]);
|
|
2732
2773
|
/**
|
|
2733
2774
|
* Deduplicated command names for `directive commands`, preferring colon-style
|
|
2734
2775
|
* task verbs over dash-style canonical stems when both exist (#2172).
|
|
@@ -2742,6 +2783,7 @@ export function preferredCommandNames() {
|
|
|
2742
2783
|
...TOP_LEVEL_COMMAND_NAMES,
|
|
2743
2784
|
...SCOPE_COMMAND_NAMES,
|
|
2744
2785
|
...aliasKeys,
|
|
2786
|
+
...SCM_BODY_DUAL_INVOKE_VERBS,
|
|
2745
2787
|
...unaliasedCanonicals,
|
|
2746
2788
|
]),
|
|
2747
2789
|
].sort();
|
|
@@ -2910,20 +2952,54 @@ async function invokeHandler(handler, argv) {
|
|
|
2910
2952
|
}
|
|
2911
2953
|
const PLAN_SEQUENCE_VERBS = "set|current|clear|advance";
|
|
2912
2954
|
/**
|
|
2913
|
-
* Unknown-colon-verb remediation (#3439 / #2652).
|
|
2914
|
-
*
|
|
2915
|
-
*
|
|
2955
|
+
* Unknown-colon-verb remediation (#3439 / #2652 / #5521).
|
|
2956
|
+
* Never re-suggest the failing `deft <verb>` spelling. Prefer Taskfile
|
|
2957
|
+
* dual-invoke forms when known; demote hyphen stems; no `task --list` shell-out.
|
|
2916
2958
|
*/
|
|
2917
|
-
export function unknownColonVerbHint(verb) {
|
|
2959
|
+
export function unknownColonVerbHint(verb, context = "unknown") {
|
|
2918
2960
|
if (verb.startsWith("plan-sequence:") && !(verb in PLAN_SEQUENCE_ALIAS_SUBCOMMANDS)) {
|
|
2919
2961
|
return (`hint: plan-sequence verbs are ${PLAN_SEQUENCE_VERBS} ` +
|
|
2920
2962
|
`(e.g. \`deft plan-sequence:current\`). '${verb}' is not a verb. ` +
|
|
2921
2963
|
`Do not run bare \`task ${verb}\` -- consumer include-only Taskfiles cannot resolve it.\n`);
|
|
2922
2964
|
}
|
|
2923
2965
|
const hyphen = verb.replaceAll(":", "-");
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2966
|
+
const hyphenNote = `Hyphen stem \`${hyphen}\` is not primary recovery.`;
|
|
2967
|
+
const listing = "List registered CLI verbs with `deft commands`.";
|
|
2968
|
+
if (SCM_BODY_DUAL_INVOKE_VERBS.has(verb)) {
|
|
2969
|
+
if (context === "include-only") {
|
|
2970
|
+
return (`hint: try \`task deft:${verb}\` (consumer include Taskfile). ` +
|
|
2971
|
+
`Bare \`task ${verb}\` is framework-only. ${hyphenNote} ${listing}\n`);
|
|
2972
|
+
}
|
|
2973
|
+
if (context === "no-taskfile") {
|
|
2974
|
+
return (`hint: Taskfile recovery is unavailable here. ` +
|
|
2975
|
+
`On a framework checkout with go-task: \`task ${verb}\`; ` +
|
|
2976
|
+
`on an include-only deposit: \`task deft:${verb}\`. ${hyphenNote} ${listing}\n`);
|
|
2977
|
+
}
|
|
2978
|
+
if (context === "framework") {
|
|
2979
|
+
return (`hint: try \`task ${verb}\` (framework Taskfile) or \`task deft:${verb}\` (consumer include). ` +
|
|
2980
|
+
`${hyphenNote} ${listing}\n`);
|
|
2981
|
+
}
|
|
2982
|
+
return (`hint: if go-task is available, try \`task ${verb}\` (framework) or ` +
|
|
2983
|
+
`\`task deft:${verb}\` (consumer include) — Taskfile recovery is conditional. ` +
|
|
2984
|
+
`${hyphenNote} ${listing}\n`);
|
|
2985
|
+
}
|
|
2986
|
+
if (context === "include-only") {
|
|
2987
|
+
return (`hint: do not retry the same \`deft ${verb}\` spelling. ` +
|
|
2988
|
+
`If a Taskfile task exists, try \`task deft:${verb}\` (include-only). ` +
|
|
2989
|
+
`${hyphenNote} ${listing}\n`);
|
|
2990
|
+
}
|
|
2991
|
+
if (context === "no-taskfile") {
|
|
2992
|
+
return (`hint: do not retry the same \`deft ${verb}\` spelling. ` +
|
|
2993
|
+
`Taskfile recovery is unavailable here. ${hyphenNote} ${listing}\n`);
|
|
2994
|
+
}
|
|
2995
|
+
if (context === "framework") {
|
|
2996
|
+
return (`hint: do not retry the same \`deft ${verb}\` spelling. ` +
|
|
2997
|
+
`If a Taskfile task exists, try \`task ${verb}\` (framework) or \`task deft:${verb}\` (include). ` +
|
|
2998
|
+
`${hyphenNote} ${listing}\n`);
|
|
2999
|
+
}
|
|
3000
|
+
return (`hint: do not retry the same \`deft ${verb}\` spelling. ` +
|
|
3001
|
+
`If a Taskfile task exists, try \`task ${verb}\` (framework) or \`task deft:${verb}\` (include) — ` +
|
|
3002
|
+
`Taskfile recovery is conditional. ${hyphenNote} ${listing}\n`);
|
|
2927
3003
|
}
|
|
2928
3004
|
function versionBanner() {
|
|
2929
3005
|
return `${identityBanner()}\n`;
|
|
@@ -2957,6 +3033,7 @@ export async function dispatch(argv, io = defaultIo()) {
|
|
|
2957
3033
|
const authzSubcommand = verb !== undefined ? AUTHZ_ACTION_ALIAS_SUBCOMMANDS[verb] : undefined;
|
|
2958
3034
|
const escalationSubcommand = verb !== undefined ? ESCALATION_ACTION_ALIAS_SUBCOMMANDS[verb] : undefined;
|
|
2959
3035
|
const planSequenceSubcommand = verb !== undefined ? PLAN_SEQUENCE_ALIAS_SUBCOMMANDS[verb] : undefined;
|
|
3036
|
+
const tutorialSubcommand = verb !== undefined ? TUTORIAL_ALIAS_SUBCOMMANDS[verb] : undefined;
|
|
2960
3037
|
const productSignalSubcommand = verb !== undefined ? PRODUCT_SIGNAL_ALIAS_SUBCOMMANDS[verb] : undefined;
|
|
2961
3038
|
const freshnessSubcommand = verb !== undefined ? FRESHNESS_ALIAS_SUBCOMMANDS[verb] : undefined;
|
|
2962
3039
|
const vbriefValidateSubcommand = verb === "verify:vbrief-conformance" && canonical === "vbrief-validate"
|
|
@@ -2974,13 +3051,15 @@ export async function dispatch(argv, io = defaultIo()) {
|
|
|
2974
3051
|
? [escalationSubcommand, ...rest]
|
|
2975
3052
|
: planSequenceSubcommand !== undefined && canonical === "plan-sequence"
|
|
2976
3053
|
? [planSequenceSubcommand, ...rest]
|
|
2977
|
-
:
|
|
2978
|
-
? [
|
|
2979
|
-
:
|
|
2980
|
-
? [
|
|
2981
|
-
:
|
|
2982
|
-
? [
|
|
2983
|
-
:
|
|
3054
|
+
: tutorialSubcommand !== undefined && canonical === "tutorial"
|
|
3055
|
+
? [tutorialSubcommand, ...rest]
|
|
3056
|
+
: productSignalSubcommand !== undefined && canonical === "product-signal"
|
|
3057
|
+
? [productSignalSubcommand, ...rest]
|
|
3058
|
+
: freshnessSubcommand !== undefined && canonical === "freshness-report"
|
|
3059
|
+
? [freshnessSubcommand, ...rest]
|
|
3060
|
+
: vbriefValidateSubcommand !== undefined
|
|
3061
|
+
? [vbriefValidateSubcommand, ...rest]
|
|
3062
|
+
: rest;
|
|
2984
3063
|
const helpRc = interceptHelp(canonical.replaceAll("-", "_"), handlerArgv, {
|
|
2985
3064
|
write: io.writeOut,
|
|
2986
3065
|
});
|
package/dist/preflight-gh.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ interface ParsedArgs {
|
|
|
7
7
|
quiet?: boolean;
|
|
8
8
|
error?: string;
|
|
9
9
|
}
|
|
10
|
+
/** Typed-only deliveryBranch union for CLI-seeded DEFAULT_BRANCHES (#5520). */
|
|
11
|
+
export declare function enrichBranchesWithTypedDelivery(projectRoot: string | undefined, branches: ReadonlySet<string>): Set<string>;
|
|
10
12
|
export declare function parseArgs(argv: string[]): ParsedArgs;
|
|
11
13
|
export declare function run(argv: string[]): number | Promise<number>;
|
|
12
14
|
export {};
|
package/dist/preflight-gh.js
CHANGED
|
@@ -13,7 +13,19 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { createInterface } from "node:readline";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
|
+
import { resolveDeliveryBranch } from "@deftai/directive-core/policy";
|
|
16
17
|
import { DEFAULT_BRANCHES, evaluateCommand, evaluatePrePush, parsePrePushStdin, runSelfTest, } from "@deftai/directive-core/preflight";
|
|
18
|
+
/** Typed-only deliveryBranch union for CLI-seeded DEFAULT_BRANCHES (#5520). */
|
|
19
|
+
export function enrichBranchesWithTypedDelivery(projectRoot, branches) {
|
|
20
|
+
const next = new Set(branches);
|
|
21
|
+
if (projectRoot === undefined || projectRoot.length === 0)
|
|
22
|
+
return next;
|
|
23
|
+
const delivery = resolveDeliveryBranch(projectRoot);
|
|
24
|
+
if (delivery.source === "typed" && delivery.error === null && delivery.branch.trim().length > 0) {
|
|
25
|
+
next.add(delivery.branch);
|
|
26
|
+
}
|
|
27
|
+
return next;
|
|
28
|
+
}
|
|
17
29
|
export function parseArgs(argv) {
|
|
18
30
|
const parsed = { defaultBranches: new Set(DEFAULT_BRANCHES) };
|
|
19
31
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -66,7 +78,8 @@ export function run(argv) {
|
|
|
66
78
|
return 2;
|
|
67
79
|
}
|
|
68
80
|
const quiet = args.quiet ?? false;
|
|
69
|
-
|
|
81
|
+
// CLI seeds DEFAULT_BRANCHES; union typed delivery when --project-root is set (#5520).
|
|
82
|
+
const branches = enrichBranchesWithTypedDelivery(args.projectRoot, args.defaultBranches ?? new Set(DEFAULT_BRANCHES));
|
|
70
83
|
if (args.mode === "self-test") {
|
|
71
84
|
const [code, msg] = runSelfTest();
|
|
72
85
|
if (code === 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deftai/directive",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.125.1",
|
|
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/",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"provenance": true
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@deftai/directive-core": "^0.
|
|
39
|
-
"@deftai/directive-content": "^0.
|
|
38
|
+
"@deftai/directive-core": "^0.125.1",
|
|
39
|
+
"@deftai/directive-content": "^0.125.1"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "tsc -b",
|