@deftai/directive-core 0.72.0 → 0.73.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/category-b-namespace/index.js +16 -2
- package/dist/codebase/default-extractor.js +9 -1
- package/dist/codebase/map.js +1 -1
- package/dist/doctor/checks.d.ts +9 -0
- package/dist/doctor/checks.js +85 -5
- package/dist/doctor/main.js +2 -1
- package/dist/eval/health.js +7 -1
- package/dist/eval/readback.js +7 -1
- package/dist/init-deposit/gitignore.js +6 -0
- package/dist/init-deposit/hygiene.d.ts +24 -0
- package/dist/init-deposit/hygiene.js +55 -0
- package/dist/init-deposit/refresh.js +22 -6
- package/dist/init-deposit/scaffold.d.ts +11 -1
- package/dist/init-deposit/scaffold.js +4 -4
- package/dist/integration-e2e/helpers.js +7 -7
- package/dist/layout/index.d.ts +1 -1
- package/dist/layout/index.js +1 -1
- package/dist/layout/resolve.d.ts +47 -31
- package/dist/layout/resolve.js +93 -36
- package/dist/lifecycle/lifecycle-hygiene.d.ts +1 -1
- package/dist/lifecycle/lifecycle-hygiene.js +1 -1
- package/dist/migrate-preflight/index.js +10 -10
- package/dist/policy/resolve.d.ts +2 -2
- package/dist/policy/resolve.js +11 -3
- package/dist/policy/wip.d.ts +1 -1
- package/dist/policy/wip.js +15 -3
- package/dist/preflight-cache/evaluate.js +1 -1
- package/dist/release/native-steps.js +14 -2
- package/dist/render/export-spec.js +2 -2
- package/dist/render/project-render.js +40 -9
- package/dist/scope/decompose.js +12 -2
- package/dist/session/resume-conditions.js +2 -2
- package/dist/session/ritual-sentinel.d.ts +1 -1
- package/dist/session/ritual-sentinel.js +6 -4
- package/dist/slice/constants.d.ts +1 -1
- package/dist/slice/constants.js +1 -1
- package/dist/slice/project-context.js +1 -1
- package/dist/spec-authority/resolver.js +9 -2
- package/dist/swarm/complete-cohort.js +14 -1
- package/dist/swarm/readiness.js +33 -3
- package/dist/task-surface/index.js +3 -3
- package/dist/triage/actions/candidates-log.d.ts +1 -1
- package/dist/triage/bootstrap/gitignore.js +22 -10
- package/dist/triage/bootstrap/index.d.ts +1 -1
- package/dist/triage/bootstrap/index.js +9 -3
- package/dist/triage/cache-path.d.ts +1 -1
- package/dist/triage/cache-path.js +32 -6
- package/dist/triage/classify/index.d.ts +1 -1
- package/dist/triage/classify/index.js +11 -4
- package/dist/triage/help/registry-data.d.ts +2 -2
- package/dist/triage/help/registry-data.js +2 -2
- package/dist/triage/queue/constants.d.ts +4 -4
- package/dist/triage/queue/constants.js +4 -4
- package/dist/triage/queue/scope-walk.js +7 -1
- package/dist/triage/reconcile/reconcile.js +23 -3
- package/dist/triage/reconcile/types.d.ts +1 -1
- package/dist/triage/reconcile/types.js +1 -1
- package/dist/triage/refresh/refresh.js +9 -2
- package/dist/triage/scope/constants.d.ts +2 -2
- package/dist/triage/scope/constants.js +2 -2
- package/dist/triage/scope/renderers.js +7 -1
- package/dist/triage/smoketest/index.js +9 -6
- package/dist/triage/subscribe/index.d.ts +2 -2
- package/dist/triage/subscribe/index.js +2 -2
- package/dist/triage/summary/index.d.ts +2 -2
- package/dist/triage/summary/index.js +1 -1
- package/dist/triage/summary/reconcilable.d.ts +1 -1
- package/dist/triage/welcome/constants.d.ts +2 -2
- package/dist/triage/welcome/constants.js +2 -2
- package/dist/triage/welcome/onboard.js +8 -1
- package/dist/triage/welcome/prior-state.js +14 -2
- package/dist/triage/welcome/summary.js +14 -2
- package/dist/triage/welcome/writers.js +7 -1
- package/dist/validate-content/validate-strategy-output.js +11 -1
- package/dist/vbrief-build/parity-scenarios.js +3 -3
- package/dist/vbrief-reconcile/labels.js +16 -1
- package/dist/vbrief-reconcile/parity-scenarios.js +10 -10
- package/dist/vbrief-reconcile/umbrellas.js +16 -1
- package/dist/vbrief-validate/main.js +13 -1
- package/dist/vbrief-validate/precutover.js +33 -5
- package/dist/vbrief-validate/staleness.d.ts +1 -1
- package/dist/vbrief-validate/staleness.js +5 -2
- package/dist/verify-source/code-structure-validate.js +7 -1
- package/dist/xbrief-migrate/signpost.d.ts +4 -4
- package/dist/xbrief-migrate/signpost.js +11 -15
- package/package.json +3 -3
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* order-preserving (the namespaced key takes the legacy key's slot, keeping
|
|
10
10
|
* artifact diffs minimal).
|
|
11
11
|
*/
|
|
12
|
-
import { readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync, } from "node:fs";
|
|
13
13
|
import { join, relative, resolve } from "node:path";
|
|
14
14
|
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
15
15
|
import { LEGACY_PLAN_COMPLETED_NOTE_KEY, LEGACY_PLAN_POLICY_KEY, PLAN_COMPLETED_NOTE_KEY, PLAN_POLICY_KEY, } from "../policy/plan-extensions.js";
|
|
@@ -85,7 +85,21 @@ function collectVbriefFiles(dir, acc = []) {
|
|
|
85
85
|
*/
|
|
86
86
|
export function migrateCategoryBCorpus(projectRoot) {
|
|
87
87
|
const root = resolve(projectRoot);
|
|
88
|
-
|
|
88
|
+
let vbriefDir;
|
|
89
|
+
try {
|
|
90
|
+
vbriefDir = resolveLifecycleRoot(root);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// If xbrief/ layout is absent, fall back to vbrief/ for this pre-migration tool
|
|
94
|
+
// (category-b migration rewrites policy keys regardless of layout stage).
|
|
95
|
+
const legacyDir = join(root, "vbrief");
|
|
96
|
+
if (existsSync(legacyDir)) {
|
|
97
|
+
vbriefDir = legacyDir;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return { scanned: 0, changed: [], conflicts: [] };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
89
103
|
let scanned = 0;
|
|
90
104
|
const changed = [];
|
|
91
105
|
const conflicts = [];
|
|
@@ -101,7 +101,15 @@ function sourcePathRel(projectRoot, sourcePath) {
|
|
|
101
101
|
}
|
|
102
102
|
/** Return the authored codeStructure source path used by the default extractor. */
|
|
103
103
|
export function defaultCodeStructurePath(projectRoot, codeStructurePath) {
|
|
104
|
-
|
|
104
|
+
if (codeStructurePath !== undefined)
|
|
105
|
+
return codeStructurePath;
|
|
106
|
+
try {
|
|
107
|
+
return resolveProjectDefinitionPath(projectRoot);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// No xbrief/ layout; return canonical path so callers get a predictable "not found" result.
|
|
111
|
+
return join(projectRoot, "xbrief", "PROJECT-DEFINITION.xbrief.json");
|
|
112
|
+
}
|
|
105
113
|
}
|
|
106
114
|
function stableId(value) {
|
|
107
115
|
let slug = "";
|
package/dist/codebase/map.js
CHANGED
|
@@ -10,7 +10,7 @@ export const GENERATED_SENTINEL = "AUTO-GENERATED by task codebase:map";
|
|
|
10
10
|
export const DEFAULT_OUTPUT_PATH = ".planning/codebase/MAP.md";
|
|
11
11
|
export const BANNER_TEMPLATE = "<!-- AUTO-GENERATED by task codebase:map -- DO NOT EDIT MANUALLY -->\n" +
|
|
12
12
|
"<!-- Purpose: generated codebase MAP projection -->\n" +
|
|
13
|
-
"<!-- Source of truth:
|
|
13
|
+
"<!-- Source of truth: xbrief/PROJECT-DEFINITION.xbrief.json " +
|
|
14
14
|
"plan.architecture.codeStructure -->\n" +
|
|
15
15
|
"<!-- Regenerate with: task codebase:map -->\n";
|
|
16
16
|
export function markdownText(value) {
|
package/dist/doctor/checks.d.ts
CHANGED
|
@@ -30,6 +30,15 @@ export declare function checkCanonicalVendoredNpmSignpost(projectRoot: string, s
|
|
|
30
30
|
* deposit is still a working install, just an unpinned one.
|
|
31
31
|
*/
|
|
32
32
|
export declare function checkManifestVersionReportable(projectRoot: string, installRoot: string | null, seams?: CheckSeams): CheckResult;
|
|
33
|
+
/**
|
|
34
|
+
* #2206: check that the consumer `.gitignore` carries the canonical Deft baseline
|
|
35
|
+
* entries. Advisory (exit-exempt) because missing entries are an adoption risk, not
|
|
36
|
+
* a broken install.
|
|
37
|
+
*
|
|
38
|
+
* Skips when `.gitignore` is absent (greenfield project that has not yet run
|
|
39
|
+
* `directive init` or `directive update`).
|
|
40
|
+
*/
|
|
41
|
+
export declare function checkGitignoreCoverage(projectRoot: string, seams?: CheckSeams): CheckResult;
|
|
33
42
|
export declare function deriveExitCode(checks: readonly CheckResult[], errors: readonly string[]): number;
|
|
34
43
|
export declare function runChecksImpl(projectRoot: string, seams?: CheckSeams & {
|
|
35
44
|
isDir?: (p: string) => boolean;
|
package/dist/doctor/checks.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
+
import { CANONICAL_GITIGNORE_BASELINE } from "../init-deposit/gitignore.js";
|
|
2
3
|
import { detectLegacyLayout, legacyLayoutSignpostLine, } from "../init-deposit/legacy-detect.js";
|
|
3
4
|
import { detectCanonicalVendoredManifest, isNpmManaged, NPM_MANAGED_SENTINEL_KEY, NPM_MANAGED_SENTINEL_VALUE, } from "../init-deposit/migrate.js";
|
|
4
5
|
import { resolveLifecycleRoot } from "../layout/resolve.js";
|
|
5
6
|
import { findSkillPathsInText } from "../text/redos-safe.js";
|
|
7
|
+
import { stripGitignoreInlineComment } from "../triage/bootstrap/gitignore.js";
|
|
6
8
|
import { CANONICAL_UPGRADE_COMMAND, GO_BRIDGE_RELEASES_URL, UPGRADING_DOC_URL, } from "./constants.js";
|
|
7
9
|
import { isDeprecationRedirectStub, locateManifest, manifestCandidatePaths, manifestReportableVersion, manifestTagToVersion, parseInstallManifest, parseInstallRootFromAgentsMd, parseManifest, } from "./manifest.js";
|
|
8
10
|
import { readTextSafe } from "./paths.js";
|
|
@@ -127,10 +129,14 @@ export function checkManifestAgreement(projectRoot, installRoot, seams = {}) {
|
|
|
127
129
|
const isFile = seams.isFile ?? ((p) => readText(p, seams) !== null);
|
|
128
130
|
const manifestPath = locateManifest(projectRoot, installRoot, isFile);
|
|
129
131
|
const expectedManifestPath = manifestPath ?? manifestCandidatePaths(projectRoot, installRoot)[0];
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
let layoutRoot;
|
|
133
|
+
try {
|
|
134
|
+
layoutRoot = resolveLifecycleRoot(projectRoot);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
layoutRoot = projectRoot; // No xbrief/ layout; fall back to project root for bare version check.
|
|
138
|
+
}
|
|
139
|
+
const bareCandidates = [join(layoutRoot, ".deft-version"), join(projectRoot, ".deft-version")];
|
|
134
140
|
const barePath = bareCandidates.find((p) => isFile(p)) ?? null;
|
|
135
141
|
const manifestText = manifestPath ? readText(manifestPath, seams) : null;
|
|
136
142
|
const bareText = barePath ? readText(barePath, seams) : null;
|
|
@@ -436,8 +442,80 @@ export function checkManifestVersionReportable(projectRoot, installRoot, seams =
|
|
|
436
442
|
data: { manifest_path: manifestPath, version: null, sha: null, source: reportable.source },
|
|
437
443
|
};
|
|
438
444
|
}
|
|
445
|
+
/**
|
|
446
|
+
* Collect the normalised (inline-comment-stripped) gitignore patterns from a
|
|
447
|
+
* `.gitignore` file text. Uses the shared `stripGitignoreInlineComment` helper
|
|
448
|
+
* so coverage checks stay consistent with `ensureInitGitignoreLines`.
|
|
449
|
+
*/
|
|
450
|
+
function collectGitignorePresent(text) {
|
|
451
|
+
const present = new Set();
|
|
452
|
+
for (const raw of text.split("\n")) {
|
|
453
|
+
const line = stripGitignoreInlineComment(raw);
|
|
454
|
+
if (line)
|
|
455
|
+
present.add(line);
|
|
456
|
+
}
|
|
457
|
+
return present;
|
|
458
|
+
}
|
|
459
|
+
function gitignoreLineIsCovered(present, line) {
|
|
460
|
+
return present.has(line);
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* #2206: check that the consumer `.gitignore` carries the canonical Deft baseline
|
|
464
|
+
* entries. Advisory (exit-exempt) because missing entries are an adoption risk, not
|
|
465
|
+
* a broken install.
|
|
466
|
+
*
|
|
467
|
+
* Skips when `.gitignore` is absent (greenfield project that has not yet run
|
|
468
|
+
* `directive init` or `directive update`).
|
|
469
|
+
*/
|
|
470
|
+
export function checkGitignoreCoverage(projectRoot, seams = {}) {
|
|
471
|
+
const gitignorePath = join(projectRoot, ".gitignore");
|
|
472
|
+
const text = readText(gitignorePath, seams);
|
|
473
|
+
if (text === null) {
|
|
474
|
+
return {
|
|
475
|
+
name: "gitignore-coverage",
|
|
476
|
+
status: "skip",
|
|
477
|
+
detail: ".gitignore not found; run `directive init` or `directive update` to create it.",
|
|
478
|
+
data: { gitignore_path: gitignorePath, missing: [] },
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
const present = collectGitignorePresent(text);
|
|
482
|
+
const missing = [];
|
|
483
|
+
for (const line of CANONICAL_GITIGNORE_BASELINE) {
|
|
484
|
+
if (!gitignoreLineIsCovered(present, line)) {
|
|
485
|
+
missing.push(line);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
// Check .deft/core/ separately — only required for hybrid/greenfield installs.
|
|
489
|
+
// We conservatively omit it from the missing list here (tracked-deposit projects
|
|
490
|
+
// legitimately omit it). The update path handles this correctly per layout.
|
|
491
|
+
if (missing.length === 0) {
|
|
492
|
+
return {
|
|
493
|
+
name: "gitignore-coverage",
|
|
494
|
+
status: "pass",
|
|
495
|
+
detail: "All canonical Deft .gitignore entries are present.",
|
|
496
|
+
data: { gitignore_path: gitignorePath, missing: [] },
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
return {
|
|
500
|
+
name: "gitignore-coverage",
|
|
501
|
+
status: "fail",
|
|
502
|
+
detail: `Deft .gitignore coverage incomplete: ${missing.length} canonical entr${missing.length === 1 ? "y" : "ies"} ` +
|
|
503
|
+
`missing (${missing.slice(0, 3).join(", ")}${missing.length > 3 ? ", …" : ""}). ` +
|
|
504
|
+
"Run `directive update` to add the missing entries (idempotent, safe on re-run). " +
|
|
505
|
+
`Full missing list: ${JSON.stringify(missing)}.`,
|
|
506
|
+
data: {
|
|
507
|
+
gitignore_path: gitignorePath,
|
|
508
|
+
missing,
|
|
509
|
+
suggested_fix: "directive update",
|
|
510
|
+
},
|
|
511
|
+
};
|
|
512
|
+
}
|
|
439
513
|
export function deriveExitCode(checks, errors) {
|
|
440
|
-
const exitExempt = new Set([
|
|
514
|
+
const exitExempt = new Set([
|
|
515
|
+
"canonical-vendored-npm-signpost",
|
|
516
|
+
"manifest-version-reportable",
|
|
517
|
+
"gitignore-coverage",
|
|
518
|
+
]);
|
|
441
519
|
if (errors.length > 0 || checks.some((c) => c.status === "error")) {
|
|
442
520
|
return 2;
|
|
443
521
|
}
|
|
@@ -476,6 +554,7 @@ export function runChecksImpl(projectRoot, seams = {}) {
|
|
|
476
554
|
checks.push(checkManifestVersionReportable(projectRoot, null, seams));
|
|
477
555
|
checks.push(checkLegacyLayout(projectRoot, seams));
|
|
478
556
|
checks.push(checkCanonicalVendoredNpmSignpost(projectRoot, seams));
|
|
557
|
+
checks.push(checkGitignoreCoverage(projectRoot, seams));
|
|
479
558
|
return {
|
|
480
559
|
projectRoot,
|
|
481
560
|
installRoot: null,
|
|
@@ -491,6 +570,7 @@ export function runChecksImpl(projectRoot, seams = {}) {
|
|
|
491
570
|
checks.push(checkInstallPathConsistency(projectRoot, installRoot, seams));
|
|
492
571
|
checks.push(checkLegacyLayout(projectRoot, seams));
|
|
493
572
|
checks.push(checkCanonicalVendoredNpmSignpost(projectRoot, seams));
|
|
573
|
+
checks.push(checkGitignoreCoverage(projectRoot, seams));
|
|
494
574
|
return {
|
|
495
575
|
projectRoot,
|
|
496
576
|
installRoot,
|
package/dist/doctor/main.js
CHANGED
|
@@ -373,7 +373,8 @@ function runInstallIntegrityChecks(projectRoot, sink, addFinding, seams) {
|
|
|
373
373
|
}
|
|
374
374
|
if ((name === "legacy-layout" ||
|
|
375
375
|
name === "canonical-vendored-npm-signpost" ||
|
|
376
|
-
name === "manifest-version-reportable"
|
|
376
|
+
name === "manifest-version-reportable" ||
|
|
377
|
+
name === "gitignore-coverage") &&
|
|
377
378
|
status === "fail") {
|
|
378
379
|
sink.warn(`${name}: ${detail}`);
|
|
379
380
|
addFinding({
|
package/dist/eval/health.js
CHANGED
|
@@ -21,7 +21,13 @@ function isFrameworkSourceCheckout(projectRoot) {
|
|
|
21
21
|
return existsSync(manifest) && existsSync(cliPkg);
|
|
22
22
|
}
|
|
23
23
|
function loadPlan(projectRoot) {
|
|
24
|
-
|
|
24
|
+
let filepath;
|
|
25
|
+
try {
|
|
26
|
+
filepath = resolveProjectDefinitionPath(projectRoot);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null; // No xbrief/ layout; no project definition.
|
|
30
|
+
}
|
|
25
31
|
if (!existsSync(filepath)) {
|
|
26
32
|
return null;
|
|
27
33
|
}
|
package/dist/eval/readback.js
CHANGED
|
@@ -28,7 +28,13 @@ function parseJsonObjectOrNull(text) {
|
|
|
28
28
|
return null;
|
|
29
29
|
}
|
|
30
30
|
function readHealthHistoryRows(projectRoot) {
|
|
31
|
-
|
|
31
|
+
let path;
|
|
32
|
+
try {
|
|
33
|
+
path = healthHistoryPath(projectRoot);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return []; // No xbrief/ layout; no health history.
|
|
37
|
+
}
|
|
32
38
|
if (!existsSync(path)) {
|
|
33
39
|
return [];
|
|
34
40
|
}
|
|
@@ -44,7 +44,13 @@ export const CANONICAL_GITIGNORE_BASELINE = [
|
|
|
44
44
|
"vbrief/*.lock",
|
|
45
45
|
".deft/core.bak-*/",
|
|
46
46
|
".deft/*.bak-*",
|
|
47
|
+
// xBRIEF-era migration-backup directories created by `deft migrate:xbrief` (#2206).
|
|
48
|
+
".deft/xbrief-migrate-backup-*/",
|
|
47
49
|
"*.premigrate.*",
|
|
50
|
+
// Generated version-eval results live under `.eval/results/` (NOT triage-cache)
|
|
51
|
+
// for both the legacy `vbrief/` tree and the post-#2034 `xbrief/` tree (#2206).
|
|
52
|
+
"vbrief/.eval/results/",
|
|
53
|
+
"xbrief/.eval/results/",
|
|
48
54
|
];
|
|
49
55
|
const DEFT_FRAMEWORK_GITIGNORE_HEADER = "# Deft framework: ignore local-only caches and scratch directories\n";
|
|
50
56
|
const DEFT_CORE_GITIGNORE_RATIONALE = "# Hybrid deposit (#1942): reconstituted by `directive init` like node_modules.\n" +
|
|
@@ -37,6 +37,30 @@ export declare function stageFrameworkPaths(projectDir: string, paths: readonly
|
|
|
37
37
|
staged: boolean;
|
|
38
38
|
error: Error | null;
|
|
39
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Framework-internal subdirectories that are shipped as part of the source
|
|
42
|
+
* repository but are NOT included in the `@deftai/directive-content` npm
|
|
43
|
+
* package deposited into `.deft/core/`. If one of these paths survives from
|
|
44
|
+
* a prior git-vendored install, `deft update`'s additive file-swap will never
|
|
45
|
+
* remove it — causing the deposit-hygiene advisory to persist indefinitely.
|
|
46
|
+
*
|
|
47
|
+
* Each entry is a relative path within `.deft/core/`; presence in the CONTENT
|
|
48
|
+
* root overrides the prune (i.e. if the content package ever ships `packages/`
|
|
49
|
+
* again, we won't prune it).
|
|
50
|
+
*
|
|
51
|
+
* Refs #2347.
|
|
52
|
+
*/
|
|
53
|
+
export declare const STRAY_DEPOSIT_FRAMEWORK_PATHS: readonly ["packages"];
|
|
54
|
+
export interface PruneStrayDepositPathsResult {
|
|
55
|
+
readonly pruned: string[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Remove framework-source subdirectories from `.deft/core/` that are not
|
|
59
|
+
* present in the deposited content package (#2347). Silently skips any path
|
|
60
|
+
* that is also present in `contentRoot` (future-safe: if the content package
|
|
61
|
+
* ever ships `packages/` we stop pruning it).
|
|
62
|
+
*/
|
|
63
|
+
export declare function pruneStrayDepositPaths(deftDir: string, contentRoot: string, io: InitDepositIo): Promise<PruneStrayDepositPathsResult>;
|
|
40
64
|
export declare const COMMIT_HYGIENE_BRANCH_NAME = "chore/deft-framework-upgrade";
|
|
41
65
|
export declare function printCommitGuidance(io: InitDepositIo, paths: readonly string[], staged: boolean): void;
|
|
42
66
|
export interface DepositStagePathsOptions extends StageFrameworkPathsSeams, FrameworkStagePathsOptions {
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { execFileSync } from "node:child_process";
|
|
8
8
|
import { existsSync } from "node:fs";
|
|
9
|
+
import { rm, stat } from "node:fs/promises";
|
|
9
10
|
import { join, relative } from "node:path";
|
|
10
11
|
import { gitPorcelain } from "../story-ready/git.js";
|
|
11
12
|
import { CANONICAL_INSTALL_ROOT } from "./constants.js";
|
|
@@ -120,6 +121,60 @@ export function stageFrameworkPaths(projectDir, paths, seams = {}) {
|
|
|
120
121
|
return { staged: false, error };
|
|
121
122
|
}
|
|
122
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Framework-internal subdirectories that are shipped as part of the source
|
|
126
|
+
* repository but are NOT included in the `@deftai/directive-content` npm
|
|
127
|
+
* package deposited into `.deft/core/`. If one of these paths survives from
|
|
128
|
+
* a prior git-vendored install, `deft update`'s additive file-swap will never
|
|
129
|
+
* remove it — causing the deposit-hygiene advisory to persist indefinitely.
|
|
130
|
+
*
|
|
131
|
+
* Each entry is a relative path within `.deft/core/`; presence in the CONTENT
|
|
132
|
+
* root overrides the prune (i.e. if the content package ever ships `packages/`
|
|
133
|
+
* again, we won't prune it).
|
|
134
|
+
*
|
|
135
|
+
* Refs #2347.
|
|
136
|
+
*/
|
|
137
|
+
export const STRAY_DEPOSIT_FRAMEWORK_PATHS = ["packages"];
|
|
138
|
+
/**
|
|
139
|
+
* Remove framework-source subdirectories from `.deft/core/` that are not
|
|
140
|
+
* present in the deposited content package (#2347). Silently skips any path
|
|
141
|
+
* that is also present in `contentRoot` (future-safe: if the content package
|
|
142
|
+
* ever ships `packages/` we stop pruning it).
|
|
143
|
+
*/
|
|
144
|
+
export async function pruneStrayDepositPaths(deftDir, contentRoot, io) {
|
|
145
|
+
const pruned = [];
|
|
146
|
+
for (const rel of STRAY_DEPOSIT_FRAMEWORK_PATHS) {
|
|
147
|
+
const depositPath = join(deftDir, rel);
|
|
148
|
+
const contentPath = join(contentRoot, rel);
|
|
149
|
+
let isInDeposit = false;
|
|
150
|
+
let isInContent = false;
|
|
151
|
+
try {
|
|
152
|
+
isInDeposit = (await stat(depositPath)).isDirectory();
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// absent — nothing to prune
|
|
156
|
+
}
|
|
157
|
+
if (!isInDeposit)
|
|
158
|
+
continue;
|
|
159
|
+
try {
|
|
160
|
+
isInContent = (await stat(contentPath)).isDirectory();
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// not in content package — safe to prune
|
|
164
|
+
}
|
|
165
|
+
if (isInContent)
|
|
166
|
+
continue;
|
|
167
|
+
try {
|
|
168
|
+
await rm(depositPath, { recursive: true, force: true });
|
|
169
|
+
pruned.push(rel);
|
|
170
|
+
io.printf(`Pruned stray framework-source tree .deft/core/${rel}/ — not shipped by @deftai/directive-content (#2347).\n`);
|
|
171
|
+
}
|
|
172
|
+
catch (cause) {
|
|
173
|
+
io.printf(`Warning: could not prune .deft/core/${rel}/: ${String(cause)}\n`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return { pruned };
|
|
177
|
+
}
|
|
123
178
|
export const COMMIT_HYGIENE_BRANCH_NAME = "chore/deft-framework-upgrade";
|
|
124
179
|
export function printCommitGuidance(io, paths, staged) {
|
|
125
180
|
if (paths.length === 0)
|
|
@@ -20,8 +20,8 @@ import { resolveLifecycleRoot } from "../layout/resolve.js";
|
|
|
20
20
|
import { DEV_FALLBACK } from "../platform/constants.js";
|
|
21
21
|
import { checkLocalEngineIntegrity, classify, ENGINE_PACKAGE, plan, renderGlobalInstall, resolveEngine, } from "../resolution/index.js";
|
|
22
22
|
import { gitPorcelain } from "../story-ready/git.js";
|
|
23
|
-
import { ensureInitGitignoreLines } from "./gitignore.js";
|
|
24
|
-
import { depositStagePaths, isInstallerManagedPath, printCommitGuidance } from "./hygiene.js";
|
|
23
|
+
import { ensureInitGitignoreLines, isDepositTrackedInGit } from "./gitignore.js";
|
|
24
|
+
import { depositStagePaths, isInstallerManagedPath, printCommitGuidance, pruneStrayDepositPaths, } from "./hygiene.js";
|
|
25
25
|
import { parseInitArgv } from "./init-deposit.js";
|
|
26
26
|
import { buildLegacyRefusalJson, buildLegacyRefusalMessage, detectLegacyLayout, LEGACY_LAYOUT_REFUSED_EXIT_CODE, LegacyLayoutRefusedError, } from "./legacy-detect.js";
|
|
27
27
|
import { printMigrateNudgeIfNeeded } from "./migrate.js";
|
|
@@ -155,14 +155,20 @@ function syncBareVersionMarker(projectDir, version) {
|
|
|
155
155
|
const normalized = normalizeVersion(version);
|
|
156
156
|
if (!normalized || normalized === DEV_FALLBACK)
|
|
157
157
|
return;
|
|
158
|
-
|
|
158
|
+
let vbriefDir = null;
|
|
159
|
+
try {
|
|
160
|
+
vbriefDir = resolveLifecycleRoot(projectDir);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// No xbrief/ layout present — write the root-level derivative instead.
|
|
164
|
+
}
|
|
159
165
|
let targetDir = projectDir;
|
|
160
166
|
try {
|
|
161
|
-
if (statSync(vbriefDir).isDirectory())
|
|
167
|
+
if (vbriefDir !== null && statSync(vbriefDir).isDirectory())
|
|
162
168
|
targetDir = vbriefDir;
|
|
163
169
|
}
|
|
164
170
|
catch {
|
|
165
|
-
//
|
|
171
|
+
// xbrief/ absent — write the root-level derivative instead
|
|
166
172
|
}
|
|
167
173
|
try {
|
|
168
174
|
mkdirSync(targetDir, { recursive: true });
|
|
@@ -352,6 +358,10 @@ export async function runRefreshDeposit(args, io, seams = {}) {
|
|
|
352
358
|
const versionSkewNotice = buildVersionSkewNotice(engineVersion, contentVersion, previousDepositVersion);
|
|
353
359
|
await copyContent(contentRoot, deftDir);
|
|
354
360
|
await prunePythonArtifactsFromDeposit(deftDir, projectDir, io);
|
|
361
|
+
// #2347: prune framework-source paths that the content package does not ship.
|
|
362
|
+
// The additive file-swap never removes them, causing the deposit-hygiene
|
|
363
|
+
// advisory to persist across every upgrade until manually cleaned.
|
|
364
|
+
await pruneStrayDepositPaths(deftDir, contentRoot, io);
|
|
355
365
|
const nowIso = seams.nowIso ?? (() => new Date().toISOString().replace(/\.\d{3}Z$/, "Z"));
|
|
356
366
|
const manifestFields = {
|
|
357
367
|
ref: contentVersion.startsWith("v") ? contentVersion : `v${contentVersion}`,
|
|
@@ -372,7 +382,13 @@ export async function runRefreshDeposit(args, io, seams = {}) {
|
|
|
372
382
|
// fails and the operator must hand-edit the marker).
|
|
373
383
|
syncBareVersionMarker(projectDir, contentVersion);
|
|
374
384
|
const agentsMdUpdated = writeAgentsMd(projectDir, deftDir, io);
|
|
375
|
-
|
|
385
|
+
// #2148: the deft-core-guard CI workflow is only meaningful when the deposit
|
|
386
|
+
// is git-tracked (committed vendor layout). On an npm-managed (gitignored)
|
|
387
|
+
// deposit it creates untracked noise after every `directive update`. Probe
|
|
388
|
+
// git-tracked status once and share the result with the gitignore upkeep below.
|
|
389
|
+
const depositTracked = isDepositTrackedInGit(projectDir, seams.gitLsFiles);
|
|
390
|
+
const skipGuardWorkflow = depositTracked !== true;
|
|
391
|
+
await depositNeutralization(projectDir, io, { skipGuardWorkflow });
|
|
376
392
|
// #2266: non-destructive `.gitignore` upkeep for framework-owned paths. This
|
|
377
393
|
// NEVER un-tracks a committed deposit -- `ensureInitGitignoreLines` only writes
|
|
378
394
|
// `.gitignore` and leaves an already-tracked `.deft/core` tracked. The
|
|
@@ -67,6 +67,16 @@ export declare function ensureCodeqlPathsIgnore(projectDir: string, io: InitDepo
|
|
|
67
67
|
export declare function ensureCoreGuardWorkflow(projectDir: string, io: InitDepositIo): boolean;
|
|
68
68
|
export declare function pruneFrameworkSelfTests(projectDir: string, io: InitDepositIo): Promise<boolean>;
|
|
69
69
|
export declare function pruneVendoredTsTests(projectDir: string, io: InitDepositIo): Promise<number>;
|
|
70
|
+
export interface DepositNeutralizationOptions {
|
|
71
|
+
/**
|
|
72
|
+
* #2148: skip depositing `.github/workflows/deft-core-guard.yml` when the
|
|
73
|
+
* framework deposit is not git-tracked (npm-managed / gitignored layout). The
|
|
74
|
+
* guard CI check is meaningless when there is no committed `.deft/core/**` to
|
|
75
|
+
* guard; skipping it prevents the file from re-appearing as untracked noise
|
|
76
|
+
* after every `directive update`.
|
|
77
|
+
*/
|
|
78
|
+
readonly skipGuardWorkflow?: boolean;
|
|
79
|
+
}
|
|
70
80
|
/** Best-effort #1430 neutralization deposit (mirrors depositNeutralization). */
|
|
71
|
-
export declare function depositNeutralization(projectDir: string, io: InitDepositIo): Promise<void>;
|
|
81
|
+
export declare function depositNeutralization(projectDir: string, io: InitDepositIo, options?: DepositNeutralizationOptions): Promise<void>;
|
|
72
82
|
//# sourceMappingURL=scaffold.d.ts.map
|
|
@@ -10,8 +10,8 @@ import { mkdir, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
|
10
10
|
import { platform } from "node:os";
|
|
11
11
|
import { dirname, join, relative } from "node:path";
|
|
12
12
|
import { copyTree } from "../deposit/copy-tree.js";
|
|
13
|
-
import { resolveLifecycleRoot } from "../layout/resolve.js";
|
|
14
13
|
import { agentsRefreshPlan } from "../platform/agents-md.js";
|
|
14
|
+
import { MIGRATED_ARTIFACT_DIR } from "../xbrief-migrate/constants.js";
|
|
15
15
|
import { CANONICAL_INSTALL_ROOT } from "./constants.js";
|
|
16
16
|
import { installerManagedGuardEre } from "./hygiene.js";
|
|
17
17
|
export { CANONICAL_INSTALL_ROOT };
|
|
@@ -322,7 +322,7 @@ function vbriefLifecycleDirsPresent(consumerVbrief) {
|
|
|
322
322
|
});
|
|
323
323
|
}
|
|
324
324
|
export async function writeConsumerVbrief(projectDir, deftDir, io) {
|
|
325
|
-
const consumerVbrief =
|
|
325
|
+
const consumerVbrief = join(projectDir, MIGRATED_ARTIFACT_DIR);
|
|
326
326
|
const schemasDst = join(consumerVbrief, "schemas");
|
|
327
327
|
const vbriefMdDst = join(consumerVbrief, "vbrief.md");
|
|
328
328
|
const schemasPresent = existsSync(schemasDst) && statSync(schemasDst).isDirectory();
|
|
@@ -774,12 +774,12 @@ export async function pruneVendoredTsTests(projectDir, io) {
|
|
|
774
774
|
return removed;
|
|
775
775
|
}
|
|
776
776
|
/** Best-effort #1430 neutralization deposit (mirrors depositNeutralization). */
|
|
777
|
-
export async function depositNeutralization(projectDir, io) {
|
|
777
|
+
export async function depositNeutralization(projectDir, io, options = {}) {
|
|
778
778
|
const steps = [
|
|
779
779
|
() => ensureGitattributes(projectDir, io),
|
|
780
780
|
() => ensureGreptileIgnore(projectDir, io),
|
|
781
781
|
() => ensureCodeqlPathsIgnore(projectDir, io),
|
|
782
|
-
() => ensureCoreGuardWorkflow(projectDir, io),
|
|
782
|
+
...(options.skipGuardWorkflow ? [] : [() => ensureCoreGuardWorkflow(projectDir, io)]),
|
|
783
783
|
() => pruneFrameworkSelfTests(projectDir, io),
|
|
784
784
|
async () => (await pruneVendoredTsTests(projectDir, io)) > 0,
|
|
785
785
|
];
|
|
@@ -77,12 +77,12 @@ export function populateCacheLayout(cacheRoot, repo, issueNumbers) {
|
|
|
77
77
|
}
|
|
78
78
|
export function createConsumerProject(parent) {
|
|
79
79
|
const root = join(parent, "consumer");
|
|
80
|
-
mkdirSync(join(root, "
|
|
81
|
-
mkdirSync(join(root, "
|
|
82
|
-
mkdirSync(join(root, "
|
|
83
|
-
mkdirSync(join(root, "
|
|
84
|
-
mkdirSync(join(root, "
|
|
85
|
-
writeFileSync(join(root, "
|
|
80
|
+
mkdirSync(join(root, "xbrief", "proposed"), { recursive: true });
|
|
81
|
+
mkdirSync(join(root, "xbrief", "pending"), { recursive: true });
|
|
82
|
+
mkdirSync(join(root, "xbrief", "active"), { recursive: true });
|
|
83
|
+
mkdirSync(join(root, "xbrief", "completed"), { recursive: true });
|
|
84
|
+
mkdirSync(join(root, "xbrief", "cancelled"), { recursive: true });
|
|
85
|
+
writeFileSync(join(root, "xbrief", "specification.xbrief.json"), `${JSON.stringify({
|
|
86
86
|
vBRIEFInfo: { version: "0.5" },
|
|
87
87
|
plan: {
|
|
88
88
|
title: "Consumer Project",
|
|
@@ -96,7 +96,7 @@ export function createConsumerProject(parent) {
|
|
|
96
96
|
return root;
|
|
97
97
|
}
|
|
98
98
|
export function writeScopeVbrief(projectRoot, folder, filename, status = "proposed") {
|
|
99
|
-
const target = join(projectRoot, "
|
|
99
|
+
const target = join(projectRoot, "xbrief", folder, filename);
|
|
100
100
|
writeFileSync(target, `${JSON.stringify({
|
|
101
101
|
vBRIEFInfo: { version: "0.5" },
|
|
102
102
|
plan: {
|
package/dist/layout/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { ARTIFACT_SUFFIXES, hasArtifactSuffix, isLifecycleArtifactPath,
|
|
1
|
+
export { ARTIFACT_SUFFIXES, hasArtifactSuffix, isLifecycleArtifactPath, 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
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/layout/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { ARTIFACT_SUFFIXES, hasArtifactSuffix, isLifecycleArtifactPath,
|
|
1
|
+
export { ARTIFACT_SUFFIXES, hasArtifactSuffix, isLifecycleArtifactPath, 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
2
|
//# sourceMappingURL=index.js.map
|
package/dist/layout/resolve.d.ts
CHANGED
|
@@ -1,28 +1,39 @@
|
|
|
1
|
-
import { LEGACY_ARTIFACT_DIR,
|
|
2
|
-
export { LEGACY_ARTIFACT_DIR,
|
|
1
|
+
import { LEGACY_ARTIFACT_DIR, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY } from "../xbrief-migrate/constants.js";
|
|
2
|
+
export { LEGACY_ARTIFACT_DIR, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY, };
|
|
3
3
|
/**
|
|
4
|
-
* Lifecycle directory names recognized by the layout-aware resolver
|
|
5
|
-
*
|
|
4
|
+
* Lifecycle directory names recognized by the layout-aware resolver and path
|
|
5
|
+
* validators. Includes both `xbrief` (canonical) and `vbrief` (legacy) so that
|
|
6
|
+
* path-validation helpers remain accurate during and after migration.
|
|
6
7
|
*/
|
|
7
8
|
export declare const LIFECYCLE_DIR_NAMES: readonly ["xbrief", "vbrief"];
|
|
8
9
|
/**
|
|
9
|
-
* Artifact filename suffixes recognized by the layout-aware resolver
|
|
10
|
-
*
|
|
10
|
+
* Artifact filename suffixes recognized by the layout-aware resolver and path
|
|
11
|
+
* validators. Includes both `.xbrief.json` (canonical) and `.vbrief.json`
|
|
12
|
+
* (legacy) so that path-validation helpers remain accurate during and after
|
|
13
|
+
* migration.
|
|
11
14
|
*/
|
|
12
15
|
export declare const ARTIFACT_SUFFIXES: readonly [".xbrief.json", ".vbrief.json"];
|
|
13
|
-
/** The on-disk lifecycle layout an engine call site should resolve against (#2109). */
|
|
16
|
+
/** The on-disk lifecycle layout an engine call site should resolve against (#2109 / #2112). */
|
|
14
17
|
export interface LifecycleLayout {
|
|
15
|
-
/** The lifecycle directory name -- `xbrief`
|
|
16
|
-
readonly artifactDir: typeof MIGRATED_ARTIFACT_DIR
|
|
17
|
-
/** The artifact filename suffix
|
|
18
|
-
readonly artifactSuffix: typeof MIGRATED_ARTIFACT_SUFFIX
|
|
19
|
-
/** The
|
|
20
|
-
readonly infoRootKey: typeof MIGRATED_INFO_ROOT_KEY
|
|
21
|
-
/** Absolute path to the resolved lifecycle root (`<projectRoot
|
|
18
|
+
/** The lifecycle directory name -- always `xbrief` after the vbrief read path removal (#2112). */
|
|
19
|
+
readonly artifactDir: typeof MIGRATED_ARTIFACT_DIR;
|
|
20
|
+
/** The artifact filename suffix -- always `.xbrief.json` after #2112. */
|
|
21
|
+
readonly artifactSuffix: typeof MIGRATED_ARTIFACT_SUFFIX;
|
|
22
|
+
/** The `xBRIEFInfo` root key. */
|
|
23
|
+
readonly infoRootKey: typeof MIGRATED_INFO_ROOT_KEY;
|
|
24
|
+
/** Absolute path to the resolved lifecycle root (`<projectRoot>/xbrief`). */
|
|
22
25
|
readonly root: string;
|
|
23
|
-
/**
|
|
24
|
-
readonly migrated:
|
|
26
|
+
/** Always `true` -- the legacy vbrief read path was removed in #2112. */
|
|
27
|
+
readonly migrated: true;
|
|
25
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Returns the layout root for non-layout-sensitive helpers (#2112).
|
|
31
|
+
*
|
|
32
|
+
* - If a valid `xbrief/` layout exists, returns its root.
|
|
33
|
+
* - If only `vbrief/` exists (legacy-only), throws so the caller surfaces the migrate hint.
|
|
34
|
+
* - If neither exists (empty/new project), falls back to `<projectRoot>/xbrief/` canonical path.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveLayoutRootOrCanonical(projectRoot: string): string;
|
|
26
37
|
/** True when `name` ends with any recognized artifact suffix (.xbrief.json or .vbrief.json). */
|
|
27
38
|
export declare function hasArtifactSuffix(name: string): boolean;
|
|
28
39
|
/**
|
|
@@ -31,24 +42,30 @@ export declare function hasArtifactSuffix(name: string): boolean;
|
|
|
31
42
|
*/
|
|
32
43
|
export declare function stripArtifactSuffix(name: string): string;
|
|
33
44
|
/**
|
|
34
|
-
* True when a POSIX-style path is a lifecycle artifact
|
|
35
|
-
*
|
|
45
|
+
* True when a POSIX-style path is a lifecycle artifact path carrying a
|
|
46
|
+
* recognized lifecycle directory prefix (`xbrief/` or `vbrief/`) and a
|
|
47
|
+
* recognized artifact suffix. The `vbrief/` prefix and `.vbrief.json` suffix
|
|
48
|
+
* remain recognized for path-validation purposes during and after migration.
|
|
36
49
|
*/
|
|
37
50
|
export declare function isLifecycleArtifactPath(posix: string): boolean;
|
|
38
51
|
/**
|
|
39
|
-
* Resolve the active lifecycle layout for `projectRoot` (#2109 part 1).
|
|
52
|
+
* Resolve the active lifecycle layout for `projectRoot` (#2109 part 1 / #2112).
|
|
53
|
+
*
|
|
54
|
+
* Requires the migrated `xbrief/` layout: the `xbrief/` directory must exist
|
|
55
|
+
* AND contain at least one `.xbrief.json` artifact. If no such layout is found,
|
|
56
|
+
* throws with a clear error directing the operator to run `deft migrate:xbrief`.
|
|
57
|
+
*
|
|
58
|
+
* The legacy `vbrief/` read-path fallback was removed in #2112 (0.73.0 MINOR).
|
|
59
|
+
* Projects that have not migrated must run `deft migrate:xbrief` first.
|
|
40
60
|
*
|
|
41
|
-
*
|
|
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.
|
|
61
|
+
* @throws {Error} When no `xbrief/` layout with `.xbrief.json` artifacts exists.
|
|
45
62
|
*/
|
|
46
63
|
export declare function resolveLifecycleLayout(projectRoot: string): LifecycleLayout;
|
|
47
64
|
/** Convenience accessor for the absolute resolved lifecycle root directory. */
|
|
48
65
|
export declare function resolveLifecycleRoot(projectRoot: string): string;
|
|
49
66
|
/**
|
|
50
|
-
* Absolute path to a lifecycle folder under the resolved layout root
|
|
51
|
-
* (e.g. `<root
|
|
67
|
+
* Absolute path to a lifecycle folder under the resolved `xbrief/` layout root
|
|
68
|
+
* (e.g. `<root>/xbrief/active`). Layout-aware (#2109 part 2a / #2112).
|
|
52
69
|
*/
|
|
53
70
|
export declare function resolveLifecycleFolder(projectRoot: string, folder: string): string;
|
|
54
71
|
/** Absolute path to the layout-aware `.eval/` directory for version-eval results (#1703). */
|
|
@@ -68,20 +85,19 @@ export declare function projectDefinitionFilename(projectRoot: string): string;
|
|
|
68
85
|
export declare function resolveProjectDefinitionPath(projectRoot: string): string;
|
|
69
86
|
/**
|
|
70
87
|
* POSIX-style display path to the resolved PROJECT-DEFINITION artifact relative
|
|
71
|
-
* to the project root (e.g. `
|
|
88
|
+
* to the project root (e.g. `xbrief/PROJECT-DEFINITION.xbrief.json`).
|
|
72
89
|
*/
|
|
73
90
|
export declare function projectDefinitionRelPath(projectRoot: string): string;
|
|
74
91
|
/**
|
|
75
|
-
* Absolute path to the resolved specification artifact (#2132).
|
|
92
|
+
* Absolute path to the resolved specification artifact (#2132 / #2112).
|
|
76
93
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* layout resolver used by the #2109 Part-2a call-site sweep.
|
|
94
|
+
* Returns `xbrief/specification.xbrief.json`; throws when no migrated xbrief/
|
|
95
|
+
* layout is present (see `resolveLifecycleLayout`).
|
|
80
96
|
*/
|
|
81
97
|
export declare function resolveSpecArtifactPath(projectRoot: string): string;
|
|
82
98
|
/**
|
|
83
99
|
* POSIX-style display path to the resolved specification artifact relative to
|
|
84
|
-
* the project root (
|
|
100
|
+
* the project root (`xbrief/specification.xbrief.json`).
|
|
85
101
|
*/
|
|
86
102
|
export declare function specArtifactRelPath(projectRoot: string): string;
|
|
87
103
|
//# sourceMappingURL=resolve.d.ts.map
|