@deftai/directive-core 0.65.0 → 0.66.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +1 -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.d.ts +24 -0
- package/dist/intake/issue-ingest.js +113 -16
- package/dist/intake/reconcile-issues.js +11 -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 +8 -5
- 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/cache.js +3 -2
- package/dist/triage/queue/ranking-labels.js +2 -1
- package/dist/triage/queue/scope-walk.js +8 -6
- 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 +13 -7
- package/dist/triage/summary/index.js +7 -5
- package/dist/triage/summary/reconcilable.js +6 -4
- package/dist/triage/summary/scope-drift.js +2 -1
- package/dist/triage/welcome/prior-state.js +9 -9
- package/dist/triage/welcome/summary.js +9 -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 +7 -3
- package/dist/verify-source/contract-drift.js +40 -22
- 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
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { spawnSync } from "node:child_process";
|
|
16
16
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
17
17
|
import { basename, extname, join, resolve } from "node:path";
|
|
18
|
+
import { hasArtifactSuffix, LIFECYCLE_DIR_NAMES } from "../layout/resolve.js";
|
|
18
19
|
// ---------------------------------------------------------------------------
|
|
19
20
|
// Classification constants
|
|
20
21
|
// ---------------------------------------------------------------------------
|
|
@@ -699,11 +700,12 @@ export function scanDiff(diffText) {
|
|
|
699
700
|
function changedStoryRecords(projectRoot, changedPaths) {
|
|
700
701
|
const records = [];
|
|
701
702
|
for (const rel of changedPaths) {
|
|
702
|
-
if (!rel
|
|
703
|
+
if (!hasArtifactSuffix(rel))
|
|
703
704
|
continue;
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
705
|
+
const inStoryFolder = LIFECYCLE_DIR_NAMES.some((dir) => rel.startsWith(`${dir}/active/`) ||
|
|
706
|
+
rel.startsWith(`${dir}/pending/`) ||
|
|
707
|
+
rel.startsWith(`${dir}/proposed/`));
|
|
708
|
+
if (!inStoryFolder)
|
|
707
709
|
continue;
|
|
708
710
|
const path = join(resolve(projectRoot), rel);
|
|
709
711
|
const [payload, error] = loadJsonFile(path);
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
2
|
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
|
+
import { referenceTypeMatches } from "@deftai/directive-types";
|
|
4
5
|
import { sortedStringifyCompact } from "../codebase/json.js";
|
|
6
|
+
import { hasArtifactSuffix, resolveLifecycleFolder } from "../layout/resolve.js";
|
|
5
7
|
import { classifyBucket, loadBucketMatchers, resolveCapacityAllocation, SOURCE_MATCH, } from "../policy/capacity.js";
|
|
6
8
|
export const COMPLETED_FOLDER = "completed";
|
|
7
9
|
export const CACHE_RELPATH = [".deft-cache", "github-issue"];
|
|
@@ -32,7 +34,7 @@ export function extractIssueRef(plan) {
|
|
|
32
34
|
continue;
|
|
33
35
|
}
|
|
34
36
|
const rec = ref;
|
|
35
|
-
if (rec.type
|
|
37
|
+
if (!referenceTypeMatches(String(rec.type ?? ""), "github-issue")) {
|
|
36
38
|
continue;
|
|
37
39
|
}
|
|
38
40
|
const uri = rec.uri;
|
|
@@ -186,14 +188,14 @@ export async function backfill(projectRoot, options = {}) {
|
|
|
186
188
|
result.exit_code = 2;
|
|
187
189
|
return result;
|
|
188
190
|
}
|
|
189
|
-
const completedDir =
|
|
191
|
+
const completedDir = resolveLifecycleFolder(projectRoot, COMPLETED_FOLDER);
|
|
190
192
|
if (!existsSync(completedDir)) {
|
|
191
193
|
return result;
|
|
192
194
|
}
|
|
193
195
|
let paths;
|
|
194
196
|
try {
|
|
195
197
|
paths = readdirSync(completedDir)
|
|
196
|
-
.filter((name) => name
|
|
198
|
+
.filter((name) => hasArtifactSuffix(name))
|
|
197
199
|
.sort();
|
|
198
200
|
}
|
|
199
201
|
catch {
|
package/dist/capacity/show.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
|
+
import { referenceTypeMatches } from "@deftai/directive-types";
|
|
4
|
+
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
3
5
|
import { recommendAutonomyLevel, resolveAutonomy } from "../policy/autonomy.js";
|
|
4
6
|
import { CAPACITY_UNIT_COST, DEFAULT_CAPACITY_UNIT, resolveCapacityAllocation, } from "../policy/capacity.js";
|
|
5
7
|
import { DEFAULT_PENDING_DECISIONS_THRESHOLD, pendingDecisionsNudgeLine, summarizeDecisionBacklog, } from "../policy/decisions.js";
|
|
@@ -25,7 +27,7 @@ function planHasChildren(plan) {
|
|
|
25
27
|
}
|
|
26
28
|
return refs.some((ref) => typeof ref === "object" &&
|
|
27
29
|
ref !== null &&
|
|
28
|
-
ref.type
|
|
30
|
+
referenceTypeMatches(String(ref.type ?? ""), "plan"));
|
|
29
31
|
}
|
|
30
32
|
function coerceCost(value) {
|
|
31
33
|
if (typeof value === "boolean") {
|
|
@@ -109,7 +111,7 @@ export function iterVbriefPlans(vbriefRoot) {
|
|
|
109
111
|
continue;
|
|
110
112
|
}
|
|
111
113
|
for (const name of names.sort()) {
|
|
112
|
-
if (!name
|
|
114
|
+
if (!hasArtifactSuffix(name)) {
|
|
113
115
|
continue;
|
|
114
116
|
}
|
|
115
117
|
const child = join(folderPath, name);
|
|
@@ -158,7 +160,7 @@ function resolveEffectiveUnit(unitRequested, costEligible, costWithActual) {
|
|
|
158
160
|
export function computeReport(projectRoot, options = {}) {
|
|
159
161
|
const now = options.now ?? new Date();
|
|
160
162
|
const allocation = options.allocation ?? resolveCapacityAllocation(projectRoot);
|
|
161
|
-
const vbriefRoot =
|
|
163
|
+
const vbriefRoot = resolveLifecycleRoot(projectRoot);
|
|
162
164
|
const records = iterVbriefPlans(vbriefRoot).map(([folder, plan]) => classifyRecord(plan, folder, allocation, now));
|
|
163
165
|
const tallies = new Map();
|
|
164
166
|
for (const bucket of allocation.buckets) {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
type JsonObject = Record<string, unknown>;
|
|
2
|
+
export interface CategoryBKeyRename {
|
|
3
|
+
readonly legacyKey: string;
|
|
4
|
+
readonly namespacedKey: string;
|
|
5
|
+
}
|
|
6
|
+
/** The locked Category B renames (#1650): directive's own config, not xbrief data. */
|
|
7
|
+
export declare const CATEGORY_B_KEY_RENAMES: readonly CategoryBKeyRename[];
|
|
8
|
+
/** Raised when both the bare and namespaced form of a Category B key exist. */
|
|
9
|
+
export declare class CategoryBConflictError extends Error {
|
|
10
|
+
constructor(legacyKey: string, namespacedKey: string);
|
|
11
|
+
}
|
|
12
|
+
export interface NamespaceResult {
|
|
13
|
+
readonly doc: JsonObject;
|
|
14
|
+
readonly changed: boolean;
|
|
15
|
+
readonly renamedKeys: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Idempotently rename Category B bare plan keys to their namespaced form.
|
|
19
|
+
* Mutates and returns the supplied document. Throws {@link CategoryBConflictError}
|
|
20
|
+
* when a plan carries both the bare and namespaced form of the same key.
|
|
21
|
+
*/
|
|
22
|
+
export declare function namespaceCategoryBPlan(doc: unknown): NamespaceResult;
|
|
23
|
+
export interface CorpusMigrationConflict {
|
|
24
|
+
readonly path: string;
|
|
25
|
+
readonly message: string;
|
|
26
|
+
}
|
|
27
|
+
export interface CorpusMigrationResult {
|
|
28
|
+
readonly scanned: number;
|
|
29
|
+
readonly changed: readonly string[];
|
|
30
|
+
readonly conflicts: readonly CorpusMigrationConflict[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Walk `vbrief/**\/*.vbrief.json` under projectRoot and namespace every
|
|
34
|
+
* Category B key in place. Idempotent: a second run reports zero changes.
|
|
35
|
+
* Files with a bare/namespaced conflict are reported, not rewritten.
|
|
36
|
+
*/
|
|
37
|
+
export declare function migrateCategoryBCorpus(projectRoot: string): CorpusMigrationResult;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Category B corpus codemod (#1650 / #2034).
|
|
3
|
+
*
|
|
4
|
+
* Renames the two grandfathered bare directive-config plan keys (`policy`,
|
|
5
|
+
* `completedNote`) to their `x-directive/` namespaced form across the vBRIEF
|
|
6
|
+
* corpus so the #1620 conformance gate can drop its temporary ALLOW_LIST.
|
|
7
|
+
*
|
|
8
|
+
* The transform is idempotent (already-namespaced artifacts are unchanged) and
|
|
9
|
+
* order-preserving (the namespaced key takes the legacy key's slot, keeping
|
|
10
|
+
* artifact diffs minimal).
|
|
11
|
+
*/
|
|
12
|
+
import { readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { join, relative, resolve } from "node:path";
|
|
14
|
+
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
15
|
+
import { LEGACY_PLAN_COMPLETED_NOTE_KEY, LEGACY_PLAN_POLICY_KEY, PLAN_COMPLETED_NOTE_KEY, PLAN_POLICY_KEY, } from "../policy/plan-extensions.js";
|
|
16
|
+
/** The locked Category B renames (#1650): directive's own config, not xbrief data. */
|
|
17
|
+
export const CATEGORY_B_KEY_RENAMES = [
|
|
18
|
+
{ legacyKey: LEGACY_PLAN_POLICY_KEY, namespacedKey: PLAN_POLICY_KEY },
|
|
19
|
+
{ legacyKey: LEGACY_PLAN_COMPLETED_NOTE_KEY, namespacedKey: PLAN_COMPLETED_NOTE_KEY },
|
|
20
|
+
];
|
|
21
|
+
/** Raised when both the bare and namespaced form of a Category B key exist. */
|
|
22
|
+
export class CategoryBConflictError extends Error {
|
|
23
|
+
constructor(legacyKey, namespacedKey) {
|
|
24
|
+
super(`plan has both bare '${legacyKey}' and namespaced '${namespacedKey}' -- ` +
|
|
25
|
+
"resolve the conflict by hand before migrating.");
|
|
26
|
+
this.name = "CategoryBConflictError";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function isPlainObject(value) {
|
|
30
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Idempotently rename Category B bare plan keys to their namespaced form.
|
|
34
|
+
* Mutates and returns the supplied document. Throws {@link CategoryBConflictError}
|
|
35
|
+
* when a plan carries both the bare and namespaced form of the same key.
|
|
36
|
+
*/
|
|
37
|
+
export function namespaceCategoryBPlan(doc) {
|
|
38
|
+
if (!isPlainObject(doc)) {
|
|
39
|
+
return { doc: doc, changed: false, renamedKeys: [] };
|
|
40
|
+
}
|
|
41
|
+
const plan = doc.plan;
|
|
42
|
+
if (!isPlainObject(plan)) {
|
|
43
|
+
return { doc, changed: false, renamedKeys: [] };
|
|
44
|
+
}
|
|
45
|
+
const renames = CATEGORY_B_KEY_RENAMES.filter((rename) => rename.legacyKey in plan);
|
|
46
|
+
if (renames.length === 0) {
|
|
47
|
+
return { doc, changed: false, renamedKeys: [] };
|
|
48
|
+
}
|
|
49
|
+
for (const { legacyKey, namespacedKey } of renames) {
|
|
50
|
+
if (namespacedKey in plan) {
|
|
51
|
+
throw new CategoryBConflictError(legacyKey, namespacedKey);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const renameMap = new Map(renames.map((r) => [r.legacyKey, r.namespacedKey]));
|
|
55
|
+
const rebuilt = {};
|
|
56
|
+
for (const [key, value] of Object.entries(plan)) {
|
|
57
|
+
rebuilt[renameMap.get(key) ?? key] = value;
|
|
58
|
+
}
|
|
59
|
+
doc.plan = rebuilt;
|
|
60
|
+
return { doc, changed: true, renamedKeys: renames.map((r) => r.namespacedKey) };
|
|
61
|
+
}
|
|
62
|
+
function collectVbriefFiles(dir, acc = []) {
|
|
63
|
+
let entries;
|
|
64
|
+
try {
|
|
65
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return acc;
|
|
69
|
+
}
|
|
70
|
+
for (const entry of entries) {
|
|
71
|
+
const full = join(dir, entry.name);
|
|
72
|
+
if (entry.isDirectory()) {
|
|
73
|
+
collectVbriefFiles(full, acc);
|
|
74
|
+
}
|
|
75
|
+
else if (entry.isFile() && hasArtifactSuffix(entry.name)) {
|
|
76
|
+
acc.push(full);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return acc;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Walk `vbrief/**\/*.vbrief.json` under projectRoot and namespace every
|
|
83
|
+
* Category B key in place. Idempotent: a second run reports zero changes.
|
|
84
|
+
* Files with a bare/namespaced conflict are reported, not rewritten.
|
|
85
|
+
*/
|
|
86
|
+
export function migrateCategoryBCorpus(projectRoot) {
|
|
87
|
+
const root = resolve(projectRoot);
|
|
88
|
+
const vbriefDir = resolveLifecycleRoot(root);
|
|
89
|
+
let scanned = 0;
|
|
90
|
+
const changed = [];
|
|
91
|
+
const conflicts = [];
|
|
92
|
+
for (const file of collectVbriefFiles(vbriefDir)) {
|
|
93
|
+
if (!statSync(file).isFile()) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
scanned += 1;
|
|
97
|
+
let parsed;
|
|
98
|
+
try {
|
|
99
|
+
parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const relPath = relative(root, file).replace(/\\/g, "/");
|
|
105
|
+
let result;
|
|
106
|
+
try {
|
|
107
|
+
result = namespaceCategoryBPlan(parsed);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
conflicts.push({ path: relPath, message: err instanceof Error ? err.message : String(err) });
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (result.changed) {
|
|
114
|
+
writeFileSync(file, `${JSON.stringify(result.doc, null, 2)}\n`, "utf8");
|
|
115
|
+
changed.push(relPath);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return { scanned, changed: changed.sort(), conflicts };
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { existsSync, globSync, readdirSync, readFileSync, realpathSync, statSync, } from "node:fs";
|
|
3
3
|
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
4
|
+
import { resolveProjectDefinitionPath } from "../layout/resolve.js";
|
|
4
5
|
import { extractCodeStructure, loadJsonFile } from "../verify-source/code-structure-validate.js";
|
|
5
6
|
import { sortedStringifyPretty } from "./json.js";
|
|
6
7
|
import { CODEBASE_MAP_FORMAT_VERSION, CODEBASE_MAP_KIND, CODEBASE_PROVIDER_CONTRACT_VERSION, } from "./projection-registry.js";
|
|
@@ -100,7 +101,7 @@ function sourcePathRel(projectRoot, sourcePath) {
|
|
|
100
101
|
}
|
|
101
102
|
/** Return the authored codeStructure source path used by the default extractor. */
|
|
102
103
|
export function defaultCodeStructurePath(projectRoot, codeStructurePath) {
|
|
103
|
-
return codeStructurePath ??
|
|
104
|
+
return codeStructurePath ?? resolveProjectDefinitionPath(projectRoot);
|
|
104
105
|
}
|
|
105
106
|
function stableId(value) {
|
|
106
107
|
let slug = "";
|
package/dist/codebase/map.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
|
+
import { resolveProjectDefinitionPath } from "../layout/resolve.js";
|
|
3
4
|
import { extractCodeStructure, loadJsonFile } from "../verify-source/code-structure-validate.js";
|
|
4
5
|
import { CodeStructureConfigError, configErrorToDict, defaultCodeStructurePath, } from "./default-extractor.js";
|
|
5
6
|
import { sortedStringifyPretty } from "./json.js";
|
|
@@ -73,7 +74,7 @@ export function projectionOutputPath(projectRoot, explicitOutput) {
|
|
|
73
74
|
if (explicitOutput !== undefined && explicitOutput !== null && explicitOutput.length > 0) {
|
|
74
75
|
return explicitOutput;
|
|
75
76
|
}
|
|
76
|
-
const projectDefinition =
|
|
77
|
+
const projectDefinition = resolveProjectDefinitionPath(projectRoot);
|
|
77
78
|
if (!existsSync(projectDefinition)) {
|
|
78
79
|
return DEFAULT_OUTPUT_PATH;
|
|
79
80
|
}
|
|
@@ -4,6 +4,8 @@ import { existsSync, readFileSync, statSync } from "node:fs";
|
|
|
4
4
|
import { dirname, isAbsolute, join, posix, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { contentRoot } from "../content-root.js";
|
|
7
|
+
import { resolveProjectDefinitionPath } from "../layout/resolve.js";
|
|
8
|
+
import { readPlanPolicy } from "../policy/plan-extensions.js";
|
|
7
9
|
import { loadJsonFile } from "../verify-source/code-structure-validate.js";
|
|
8
10
|
import { CODEBASE_MAP_SCHEMA_PATH } from "./constants.js";
|
|
9
11
|
import { buildCodebaseMap, CodeStructureConfigError, configErrorToDict, defaultCodeStructurePath, fileSha256, } from "./default-extractor.js";
|
|
@@ -254,7 +256,7 @@ function isSafeRelativePath(value) {
|
|
|
254
256
|
return !text.split("/").includes("..");
|
|
255
257
|
}
|
|
256
258
|
function projectDefinitionPath(projectRoot) {
|
|
257
|
-
return
|
|
259
|
+
return resolveProjectDefinitionPath(projectRoot);
|
|
258
260
|
}
|
|
259
261
|
function expectValue(expect, ...keys) {
|
|
260
262
|
if (typeof expect !== "object" || expect === null || Array.isArray(expect)) {
|
|
@@ -282,7 +284,7 @@ export function loadProviderArtifactPolicy(projectRoot, kind = CODEBASE_MAP_KIND
|
|
|
282
284
|
if (typeof plan !== "object" || plan === null || Array.isArray(plan)) {
|
|
283
285
|
return providerArtifactPolicyEmpty();
|
|
284
286
|
}
|
|
285
|
-
const policy = plan
|
|
287
|
+
const policy = readPlanPolicy(plan);
|
|
286
288
|
if (typeof policy !== "object" || policy === null || Array.isArray(policy)) {
|
|
287
289
|
return providerArtifactPolicyEmpty();
|
|
288
290
|
}
|
|
@@ -70,7 +70,7 @@ const SKIP_DIRS = new Set([
|
|
|
70
70
|
// broke CI when dependency versions drifted (#1993 follow-up).
|
|
71
71
|
"node_modules",
|
|
72
72
|
]);
|
|
73
|
-
const MIGRATION_ARTIFACT_TREES = ["vbrief/migration"];
|
|
73
|
+
const MIGRATION_ARTIFACT_TREES = ["xbrief/migration", "vbrief/migration"];
|
|
74
74
|
export function isMigrationArtifact(rel) {
|
|
75
75
|
if (MIGRATION_ARTIFACT_TREES.some((t) => rel.startsWith(`${t}/`))) {
|
|
76
76
|
return true;
|
package/dist/doctor/checks.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { detectLegacyLayout, legacyLayoutSignpostLine, } from "../init-deposit/legacy-detect.js";
|
|
3
3
|
import { detectCanonicalVendoredManifest, isNpmManaged, NPM_MANAGED_SENTINEL_KEY, NPM_MANAGED_SENTINEL_VALUE, } from "../init-deposit/migrate.js";
|
|
4
|
+
import { resolveLifecycleRoot } from "../layout/resolve.js";
|
|
4
5
|
import { findSkillPathsInText } from "../text/redos-safe.js";
|
|
5
6
|
import { CANONICAL_UPGRADE_COMMAND, GO_BRIDGE_RELEASES_URL, UPGRADING_DOC_URL, } from "./constants.js";
|
|
6
7
|
import { isDeprecationRedirectStub, locateManifest, manifestCandidatePaths, manifestTagToVersion, parseInstallManifest, parseInstallRootFromAgentsMd, parseManifest, } from "./manifest.js";
|
|
@@ -127,7 +128,7 @@ export function checkManifestAgreement(projectRoot, installRoot, seams = {}) {
|
|
|
127
128
|
const manifestPath = locateManifest(projectRoot, installRoot, isFile);
|
|
128
129
|
const expectedManifestPath = manifestPath ?? manifestCandidatePaths(projectRoot, installRoot)[0];
|
|
129
130
|
const bareCandidates = [
|
|
130
|
-
join(projectRoot, "
|
|
131
|
+
join(resolveLifecycleRoot(projectRoot), ".deft-version"),
|
|
131
132
|
join(projectRoot, ".deft-version"),
|
|
132
133
|
];
|
|
133
134
|
const barePath = bareCandidates.find((p) => isFile(p)) ?? null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
+
import { resolveEvalPath } from "../layout/resolve.js";
|
|
3
4
|
import { CLEAN_WINDOW_HOURS, DIRTY_WINDOW_HOURS, ENV_STATE_PATH } from "./constants.js";
|
|
4
|
-
const STATE_PARENT = join("vbrief", ".eval");
|
|
5
5
|
const STATE_FILENAME = "doctor-state.json";
|
|
6
6
|
export function statePath(projectRoot) {
|
|
7
7
|
const override = process.env[ENV_STATE_PATH]?.trim();
|
|
@@ -10,7 +10,7 @@ export function statePath(projectRoot) {
|
|
|
10
10
|
? join(process.env.HOME ?? projectRoot, override.slice(1))
|
|
11
11
|
: override;
|
|
12
12
|
}
|
|
13
|
-
return
|
|
13
|
+
return resolveEvalPath(projectRoot, STATE_FILENAME);
|
|
14
14
|
}
|
|
15
15
|
function parseIso(ts) {
|
|
16
16
|
if (typeof ts !== "string" || !ts) {
|
|
@@ -78,6 +78,25 @@ export const SCANNABLE_EXTENSIONS = new Set([
|
|
|
78
78
|
* POSIX form. Ported verbatim from the Python `BUILTIN_ALLOW_LIST`.
|
|
79
79
|
*/
|
|
80
80
|
export const BUILTIN_ALLOW_LIST = [
|
|
81
|
+
// Migrated xbrief/ layout (#2109). The #798 vBRIEF legitimately carries
|
|
82
|
+
// mojibake byte sequences as its subject matter; keep it allow-listed under
|
|
83
|
+
// the canonical layout.
|
|
84
|
+
"xbrief/active/*-798-*.xbrief.json",
|
|
85
|
+
"xbrief/completed/*-798-*.xbrief.json",
|
|
86
|
+
"xbrief/cancelled/*-798-*.xbrief.json",
|
|
87
|
+
"xbrief/pending/*-798-*.xbrief.json",
|
|
88
|
+
"xbrief/proposed/*-798-*.xbrief.json",
|
|
89
|
+
".deft/core/xbrief/active/*-798-*.xbrief.json",
|
|
90
|
+
".deft/core/xbrief/completed/*-798-*.xbrief.json",
|
|
91
|
+
".deft/core/xbrief/cancelled/*-798-*.xbrief.json",
|
|
92
|
+
".deft/core/xbrief/pending/*-798-*.xbrief.json",
|
|
93
|
+
".deft/core/xbrief/proposed/*-798-*.xbrief.json",
|
|
94
|
+
"deft/xbrief/active/*-798-*.xbrief.json",
|
|
95
|
+
"deft/xbrief/completed/*-798-*.xbrief.json",
|
|
96
|
+
"deft/xbrief/cancelled/*-798-*.xbrief.json",
|
|
97
|
+
"deft/xbrief/pending/*-798-*.xbrief.json",
|
|
98
|
+
"deft/xbrief/proposed/*-798-*.xbrief.json",
|
|
99
|
+
// Legacy vbrief/ layout (back-compat read support; removed by #2112).
|
|
81
100
|
"vbrief/active/*-798-*.vbrief.json",
|
|
82
101
|
"vbrief/completed/*-798-*.vbrief.json",
|
|
83
102
|
"vbrief/cancelled/*-798-*.vbrief.json",
|
package/dist/encoding/scan.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
+
import { hasArtifactSuffix, LIFECYCLE_DIR_NAMES } from "../layout/resolve.js";
|
|
2
3
|
import { MOJIBAKE_PATTERNS, NO_BOM_EXTENSIONS, REPLACEMENT_CHAR, UTF8_BOM, VBRIEF_CONTROL_CHAR_LABELS, } from "./patterns.js";
|
|
3
4
|
import { pythonSplitlines, stripMarkdownQuotes } from "./text.js";
|
|
4
5
|
/** Render a finding as the Python oracle does: ` path:line [label] context`. */
|
|
@@ -95,11 +96,11 @@ export function scanFile(relPath, fullPath) {
|
|
|
95
96
|
}
|
|
96
97
|
/** Return true for in-flight vBRIEF files that may receive issue ingest. */
|
|
97
98
|
export function isVbriefNarrativeControlScope(relPath) {
|
|
98
|
-
if (!relPath
|
|
99
|
+
if (!hasArtifactSuffix(relPath)) {
|
|
99
100
|
return false;
|
|
100
101
|
}
|
|
101
102
|
const normalized = `/${relPath.replace(/\\/g, "/")}`;
|
|
102
|
-
return normalized.includes(
|
|
103
|
+
return LIFECYCLE_DIR_NAMES.some((dir) => normalized.includes(`/${dir}/proposed/`) || normalized.includes(`/${dir}/active/`));
|
|
103
104
|
}
|
|
104
105
|
function tabIsNonIndentation(value, index) {
|
|
105
106
|
const lineStart = value.lastIndexOf("\n", index - 1) + 1;
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export * as codebase from "./codebase/index.js";
|
|
|
16
16
|
export * as doctor from "./doctor/index.js";
|
|
17
17
|
export * from "./encoding/index.js";
|
|
18
18
|
export * as intake from "./intake/index.js";
|
|
19
|
+
export * as layout from "./layout/index.js";
|
|
19
20
|
export * as legacyBridge from "./legacy-bridge/index.js";
|
|
20
21
|
export * as lifecycle from "./lifecycle/index.js";
|
|
21
22
|
export * as orchestration from "./orchestration/index.js";
|
|
@@ -49,6 +50,7 @@ export * as vbriefValidation from "./vbrief-validation/index.js";
|
|
|
49
50
|
export * as verifyEnv from "./verify-env/index.js";
|
|
50
51
|
export * as verifySource from "./verify-source/index.js";
|
|
51
52
|
export * as wipCap from "./wip-cap/index.js";
|
|
53
|
+
export * as xbriefMigrate from "./xbrief-migrate/index.js";
|
|
52
54
|
export declare const CORE_PACKAGE: "@deftai/directive-core";
|
|
53
55
|
/** Returns identifying metadata for the core engine package. */
|
|
54
56
|
export declare function engineInfo(): EngineInfo;
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ export * as codebase from "./codebase/index.js";
|
|
|
16
16
|
export * as doctor from "./doctor/index.js";
|
|
17
17
|
export * from "./encoding/index.js";
|
|
18
18
|
export * as intake from "./intake/index.js";
|
|
19
|
+
export * as layout from "./layout/index.js";
|
|
19
20
|
export * as legacyBridge from "./legacy-bridge/index.js";
|
|
20
21
|
export * as lifecycle from "./lifecycle/index.js";
|
|
21
22
|
export * as orchestration from "./orchestration/index.js";
|
|
@@ -49,6 +50,7 @@ export * as vbriefValidation from "./vbrief-validation/index.js";
|
|
|
49
50
|
export * as verifyEnv from "./verify-env/index.js";
|
|
50
51
|
export * as verifySource from "./verify-source/index.js";
|
|
51
52
|
export * as wipCap from "./wip-cap/index.js";
|
|
53
|
+
export * as xbriefMigrate from "./xbrief-migrate/index.js";
|
|
52
54
|
export const CORE_PACKAGE = "@deftai/directive-core";
|
|
53
55
|
/** Returns identifying metadata for the core engine package. */
|
|
54
56
|
export function engineInfo() {
|
|
@@ -14,6 +14,7 @@ import { prunePythonArtifactsFromDeposit } from "../deposit/python-free.js";
|
|
|
14
14
|
import { resolveInstalledContentRoot } from "../deposit/resolve-content.js";
|
|
15
15
|
import { manifestTagToVersion, parseInstallManifest } from "../doctor/manifest.js";
|
|
16
16
|
import { readCorePackageVersion } from "../engine-version.js";
|
|
17
|
+
import { resolveLifecycleRoot } from "../layout/resolve.js";
|
|
17
18
|
import { DEV_FALLBACK } from "../platform/constants.js";
|
|
18
19
|
import { gitPorcelain } from "../story-ready/git.js";
|
|
19
20
|
import { parseInitArgv } from "./init-deposit.js";
|
|
@@ -92,7 +93,7 @@ function syncBareVersionMarker(projectDir, version) {
|
|
|
92
93
|
const normalized = normalizeVersion(version);
|
|
93
94
|
if (!normalized || normalized === DEV_FALLBACK)
|
|
94
95
|
return;
|
|
95
|
-
const vbriefDir =
|
|
96
|
+
const vbriefDir = resolveLifecycleRoot(projectDir);
|
|
96
97
|
let targetDir = projectDir;
|
|
97
98
|
try {
|
|
98
99
|
if (statSync(vbriefDir).isDirectory())
|
|
@@ -10,6 +10,7 @@ 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";
|
|
13
14
|
import { agentsRefreshPlan } from "../platform/agents-md.js";
|
|
14
15
|
export const CANONICAL_INSTALL_ROOT = ".deft/core";
|
|
15
16
|
export const CORE_GLOB = ".deft/core/**";
|
|
@@ -262,7 +263,7 @@ function vbriefLifecycleDirsPresent(consumerVbrief) {
|
|
|
262
263
|
});
|
|
263
264
|
}
|
|
264
265
|
export async function writeConsumerVbrief(projectDir, deftDir, io) {
|
|
265
|
-
const consumerVbrief =
|
|
266
|
+
const consumerVbrief = resolveLifecycleRoot(projectDir);
|
|
266
267
|
const schemasDst = join(consumerVbrief, "schemas");
|
|
267
268
|
const vbriefMdDst = join(consumerVbrief, "vbrief.md");
|
|
268
269
|
const schemasPresent = existsSync(schemasDst) && statSync(schemasDst).isDirectory();
|
|
@@ -3,10 +3,12 @@ import { join, relative, resolve } from "node:path";
|
|
|
3
3
|
import { locateManifest, manifestTagToVersion, parseInstallManifest } from "../doctor/manifest.js";
|
|
4
4
|
import { readCorePackageVersion } from "../engine-version.js";
|
|
5
5
|
import { buildInstallManifestText, CANONICAL_INSTALL_ROOT, } from "../init-deposit/scaffold.js";
|
|
6
|
+
import { resolveLifecycleRoot } from "../layout/resolve.js";
|
|
6
7
|
import { agentsRefreshPlan } from "../platform/agents-md.js";
|
|
7
8
|
import { DEV_FALLBACK } from "../platform/constants.js";
|
|
8
9
|
import { resolveVersion } from "../platform/resolve-version.js";
|
|
9
10
|
import { detectPreCutoverLegacy, frozenPreCutoverMigrationGuidance, } from "../vbrief-validate/precutover.js";
|
|
11
|
+
import { detectLegacyVbriefLayout, emitXbriefMigration, isPatchOnlyUpgrade, renderXbriefMigrationLine, runXbriefMigration, } from "../xbrief-migrate/index.js";
|
|
10
12
|
const ENGINE_PACKAGE_FALLBACK = "0.0.0";
|
|
11
13
|
/**
|
|
12
14
|
* Resolve the framework version for an upgrade (#2053).
|
|
@@ -71,7 +73,10 @@ function readManagedByAt(installRoot) {
|
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
function versionMarkerPaths(projectRoot) {
|
|
74
|
-
return [
|
|
76
|
+
return [
|
|
77
|
+
join(resolveLifecycleRoot(projectRoot), ".deft-version"),
|
|
78
|
+
join(projectRoot, ".deft-version"),
|
|
79
|
+
];
|
|
75
80
|
}
|
|
76
81
|
function readVersionMarker(projectRoot) {
|
|
77
82
|
for (const candidate of versionMarkerPaths(projectRoot)) {
|
|
@@ -173,6 +178,24 @@ function runAgentsRefresh(projectRoot, frameworkRoot, io) {
|
|
|
173
178
|
io.writeOut(`AGENTS.md updated (state=${state}).\n`);
|
|
174
179
|
return 0;
|
|
175
180
|
}
|
|
181
|
+
function handleLegacyXbriefLayout(args, io, recorded, normalizedVersion) {
|
|
182
|
+
const detection = detectLegacyVbriefLayout(args.projectRoot);
|
|
183
|
+
if (!detection.legacyLayout) {
|
|
184
|
+
return 0;
|
|
185
|
+
}
|
|
186
|
+
io.writeOut(`${renderXbriefMigrationLine(args.projectRoot)}\n`);
|
|
187
|
+
const patchInert = isPatchOnlyUpgrade(recorded, normalizedVersion);
|
|
188
|
+
if (!args.migrate || patchInert) {
|
|
189
|
+
return 0;
|
|
190
|
+
}
|
|
191
|
+
const outcome = runXbriefMigration({
|
|
192
|
+
projectRoot: args.projectRoot,
|
|
193
|
+
frameworkRoot: args.frameworkRoot,
|
|
194
|
+
force: args.force,
|
|
195
|
+
}, io);
|
|
196
|
+
const code = emitXbriefMigration(outcome, io, { projectRoot: args.projectRoot });
|
|
197
|
+
return code;
|
|
198
|
+
}
|
|
176
199
|
/** Port of ``run upgrade`` / ``task install:upgrade`` for the consumer task surface (#1061 / #2022). */
|
|
177
200
|
export function runInstallUpgrade(args, io) {
|
|
178
201
|
const projectRoot = resolve(args.projectRoot);
|
|
@@ -189,13 +212,16 @@ export function runInstallUpgrade(args, io) {
|
|
|
189
212
|
const recorded = readVersionMarker(projectRoot);
|
|
190
213
|
if (recorded === normalizedVersion) {
|
|
191
214
|
io.writeOut(`Project already at ${normalizedVersion}. Nothing to do.\n`);
|
|
215
|
+
const xbriefCode = handleLegacyXbriefLayout(args, io, recorded, normalizedVersion);
|
|
216
|
+
if (xbriefCode !== 0)
|
|
217
|
+
return xbriefCode;
|
|
192
218
|
return runAgentsRefresh(projectRoot, agentsRoot, io);
|
|
193
219
|
}
|
|
194
220
|
const legacy = detectPreCutoverLegacy(projectRoot);
|
|
195
221
|
if (legacy.length > 0) {
|
|
196
222
|
io.writeOut(`Pre-v0.20 document model detected (${legacy.join(", ")}). ${frozenPreCutoverMigrationGuidance()}\n`);
|
|
197
223
|
}
|
|
198
|
-
const vbriefDir =
|
|
224
|
+
const vbriefDir = resolveLifecycleRoot(projectRoot);
|
|
199
225
|
const targetDir = existsSync(vbriefDir) && statSync(vbriefDir).isDirectory() ? vbriefDir : projectRoot;
|
|
200
226
|
writeVersionMarker(targetDir, normalizedVersion);
|
|
201
227
|
const writtenManifestPath = installRoot !== null
|
|
@@ -217,6 +243,9 @@ export function runInstallUpgrade(args, io) {
|
|
|
217
243
|
io.writeOut(`Updated .deft-version from ${recorded} to ${normalizedVersion}.\n`);
|
|
218
244
|
}
|
|
219
245
|
io.writeOut(`If legacy SPECIFICATION.md or PROJECT.md content remains, see UPGRADING.md § Frozen pre-v0.20 document-model migration (#2068).\n`);
|
|
246
|
+
const xbriefCode = handleLegacyXbriefLayout(args, io, recorded, normalizedVersion);
|
|
247
|
+
if (xbriefCode !== 0)
|
|
248
|
+
return xbriefCode;
|
|
220
249
|
return runAgentsRefresh(projectRoot, agentsRoot, io);
|
|
221
250
|
}
|
|
222
251
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ScmCallFn } from "./reconcile-issues.js";
|
|
2
|
-
export declare const GITHUB_ISSUE_REF_TYPE = "x-
|
|
2
|
+
export declare const GITHUB_ISSUE_REF_TYPE = "x-xbrief/github-issue";
|
|
3
3
|
export declare const EXTERNAL_TRUST_LEVEL = "external";
|
|
4
4
|
export declare class IssueEmitError extends Error {
|
|
5
5
|
constructor(message: string);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { globSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join, relative, resolve } from "node:path";
|
|
4
|
+
import { referenceTypeMatches } from "@deftai/directive-types";
|
|
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
|
-
export const GITHUB_ISSUE_REF_TYPE = "x-
|
|
8
|
+
export const GITHUB_ISSUE_REF_TYPE = "x-xbrief/github-issue";
|
|
8
9
|
export const EXTERNAL_TRUST_LEVEL = "external";
|
|
9
10
|
const ISSUE_URL_PATTERN = /https?:\/\/\S+?\/issues\/\d+/;
|
|
10
11
|
export class IssueEmitError extends Error {
|
|
@@ -44,7 +45,7 @@ export function existingGithubIssueRef(data) {
|
|
|
44
45
|
for (const ref of refs) {
|
|
45
46
|
if (ref !== null && typeof ref === "object" && !Array.isArray(ref)) {
|
|
46
47
|
const obj = ref;
|
|
47
|
-
if (obj.type
|
|
48
|
+
if (referenceTypeMatches(String(obj.type ?? ""), "github-issue")) {
|
|
48
49
|
const uri = obj.uri ?? obj.url;
|
|
49
50
|
return typeof uri === "string" && uri.length > 0 ? uri : "";
|
|
50
51
|
}
|