@deftai/directive-core 0.71.1 → 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/events/attribution-enrichment.d.ts +35 -0
- package/dist/events/attribution-enrichment.js +74 -0
- package/dist/events/attribution-ledger.js +6 -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/index.js +3 -3
- package/dist/policy/resolve.d.ts +2 -2
- package/dist/policy/resolve.js +11 -3
- package/dist/policy/value-feedback-autoenable.d.ts +33 -0
- package/dist/policy/value-feedback-autoenable.js +67 -0
- package/dist/policy/value-feedback.d.ts +30 -5
- package/dist/policy/value-feedback.js +52 -34
- 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
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Record-shape version for attribution ledger entries (#2376). Bump on shape changes. */
|
|
2
|
+
export declare const ATTRIBUTION_SCHEMA_VERSION: 1;
|
|
3
|
+
/** Project-local, gitignored install-identity file. */
|
|
4
|
+
export declare const INSTALL_ID_REL: string;
|
|
5
|
+
/** Identity + provenance fields stamped onto every attribution record (#2376). */
|
|
6
|
+
export interface AttributionEnrichment {
|
|
7
|
+
/** Normalized `owner/name` of the origin remote, or null when unavailable. */
|
|
8
|
+
readonly repo: string | null;
|
|
9
|
+
/** directive engine version at emit time. */
|
|
10
|
+
readonly directive_version: string;
|
|
11
|
+
/** Stable per-checkout uuid, or null when it cannot be read/created. */
|
|
12
|
+
readonly install_id: string | null;
|
|
13
|
+
/** Attribution record-shape version. */
|
|
14
|
+
readonly schema_version: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Read-or-create a stable per-checkout install id in `.deft-cache/install-id`.
|
|
18
|
+
* Best-effort: returns null (never throws) if the file cannot be read or written.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveInstallId(projectRoot: string): string | null;
|
|
21
|
+
export interface BuildAttributionEnrichmentOptions {
|
|
22
|
+
/** Test seam for origin-repo resolution; defaults to `inferRepoFromGit`. */
|
|
23
|
+
readonly repoResolver?: (projectRoot: string) => string | null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Build the identity/provenance enrichment stamped on attribution records (#2376).
|
|
27
|
+
*
|
|
28
|
+
* Memoized per `projectRoot` (identity/version/repo are stable within a session)
|
|
29
|
+
* so a caller that emits many signals in one run does not spawn a git process and
|
|
30
|
+
* open the install-id file per event -- mirrors `detectOriginOrg`'s cache to keep
|
|
31
|
+
* this off the hot emit path (#2377 review). A custom `repoResolver` bypasses the
|
|
32
|
+
* cache so tests stay deterministic. Every field degrades gracefully; never throws.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildAttributionEnrichment(projectRoot: string, options?: BuildAttributionEnrichmentOptions): AttributionEnrichment;
|
|
35
|
+
//# sourceMappingURL=attribution-enrichment.d.ts.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { readCorePackageVersion } from "../engine-version.js";
|
|
5
|
+
import { inferRepoFromGit } from "../triage/queue/repo.js";
|
|
6
|
+
/** Record-shape version for attribution ledger entries (#2376). Bump on shape changes. */
|
|
7
|
+
export const ATTRIBUTION_SCHEMA_VERSION = 1;
|
|
8
|
+
/** Project-local, gitignored install-identity file. */
|
|
9
|
+
export const INSTALL_ID_REL = join(".deft-cache", "install-id");
|
|
10
|
+
/**
|
|
11
|
+
* Read-or-create a stable per-checkout install id in `.deft-cache/install-id`.
|
|
12
|
+
* Best-effort: returns null (never throws) if the file cannot be read or written.
|
|
13
|
+
*/
|
|
14
|
+
export function resolveInstallId(projectRoot) {
|
|
15
|
+
const path = resolve(projectRoot, INSTALL_ID_REL);
|
|
16
|
+
try {
|
|
17
|
+
if (existsSync(path)) {
|
|
18
|
+
const existing = readFileSync(path, "utf8").trim();
|
|
19
|
+
if (existing.length > 0) {
|
|
20
|
+
return existing;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// fall through and try to (re)create
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const id = randomUUID();
|
|
29
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
30
|
+
writeFileSync(path, `${id}\n`, "utf8");
|
|
31
|
+
return id;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const enrichmentCache = new Map();
|
|
38
|
+
/**
|
|
39
|
+
* Build the identity/provenance enrichment stamped on attribution records (#2376).
|
|
40
|
+
*
|
|
41
|
+
* Memoized per `projectRoot` (identity/version/repo are stable within a session)
|
|
42
|
+
* so a caller that emits many signals in one run does not spawn a git process and
|
|
43
|
+
* open the install-id file per event -- mirrors `detectOriginOrg`'s cache to keep
|
|
44
|
+
* this off the hot emit path (#2377 review). A custom `repoResolver` bypasses the
|
|
45
|
+
* cache so tests stay deterministic. Every field degrades gracefully; never throws.
|
|
46
|
+
*/
|
|
47
|
+
export function buildAttributionEnrichment(projectRoot, options = {}) {
|
|
48
|
+
const useCache = options.repoResolver === undefined;
|
|
49
|
+
if (useCache) {
|
|
50
|
+
const cached = enrichmentCache.get(projectRoot);
|
|
51
|
+
if (cached !== undefined) {
|
|
52
|
+
return cached;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const resolver = options.repoResolver ?? inferRepoFromGit;
|
|
56
|
+
let repo = null;
|
|
57
|
+
try {
|
|
58
|
+
repo = resolver(projectRoot);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
repo = null;
|
|
62
|
+
}
|
|
63
|
+
const enrichment = {
|
|
64
|
+
repo,
|
|
65
|
+
directive_version: readCorePackageVersion(),
|
|
66
|
+
install_id: resolveInstallId(projectRoot),
|
|
67
|
+
schema_version: ATTRIBUTION_SCHEMA_VERSION,
|
|
68
|
+
};
|
|
69
|
+
if (useCache) {
|
|
70
|
+
enrichmentCache.set(projectRoot, enrichment);
|
|
71
|
+
}
|
|
72
|
+
return enrichment;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=attribution-enrichment.js.map
|
|
@@ -2,6 +2,7 @@ import { resolve } from "node:path";
|
|
|
2
2
|
import { DEFAULT_EVENT_LOG, emit } from "../lifecycle/events.js";
|
|
3
3
|
import { isValueFeedbackPathAllowed, resolveValueFeedback, } from "../policy/value-feedback.js";
|
|
4
4
|
import { ATTRIBUTION_EVENT_NAMES } from "./attribution-constants.js";
|
|
5
|
+
import { buildAttributionEnrichment } from "./attribution-enrichment.js";
|
|
5
6
|
export { ALL_ATTRIBUTION_EVENT_NAMES, ATTRIBUTION_EVENT_NAMES, ATTRIBUTION_REQUIRED_PAYLOAD, } from "./attribution-constants.js";
|
|
6
7
|
function resolveLedgerLogPath(projectRoot, logPath) {
|
|
7
8
|
if (logPath !== undefined && logPath !== null) {
|
|
@@ -28,9 +29,13 @@ export function emitAttributionSignal(name, payload, options) {
|
|
|
28
29
|
}
|
|
29
30
|
const signalClass = signalClassForEvent(name);
|
|
30
31
|
const logPath = resolveLedgerLogPath(options.projectRoot, options.logPath);
|
|
32
|
+
const enrichment = buildAttributionEnrichment(options.projectRoot);
|
|
33
|
+
// Authoritative fields (signal_class + provenance enrichment) are spread LAST
|
|
34
|
+
// so a caller payload can never silently shadow them (#2377 review).
|
|
31
35
|
return emit(name, {
|
|
32
|
-
signal_class: signalClass,
|
|
33
36
|
...payload,
|
|
37
|
+
signal_class: signalClass,
|
|
38
|
+
...enrichment,
|
|
34
39
|
}, { logPath });
|
|
35
40
|
}
|
|
36
41
|
catch {
|
|
@@ -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
|