@deftai/directive-core 0.72.0 → 0.73.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/branch/evaluate.js +2 -1
- 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/deposit/copy-tree.js +31 -7
- 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 +30 -0
- package/dist/init-deposit/hygiene.js +60 -1
- package/dist/init-deposit/refresh.d.ts +16 -2
- package/dist/init-deposit/refresh.js +162 -52
- package/dist/init-deposit/scaffold.d.ts +11 -1
- package/dist/init-deposit/scaffold.js +9 -8
- 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/disclosure.d.ts +1 -0
- package/dist/policy/disclosure.js +1 -0
- package/dist/policy/index.d.ts +1 -0
- package/dist/policy/index.js +1 -0
- package/dist/policy/policy-invocation.d.ts +5 -0
- package/dist/policy/policy-invocation.js +9 -0
- package/dist/policy/resolve.d.ts +2 -2
- package/dist/policy/resolve.js +15 -5
- package/dist/policy/value-feedback.js +6 -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/constants.d.ts +1 -1
- package/dist/swarm/constants.js +2 -1
- package/dist/swarm/readiness.js +33 -3
- package/dist/swarm/subagent-backend.js +2 -1
- 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/ts-check-lane/run-lane.d.ts +4 -0
- package/dist/ts-check-lane/run-lane.js +20 -6
- package/dist/validate-content/validate-strategy-output.js +11 -1
- package/dist/value/feedback-file.js +3 -2
- package/dist/value/readback.js +3 -2
- 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
package/dist/scope/decompose.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { accessSync, constants, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
10
10
|
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
11
11
|
import { referenceTypeMatches } from "@deftai/directive-types";
|
|
12
|
-
import { hasArtifactSuffix, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
12
|
+
import { hasArtifactSuffix, LEGACY_ARTIFACT_DIR, MIGRATED_ARTIFACT_DIR, resolveLifecycleRoot, } from "../layout/resolve.js";
|
|
13
13
|
import { referenceWithDefaultTrust, slugify } from "../vbrief-build/build.js";
|
|
14
14
|
import { EMITTED_VBRIEF_VERSION } from "../vbrief-build/constants.js";
|
|
15
15
|
import { formatVbriefJson } from "./vbrief-json.js";
|
|
@@ -400,7 +400,17 @@ export function storyQualityIssues(opts) {
|
|
|
400
400
|
// Path helpers
|
|
401
401
|
// ---------------------------------------------------------------------------
|
|
402
402
|
function vbriefDir(projectRoot) {
|
|
403
|
-
|
|
403
|
+
try {
|
|
404
|
+
return resolveLifecycleRoot(projectRoot);
|
|
405
|
+
}
|
|
406
|
+
catch (err) {
|
|
407
|
+
// Re-throw if only vbrief/ exists (legacy-only); fall back to canonical xbrief/ path otherwise.
|
|
408
|
+
if (existsSync(join(projectRoot, LEGACY_ARTIFACT_DIR)) &&
|
|
409
|
+
!existsSync(join(projectRoot, MIGRATED_ARTIFACT_DIR))) {
|
|
410
|
+
throw err;
|
|
411
|
+
}
|
|
412
|
+
return join(projectRoot, MIGRATED_ARTIFACT_DIR);
|
|
413
|
+
}
|
|
404
414
|
}
|
|
405
415
|
function relToVbrief(vbriefDirPath, path) {
|
|
406
416
|
const resolvedPath = resolve(path);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
|
-
import { hasArtifactSuffix } from "../layout/resolve.js";
|
|
4
|
+
import { hasArtifactSuffix, MIGRATED_ARTIFACT_DIR } from "../layout/resolve.js";
|
|
5
5
|
export const RESUME_ELIGIBLE_DECISION = "resume-eligible";
|
|
6
6
|
export const EVALUATOR_ACTOR = "agent:resume-evaluator";
|
|
7
7
|
export const CACHE_DIR_NAME = ".deft-cache";
|
|
@@ -258,7 +258,7 @@ export function evaluate(expr, ctx) {
|
|
|
258
258
|
throw new ResumeGrammarError(`unknown composition op ${JSON.stringify(expr.op)}`);
|
|
259
259
|
}
|
|
260
260
|
function countPending(projectRoot) {
|
|
261
|
-
const folder = join(resolve(projectRoot),
|
|
261
|
+
const folder = join(resolve(projectRoot), MIGRATED_ARTIFACT_DIR, PENDING_LIFECYCLE_DIR);
|
|
262
262
|
try {
|
|
263
263
|
if (!statSync(folder).isDirectory())
|
|
264
264
|
return 0;
|
|
@@ -3,7 +3,7 @@ export declare const RITUAL_STATE_SCHEMA_VERSION = 1;
|
|
|
3
3
|
export declare const SENTINEL_RELPATH: readonly [".deft", "last-session.json"];
|
|
4
4
|
export declare const RITUAL_STATE_RELPATH: readonly [".deft", "ritual-state.json"];
|
|
5
5
|
export declare const MIN_RESUME_AGE_MS: number;
|
|
6
|
-
export declare const ACTIVE_VBRIEF_PREFIX
|
|
6
|
+
export declare const ACTIVE_VBRIEF_PREFIX: string;
|
|
7
7
|
export interface Sentinel {
|
|
8
8
|
readonly schemaVersion: number;
|
|
9
9
|
readonly deftVersion: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { closeSync, existsSync, fdatasyncSync, mkdirSync, openSync, readdirSync, readFileSync, renameSync, statSync, writeSync, } from "node:fs";
|
|
2
2
|
import { join, relative, resolve } from "node:path";
|
|
3
|
-
import { hasArtifactSuffix } from "../layout/resolve.js";
|
|
3
|
+
import { hasArtifactSuffix, LEGACY_ARTIFACT_DIR, MIGRATED_ARTIFACT_DIR, } from "../layout/resolve.js";
|
|
4
4
|
import { stableJson } from "./json.js";
|
|
5
5
|
import { parseTimestamp, timestampIso } from "./time.js";
|
|
6
6
|
export const SCHEMA_VERSION = 1;
|
|
@@ -8,7 +8,7 @@ export const RITUAL_STATE_SCHEMA_VERSION = 1;
|
|
|
8
8
|
export const SENTINEL_RELPATH = [".deft", "last-session.json"];
|
|
9
9
|
export const RITUAL_STATE_RELPATH = [".deft", "ritual-state.json"];
|
|
10
10
|
export const MIN_RESUME_AGE_MS = 2 * 60 * 60 * 1000;
|
|
11
|
-
export const ACTIVE_VBRIEF_PREFIX =
|
|
11
|
+
export const ACTIVE_VBRIEF_PREFIX = `${MIGRATED_ARTIFACT_DIR}/active/`;
|
|
12
12
|
export function ritualStatePath(projectRoot) {
|
|
13
13
|
return join(resolve(projectRoot), ...RITUAL_STATE_RELPATH);
|
|
14
14
|
}
|
|
@@ -249,7 +249,9 @@ export function writeSentinel(projectRoot, input) {
|
|
|
249
249
|
schemaVersion: SCHEMA_VERSION,
|
|
250
250
|
deftVersion: input.deftVersion,
|
|
251
251
|
timestamp: timestampIso(instant),
|
|
252
|
-
lastActiveVbrief: input.lastActiveVbrief
|
|
252
|
+
lastActiveVbrief: input.lastActiveVbrief
|
|
253
|
+
.replace(/\\/g, "/")
|
|
254
|
+
.replace(`${LEGACY_ARTIFACT_DIR}/active/`, `${MIGRATED_ARTIFACT_DIR}/active/`),
|
|
253
255
|
lastBranch: input.lastBranch,
|
|
254
256
|
};
|
|
255
257
|
atomicWriteJson(sentinelFile, payload, ".last-session.");
|
|
@@ -290,7 +292,7 @@ export function computeResumeSignal(sentinel, now, projectRoot) {
|
|
|
290
292
|
`${elapsedLabel} ago. Resume? Run \`task vbrief:show ${lastActive}\`.`);
|
|
291
293
|
}
|
|
292
294
|
export function detectLatestActiveVbrief(projectRoot) {
|
|
293
|
-
const activeDir = join(resolve(projectRoot),
|
|
295
|
+
const activeDir = join(resolve(projectRoot), MIGRATED_ARTIFACT_DIR, "active");
|
|
294
296
|
try {
|
|
295
297
|
if (!existsSync(activeDir)) {
|
|
296
298
|
return null;
|
|
@@ -14,5 +14,5 @@ export declare const CHILD_ALLOWED_FIELDS: Set<"n" | "url" | "wave" | "role">;
|
|
|
14
14
|
export declare const UUID_RE: RegExp;
|
|
15
15
|
export declare const ISO8601_RE: RegExp;
|
|
16
16
|
export declare const WAVE_FLAG_RE: RegExp;
|
|
17
|
-
export declare const PROJECT_ROOT_SENTINELS: readonly ["vbrief", ".git"];
|
|
17
|
+
export declare const PROJECT_ROOT_SENTINELS: readonly ["xbrief", "vbrief", ".git"];
|
|
18
18
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/slice/constants.js
CHANGED
|
@@ -26,5 +26,5 @@ export const CHILD_ALLOWED_FIELDS = new Set(CHILD_REQUIRED_FIELDS);
|
|
|
26
26
|
export const UUID_RE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
27
27
|
export const ISO8601_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/;
|
|
28
28
|
export const WAVE_FLAG_RE = /^--wave-(\d+)(?:=(.*))?$/;
|
|
29
|
-
export const PROJECT_ROOT_SENTINELS = ["vbrief", ".git"];
|
|
29
|
+
export const PROJECT_ROOT_SENTINELS = ["xbrief", "vbrief", ".git"];
|
|
30
30
|
//# sourceMappingURL=constants.js.map
|
|
@@ -77,7 +77,7 @@ export function resolveRootAndRepo(cliProjectRoot, cliRepo, requireRepo) {
|
|
|
77
77
|
export function formatMissingRootError() {
|
|
78
78
|
return ("error: cannot determine project root. Pass --project-root PATH, " +
|
|
79
79
|
"set $DEFT_PROJECT_ROOT, or run from inside a directory tree that " +
|
|
80
|
-
"contains
|
|
80
|
+
"contains xbrief/ or .git/ (#535).");
|
|
81
81
|
}
|
|
82
82
|
export function formatMissingRepoError() {
|
|
83
83
|
return ("error: cannot determine repo slug. Pass --repo OWNER/NAME, " +
|
|
@@ -5,8 +5,15 @@ import { SPEC_RENDER_BANNER } from "../render/constants.js";
|
|
|
5
5
|
import { contentHasGeneratedPdSource, contentHasGeneratedSpecSource, EXPORT_SPEC_PD_BANNER, GENERATED_SPEC_PURPOSE, } from "./constants.js";
|
|
6
6
|
export function resolveSpecAuthority(projectRoot) {
|
|
7
7
|
const root = projectRoot;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
let layout;
|
|
9
|
+
let vbriefDir;
|
|
10
|
+
try {
|
|
11
|
+
layout = resolveLifecycleLayout(root);
|
|
12
|
+
vbriefDir = resolveLifecycleRoot(root);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return null; // No xbrief/ layout; spec authority unavailable.
|
|
16
|
+
}
|
|
10
17
|
const projectDefPath = resolveProjectDefinitionPath(root);
|
|
11
18
|
if (!existsSync(projectDefPath))
|
|
12
19
|
return null;
|
|
@@ -230,7 +230,20 @@ function completeParent(parentPath, vbriefDir, projectRoot, settled, dryRun) {
|
|
|
230
230
|
};
|
|
231
231
|
}
|
|
232
232
|
export function sweepCohort(storyPaths, projectRoot, dryRun) {
|
|
233
|
-
|
|
233
|
+
let vbriefDir;
|
|
234
|
+
try {
|
|
235
|
+
vbriefDir = resolveLifecycleRoot(projectRoot);
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return {
|
|
239
|
+
project_root: resolve(projectRoot),
|
|
240
|
+
dry_run: dryRun,
|
|
241
|
+
stories: [],
|
|
242
|
+
parents: [],
|
|
243
|
+
errors: [],
|
|
244
|
+
ok: true,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
234
247
|
const result = {
|
|
235
248
|
project_root: resolve(projectRoot),
|
|
236
249
|
dry_run: dryRun,
|
|
@@ -7,7 +7,7 @@ export declare const EXIT_UNCLEAN = 1;
|
|
|
7
7
|
export declare const EXIT_EXTERNAL_ERROR = 2;
|
|
8
8
|
export declare const DEFAULT_BASE_BRANCH = "master";
|
|
9
9
|
export declare const LEAF_CODING_WORKER_ROLE = "leaf-implementation";
|
|
10
|
-
export declare const SUBAGENT_BACKEND_SET_CMD
|
|
10
|
+
export declare const SUBAGENT_BACKEND_SET_CMD: string;
|
|
11
11
|
export declare const GATE_ADVISE = "advise";
|
|
12
12
|
export declare const GATE_ENFORCE = "enforce";
|
|
13
13
|
export declare const READY = "ready";
|
package/dist/swarm/constants.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { policySetInvocation } from "../policy/policy-invocation.js";
|
|
1
2
|
export const EXIT_OK = 0;
|
|
2
3
|
export const EXIT_GATE_FAILED = 1;
|
|
3
4
|
export const EXIT_CONFIG_ERROR = 2;
|
|
@@ -7,7 +8,7 @@ export const EXIT_UNCLEAN = 1;
|
|
|
7
8
|
export const EXIT_EXTERNAL_ERROR = 2;
|
|
8
9
|
export const DEFAULT_BASE_BRANCH = "master";
|
|
9
10
|
export const LEAF_CODING_WORKER_ROLE = "leaf-implementation";
|
|
10
|
-
export const SUBAGENT_BACKEND_SET_CMD = "
|
|
11
|
+
export const SUBAGENT_BACKEND_SET_CMD = `${policySetInvocation("subagent-backend", " -- --set {backend_id}")}`;
|
|
11
12
|
export const GATE_ADVISE = "advise";
|
|
12
13
|
export const GATE_ENFORCE = "enforce";
|
|
13
14
|
export const READY = "ready";
|
package/dist/swarm/readiness.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
2
|
import { basename, join, resolve } from "node:path";
|
|
3
3
|
import { referenceTypeMatches } from "@deftai/directive-types";
|
|
4
|
-
import { ARTIFACT_SUFFIXES, hasArtifactSuffix, LIFECYCLE_DIR_NAMES, resolveLifecycleLayout, resolveLifecycleRoot, stripArtifactSuffix, } from "../layout/resolve.js";
|
|
4
|
+
import { ARTIFACT_SUFFIXES, hasArtifactSuffix, LEGACY_ARTIFACT_DIR, LIFECYCLE_DIR_NAMES, MIGRATED_ARTIFACT_DIR, MIGRATED_ARTIFACT_SUFFIX, MIGRATED_INFO_ROOT_KEY, resolveLifecycleLayout, resolveLifecycleRoot, stripArtifactSuffix, } from "../layout/resolve.js";
|
|
5
5
|
import { acceptanceTextsFromItems, asStrList, deprecatedSubitemsIssues, itemHasTraces, itemsHaveAcceptance, missingRequiredSwarmFields, storyQualityIssues, } from "../vbrief-validation/story-quality.js";
|
|
6
6
|
import { LIFECYCLE_FOLDERS, READY } from "./constants.js";
|
|
7
7
|
function loadJson(path) {
|
|
@@ -26,7 +26,31 @@ function projectRel(projectRoot, path) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
function expandPaths(projectRoot, patterns) {
|
|
29
|
-
|
|
29
|
+
// Use the canonical xbrief layout; re-throw only if a legacy vbrief/-only tree is detected (#2112).
|
|
30
|
+
let layout;
|
|
31
|
+
try {
|
|
32
|
+
layout = resolveLifecycleLayout(projectRoot);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
const xbriefDir = join(projectRoot, MIGRATED_ARTIFACT_DIR);
|
|
36
|
+
if (existsSync(xbriefDir)) {
|
|
37
|
+
// xbrief/ dir exists but has no artifacts yet -- treat as valid (empty) layout.
|
|
38
|
+
layout = {
|
|
39
|
+
root: xbriefDir,
|
|
40
|
+
artifactDir: MIGRATED_ARTIFACT_DIR,
|
|
41
|
+
artifactSuffix: MIGRATED_ARTIFACT_SUFFIX,
|
|
42
|
+
infoRootKey: MIGRATED_INFO_ROOT_KEY,
|
|
43
|
+
migrated: true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
else if (existsSync(join(projectRoot, LEGACY_ARTIFACT_DIR))) {
|
|
47
|
+
throw err; // Legacy-only project: operator must run deft migrate:xbrief.
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// Neither exists -- return empty list.
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
30
54
|
const usePatterns = patterns.length > 0 ? patterns : [`${layout.artifactDir}/active/*${layout.artifactSuffix}`];
|
|
31
55
|
const out = [];
|
|
32
56
|
const seen = new Set();
|
|
@@ -210,7 +234,13 @@ function acceptanceCountJustification(plan, swarm) {
|
|
|
210
234
|
}
|
|
211
235
|
function allScopeIds(projectRoot) {
|
|
212
236
|
const ids = new Map();
|
|
213
|
-
|
|
237
|
+
let vbriefDir;
|
|
238
|
+
try {
|
|
239
|
+
vbriefDir = resolveLifecycleRoot(projectRoot);
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
return ids; // No xbrief/ layout; no scope IDs.
|
|
243
|
+
}
|
|
214
244
|
for (const folder of LIFECYCLE_FOLDERS) {
|
|
215
245
|
const dir = join(vbriefDir, folder);
|
|
216
246
|
if (!existsSync(dir)) {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* @see {@link https://github.com/deftai/directive/issues/1860} Hard deletion tracking
|
|
13
13
|
*/
|
|
14
14
|
import { readPlanPolicy } from "../policy/plan-extensions.js";
|
|
15
|
+
import { policySetInvocation } from "../policy/policy-invocation.js";
|
|
15
16
|
import { loadProjectDefinition } from "../policy/resolve.js";
|
|
16
17
|
import { LEAF_CODING_WORKER_ROLE, SUBAGENT_BACKEND_SET_CMD } from "./constants.js";
|
|
17
18
|
const TRUTHY = new Set(["1", "true", "yes", "on"]);
|
|
@@ -132,7 +133,7 @@ export function enforceSubagentBackendPolicy(projectRoot, environ = process.env)
|
|
|
132
133
|
error: `${detail}\n` +
|
|
133
134
|
"Select a coding sub-agent backend before headless dispatch:\n" +
|
|
134
135
|
`${listing}\n` +
|
|
135
|
-
|
|
136
|
+
`Probe harness availability: ${policySetInvocation("subagent-backends")}\n` +
|
|
136
137
|
`Persist a choice: ${SUBAGENT_BACKEND_SET_CMD.replace("{backend_id}", "<id>")}`,
|
|
137
138
|
};
|
|
138
139
|
}
|
|
@@ -72,10 +72,10 @@ export function runChangeInit(projectRoot, name, io) {
|
|
|
72
72
|
return 1;
|
|
73
73
|
}
|
|
74
74
|
mkdirSync(join(base, "specs"), { recursive: true });
|
|
75
|
-
writeFileSync(join(base, "proposal.
|
|
76
|
-
writeFileSync(join(base, "tasks.
|
|
75
|
+
writeFileSync(join(base, "proposal.xbrief.json"), `${JSON.stringify(proposalTemplate(trimmed), null, 2)}\n`, "utf8");
|
|
76
|
+
writeFileSync(join(base, "tasks.xbrief.json"), `${JSON.stringify(tasksTemplate(trimmed), null, 2)}\n`, "utf8");
|
|
77
77
|
io.writeOut(`OK: Created change proposal at ${base}/\n`);
|
|
78
|
-
for (const file of ["proposal.
|
|
78
|
+
for (const file of ["proposal.xbrief.json", "tasks.xbrief.json", "specs/"]) {
|
|
79
79
|
io.writeOut(` - ${file}\n`);
|
|
80
80
|
}
|
|
81
81
|
return 0;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolveCandidatesLogPath } from "../cache-path.js";
|
|
2
2
|
import type { AuditEntry, CandidatesLog } from "./types.js";
|
|
3
3
|
/** Display/back-compat constant; resolution flows through resolveTriageCachePath (#1703). */
|
|
4
|
-
export declare const AUDIT_LOG_REL_PATH = "
|
|
4
|
+
export declare const AUDIT_LOG_REL_PATH = "xbrief/.triage-cache/candidates.jsonl";
|
|
5
5
|
export { resolveCandidatesLogPath };
|
|
6
6
|
/** Read every well-formed audit-log row in insertion order (#1698 shared reader). */
|
|
7
7
|
export declare function readAuditLog(logPath: string, repo?: string | null): AuditEntry[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, relative } from "node:path";
|
|
3
|
-
import { resolveLifecycleLayout } from "../../layout/resolve.js";
|
|
3
|
+
import { MIGRATED_ARTIFACT_DIR, resolveLifecycleLayout } from "../../layout/resolve.js";
|
|
4
4
|
import { resolveCandidatesLogPath, resolveTriageCachePath, TRIAGE_CACHE_DIR_NAME, triageCacheRelPath, } from "../cache-path.js";
|
|
5
5
|
/** POSIX-style display path for `absPath` relative to `projectRoot` (#2109). */
|
|
6
6
|
function evalRelDisplay(projectRoot, absPath) {
|
|
@@ -13,11 +13,11 @@ export const GITIGNORE_DEFT_RUNTIME_SENTINELS = [
|
|
|
13
13
|
];
|
|
14
14
|
/** Legacy static vbrief paths kept for tests referencing the pre-#1703 constant shape. */
|
|
15
15
|
export const GITIGNORE_EVAL_ENTRIES = [
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
16
|
+
"xbrief/.triage-cache/candidates.jsonl",
|
|
17
|
+
"xbrief/.triage-cache/summary-history.jsonl",
|
|
18
|
+
"xbrief/.triage-cache/scope-lifecycle.jsonl",
|
|
19
|
+
"xbrief/.triage-cache/decompositions/",
|
|
20
|
+
"xbrief/.triage-cache/doctor-state.json",
|
|
21
21
|
];
|
|
22
22
|
/** Layout-aware gitignore lines for triage working-set files (#1703). */
|
|
23
23
|
export function gitignoreTriageCacheEntries(projectRoot) {
|
|
@@ -31,8 +31,14 @@ export function gitignoreTriageCacheEntries(projectRoot) {
|
|
|
31
31
|
];
|
|
32
32
|
}
|
|
33
33
|
export function gitattributesTriageCacheGlob(projectRoot) {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
let artifactDir;
|
|
35
|
+
try {
|
|
36
|
+
artifactDir = resolveLifecycleLayout(projectRoot).artifactDir;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
artifactDir = MIGRATED_ARTIFACT_DIR; // No layout; default to xbrief/.
|
|
40
|
+
}
|
|
41
|
+
return `${artifactDir}/${TRIAGE_CACHE_DIR_NAME}/*.jsonl`;
|
|
36
42
|
}
|
|
37
43
|
export const GITATTRIBUTES_EVAL_RULE = "vbrief/.triage-cache/*.jsonl merge=union";
|
|
38
44
|
export const FORBIDDEN_BLANKET_EVAL_LINES = [
|
|
@@ -154,8 +160,14 @@ operators should know:
|
|
|
154
160
|
`;
|
|
155
161
|
/** Layout-aware triage-cache README body for the active lifecycle tree (#2344 / #2349). */
|
|
156
162
|
export function generateTriageCacheReadmeBody(projectRoot) {
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
let artifactDir;
|
|
164
|
+
try {
|
|
165
|
+
artifactDir = resolveLifecycleLayout(projectRoot).artifactDir;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
artifactDir = MIGRATED_ARTIFACT_DIR; // No layout; default to xbrief/.
|
|
169
|
+
}
|
|
170
|
+
const triagePrefix = `${artifactDir}/${TRIAGE_CACHE_DIR_NAME}`;
|
|
159
171
|
return EVAL_README_BODY.replaceAll("vbrief/.triage-cache", triagePrefix);
|
|
160
172
|
}
|
|
161
173
|
function stepOutcome(name, ok, message, details = {}, error = null) {
|
|
@@ -2,7 +2,7 @@ import type { BootstrapResult, CacheModule, RunBootstrapOptions, StepOutcome } f
|
|
|
2
2
|
export * from "./gitignore.js";
|
|
3
3
|
export * from "./types.js";
|
|
4
4
|
export declare const CACHE_DIR_NAME = ".deft-cache";
|
|
5
|
-
export declare const AUDIT_LOG_RELPATH = "
|
|
5
|
+
export declare const AUDIT_LOG_RELPATH = "xbrief/.triage-cache/candidates.jsonl";
|
|
6
6
|
export declare const BACKFILL_FOLDERS: readonly ["proposed", "pending", "active"];
|
|
7
7
|
export declare const BOOTSTRAP_ACTOR = "agent:bootstrap";
|
|
8
8
|
export declare const DEFAULT_FETCH_TIMEOUT_S = 3600;
|
|
@@ -11,7 +11,7 @@ import { PROGRESS_DEFAULT } from "./types.js";
|
|
|
11
11
|
export * from "./gitignore.js";
|
|
12
12
|
export * from "./types.js";
|
|
13
13
|
export const CACHE_DIR_NAME = ".deft-cache";
|
|
14
|
-
export const AUDIT_LOG_RELPATH = "
|
|
14
|
+
export const AUDIT_LOG_RELPATH = "xbrief/.triage-cache/candidates.jsonl";
|
|
15
15
|
export const BACKFILL_FOLDERS = ["proposed", "pending", "active"];
|
|
16
16
|
export const BOOTSTRAP_ACTOR = "agent:bootstrap";
|
|
17
17
|
export const DEFAULT_FETCH_TIMEOUT_S = 3600;
|
|
@@ -374,9 +374,15 @@ export function stepBackfillAuditLog(projectRoot, repo, options = {}) {
|
|
|
374
374
|
if (repo === null) {
|
|
375
375
|
return stepOutcome("backfill_audit_log", true, "skipped (no --repo provided; pass --repo OWNER/NAME to backfill)", { skipped: "no-repo" });
|
|
376
376
|
}
|
|
377
|
-
|
|
377
|
+
let vbriefRoot;
|
|
378
|
+
try {
|
|
379
|
+
vbriefRoot = resolveLifecycleRoot(projectRoot);
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
return stepOutcome("backfill_audit_log", true, `skipped (no xbrief/ layout under ${projectRoot})`, { skipped: "no-xbrief" });
|
|
383
|
+
}
|
|
378
384
|
if (!existsSync(vbriefRoot)) {
|
|
379
|
-
return stepOutcome("backfill_audit_log", true, `skipped (no
|
|
385
|
+
return stepOutcome("backfill_audit_log", true, `skipped (no xbrief/ directory under ${projectRoot})`, { skipped: "no-xbrief" });
|
|
380
386
|
}
|
|
381
387
|
const auditPath = resolveCandidatesLogPath(projectRoot);
|
|
382
388
|
const alreadyLogged = existingAuditIssueNumbers(auditPath);
|
|
@@ -33,7 +33,7 @@ export declare function resolveTriageCachePath(projectRoot: string, ...segments:
|
|
|
33
33
|
/** Display helper: project-root-relative POSIX path for logs and gitignore copy. */
|
|
34
34
|
export declare function triageCacheDisplayPath(projectRoot: string, absPath: string): string;
|
|
35
35
|
/** Back-compat display constant; resolution flows through `resolveTriageCachePath`. */
|
|
36
|
-
export declare const TRIAGE_CANDIDATES_LOG_REL_PATH = "
|
|
36
|
+
export declare const TRIAGE_CANDIDATES_LOG_REL_PATH = "xbrief/.triage-cache/candidates.jsonl";
|
|
37
37
|
/** Layout-aware candidates audit-log path. */
|
|
38
38
|
export declare function resolveCandidatesLogPath(projectRoot: string): string;
|
|
39
39
|
/** Ensure the triage cache directory exists (post-migration). */
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { existsSync, mkdirSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { join, relative } from "node:path";
|
|
9
|
-
import { resolveEvalDir, resolveLifecycleLayout, resolveLifecycleRoot } from "../layout/resolve.js";
|
|
9
|
+
import { MIGRATED_ARTIFACT_DIR, resolveEvalDir, resolveLifecycleLayout, resolveLifecycleRoot, } from "../layout/resolve.js";
|
|
10
10
|
import { generateTriageCacheReadmeBody } from "./bootstrap/gitignore.js";
|
|
11
11
|
/** Directory name for the triage working-set cache (not version-eval results). */
|
|
12
12
|
export const TRIAGE_CACHE_DIR_NAME = ".triage-cache";
|
|
@@ -26,19 +26,45 @@ export const TRIAGE_CACHE_FILE_NAMES = [
|
|
|
26
26
|
export const TRIAGE_CACHE_DIR_NAMES = ["decompositions"];
|
|
27
27
|
/** Absolute path to the layout-aware `.triage-cache/` directory. */
|
|
28
28
|
export function resolveTriageCacheDir(projectRoot) {
|
|
29
|
-
|
|
29
|
+
let layoutRoot;
|
|
30
|
+
try {
|
|
31
|
+
layoutRoot = resolveLifecycleRoot(projectRoot);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
layoutRoot = join(projectRoot, MIGRATED_ARTIFACT_DIR); // No xbrief/ layout; use canonical path.
|
|
35
|
+
}
|
|
36
|
+
return join(layoutRoot, TRIAGE_CACHE_DIR_NAME);
|
|
30
37
|
}
|
|
31
38
|
/** POSIX-style path relative to project root (e.g. `xbrief/.triage-cache/foo`). */
|
|
32
39
|
export function triageCacheRelPath(projectRoot, ...segments) {
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
let artifactDir;
|
|
41
|
+
try {
|
|
42
|
+
const layout = resolveLifecycleLayout(projectRoot);
|
|
43
|
+
artifactDir = layout.artifactDir;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
artifactDir = "xbrief"; // No layout; default to xbrief/ path for display purposes.
|
|
47
|
+
}
|
|
48
|
+
return [artifactDir, TRIAGE_CACHE_DIR_NAME, ...segments].join("/");
|
|
35
49
|
}
|
|
36
50
|
/**
|
|
37
51
|
* Idempotently move triage working-set artefacts from legacy `.eval/` into
|
|
38
52
|
* `.triage-cache/` when the new location is absent.
|
|
39
53
|
*/
|
|
40
54
|
export function migrateLegacyTriageCacheFromEval(projectRoot) {
|
|
41
|
-
|
|
55
|
+
let legacyDir;
|
|
56
|
+
try {
|
|
57
|
+
legacyDir = resolveEvalDir(projectRoot);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return {
|
|
61
|
+
migratedFiles: [],
|
|
62
|
+
skippedFiles: [],
|
|
63
|
+
migratedDirs: [],
|
|
64
|
+
regeneratedFiles: [],
|
|
65
|
+
removedLegacyFiles: [],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
42
68
|
const targetDir = resolveTriageCacheDir(projectRoot);
|
|
43
69
|
const migratedFiles = [];
|
|
44
70
|
const skippedFiles = [];
|
|
@@ -100,7 +126,7 @@ export function triageCacheDisplayPath(projectRoot, absPath) {
|
|
|
100
126
|
return relative(projectRoot, absPath).split(/[\\/]/).join("/");
|
|
101
127
|
}
|
|
102
128
|
/** Back-compat display constant; resolution flows through `resolveTriageCachePath`. */
|
|
103
|
-
export const TRIAGE_CANDIDATES_LOG_REL_PATH = "
|
|
129
|
+
export const TRIAGE_CANDIDATES_LOG_REL_PATH = "xbrief/.triage-cache/candidates.jsonl";
|
|
104
130
|
/** Layout-aware candidates audit-log path. */
|
|
105
131
|
export function resolveCandidatesLogPath(projectRoot) {
|
|
106
132
|
return resolveTriageCachePath(projectRoot, "candidates.jsonl");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Filesystem-relative location of the PROJECT-DEFINITION vBRIEF. */
|
|
2
|
-
export declare const PROJECT_DEFINITION_REL_PATH = "
|
|
2
|
+
export declare const PROJECT_DEFINITION_REL_PATH = "xbrief/PROJECT-DEFINITION.xbrief.json";
|
|
3
3
|
/** Threshold in days for the "dormant" universal rule (Decision 1). */
|
|
4
4
|
export declare const DORMANT_AGE_DAYS = 90;
|
|
5
5
|
/** Threshold in characters for "thin body" used by the dormant rule. */
|
|
@@ -30,7 +30,7 @@ function pythonRepr(value) {
|
|
|
30
30
|
return pyRepr(value);
|
|
31
31
|
}
|
|
32
32
|
/** Filesystem-relative location of the PROJECT-DEFINITION vBRIEF. */
|
|
33
|
-
export const PROJECT_DEFINITION_REL_PATH = "
|
|
33
|
+
export const PROJECT_DEFINITION_REL_PATH = "xbrief/PROJECT-DEFINITION.xbrief.json";
|
|
34
34
|
/** Threshold in days for the "dormant" universal rule (Decision 1). */
|
|
35
35
|
export const DORMANT_AGE_DAYS = 90;
|
|
36
36
|
/** Threshold in characters for "thin body" used by the dormant rule. */
|
|
@@ -255,7 +255,14 @@ export function validateHoldMarkers(markers) {
|
|
|
255
255
|
return { errors, warnings };
|
|
256
256
|
}
|
|
257
257
|
export function projectDefinitionPath(projectRoot) {
|
|
258
|
-
|
|
258
|
+
const root = projectRoot ?? process.cwd();
|
|
259
|
+
try {
|
|
260
|
+
return resolveProjectDefinitionPath(root);
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// No xbrief/ layout; return canonical path so callers get a predictable "not found" result.
|
|
264
|
+
return join(root, "xbrief", "PROJECT-DEFINITION.xbrief.json");
|
|
265
|
+
}
|
|
259
266
|
}
|
|
260
267
|
function loadProjectDefinition(projectRoot) {
|
|
261
268
|
const path = projectDefinitionPath(projectRoot);
|
|
@@ -698,7 +705,7 @@ export function validateProject(projectRoot) {
|
|
|
698
705
|
return {
|
|
699
706
|
code: 0,
|
|
700
707
|
stdout: "OK: no PROJECT-DEFINITION at " +
|
|
701
|
-
`${
|
|
708
|
+
`${projectDefinitionPath(root)} -- ` +
|
|
702
709
|
"framework defaults apply with no consumer overrides.\n",
|
|
703
710
|
stderr: "",
|
|
704
711
|
};
|
|
@@ -711,7 +718,7 @@ export function validateProject(projectRoot) {
|
|
|
711
718
|
stderr: "FAIL: PROJECT-DEFINITION.plan is not an object\n",
|
|
712
719
|
};
|
|
713
720
|
}
|
|
714
|
-
const rel =
|
|
721
|
+
const rel = projectDefinitionPath(root);
|
|
715
722
|
const classifyErrs = validateTriageAutoClassifyOnPlan(plan, rel);
|
|
716
723
|
const holderErrs = validateTriageHoldMarkersOnPlan(plan, rel);
|
|
717
724
|
const errors = [...classifyErrs, ...holderErrs];
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Hand-maintained help registry. Edit directly; no generator script. */
|
|
2
2
|
export declare const registryData: {
|
|
3
3
|
readonly registry: {
|
|
4
4
|
readonly "task triage:summary": {
|
|
5
5
|
readonly name: "task triage:summary";
|
|
6
6
|
readonly summary: "One-line state for session-start ritual";
|
|
7
7
|
readonly refs: "(D2 / #1122)";
|
|
8
|
-
readonly description: "Emit the one-line triage state consumed by the session-start ritual. Always exits 0 (status surface, not a gate); appends a JSONL record to
|
|
8
|
+
readonly description: "Emit the one-line triage state consumed by the session-start ritual. Always exits 0 (status surface, not a gate); appends a JSONL record to <lifecycle-root>/.triage-cache/summary-history.jsonl for observability.";
|
|
9
9
|
readonly usage: "task triage:summary [-- --json] [--no-history]";
|
|
10
10
|
readonly flags: readonly [readonly ["--json", "(off)", "Emit the structured record as JSON instead of the one-liner."], readonly ["--no-history", "(off)", "Suppress the history sidecar append (test-only)."], readonly ["--project-root PATH", "(cwd)", "Project root override (Taskfile threads USER_WORKING_DIR)."]];
|
|
11
11
|
readonly examples: readonly ["task triage:summary", "task triage:summary -- --json | jq"];
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Hand-maintained help registry. Edit directly; no generator script. */
|
|
2
2
|
export const registryData = {
|
|
3
3
|
registry: {
|
|
4
4
|
"task triage:summary": {
|
|
5
5
|
name: "task triage:summary",
|
|
6
6
|
summary: "One-line state for session-start ritual",
|
|
7
7
|
refs: "(D2 / #1122)",
|
|
8
|
-
description: "Emit the one-line triage state consumed by the session-start ritual. Always exits 0 (status surface, not a gate); appends a JSONL record to
|
|
8
|
+
description: "Emit the one-line triage state consumed by the session-start ritual. Always exits 0 (status surface, not a gate); appends a JSONL record to <lifecycle-root>/.triage-cache/summary-history.jsonl for observability.",
|
|
9
9
|
usage: "task triage:summary [-- --json] [--no-history]",
|
|
10
10
|
flags: [
|
|
11
11
|
["--json", "(off)", "Emit the structured record as JSON instead of the one-liner."],
|
|
@@ -4,14 +4,14 @@ export declare const CACHE_DIR_NAME = ".deft-cache";
|
|
|
4
4
|
export declare const CACHE_SOURCE_GITHUB_ISSUE = "github-issue";
|
|
5
5
|
/** Env var honoured for repo inference when `--repo` is absent (#1238). */
|
|
6
6
|
export declare const ENV_TRIAGE_REPO = "DEFT_TRIAGE_REPO";
|
|
7
|
-
/** PROJECT-DEFINITION
|
|
8
|
-
export declare const PROJECT_DEFINITION_REL_PATH = "
|
|
7
|
+
/** PROJECT-DEFINITION xBRIEF location for typed-policy lookup. */
|
|
8
|
+
export declare const PROJECT_DEFINITION_REL_PATH = "xbrief/PROJECT-DEFINITION.xbrief.json";
|
|
9
9
|
/** Default queue limit when `--limit` is omitted on the CLI surface. */
|
|
10
10
|
export declare const DEFAULT_QUEUE_LIMIT = 25;
|
|
11
11
|
/** Default audit log path relative to the deft framework root (candidates_log.REPO_ROOT). */
|
|
12
|
-
export declare const DEFAULT_AUDIT_LOG_REL_PATH = "
|
|
12
|
+
export declare const DEFAULT_AUDIT_LOG_REL_PATH = "xbrief/.triage-cache/candidates.jsonl";
|
|
13
13
|
/** Default slices log path relative to project root. */
|
|
14
|
-
export declare const DEFAULT_SLICES_LOG_REL_PATH = "
|
|
14
|
+
export declare const DEFAULT_SLICES_LOG_REL_PATH = "xbrief/.triage-cache/slices.jsonl";
|
|
15
15
|
/** Group display order (#1128 / D13 / #1286). */
|
|
16
16
|
export declare const GROUP_ORDER: readonly ["ORPHAN", "RESUME", "URGENT", "untriaged", "other", "BLOCKED"];
|
|
17
17
|
export type QueueGroup = (typeof GROUP_ORDER)[number];
|
|
@@ -4,14 +4,14 @@ export const CACHE_DIR_NAME = ".deft-cache";
|
|
|
4
4
|
export const CACHE_SOURCE_GITHUB_ISSUE = "github-issue";
|
|
5
5
|
/** Env var honoured for repo inference when `--repo` is absent (#1238). */
|
|
6
6
|
export const ENV_TRIAGE_REPO = "DEFT_TRIAGE_REPO";
|
|
7
|
-
/** PROJECT-DEFINITION
|
|
8
|
-
export const PROJECT_DEFINITION_REL_PATH = "
|
|
7
|
+
/** PROJECT-DEFINITION xBRIEF location for typed-policy lookup. */
|
|
8
|
+
export const PROJECT_DEFINITION_REL_PATH = "xbrief/PROJECT-DEFINITION.xbrief.json";
|
|
9
9
|
/** Default queue limit when `--limit` is omitted on the CLI surface. */
|
|
10
10
|
export const DEFAULT_QUEUE_LIMIT = 25;
|
|
11
11
|
/** Default audit log path relative to the deft framework root (candidates_log.REPO_ROOT). */
|
|
12
|
-
export const DEFAULT_AUDIT_LOG_REL_PATH = "
|
|
12
|
+
export const DEFAULT_AUDIT_LOG_REL_PATH = "xbrief/.triage-cache/candidates.jsonl";
|
|
13
13
|
/** Default slices log path relative to project root. */
|
|
14
|
-
export const DEFAULT_SLICES_LOG_REL_PATH = "
|
|
14
|
+
export const DEFAULT_SLICES_LOG_REL_PATH = "xbrief/.triage-cache/slices.jsonl";
|
|
15
15
|
/** Group display order (#1128 / D13 / #1286). */
|
|
16
16
|
export const GROUP_ORDER = ["ORPHAN", "RESUME", "URGENT", "untriaged", "other", "BLOCKED"];
|
|
17
17
|
/** Display labels per group (left-of-issue marker). */
|
|
@@ -113,7 +113,13 @@ export function scopeIsBlocked(plan, completedIds) {
|
|
|
113
113
|
return deps.length > 0 && deps.some((dep) => !completedIds.has(dep));
|
|
114
114
|
}
|
|
115
115
|
function walkScopeFolders(projectRoot, folders, visitor) {
|
|
116
|
-
|
|
116
|
+
let base;
|
|
117
|
+
try {
|
|
118
|
+
base = resolveLifecycleRoot(projectRoot);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return; // No xbrief/ layout present -- nothing to walk.
|
|
122
|
+
}
|
|
117
123
|
for (const folder of folders) {
|
|
118
124
|
const folderDir = join(base, folder);
|
|
119
125
|
if (!existsSync(folderDir)) {
|