@deftai/directive-core 0.64.0 → 0.66.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/architecture/sor-preflight.js +6 -4
- package/dist/capacity/backfill.js +5 -3
- package/dist/capacity/show.js +5 -3
- package/dist/category-b-namespace/index.d.ts +39 -0
- package/dist/category-b-namespace/index.js +120 -0
- package/dist/codebase/default-extractor.js +2 -1
- package/dist/codebase/map.js +2 -1
- package/dist/codebase/provider.js +4 -2
- package/dist/content-contracts/standards/_helpers.js +3 -1
- package/dist/doctor/checks.js +2 -1
- package/dist/doctor/doctor-state.js +2 -2
- package/dist/encoding/patterns.js +19 -0
- package/dist/encoding/scan.js +3 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/init-deposit/refresh.js +2 -1
- package/dist/init-deposit/scaffold.js +2 -1
- package/dist/install-upgrade/index.d.ts +2 -0
- package/dist/install-upgrade/index.js +31 -2
- package/dist/intake/issue-emit.d.ts +1 -1
- package/dist/intake/issue-emit.js +3 -2
- package/dist/intake/issue-ingest.js +17 -14
- package/dist/intake/markdown-scanners.d.ts +3 -1
- package/dist/intake/markdown-scanners.js +10 -3
- package/dist/intake/reconcile-issues.js +13 -4
- package/dist/layout/index.d.ts +2 -0
- package/dist/layout/index.js +2 -0
- package/dist/layout/resolve.d.ts +87 -0
- package/dist/layout/resolve.js +159 -0
- package/dist/lifecycle/lifecycle-hygiene.d.ts +1 -1
- package/dist/lifecycle/lifecycle-hygiene.js +8 -5
- package/dist/orchestration/judgment-policy.js +4 -6
- package/dist/orchestration/verify-judgment-gates.d.ts +1 -0
- package/dist/orchestration/verify-judgment-gates.js +4 -2
- package/dist/policy/autonomy.js +4 -6
- package/dist/policy/capacity.js +4 -6
- package/dist/policy/decisions.d.ts +1 -0
- package/dist/policy/decisions.js +4 -2
- package/dist/policy/index.d.ts +1 -0
- package/dist/policy/index.js +3 -1
- package/dist/policy/plan-extensions.d.ts +35 -0
- package/dist/policy/plan-extensions.js +57 -0
- package/dist/policy/resolve.d.ts +6 -2
- package/dist/policy/resolve.js +18 -8
- package/dist/policy/wip.js +6 -4
- package/dist/preflight-cache/evaluate.js +11 -45
- package/dist/release/native-steps.js +4 -3
- package/dist/render/framework-commands.js +2 -1
- package/dist/render/prd-render.js +2 -2
- package/dist/render/project-render.js +23 -5
- package/dist/render/roadmap-render.js +36 -8
- package/dist/render/scope-outlook.js +3 -2
- package/dist/scope/audit-log.js +3 -2
- package/dist/scope/capacity-stamp.js +2 -1
- package/dist/scope/decompose.js +6 -4
- package/dist/scope/decomposed-refs.js +2 -1
- package/dist/scope/demote.js +5 -4
- package/dist/scope/project-context.js +2 -1
- package/dist/scope/project-definition-sync.js +4 -3
- package/dist/scope/transition.js +6 -2
- package/dist/scope/undo.js +2 -1
- package/dist/scope/vbrief-ref.js +5 -3
- package/dist/session/resume-conditions.js +2 -1
- package/dist/session/ritual-sentinel.js +2 -1
- package/dist/session/staleness.js +2 -1
- package/dist/slice/record.js +4 -4
- package/dist/spec-authority/resolver.js +5 -5
- package/dist/swarm/complete-cohort.js +5 -4
- package/dist/swarm/launch.js +6 -7
- package/dist/swarm/readiness.js +22 -20
- package/dist/swarm/subagent-backend.js +2 -5
- package/dist/swarm/verify-review-clean.js +2 -1
- package/dist/triage/actions/candidates-log.d.ts +3 -0
- package/dist/triage/actions/candidates-log.js +8 -2
- package/dist/triage/bootstrap/gitignore.js +22 -13
- package/dist/triage/bootstrap/index.js +7 -4
- package/dist/triage/bulk/index.js +2 -1
- package/dist/triage/classify/index.js +13 -11
- package/dist/triage/queue/audit.js +3 -3
- package/dist/triage/queue/build-queue.js +6 -0
- package/dist/triage/queue/cache.js +12 -2
- package/dist/triage/queue/index.d.ts +1 -0
- package/dist/triage/queue/index.js +1 -0
- package/dist/triage/queue/ranking-labels.js +2 -1
- package/dist/triage/queue/scope-ignores-filter.d.ts +12 -0
- package/dist/triage/queue/scope-ignores-filter.js +50 -0
- package/dist/triage/queue/scope-walk.js +8 -6
- package/dist/triage/queue/types.d.ts +4 -0
- package/dist/triage/reconcile/audit.js +2 -1
- package/dist/triage/reconcile/parse-uri.js +2 -1
- package/dist/triage/reconcile/reconcile.js +8 -7
- package/dist/triage/refresh/extract.js +4 -2
- package/dist/triage/refresh/refresh.js +3 -2
- package/dist/triage/scope/mutations-core.js +13 -9
- package/dist/triage/scope/renderers.js +5 -3
- package/dist/triage/scope/resolve.js +6 -5
- package/dist/triage/scope/validate.js +3 -6
- package/dist/triage/scope-drift/add-ignore.js +4 -2
- package/dist/triage/scope-drift/scope-rules.js +3 -2
- package/dist/triage/subscribe/index.js +14 -8
- package/dist/triage/summary/index.d.ts +33 -0
- package/dist/triage/summary/index.js +180 -6
- package/dist/triage/summary/reconcilable.js +6 -4
- package/dist/triage/summary/scope-drift.js +2 -1
- package/dist/triage/welcome/default-mode.d.ts +1 -0
- package/dist/triage/welcome/default-mode.js +1 -0
- package/dist/triage/welcome/prior-state.js +9 -9
- package/dist/triage/welcome/summary.d.ts +2 -0
- package/dist/triage/welcome/summary.js +15 -8
- package/dist/triage/welcome/writers.js +12 -10
- package/dist/validate-content/capacity-policy.js +5 -4
- package/dist/validate-content/capacity-show.js +5 -3
- package/dist/validate-content/filename.d.ts +1 -1
- package/dist/validate-content/filename.js +5 -4
- package/dist/validate-content/validate-strategy-output.js +14 -5
- package/dist/vbrief-build/build.js +1 -1
- package/dist/vbrief-build/constants.js +7 -0
- package/dist/vbrief-build/speckit.js +3 -2
- package/dist/vbrief-reconcile/graph.js +3 -2
- package/dist/vbrief-reconcile/labels.js +4 -3
- package/dist/vbrief-reconcile/reconciliation.js +5 -1
- package/dist/vbrief-reconcile/swarm-deps.js +6 -5
- package/dist/vbrief-reconcile/umbrellas.d.ts +1 -1
- package/dist/vbrief-reconcile/umbrellas.js +9 -7
- package/dist/vbrief-validate/conformance.d.ts +1 -2
- package/dist/vbrief-validate/conformance.js +29 -14
- package/dist/vbrief-validate/constants.d.ts +18 -1
- package/dist/vbrief-validate/constants.js +32 -3
- package/dist/vbrief-validate/epic-links.js +3 -2
- package/dist/vbrief-validate/filename.js +5 -3
- package/dist/vbrief-validate/index.d.ts +3 -1
- package/dist/vbrief-validate/index.js +2 -1
- package/dist/vbrief-validate/main.js +17 -6
- package/dist/vbrief-validate/origin.js +1 -1
- package/dist/vbrief-validate/paths.js +2 -1
- package/dist/vbrief-validate/plan-hooks.js +4 -3
- package/dist/vbrief-validate/registry-status.d.ts +1 -0
- package/dist/vbrief-validate/registry-status.js +3 -1
- package/dist/vbrief-validate/roundtrip.d.ts +36 -0
- package/dist/vbrief-validate/roundtrip.js +168 -0
- package/dist/vbrief-validate/schema.d.ts +1 -1
- package/dist/vbrief-validate/schema.js +62 -19
- package/dist/vbrief-validate/validate-all.js +12 -4
- package/dist/verify-source/code-structure-validate.js +8 -4
- package/dist/verify-source/contract-drift.d.ts +33 -0
- package/dist/verify-source/contract-drift.js +170 -0
- package/dist/verify-source/index.d.ts +1 -0
- package/dist/verify-source/index.js +1 -0
- package/dist/xbrief-migrate/constants.d.ts +13 -0
- package/dist/xbrief-migrate/constants.js +14 -0
- package/dist/xbrief-migrate/detect.d.ts +11 -0
- package/dist/xbrief-migrate/detect.js +81 -0
- package/dist/xbrief-migrate/drift-gate.d.ts +56 -0
- package/dist/xbrief-migrate/drift-gate.js +205 -0
- package/dist/xbrief-migrate/index.d.ts +7 -0
- package/dist/xbrief-migrate/index.js +7 -0
- package/dist/xbrief-migrate/migrate-project.d.ts +33 -0
- package/dist/xbrief-migrate/migrate-project.js +189 -0
- package/dist/xbrief-migrate/signpost.d.ts +5 -0
- package/dist/xbrief-migrate/signpost.js +19 -0
- package/dist/xbrief-migrate/transforms.d.ts +46 -0
- package/dist/xbrief-migrate/transforms.js +182 -0
- package/dist/xbrief-migrate/version.d.ts +8 -0
- package/dist/xbrief-migrate/version.js +25 -0
- package/package.json +11 -3
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
3
|
import { cacheGet } from "../cache/operations.js";
|
|
4
|
+
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
4
5
|
import { call } from "../scm/call.js";
|
|
5
6
|
import { resolveProjectRoot } from "../scope/project-context.js";
|
|
6
7
|
import { resolveProjectRepo } from "../slice/project-context.js";
|
|
7
8
|
import { slugify, TODAY } from "../vbrief-build/build.js";
|
|
8
9
|
import { EMITTED_VBRIEF_VERSION } from "../vbrief-build/constants.js";
|
|
9
|
-
import { findAcHeading, parseCheckboxItems, parseListItems, sliceAcSection, stripCodeBlocks, } from "./markdown-scanners.js";
|
|
10
|
+
import { findAcHeading, parseCheckboxItems, parseListItems, sliceAcSection, stripCodeBlocks, stripFencedCodeBlocks, } from "./markdown-scanners.js";
|
|
10
11
|
import { detectRepo, extractReferencesFromVbrief, fetchOpenIssues, GITHUB_ISSUE_REF_TYPES, LIFECYCLE_FOLDERS, parseIssueNumber, } from "./reconcile-issues.js";
|
|
11
12
|
export const INGEST_STATUSES = ["proposed", "pending", "active"];
|
|
12
13
|
const STATUS_MAP = {
|
|
@@ -23,9 +24,9 @@ const CONTROL_CHAR_LABELS = {
|
|
|
23
24
|
const ORIGIN_URL_PATTERN = /https?:\/\/github\.com\/[^/\s]+\/[^/\s]+\/issues\/(\d+)/;
|
|
24
25
|
const ORIGIN_BARE_PATTERN = /issue\s*#(\d+)/i;
|
|
25
26
|
const CROSS_REF_PATTERNS = [
|
|
26
|
-
["x-
|
|
27
|
-
["x-
|
|
28
|
-
["x-
|
|
27
|
+
["x-xbrief/closes", /\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)\b/i],
|
|
28
|
+
["x-xbrief/blocks", /\bblocked[\s-]+by\s+#(\d+)\b/i],
|
|
29
|
+
["x-xbrief/refs", /\b(?:refs?|references?|see\s+also|related(?:\s+to)?)\s+#(\d+)\b/i],
|
|
29
30
|
];
|
|
30
31
|
function hasNonIndentationPrefix(text, index) {
|
|
31
32
|
const lineStart = text.lastIndexOf("\n", index) + 1;
|
|
@@ -70,7 +71,7 @@ export function extractPlanItems(body) {
|
|
|
70
71
|
if (body.length === 0) {
|
|
71
72
|
return [];
|
|
72
73
|
}
|
|
73
|
-
const text =
|
|
74
|
+
const text = stripFencedCodeBlocks(body);
|
|
74
75
|
const checkboxItems = parseCheckboxItems(text);
|
|
75
76
|
if (checkboxItems.length > 0) {
|
|
76
77
|
return checkboxItems.map((item) => ({ title: item.title, status: item.status }));
|
|
@@ -148,7 +149,7 @@ export function scanProvenanceRefs(vbriefDir) {
|
|
|
148
149
|
continue;
|
|
149
150
|
}
|
|
150
151
|
const files = readdirSync(folderPath)
|
|
151
|
-
.filter((f) => f
|
|
152
|
+
.filter((f) => hasArtifactSuffix(f))
|
|
152
153
|
.sort();
|
|
153
154
|
for (const filename of files) {
|
|
154
155
|
let data;
|
|
@@ -241,7 +242,7 @@ export function buildIssueVbrief(issue, status, repoUrl) {
|
|
|
241
242
|
const references = [
|
|
242
243
|
{
|
|
243
244
|
uri: url,
|
|
244
|
-
type: "x-
|
|
245
|
+
type: "x-xbrief/github-issue",
|
|
245
246
|
title: `Issue #${number}: ${title}`,
|
|
246
247
|
},
|
|
247
248
|
];
|
|
@@ -313,11 +314,11 @@ export function fetchSingleIssue(repo, number, options = {}) {
|
|
|
313
314
|
}
|
|
314
315
|
}
|
|
315
316
|
export function fetchIssue(repo, number, options = {}) {
|
|
316
|
-
const
|
|
317
|
-
if (
|
|
318
|
-
return
|
|
317
|
+
const live = fetchSingleIssue(repo, number, options);
|
|
318
|
+
if (live !== null) {
|
|
319
|
+
return live;
|
|
319
320
|
}
|
|
320
|
-
return
|
|
321
|
+
return fetchFromCache(repo, number, options);
|
|
321
322
|
}
|
|
322
323
|
export function ingestOne(issue, options) {
|
|
323
324
|
const number = Number(issue.number);
|
|
@@ -402,9 +403,11 @@ export function issueIngestMain(args) {
|
|
|
402
403
|
process.stderr.write("Error: Use either a single issue number OR --all, not both\n");
|
|
403
404
|
return 2;
|
|
404
405
|
}
|
|
405
|
-
const vbriefDir = resolve(args.vbriefDir ?? "./vbrief");
|
|
406
|
-
mkdirSync(vbriefDir, { recursive: true });
|
|
407
406
|
const projectRoot = resolveProjectRoot(args.projectRoot ?? undefined);
|
|
407
|
+
const vbriefDir = args.vbriefDir
|
|
408
|
+
? resolve(args.vbriefDir)
|
|
409
|
+
: resolveLifecycleRoot(args.projectRoot ? resolve(args.projectRoot) : resolve("."));
|
|
410
|
+
mkdirSync(vbriefDir, { recursive: true });
|
|
408
411
|
let repo = resolveProjectRepo(args.repo ?? undefined, projectRoot);
|
|
409
412
|
if (repo === null) {
|
|
410
413
|
repo = detectRepo();
|
|
@@ -457,7 +460,7 @@ export function issueIngestMain(args) {
|
|
|
457
460
|
}
|
|
458
461
|
export function ingestSingleForAccept(n, repo, options = {}) {
|
|
459
462
|
const root = resolve(options.projectRoot ?? process.cwd());
|
|
460
|
-
const vbriefDir =
|
|
463
|
+
const vbriefDir = resolveLifecycleRoot(root);
|
|
461
464
|
mkdirSync(vbriefDir, { recursive: true });
|
|
462
465
|
const repoUrl = resolveRepoUrl(repo);
|
|
463
466
|
const issue = fetchIssue(repo, n, {
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* Linear-time markdown scanners for issue body parsing (#1784 / #1248).
|
|
3
3
|
* Avoids nested/polynomial regex on issue bodies (ReDoS-safe).
|
|
4
4
|
*/
|
|
5
|
-
/** Strip fenced
|
|
5
|
+
/** Strip fenced code blocks only (preserves inline backtick spans). */
|
|
6
|
+
export declare function stripFencedCodeBlocks(body: string): string;
|
|
7
|
+
/** Strip fenced and inline code spans before cross-ref extraction. */
|
|
6
8
|
export declare function stripCodeBlocks(body: string): string;
|
|
7
9
|
export interface CheckboxItem {
|
|
8
10
|
readonly title: string;
|
|
@@ -2,16 +2,23 @@
|
|
|
2
2
|
* Linear-time markdown scanners for issue body parsing (#1784 / #1248).
|
|
3
3
|
* Avoids nested/polynomial regex on issue bodies (ReDoS-safe).
|
|
4
4
|
*/
|
|
5
|
-
/** Strip fenced
|
|
5
|
+
/** Strip fenced code blocks only (preserves inline backtick spans). */
|
|
6
|
+
export function stripFencedCodeBlocks(body) {
|
|
7
|
+
if (body.length === 0) {
|
|
8
|
+
return "";
|
|
9
|
+
}
|
|
10
|
+
return stripFencedCodeBlocksInner(body);
|
|
11
|
+
}
|
|
12
|
+
/** Strip fenced and inline code spans before cross-ref extraction. */
|
|
6
13
|
export function stripCodeBlocks(body) {
|
|
7
14
|
if (body.length === 0) {
|
|
8
15
|
return "";
|
|
9
16
|
}
|
|
10
|
-
let text =
|
|
17
|
+
let text = stripFencedCodeBlocksInner(body);
|
|
11
18
|
text = stripInlineCode(text);
|
|
12
19
|
return text;
|
|
13
20
|
}
|
|
14
|
-
function
|
|
21
|
+
function stripFencedCodeBlocksInner(text) {
|
|
15
22
|
let out = "";
|
|
16
23
|
let i = 0;
|
|
17
24
|
while (i < text.length) {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
2
|
import { mkdirSync, readdirSync, readFileSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
|
+
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
4
5
|
import { call } from "../scm/call.js";
|
|
6
|
+
import { updateDecomposedChildBackReferences } from "../scope/decomposed-refs.js";
|
|
5
7
|
import { resolveProjectRoot } from "../scope/project-context.js";
|
|
6
8
|
import { resolveProjectRepo } from "../slice/project-context.js";
|
|
7
9
|
export const LIFECYCLE_FOLDERS = [
|
|
@@ -12,7 +14,11 @@ export const LIFECYCLE_FOLDERS = [
|
|
|
12
14
|
"cancelled",
|
|
13
15
|
];
|
|
14
16
|
export const TERMINAL_LIFECYCLE_FOLDERS = new Set(["completed", "cancelled"]);
|
|
15
|
-
export const GITHUB_ISSUE_REF_TYPES = new Set([
|
|
17
|
+
export const GITHUB_ISSUE_REF_TYPES = new Set([
|
|
18
|
+
"github-issue",
|
|
19
|
+
"x-vbrief/github-issue",
|
|
20
|
+
"x-xbrief/github-issue",
|
|
21
|
+
]);
|
|
16
22
|
export const CANCELLED_STATE_REASONS = new Set(["NOT_PLANNED", "DUPLICATE"]);
|
|
17
23
|
const ISSUE_URL_PATTERN = /https:\/\/github\.com\/([^/\s]+)\/([^/\s]+)\/issues\/(\d+)/;
|
|
18
24
|
const ISSUE_ID_PATTERN = /^#(\d+)$/;
|
|
@@ -105,7 +111,7 @@ export function scanVbriefDir(vbriefDir) {
|
|
|
105
111
|
continue;
|
|
106
112
|
}
|
|
107
113
|
const files = readdirSync(folderPath)
|
|
108
|
-
.filter((f) => f
|
|
114
|
+
.filter((f) => hasArtifactSuffix(f))
|
|
109
115
|
.sort();
|
|
110
116
|
for (const filename of files) {
|
|
111
117
|
let data;
|
|
@@ -406,7 +412,7 @@ export function scanLifecycleAnchors(vbriefDir) {
|
|
|
406
412
|
continue;
|
|
407
413
|
}
|
|
408
414
|
const files = readdirSync(folderPath)
|
|
409
|
-
.filter((f) => f
|
|
415
|
+
.filter((f) => hasArtifactSuffix(f))
|
|
410
416
|
.sort();
|
|
411
417
|
for (const filename of files) {
|
|
412
418
|
let data;
|
|
@@ -643,6 +649,7 @@ export function applyLifecycleFixes(vbriefDir, report, projectRoot = null) {
|
|
|
643
649
|
failures.push(`failed to move ${relPath} -> ${destFolder}/`);
|
|
644
650
|
continue;
|
|
645
651
|
}
|
|
652
|
+
updateDecomposedChildBackReferences(data, src, dst, vbriefDir);
|
|
646
653
|
moved += 1;
|
|
647
654
|
}
|
|
648
655
|
return [moved, skipped, failures];
|
|
@@ -665,7 +672,9 @@ export function detectRepo() {
|
|
|
665
672
|
return null;
|
|
666
673
|
}
|
|
667
674
|
export function reconcileMain(args) {
|
|
668
|
-
const vbriefDir =
|
|
675
|
+
const vbriefDir = args.vbriefDir
|
|
676
|
+
? resolve(args.vbriefDir)
|
|
677
|
+
: resolveLifecycleRoot(args.projectRoot ? resolve(args.projectRoot) : resolve("."));
|
|
669
678
|
try {
|
|
670
679
|
if (!statSync(vbriefDir).isDirectory()) {
|
|
671
680
|
process.stderr.write(`Error: vbrief directory not found: ${vbriefDir}\n`);
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { ARTIFACT_SUFFIXES, hasArtifactSuffix, isLifecycleArtifactPath, LEGACY_ARTIFACT_DIR, LEGACY_ARTIFACT_SUFFIX, LEGACY_INFO_ROOT_KEY, LIFECYCLE_DIR_NAMES, type LifecycleLayout, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY, projectDefinitionFilename, projectDefinitionRelPath, resolveAuditDir, resolveAuditPath, resolveEvalDir, resolveEvalPath, resolveLifecycleFolder, resolveLifecycleLayout, resolveLifecycleRoot, resolveProjectDefinitionPath, resolveSpecArtifactPath, specArtifactRelPath, stripArtifactSuffix, } from "./resolve.js";
|
|
2
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { ARTIFACT_SUFFIXES, hasArtifactSuffix, isLifecycleArtifactPath, LEGACY_ARTIFACT_DIR, LEGACY_ARTIFACT_SUFFIX, LEGACY_INFO_ROOT_KEY, LIFECYCLE_DIR_NAMES, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY, projectDefinitionFilename, projectDefinitionRelPath, resolveAuditDir, resolveAuditPath, resolveEvalDir, resolveEvalPath, resolveLifecycleFolder, resolveLifecycleLayout, resolveLifecycleRoot, resolveProjectDefinitionPath, resolveSpecArtifactPath, specArtifactRelPath, stripArtifactSuffix, } from "./resolve.js";
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { LEGACY_ARTIFACT_DIR, LEGACY_ARTIFACT_SUFFIX, LEGACY_INFO_ROOT_KEY, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY } from "../xbrief-migrate/constants.js";
|
|
2
|
+
export { LEGACY_ARTIFACT_DIR, LEGACY_ARTIFACT_SUFFIX, LEGACY_INFO_ROOT_KEY, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY, };
|
|
3
|
+
/**
|
|
4
|
+
* Lifecycle directory names recognized by the layout-aware resolver, in
|
|
5
|
+
* preference order (migrated `xbrief` first, legacy `vbrief` second).
|
|
6
|
+
*/
|
|
7
|
+
export declare const LIFECYCLE_DIR_NAMES: readonly ["xbrief", "vbrief"];
|
|
8
|
+
/**
|
|
9
|
+
* Artifact filename suffixes recognized by the layout-aware resolver, in
|
|
10
|
+
* preference order (`.xbrief.json` first, `.vbrief.json` second).
|
|
11
|
+
*/
|
|
12
|
+
export declare const ARTIFACT_SUFFIXES: readonly [".xbrief.json", ".vbrief.json"];
|
|
13
|
+
/** The on-disk lifecycle layout an engine call site should resolve against (#2109). */
|
|
14
|
+
export interface LifecycleLayout {
|
|
15
|
+
/** The lifecycle directory name -- `xbrief` when migrated, else `vbrief`. */
|
|
16
|
+
readonly artifactDir: typeof MIGRATED_ARTIFACT_DIR | typeof LEGACY_ARTIFACT_DIR;
|
|
17
|
+
/** The artifact filename suffix matching `artifactDir`. */
|
|
18
|
+
readonly artifactSuffix: typeof MIGRATED_ARTIFACT_SUFFIX | typeof LEGACY_ARTIFACT_SUFFIX;
|
|
19
|
+
/** The `*BRIEFInfo` root key matching `artifactDir`. */
|
|
20
|
+
readonly infoRootKey: typeof MIGRATED_INFO_ROOT_KEY | typeof LEGACY_INFO_ROOT_KEY;
|
|
21
|
+
/** Absolute path to the resolved lifecycle root (`<projectRoot>/<artifactDir>`). */
|
|
22
|
+
readonly root: string;
|
|
23
|
+
/** True when the resolved layout is the migrated `xbrief` layout. */
|
|
24
|
+
readonly migrated: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** True when `name` ends with any recognized artifact suffix (.xbrief.json or .vbrief.json). */
|
|
27
|
+
export declare function hasArtifactSuffix(name: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Strip whichever recognized artifact suffix `name` ends with. Returns `name`
|
|
30
|
+
* unchanged when it carries no recognized suffix.
|
|
31
|
+
*/
|
|
32
|
+
export declare function stripArtifactSuffix(name: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* True when a POSIX-style path is a lifecycle artifact under either layout
|
|
35
|
+
* root (`xbrief/` or `vbrief/`) carrying either artifact suffix.
|
|
36
|
+
*/
|
|
37
|
+
export declare function isLifecycleArtifactPath(posix: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve the active lifecycle layout for `projectRoot` (#2109 part 1).
|
|
40
|
+
*
|
|
41
|
+
* Prefers the migrated `xbrief/` layout only when BOTH the `xbrief/` directory
|
|
42
|
+
* exists AND it contains at least one `.xbrief.json` artifact; otherwise falls
|
|
43
|
+
* back to the legacy `vbrief/` layout. With only `vbrief/` present (today's
|
|
44
|
+
* repo) the result is the legacy layout, so existing behavior is unchanged.
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveLifecycleLayout(projectRoot: string): LifecycleLayout;
|
|
47
|
+
/** Convenience accessor for the absolute resolved lifecycle root directory. */
|
|
48
|
+
export declare function resolveLifecycleRoot(projectRoot: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Absolute path to a lifecycle folder under the resolved layout root
|
|
51
|
+
* (e.g. `<root>/<xbrief|vbrief>/active`). Layout-aware (#2109 part 2a).
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveLifecycleFolder(projectRoot: string, folder: string): string;
|
|
54
|
+
/** Absolute path to the resolved lifecycle `.eval` cache directory (#2109 part 2a). */
|
|
55
|
+
export declare function resolveEvalDir(projectRoot: string): string;
|
|
56
|
+
/** Absolute path to a file or subpath under the resolved `.eval` cache directory. */
|
|
57
|
+
export declare function resolveEvalPath(projectRoot: string, ...segments: string[]): string;
|
|
58
|
+
/** Absolute path to the resolved lifecycle `.audit` directory (#2109 part 2a). */
|
|
59
|
+
export declare function resolveAuditDir(projectRoot: string): string;
|
|
60
|
+
/** Absolute path to a file or subpath under the resolved `.audit` directory. */
|
|
61
|
+
export declare function resolveAuditPath(projectRoot: string, ...segments: string[]): string;
|
|
62
|
+
/**
|
|
63
|
+
* The PROJECT-DEFINITION artifact filename for the resolved layout
|
|
64
|
+
* (`PROJECT-DEFINITION.xbrief.json` when migrated, else `.vbrief.json`).
|
|
65
|
+
*/
|
|
66
|
+
export declare function projectDefinitionFilename(projectRoot: string): string;
|
|
67
|
+
/** Absolute path to the resolved PROJECT-DEFINITION artifact (#2109 part 2a). */
|
|
68
|
+
export declare function resolveProjectDefinitionPath(projectRoot: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* POSIX-style display path to the resolved PROJECT-DEFINITION artifact relative
|
|
71
|
+
* to the project root (e.g. `vbrief/PROJECT-DEFINITION.vbrief.json`).
|
|
72
|
+
*/
|
|
73
|
+
export declare function projectDefinitionRelPath(projectRoot: string): string;
|
|
74
|
+
/**
|
|
75
|
+
* Absolute path to the resolved specification artifact (#2132).
|
|
76
|
+
*
|
|
77
|
+
* Prefers `xbrief/specification.xbrief.json` on a migrated tree; falls back to
|
|
78
|
+
* `vbrief/specification.vbrief.json` on an unmigrated tree. Consistent with the
|
|
79
|
+
* layout resolver used by the #2109 Part-2a call-site sweep.
|
|
80
|
+
*/
|
|
81
|
+
export declare function resolveSpecArtifactPath(projectRoot: string): string;
|
|
82
|
+
/**
|
|
83
|
+
* POSIX-style display path to the resolved specification artifact relative to
|
|
84
|
+
* the project root (e.g. `xbrief/specification.xbrief.json`).
|
|
85
|
+
*/
|
|
86
|
+
export declare function specArtifactRelPath(projectRoot: string): string;
|
|
87
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { LEGACY_ARTIFACT_DIR, LEGACY_ARTIFACT_SUFFIX, LEGACY_INFO_ROOT_KEY, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY, } from "../xbrief-migrate/constants.js";
|
|
4
|
+
export { LEGACY_ARTIFACT_DIR, LEGACY_ARTIFACT_SUFFIX, LEGACY_INFO_ROOT_KEY, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY, };
|
|
5
|
+
/**
|
|
6
|
+
* Lifecycle directory names recognized by the layout-aware resolver, in
|
|
7
|
+
* preference order (migrated `xbrief` first, legacy `vbrief` second).
|
|
8
|
+
*/
|
|
9
|
+
export const LIFECYCLE_DIR_NAMES = [MIGRATED_ARTIFACT_DIR, LEGACY_ARTIFACT_DIR];
|
|
10
|
+
/**
|
|
11
|
+
* Artifact filename suffixes recognized by the layout-aware resolver, in
|
|
12
|
+
* preference order (`.xbrief.json` first, `.vbrief.json` second).
|
|
13
|
+
*/
|
|
14
|
+
export const ARTIFACT_SUFFIXES = [MIGRATED_ARTIFACT_SUFFIX, LEGACY_ARTIFACT_SUFFIX];
|
|
15
|
+
function isDirectory(path) {
|
|
16
|
+
try {
|
|
17
|
+
return statSync(path).isDirectory();
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** True when `name` ends with any recognized artifact suffix (.xbrief.json or .vbrief.json). */
|
|
24
|
+
export function hasArtifactSuffix(name) {
|
|
25
|
+
return ARTIFACT_SUFFIXES.some((suffix) => name.endsWith(suffix));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Strip whichever recognized artifact suffix `name` ends with. Returns `name`
|
|
29
|
+
* unchanged when it carries no recognized suffix.
|
|
30
|
+
*/
|
|
31
|
+
export function stripArtifactSuffix(name) {
|
|
32
|
+
for (const suffix of ARTIFACT_SUFFIXES) {
|
|
33
|
+
if (name.endsWith(suffix)) {
|
|
34
|
+
return name.slice(0, -suffix.length);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return name;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* True when a POSIX-style path is a lifecycle artifact under either layout
|
|
41
|
+
* root (`xbrief/` or `vbrief/`) carrying either artifact suffix.
|
|
42
|
+
*/
|
|
43
|
+
export function isLifecycleArtifactPath(posix) {
|
|
44
|
+
const underLifecycleDir = LIFECYCLE_DIR_NAMES.some((dir) => posix.startsWith(`${dir}/`));
|
|
45
|
+
return underLifecycleDir && hasArtifactSuffix(posix);
|
|
46
|
+
}
|
|
47
|
+
/** Walk `root` looking for any `.xbrief.json` file (bounded iterative scan). */
|
|
48
|
+
function containsMigratedArtifact(root) {
|
|
49
|
+
const stack = [root];
|
|
50
|
+
while (stack.length > 0) {
|
|
51
|
+
const dir = stack.pop();
|
|
52
|
+
if (dir === undefined || !isDirectory(dir)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
56
|
+
if (entry.isDirectory()) {
|
|
57
|
+
stack.push(join(dir, entry.name));
|
|
58
|
+
}
|
|
59
|
+
else if (entry.isFile() && entry.name.endsWith(MIGRATED_ARTIFACT_SUFFIX)) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Resolve the active lifecycle layout for `projectRoot` (#2109 part 1).
|
|
68
|
+
*
|
|
69
|
+
* Prefers the migrated `xbrief/` layout only when BOTH the `xbrief/` directory
|
|
70
|
+
* exists AND it contains at least one `.xbrief.json` artifact; otherwise falls
|
|
71
|
+
* back to the legacy `vbrief/` layout. With only `vbrief/` present (today's
|
|
72
|
+
* repo) the result is the legacy layout, so existing behavior is unchanged.
|
|
73
|
+
*/
|
|
74
|
+
export function resolveLifecycleLayout(projectRoot) {
|
|
75
|
+
const migratedRoot = join(projectRoot, MIGRATED_ARTIFACT_DIR);
|
|
76
|
+
if (isDirectory(migratedRoot) && containsMigratedArtifact(migratedRoot)) {
|
|
77
|
+
return {
|
|
78
|
+
artifactDir: MIGRATED_ARTIFACT_DIR,
|
|
79
|
+
artifactSuffix: MIGRATED_ARTIFACT_SUFFIX,
|
|
80
|
+
infoRootKey: MIGRATED_INFO_ROOT_KEY,
|
|
81
|
+
root: migratedRoot,
|
|
82
|
+
migrated: true,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
artifactDir: LEGACY_ARTIFACT_DIR,
|
|
87
|
+
artifactSuffix: LEGACY_ARTIFACT_SUFFIX,
|
|
88
|
+
infoRootKey: LEGACY_INFO_ROOT_KEY,
|
|
89
|
+
root: join(projectRoot, LEGACY_ARTIFACT_DIR),
|
|
90
|
+
migrated: false,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** Convenience accessor for the absolute resolved lifecycle root directory. */
|
|
94
|
+
export function resolveLifecycleRoot(projectRoot) {
|
|
95
|
+
return resolveLifecycleLayout(projectRoot).root;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Absolute path to a lifecycle folder under the resolved layout root
|
|
99
|
+
* (e.g. `<root>/<xbrief|vbrief>/active`). Layout-aware (#2109 part 2a).
|
|
100
|
+
*/
|
|
101
|
+
export function resolveLifecycleFolder(projectRoot, folder) {
|
|
102
|
+
return join(resolveLifecycleRoot(projectRoot), folder);
|
|
103
|
+
}
|
|
104
|
+
/** Absolute path to the resolved lifecycle `.eval` cache directory (#2109 part 2a). */
|
|
105
|
+
export function resolveEvalDir(projectRoot) {
|
|
106
|
+
return join(resolveLifecycleRoot(projectRoot), ".eval");
|
|
107
|
+
}
|
|
108
|
+
/** Absolute path to a file or subpath under the resolved `.eval` cache directory. */
|
|
109
|
+
export function resolveEvalPath(projectRoot, ...segments) {
|
|
110
|
+
return join(resolveEvalDir(projectRoot), ...segments);
|
|
111
|
+
}
|
|
112
|
+
/** Absolute path to the resolved lifecycle `.audit` directory (#2109 part 2a). */
|
|
113
|
+
export function resolveAuditDir(projectRoot) {
|
|
114
|
+
return join(resolveLifecycleRoot(projectRoot), ".audit");
|
|
115
|
+
}
|
|
116
|
+
/** Absolute path to a file or subpath under the resolved `.audit` directory. */
|
|
117
|
+
export function resolveAuditPath(projectRoot, ...segments) {
|
|
118
|
+
return join(resolveAuditDir(projectRoot), ...segments);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The PROJECT-DEFINITION artifact filename for the resolved layout
|
|
122
|
+
* (`PROJECT-DEFINITION.xbrief.json` when migrated, else `.vbrief.json`).
|
|
123
|
+
*/
|
|
124
|
+
export function projectDefinitionFilename(projectRoot) {
|
|
125
|
+
return `PROJECT-DEFINITION${resolveLifecycleLayout(projectRoot).artifactSuffix}`;
|
|
126
|
+
}
|
|
127
|
+
/** Absolute path to the resolved PROJECT-DEFINITION artifact (#2109 part 2a). */
|
|
128
|
+
export function resolveProjectDefinitionPath(projectRoot) {
|
|
129
|
+
const layout = resolveLifecycleLayout(projectRoot);
|
|
130
|
+
return join(layout.root, `PROJECT-DEFINITION${layout.artifactSuffix}`);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* POSIX-style display path to the resolved PROJECT-DEFINITION artifact relative
|
|
134
|
+
* to the project root (e.g. `vbrief/PROJECT-DEFINITION.vbrief.json`).
|
|
135
|
+
*/
|
|
136
|
+
export function projectDefinitionRelPath(projectRoot) {
|
|
137
|
+
const layout = resolveLifecycleLayout(projectRoot);
|
|
138
|
+
return `${layout.artifactDir}/PROJECT-DEFINITION${layout.artifactSuffix}`;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Absolute path to the resolved specification artifact (#2132).
|
|
142
|
+
*
|
|
143
|
+
* Prefers `xbrief/specification.xbrief.json` on a migrated tree; falls back to
|
|
144
|
+
* `vbrief/specification.vbrief.json` on an unmigrated tree. Consistent with the
|
|
145
|
+
* layout resolver used by the #2109 Part-2a call-site sweep.
|
|
146
|
+
*/
|
|
147
|
+
export function resolveSpecArtifactPath(projectRoot) {
|
|
148
|
+
const layout = resolveLifecycleLayout(projectRoot);
|
|
149
|
+
return join(layout.root, `specification${layout.artifactSuffix}`);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* POSIX-style display path to the resolved specification artifact relative to
|
|
153
|
+
* the project root (e.g. `xbrief/specification.xbrief.json`).
|
|
154
|
+
*/
|
|
155
|
+
export function specArtifactRelPath(projectRoot) {
|
|
156
|
+
const layout = resolveLifecycleLayout(projectRoot);
|
|
157
|
+
return `${layout.artifactDir}/specification${layout.artifactSuffix}`;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -9,7 +9,7 @@ export declare const LIFECYCLE_FOLDERS: readonly ["proposed", "pending", "active
|
|
|
9
9
|
/** plan.status values that make an epic terminal. */
|
|
10
10
|
export declare const TERMINAL_STATUSES: Set<string>;
|
|
11
11
|
/** Child reference type that marks an epic as decomposed. */
|
|
12
|
-
export declare const CHILD_REF_TYPE = "x-
|
|
12
|
+
export declare const CHILD_REF_TYPE = "x-xbrief/plan";
|
|
13
13
|
/** Durable tech-debt acceptance ledger relative path segments. */
|
|
14
14
|
export declare const TECH_DEBT_LEDGER_RELPATH: readonly ["vbrief", ".audit", "epic-tech-debt-accepted.jsonl"];
|
|
15
15
|
/** Session-start nudge tiers (rate-of-harm ranking). */
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, } from "node:fs";
|
|
2
2
|
import { basename, join, resolve } from "node:path";
|
|
3
|
+
import { referenceTypeMatches } from "@deftai/directive-types";
|
|
3
4
|
import { computeReport } from "../capacity/show.js";
|
|
5
|
+
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
4
6
|
import { resolveCapacityAllocation } from "../policy/capacity.js";
|
|
7
|
+
import { readPlanPolicy } from "../policy/plan-extensions.js";
|
|
5
8
|
import { loadProjectDefinition } from "../policy/resolve.js";
|
|
6
9
|
/** Default dormancy (days) past which a partially-completed epic is stranded. */
|
|
7
10
|
export const EPIC_STRANDED_DAYS_DEFAULT = 30;
|
|
@@ -20,7 +23,7 @@ export const LIFECYCLE_FOLDERS = [
|
|
|
20
23
|
/** plan.status values that make an epic terminal. */
|
|
21
24
|
export const TERMINAL_STATUSES = new Set(["completed", "cancelled", "failed"]);
|
|
22
25
|
/** Child reference type that marks an epic as decomposed. */
|
|
23
|
-
export const CHILD_REF_TYPE = "x-
|
|
26
|
+
export const CHILD_REF_TYPE = "x-xbrief/plan";
|
|
24
27
|
/** Durable tech-debt acceptance ledger relative path segments. */
|
|
25
28
|
export const TECH_DEBT_LEDGER_RELPATH = [
|
|
26
29
|
"vbrief",
|
|
@@ -48,7 +51,7 @@ export function resolveEpicThresholds(projectRoot) {
|
|
|
48
51
|
if (data !== null && typeof data === "object") {
|
|
49
52
|
const plan = data.plan;
|
|
50
53
|
if (typeof plan === "object" && plan !== null && !Array.isArray(plan)) {
|
|
51
|
-
const pol = plan
|
|
54
|
+
const pol = readPlanPolicy(plan);
|
|
52
55
|
if (typeof pol === "object" && pol !== null && !Array.isArray(pol)) {
|
|
53
56
|
const cap = pol.capacityAllocation;
|
|
54
57
|
if (typeof cap === "object" && cap !== null && !Array.isArray(cap)) {
|
|
@@ -125,7 +128,7 @@ function childRefNames(plan) {
|
|
|
125
128
|
continue;
|
|
126
129
|
}
|
|
127
130
|
const rec = ref;
|
|
128
|
-
if (rec.type
|
|
131
|
+
if (!referenceTypeMatches(String(rec.type ?? ""), "plan")) {
|
|
129
132
|
continue;
|
|
130
133
|
}
|
|
131
134
|
const uri = rec.uri;
|
|
@@ -137,14 +140,14 @@ function childRefNames(plan) {
|
|
|
137
140
|
}
|
|
138
141
|
function iterVbriefs(projectRoot) {
|
|
139
142
|
const out = [];
|
|
140
|
-
const vroot =
|
|
143
|
+
const vroot = resolveLifecycleRoot(projectRoot);
|
|
141
144
|
for (const folder of LIFECYCLE_FOLDERS) {
|
|
142
145
|
const fdir = join(vroot, folder);
|
|
143
146
|
if (!existsSync(fdir)) {
|
|
144
147
|
continue;
|
|
145
148
|
}
|
|
146
149
|
const children = readdirSync(fdir)
|
|
147
|
-
.filter((name) => name
|
|
150
|
+
.filter((name) => hasArtifactSuffix(name))
|
|
148
151
|
.sort();
|
|
149
152
|
for (const name of children) {
|
|
150
153
|
const child = join(fdir, name);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Judgment-gate policy resolution (#1419). Port of scripts/policy.py judgment-gate section.
|
|
3
3
|
*/
|
|
4
|
+
import { readPlanPolicy } from "../policy/plan-extensions.js";
|
|
4
5
|
import { loadProjectDefinition } from "../policy/resolve.js";
|
|
5
6
|
export const GATE_CLASSES = new Set(["mechanical", "declared"]);
|
|
6
7
|
export const GATE_TIERS = new Set(["auto", "review", "block"]);
|
|
@@ -175,12 +176,9 @@ function defaultPolicy(source, error = null) {
|
|
|
175
176
|
return { gates: [], disabled: [], source, error };
|
|
176
177
|
}
|
|
177
178
|
function getPolicyBlock(data) {
|
|
178
|
-
const
|
|
179
|
-
if (typeof
|
|
180
|
-
|
|
181
|
-
if (typeof policy === "object" && policy !== null && !Array.isArray(policy)) {
|
|
182
|
-
return policy;
|
|
183
|
-
}
|
|
179
|
+
const policy = readPlanPolicy(data.plan);
|
|
180
|
+
if (typeof policy === "object" && policy !== null && !Array.isArray(policy)) {
|
|
181
|
+
return policy;
|
|
184
182
|
}
|
|
185
183
|
return {};
|
|
186
184
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Risk-tiered judgment-gate engine (#1419 Slice 3). Port of scripts/verify_judgment_gates.py.
|
|
3
3
|
*/
|
|
4
4
|
import { type JudgmentGatesPolicy } from "./judgment-policy.js";
|
|
5
|
+
/** Display/back-compat constant; resolution flows through resolveAuditDir (#2109). */
|
|
5
6
|
export declare const AUDIT_DIR_REL = "vbrief/.audit";
|
|
6
7
|
export declare const CLEARANCE_LOG_NAME = "judgment-gate-clearances.jsonl";
|
|
7
8
|
export declare const UNIVERSAL_SOURCE = "universal";
|
|
@@ -5,8 +5,10 @@ import { execFileSync } from "node:child_process";
|
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
6
|
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync } from "node:fs";
|
|
7
7
|
import { join, resolve } from "node:path";
|
|
8
|
+
import { resolveAuditDir } from "../layout/resolve.js";
|
|
8
9
|
import { resolveJudgmentGates } from "./judgment-policy.js";
|
|
9
10
|
import { matchAny } from "./pathspec.js";
|
|
11
|
+
/** Display/back-compat constant; resolution flows through resolveAuditDir (#2109). */
|
|
10
12
|
export const AUDIT_DIR_REL = "vbrief/.audit";
|
|
11
13
|
export const CLEARANCE_LOG_NAME = "judgment-gate-clearances.jsonl";
|
|
12
14
|
export const UNIVERSAL_SOURCE = "universal";
|
|
@@ -131,7 +133,7 @@ export function reportBlocking(report) {
|
|
|
131
133
|
return report.outcomes.filter(outcomeBlocking);
|
|
132
134
|
}
|
|
133
135
|
export function clearanceLogPath(projectRoot) {
|
|
134
|
-
return join(projectRoot,
|
|
136
|
+
return join(resolveAuditDir(projectRoot), CLEARANCE_LOG_NAME);
|
|
135
137
|
}
|
|
136
138
|
function utcNowIso(now) {
|
|
137
139
|
return (now ?? new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
@@ -161,7 +163,7 @@ export function readClearances(projectRoot, logPath) {
|
|
|
161
163
|
}
|
|
162
164
|
export function recordClearance(projectRoot, options) {
|
|
163
165
|
const path = options.log_path ?? clearanceLogPath(projectRoot);
|
|
164
|
-
mkdirSync(
|
|
166
|
+
mkdirSync(resolveAuditDir(projectRoot), { recursive: true });
|
|
165
167
|
const entry = {
|
|
166
168
|
clearance_id: randomUUID(),
|
|
167
169
|
timestamp: utcNowIso(options.now),
|
package/dist/policy/autonomy.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readPlanPolicy } from "./plan-extensions.js";
|
|
1
2
|
import { loadProjectDefinition } from "./resolve.js";
|
|
2
3
|
export const AUTONOMY_LEVELS = ["observe", "escalate", "execute"];
|
|
3
4
|
export const DEFAULT_AUTONOMY_LEVEL = "escalate";
|
|
@@ -81,12 +82,9 @@ export function validateAutonomy(value) {
|
|
|
81
82
|
return errors;
|
|
82
83
|
}
|
|
83
84
|
function getPolicyBlock(data) {
|
|
84
|
-
const
|
|
85
|
-
if (typeof
|
|
86
|
-
|
|
87
|
-
if (typeof policy === "object" && policy !== null && !Array.isArray(policy)) {
|
|
88
|
-
return policy;
|
|
89
|
-
}
|
|
85
|
+
const policy = readPlanPolicy(data.plan);
|
|
86
|
+
if (typeof policy === "object" && policy !== null && !Array.isArray(policy)) {
|
|
87
|
+
return policy;
|
|
90
88
|
}
|
|
91
89
|
return {};
|
|
92
90
|
}
|
package/dist/policy/capacity.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readPlanPolicy } from "../policy/plan-extensions.js";
|
|
1
2
|
import { loadProjectDefinition } from "../policy/resolve.js";
|
|
2
3
|
export const DEFAULT_CAPACITY_UNIT = "vbrief-count";
|
|
3
4
|
export const CAPACITY_UNIT_COST = "cost";
|
|
@@ -124,12 +125,9 @@ export function validateCapacityAllocation(value) {
|
|
|
124
125
|
return errors;
|
|
125
126
|
}
|
|
126
127
|
function getPolicyBlock(data) {
|
|
127
|
-
const
|
|
128
|
-
if (typeof
|
|
129
|
-
|
|
130
|
-
if (typeof policy === "object" && policy !== null && !Array.isArray(policy)) {
|
|
131
|
-
return policy;
|
|
132
|
-
}
|
|
128
|
+
const policy = readPlanPolicy(data.plan);
|
|
129
|
+
if (typeof policy === "object" && policy !== null && !Array.isArray(policy)) {
|
|
130
|
+
return policy;
|
|
133
131
|
}
|
|
134
132
|
return {};
|
|
135
133
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Display/back-compat constant; resolution flows through resolveAuditDir (#2109). */
|
|
1
2
|
export declare const PENDING_DECISIONS_AUDIT_DIR_REL = "vbrief/.audit";
|
|
2
3
|
export declare const PENDING_DECISIONS_LOG_NAME = "pending-human-decisions.jsonl";
|
|
3
4
|
export declare const DECISION_STATUS_PENDING = "pending";
|
package/dist/policy/decisions.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import { join
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { resolveAuditDir } from "../layout/resolve.js";
|
|
4
|
+
/** Display/back-compat constant; resolution flows through resolveAuditDir (#2109). */
|
|
3
5
|
export const PENDING_DECISIONS_AUDIT_DIR_REL = "vbrief/.audit";
|
|
4
6
|
export const PENDING_DECISIONS_LOG_NAME = "pending-human-decisions.jsonl";
|
|
5
7
|
export const DECISION_STATUS_PENDING = "pending";
|
|
6
8
|
export const DECISION_STATUS_RESOLVED = "resolved";
|
|
7
9
|
export const DEFAULT_PENDING_DECISIONS_THRESHOLD = 5;
|
|
8
10
|
export function pendingDecisionsLogPath(projectRoot) {
|
|
9
|
-
return join(
|
|
11
|
+
return join(resolveAuditDir(projectRoot), PENDING_DECISIONS_LOG_NAME);
|
|
10
12
|
}
|
|
11
13
|
function parseIsoTs(value) {
|
|
12
14
|
if (typeof value !== "string" || value.length === 0) {
|
package/dist/policy/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./autonomy.js";
|
|
|
2
2
|
export * from "./capacity.js";
|
|
3
3
|
export * from "./decisions.js";
|
|
4
4
|
export * from "./disclosure.js";
|
|
5
|
+
export * from "./plan-extensions.js";
|
|
5
6
|
export * from "./resolve.js";
|
|
6
7
|
export * from "./wip.js";
|
|
7
8
|
export declare const FIELD_ALLOW_DIRECT_COMMITS = "plan.policy.allowDirectCommitsToMaster";
|