@deftai/directive-core 0.98.1 → 0.100.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.
Files changed (144) hide show
  1. package/dist/authz/actions.d.ts +6 -0
  2. package/dist/authz/actions.js +3 -0
  3. package/dist/authz/classify.js +401 -75
  4. package/dist/authz/decompose-apply.d.ts +67 -0
  5. package/dist/authz/decompose-apply.js +302 -0
  6. package/dist/authz/index.d.ts +3 -1
  7. package/dist/authz/index.js +3 -1
  8. package/dist/authz/store.d.ts +53 -0
  9. package/dist/authz/store.js +219 -1
  10. package/dist/authz/types.d.ts +19 -2
  11. package/dist/authz/types.js +5 -1
  12. package/dist/consumer-check-contract/evaluate.d.ts +40 -0
  13. package/dist/consumer-check-contract/evaluate.js +188 -3
  14. package/dist/consumer-check-contract/index.d.ts +1 -1
  15. package/dist/consumer-check-contract/index.js +1 -1
  16. package/dist/content-contracts/skills/greptile-detector.d.ts +42 -0
  17. package/dist/content-contracts/skills/greptile-detector.js +202 -4
  18. package/dist/decision/index.d.ts +17 -0
  19. package/dist/decision/index.js +35 -0
  20. package/dist/decision/list.d.ts +47 -0
  21. package/dist/decision/list.js +250 -0
  22. package/dist/decision/schema.d.ts +88 -0
  23. package/dist/decision/schema.js +293 -0
  24. package/dist/decision/write.d.ts +82 -0
  25. package/dist/decision/write.js +427 -0
  26. package/dist/doctor/checks.d.ts +44 -0
  27. package/dist/doctor/checks.js +428 -2
  28. package/dist/doctor/main.d.ts +6 -7
  29. package/dist/doctor/main.js +72 -79
  30. package/dist/doctor/which.d.ts +20 -1
  31. package/dist/doctor/which.js +67 -1
  32. package/dist/eval/report.d.ts +29 -0
  33. package/dist/eval/report.js +69 -0
  34. package/dist/eval/run.d.ts +9 -0
  35. package/dist/eval/run.js +40 -4
  36. package/dist/eval/version-pin.d.ts +99 -0
  37. package/dist/eval/version-pin.js +181 -0
  38. package/dist/finish-loop/pr-finish-loop.d.ts +13 -2
  39. package/dist/finish-loop/pr-finish-loop.js +116 -5
  40. package/dist/finish-loop/types.d.ts +1 -1
  41. package/dist/hooks/dispatcher.d.ts +9 -5
  42. package/dist/hooks/dispatcher.js +23 -15
  43. package/dist/hooks/readonly.d.ts +6 -3
  44. package/dist/hooks/readonly.js +44 -25
  45. package/dist/index.d.ts +2 -0
  46. package/dist/index.js +2 -0
  47. package/dist/init-deposit/agent-hooks.d.ts +20 -0
  48. package/dist/init-deposit/agent-hooks.js +51 -31
  49. package/dist/intake/issue-ingest.js +29 -0
  50. package/dist/lifecycle/completed-consistency.d.ts +60 -0
  51. package/dist/lifecycle/completed-consistency.js +443 -0
  52. package/dist/lifecycle/completed-tracked-on-delivery.d.ts +47 -0
  53. package/dist/lifecycle/completed-tracked-on-delivery.js +415 -0
  54. package/dist/lifecycle/index.d.ts +2 -0
  55. package/dist/lifecycle/index.js +2 -0
  56. package/dist/literal-acceptance/capture.d.ts +52 -0
  57. package/dist/literal-acceptance/capture.js +658 -0
  58. package/dist/literal-acceptance/evaluate.d.ts +47 -0
  59. package/dist/literal-acceptance/evaluate.js +193 -0
  60. package/dist/literal-acceptance/index.d.ts +12 -0
  61. package/dist/literal-acceptance/index.js +12 -0
  62. package/dist/literal-acceptance/run.d.ts +38 -0
  63. package/dist/literal-acceptance/run.js +216 -0
  64. package/dist/literal-acceptance/safety.d.ts +24 -0
  65. package/dist/literal-acceptance/safety.js +251 -0
  66. package/dist/literal-acceptance/types.d.ts +82 -0
  67. package/dist/literal-acceptance/types.js +26 -0
  68. package/dist/platform/host-content-surface.d.ts +74 -0
  69. package/dist/platform/host-content-surface.js +214 -0
  70. package/dist/platform/index.d.ts +1 -0
  71. package/dist/platform/index.js +1 -0
  72. package/dist/policy/ceremony-dial.d.ts +289 -0
  73. package/dist/policy/ceremony-dial.js +980 -0
  74. package/dist/policy/deft-directive-disable.js +12 -2
  75. package/dist/policy/index.d.ts +2 -0
  76. package/dist/policy/index.js +16 -1
  77. package/dist/policy/merge-approval-head.d.ts +129 -0
  78. package/dist/policy/merge-approval-head.js +461 -0
  79. package/dist/policy/require-human-merge.d.ts +5 -0
  80. package/dist/policy/require-human-merge.js +5 -0
  81. package/dist/pr-merge-readiness/ci-gate.d.ts +20 -3
  82. package/dist/pr-merge-readiness/ci-gate.js +65 -5
  83. package/dist/pr-merge-readiness/compute.d.ts +13 -0
  84. package/dist/pr-merge-readiness/compute.js +99 -14
  85. package/dist/pr-merge-readiness/evaluate.js +10 -0
  86. package/dist/pr-merge-readiness/gh.d.ts +49 -0
  87. package/dist/pr-merge-readiness/gh.js +268 -0
  88. package/dist/pr-merge-readiness/index.d.ts +2 -2
  89. package/dist/pr-merge-readiness/index.js +2 -2
  90. package/dist/pr-merge-readiness/mergeability.js +5 -0
  91. package/dist/pr-merge-readiness/output.js +2 -0
  92. package/dist/pr-merge-readiness/parse.js +4 -0
  93. package/dist/pr-merge-readiness/test-gh-fixtures.helpers.js +4 -0
  94. package/dist/pr-merge-readiness/types.d.ts +6 -0
  95. package/dist/pr-wait-mergeable/cascade.d.ts +11 -0
  96. package/dist/pr-wait-mergeable/cascade.js +115 -1
  97. package/dist/pr-wait-mergeable/main.d.ts +4 -0
  98. package/dist/pr-wait-mergeable/main.js +4 -0
  99. package/dist/pr-wait-mergeable/types.d.ts +3 -1
  100. package/dist/pr-wait-mergeable/wrappers.d.ts +6 -1
  101. package/dist/pr-wait-mergeable/wrappers.js +7 -1
  102. package/dist/preflight/evaluate.d.ts +15 -1
  103. package/dist/preflight/evaluate.js +33 -2
  104. package/dist/render/framework-commands.js +4 -0
  105. package/dist/scope/acceptance-evidence.d.ts +76 -0
  106. package/dist/scope/acceptance-evidence.js +348 -0
  107. package/dist/scope/coverage-map.d.ts +98 -0
  108. package/dist/scope/coverage-map.js +558 -0
  109. package/dist/scope/decompose.js +125 -11
  110. package/dist/scope/effort-activate-gate.d.ts +28 -0
  111. package/dist/scope/effort-activate-gate.js +64 -0
  112. package/dist/scope/index.d.ts +4 -0
  113. package/dist/scope/index.js +4 -0
  114. package/dist/scope/parent-lineage.d.ts +125 -0
  115. package/dist/scope/parent-lineage.js +626 -0
  116. package/dist/scope/transition.d.ts +8 -0
  117. package/dist/scope/transition.js +69 -2
  118. package/dist/session/active-cli.d.ts +79 -0
  119. package/dist/session/active-cli.js +382 -0
  120. package/dist/session/effort-budget.d.ts +130 -0
  121. package/dist/session/effort-budget.js +334 -0
  122. package/dist/session/index.d.ts +2 -0
  123. package/dist/session/index.js +2 -0
  124. package/dist/session/session-start.d.ts +30 -1
  125. package/dist/session/session-start.js +234 -26
  126. package/dist/session/verify-session-ritual.d.ts +14 -0
  127. package/dist/session/verify-session-ritual.js +33 -0
  128. package/dist/story-ready/evaluate.d.ts +11 -0
  129. package/dist/story-ready/evaluate.js +41 -3
  130. package/dist/swarm/index.d.ts +2 -0
  131. package/dist/swarm/index.js +2 -0
  132. package/dist/swarm/pre-dispatch-cli.d.ts +19 -0
  133. package/dist/swarm/pre-dispatch-cli.js +143 -0
  134. package/dist/swarm/pre-dispatch.d.ts +87 -0
  135. package/dist/swarm/pre-dispatch.js +373 -0
  136. package/dist/triage/actions/candidates-log.d.ts +1 -2
  137. package/dist/triage/actions/candidates-log.js +37 -6
  138. package/dist/vbrief-activate/activate.js +6 -0
  139. package/dist/vbrief-validate/constants.d.ts +2 -0
  140. package/dist/vbrief-validate/constants.js +2 -0
  141. package/dist/vbrief-validate/schema.js +4 -1
  142. package/dist/xbrief-migrate/migrate-project.d.ts +4 -0
  143. package/dist/xbrief-migrate/migrate-project.js +92 -3
  144. package/package.json +19 -3
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Lightweight structured agent decision log schema (#1396).
3
+ *
4
+ * Intent-debt records for significant choices only. Not a full lifecycle xBRIEF
5
+ * and not a replacement for docs/decisions/ADR-*.md.
6
+ */
7
+ export const DECISION_SCHEMA_VERSION = "deft.decision.v1";
8
+ /** Directory under project root for standalone (cross-cutting) decision files. */
9
+ export const DECISIONS_DIR_REL = "xbrief/decisions";
10
+ /** Filename suffix for decision records. */
11
+ export const DECISION_FILE_SUFFIX = ".decision.json";
12
+ const CONFIDENCE_VALUES = new Set(["low", "medium", "high"]);
13
+ const RFC_VALUES = new Set([
14
+ "MUST",
15
+ "SHOULD",
16
+ "MAY",
17
+ "MUST NOT",
18
+ "SHOULD NOT",
19
+ ]);
20
+ function isPlainObject(value) {
21
+ return value !== null && typeof value === "object" && !Array.isArray(value);
22
+ }
23
+ function nonEmptyString(value) {
24
+ return typeof value === "string" && value.trim().length > 0;
25
+ }
26
+ /** Normalize timestamps to second-precision UTC with trailing Z. */
27
+ export function normalizeTimestamp(raw) {
28
+ if (raw !== undefined && raw !== null && raw.trim().length > 0) {
29
+ const parsed = new Date(raw.trim());
30
+ if (!Number.isNaN(parsed.getTime())) {
31
+ return parsed.toISOString().replace(/\.\d{3}Z$/, "Z");
32
+ }
33
+ }
34
+ return new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
35
+ }
36
+ /**
37
+ * Derive a kebab-case slug from free text (max 64 chars).
38
+ * Linear-time (no polynomial regex) for CodeQL safety on library input.
39
+ */
40
+ export function slugifyDecision(text) {
41
+ const lower = text.trim().toLowerCase();
42
+ let out = "";
43
+ let pendingHyphen = false;
44
+ for (let i = 0; i < lower.length && out.length < 64; i += 1) {
45
+ const ch = lower[i];
46
+ const code = ch.charCodeAt(0);
47
+ const isAlnum = (code >= 48 && code <= 57) || // 0-9
48
+ (code >= 97 && code <= 122); // a-z
49
+ if (isAlnum) {
50
+ if (pendingHyphen && out.length > 0) {
51
+ out += "-";
52
+ if (out.length >= 64)
53
+ break;
54
+ }
55
+ out += ch;
56
+ pendingHyphen = false;
57
+ }
58
+ else {
59
+ pendingHyphen = true;
60
+ }
61
+ }
62
+ return out.length > 0 ? out : "decision";
63
+ }
64
+ /**
65
+ * Strip terminal / bidi control chars for safe plaintext list rendering.
66
+ * Drops C0 (except tab/LF/CR → space), DEL, C1 (U+0080–U+009F), and
67
+ * Unicode bidi overrides / isolates / embeddings used for deceptive reordering.
68
+ */
69
+ export function sanitizeForTerminal(text) {
70
+ let out = "";
71
+ for (let i = 0; i < text.length; i += 1) {
72
+ const code = text.charCodeAt(i);
73
+ // Tab / LF / CR → space (never pass raw control layout to the terminal).
74
+ if (code === 9 || code === 10 || code === 13) {
75
+ out += " ";
76
+ continue;
77
+ }
78
+ // C0 + DEL
79
+ if (code < 32 || code === 127) {
80
+ continue;
81
+ }
82
+ // C1 controls (including when encoded as U+0080–U+009F)
83
+ if (code >= 0x80 && code <= 0x9f) {
84
+ continue;
85
+ }
86
+ // Bidi control characters (deceptive reordering)
87
+ // LRE/RLE/PDF/LRO/RLO, LRI/RLI/FSI/PDI, and related marks.
88
+ if (code === 0x061c || // ALM
89
+ code === 0x200e || // LRM
90
+ code === 0x200f || // RLM
91
+ (code >= 0x202a && code <= 0x202e) || // LRE..RLO
92
+ (code >= 0x2066 && code <= 0x2069) // LRI..PDI
93
+ ) {
94
+ continue;
95
+ }
96
+ out += text[i];
97
+ }
98
+ return out;
99
+ }
100
+ /** Date prefix YYYY-MM-DD from an ISO timestamp. */
101
+ export function datePrefixFromTimestamp(timestamp) {
102
+ const m = timestamp.match(/^(\d{4}-\d{2}-\d{2})/);
103
+ return m?.[1] ?? new Date().toISOString().slice(0, 10);
104
+ }
105
+ /** Build standalone filename: YYYY-MM-DD-<slug>.decision.json */
106
+ export function decisionFilename(id, timestamp) {
107
+ const date = datePrefixFromTimestamp(timestamp);
108
+ const slug = slugifyDecision(id);
109
+ return `${date}-${slug}${DECISION_FILE_SUFFIX}`;
110
+ }
111
+ /** Validate and normalize an unknown JSON value into a DecisionRecord. */
112
+ export function validateDecisionRecord(input) {
113
+ const errors = [];
114
+ if (!isPlainObject(input)) {
115
+ return { ok: false, errors: [{ field: "", message: "decision record must be a JSON object" }] };
116
+ }
117
+ const schemaVersion = input.schemaVersion;
118
+ if (schemaVersion !== undefined && schemaVersion !== DECISION_SCHEMA_VERSION) {
119
+ errors.push({
120
+ field: "schemaVersion",
121
+ message: `expected ${DECISION_SCHEMA_VERSION}, got ${String(schemaVersion)}`,
122
+ });
123
+ }
124
+ const decision = input.decision;
125
+ if (!nonEmptyString(decision)) {
126
+ errors.push({ field: "decision", message: "required non-empty string" });
127
+ }
128
+ let governingRule = null;
129
+ if (!isPlainObject(input.governingRule) && !nonEmptyString(input.governingRule)) {
130
+ errors.push({
131
+ field: "governingRule",
132
+ message: "required object { description, path?, rfc2119? } or non-empty string",
133
+ });
134
+ }
135
+ else if (nonEmptyString(input.governingRule)) {
136
+ governingRule = { description: input.governingRule.trim() };
137
+ }
138
+ else if (isPlainObject(input.governingRule)) {
139
+ const gr = input.governingRule;
140
+ if (!nonEmptyString(gr.description)) {
141
+ errors.push({ field: "governingRule.description", message: "required non-empty string" });
142
+ }
143
+ else {
144
+ let rfc2119 = null;
145
+ if (gr.rfc2119 !== undefined && gr.rfc2119 !== null) {
146
+ if (typeof gr.rfc2119 === "string" && RFC_VALUES.has(gr.rfc2119)) {
147
+ rfc2119 = gr.rfc2119;
148
+ }
149
+ else {
150
+ errors.push({
151
+ field: "governingRule.rfc2119",
152
+ message: `must be one of ${[...RFC_VALUES].join(", ")}`,
153
+ });
154
+ }
155
+ }
156
+ governingRule = {
157
+ description: gr.description.trim(),
158
+ path: typeof gr.path === "string" && gr.path.trim().length > 0 ? gr.path.trim() : null,
159
+ rfc2119,
160
+ };
161
+ }
162
+ }
163
+ const alternativesRaw = input.alternativesConsidered ?? input.alternatives;
164
+ const alternatives = [];
165
+ if (!Array.isArray(alternativesRaw)) {
166
+ errors.push({
167
+ field: "alternativesConsidered",
168
+ message: "required array of { option, whyNot? } or strings",
169
+ });
170
+ }
171
+ else if (alternativesRaw.length === 0) {
172
+ errors.push({
173
+ field: "alternativesConsidered",
174
+ message: 'must include at least one alternative (use [{option:"none"}] if truly sole path)',
175
+ });
176
+ }
177
+ else {
178
+ for (let i = 0; i < alternativesRaw.length; i += 1) {
179
+ const alt = alternativesRaw[i];
180
+ if (nonEmptyString(alt)) {
181
+ alternatives.push({ option: alt.trim() });
182
+ }
183
+ else if (isPlainObject(alt) && nonEmptyString(alt.option)) {
184
+ alternatives.push({
185
+ option: alt.option.trim(),
186
+ whyNot: typeof alt.whyNot === "string" && alt.whyNot.trim().length > 0
187
+ ? alt.whyNot.trim()
188
+ : null,
189
+ });
190
+ }
191
+ else {
192
+ errors.push({
193
+ field: `alternativesConsidered[${i}]`,
194
+ message: "must be a non-empty string or { option, whyNot? }",
195
+ });
196
+ }
197
+ }
198
+ }
199
+ const whyWinner = input.whyWinner ?? input.why_winner;
200
+ if (!nonEmptyString(whyWinner)) {
201
+ errors.push({ field: "whyWinner", message: "required non-empty string" });
202
+ }
203
+ const confidenceRaw = input.confidence;
204
+ let confidence = null;
205
+ if (!nonEmptyString(confidenceRaw) ||
206
+ !CONFIDENCE_VALUES.has(confidenceRaw.trim().toLowerCase())) {
207
+ errors.push({ field: "confidence", message: "required: low | medium | high" });
208
+ }
209
+ else {
210
+ confidence = confidenceRaw.trim().toLowerCase();
211
+ }
212
+ const scopeRaw = input.activeScopeRefs ?? input.active_scope_refs ?? input.scopeRefs;
213
+ const activeScopeRefs = [];
214
+ if (scopeRaw === undefined || scopeRaw === null) {
215
+ // optional
216
+ }
217
+ else if (Array.isArray(scopeRaw)) {
218
+ for (let i = 0; i < scopeRaw.length; i += 1) {
219
+ const s = scopeRaw[i];
220
+ if (nonEmptyString(s)) {
221
+ activeScopeRefs.push(s.trim().replace(/\\/g, "/"));
222
+ }
223
+ else {
224
+ errors.push({ field: `activeScopeRefs[${i}]`, message: "must be a non-empty path string" });
225
+ }
226
+ }
227
+ }
228
+ else if (nonEmptyString(scopeRaw)) {
229
+ activeScopeRefs.push(scopeRaw.trim().replace(/\\/g, "/"));
230
+ }
231
+ else {
232
+ errors.push({
233
+ field: "activeScopeRefs",
234
+ message: "must be a string path, array of paths, or omitted",
235
+ });
236
+ }
237
+ const revisitTrigger = input.revisitTrigger ?? input.revisit_trigger;
238
+ if (!nonEmptyString(revisitTrigger)) {
239
+ errors.push({ field: "revisitTrigger", message: "required non-empty string" });
240
+ }
241
+ let timestamp = normalizeTimestamp(typeof input.timestamp === "string" ? input.timestamp : null);
242
+ if (typeof input.timestamp === "string" && input.timestamp.trim().length > 0) {
243
+ const parsed = new Date(input.timestamp.trim());
244
+ if (Number.isNaN(parsed.getTime())) {
245
+ errors.push({ field: "timestamp", message: "invalid ISO-8601 timestamp" });
246
+ }
247
+ else {
248
+ timestamp = normalizeTimestamp(input.timestamp);
249
+ }
250
+ }
251
+ const id = typeof input.id === "string" && input.id.trim().length > 0
252
+ ? slugifyDecision(input.id)
253
+ : slugifyDecision(typeof decision === "string" ? decision : "decision");
254
+ const tags = [];
255
+ if (Array.isArray(input.tags)) {
256
+ for (const t of input.tags) {
257
+ if (nonEmptyString(t))
258
+ tags.push(t.trim());
259
+ }
260
+ }
261
+ const relatedIssues = [];
262
+ if (Array.isArray(input.relatedIssues)) {
263
+ for (const n of input.relatedIssues) {
264
+ if (typeof n === "number" && Number.isInteger(n) && n > 0)
265
+ relatedIssues.push(n);
266
+ else if (typeof n === "string" && /^\d+$/.test(n.trim()))
267
+ relatedIssues.push(Number(n.trim()));
268
+ }
269
+ }
270
+ if (errors.length > 0) {
271
+ return { ok: false, errors };
272
+ }
273
+ const record = {
274
+ schemaVersion: DECISION_SCHEMA_VERSION,
275
+ id,
276
+ decision: decision.trim(),
277
+ governingRule: governingRule,
278
+ alternativesConsidered: alternatives,
279
+ whyWinner: whyWinner.trim(),
280
+ confidence: confidence,
281
+ activeScopeRefs,
282
+ timestamp,
283
+ revisitTrigger: revisitTrigger.trim(),
284
+ ...(tags.length > 0 ? { tags } : {}),
285
+ ...(relatedIssues.length > 0 ? { relatedIssues } : {}),
286
+ };
287
+ return { ok: true, errors: [], record };
288
+ }
289
+ /** Format validation errors for CLI stderr. */
290
+ export function formatDecisionValidationErrors(errors) {
291
+ return errors.map((e) => (e.field ? `${e.field}: ${e.message}` : e.message)).join("\n");
292
+ }
293
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1,82 @@
1
+ /**
2
+ * decision:write — create a lightweight structured decision record (#1396).
3
+ */
4
+ import { type DecisionRecord, slugifyDecision } from "./schema.js";
5
+ export type DecisionWriteOutcome = "written" | "error-bad-args" | "error-config" | "error-io";
6
+ export interface DecisionWriteInput {
7
+ readonly decision?: string;
8
+ readonly governingRule?: string | {
9
+ description: string;
10
+ path?: string;
11
+ rfc2119?: string;
12
+ };
13
+ readonly alternatives?: readonly (string | {
14
+ option: string;
15
+ whyNot?: string;
16
+ })[];
17
+ readonly whyWinner?: string;
18
+ readonly confidence?: string;
19
+ readonly scope?: string | readonly string[];
20
+ readonly revisitTrigger?: string;
21
+ readonly id?: string;
22
+ readonly timestamp?: string;
23
+ readonly tags?: readonly string[];
24
+ readonly relatedIssues?: readonly number[];
25
+ /** Absolute or project-relative path to a JSON body file (full or partial record). */
26
+ readonly bodyFile?: string;
27
+ /** Force standalone under xbrief/decisions/ even when --scope is set (still links). */
28
+ readonly standalone?: boolean;
29
+ /** When true, replace an existing decision file at the same path. Default: fail if exists. */
30
+ readonly force?: boolean;
31
+ readonly projectRoot?: string | null;
32
+ readonly dryRun?: boolean;
33
+ readonly json?: boolean;
34
+ }
35
+ export interface DecisionWriteResult {
36
+ readonly outcome: DecisionWriteOutcome;
37
+ readonly exitCode: 0 | 1 | 2;
38
+ readonly path: string | null;
39
+ readonly scopePath: string | null;
40
+ readonly record: DecisionRecord | null;
41
+ readonly message: string;
42
+ }
43
+ /**
44
+ * Append a pointer line to plan.narratives.Decisions on a scope xBRIEF without
45
+ * removing existing narratives (validators accept unknown narrative keys as strings).
46
+ *
47
+ * Concurrent writers: read-modify-replace with post-write verify + retry so a
48
+ * later attach does not silently drop an earlier decision pointer.
49
+ */
50
+ export declare function appendScopeDecisionPointer(projectRoot: string, scopeRelPath: string, decisionRelPath: string, decisionSummary: string): void;
51
+ /** Write a validated decision record to disk (standalone + optional scope pointer). */
52
+ export declare function runDecisionWrite(options: DecisionWriteInput): DecisionWriteResult;
53
+ export interface DecisionWriteCliArgs {
54
+ decision?: string;
55
+ governingRule?: string;
56
+ governingPath?: string;
57
+ governingRfc?: string;
58
+ alternatives?: string[];
59
+ whyWinner?: string;
60
+ confidence?: string;
61
+ scope?: string[];
62
+ revisitTrigger?: string;
63
+ id?: string;
64
+ timestamp?: string;
65
+ tags?: string[];
66
+ relatedIssues?: number[];
67
+ bodyFile?: string;
68
+ standalone?: boolean;
69
+ force?: boolean;
70
+ dryRun?: boolean;
71
+ json?: boolean;
72
+ projectRoot?: string;
73
+ error?: string;
74
+ }
75
+ /** Parse argv for decision:write. */
76
+ export declare function parseDecisionWriteArgs(argv: readonly string[]): DecisionWriteCliArgs;
77
+ /** CLI entry for decision:write. */
78
+ export declare function decisionWriteMain(argv: readonly string[]): number;
79
+ /** Relative path helper for tests. */
80
+ export declare function relativeToProject(projectRoot: string, absPath: string): string;
81
+ export { slugifyDecision };
82
+ //# sourceMappingURL=write.d.ts.map