@delete101020/aidlc 4.0.7 → 4.0.10
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/bundle.js +246 -34
- package/dist/templates/sdlc/validators/traceability.mjs +57 -14
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -19837,6 +19837,17 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
19837
19837
|
name: zod_1.z.string().optional(),
|
|
19838
19838
|
/** Step is part of the pipeline but skipped at run time when false. Defaults to true. */
|
|
19839
19839
|
enabled: zod_1.z.boolean().default(true),
|
|
19840
|
+
/**
|
|
19841
|
+
* A step the run may fail and carry on past. Its rejection never marks the
|
|
19842
|
+
* epic failed, never parks the run cursor, and never keeps the run from
|
|
19843
|
+
* completing; the autopilot loop steps over it to whatever else is open.
|
|
19844
|
+
*
|
|
19845
|
+
* For the side branch whose findings are welcome but not required — a
|
|
19846
|
+
* second reviewer's lens, an optional QC pass. Without the flag the only
|
|
19847
|
+
* thing making such a step skippable is that nothing happens to
|
|
19848
|
+
* `depends_on` it, which the runner cannot tell from an oversight.
|
|
19849
|
+
*/
|
|
19850
|
+
optional: zod_1.z.boolean().default(false),
|
|
19840
19851
|
/** Artifact paths the step is expected to produce. Checked after work. */
|
|
19841
19852
|
produces: zod_1.z.array(zod_1.z.string().min(1)).default([]),
|
|
19842
19853
|
/**
|
|
@@ -19969,6 +19980,7 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
19969
19980
|
return {
|
|
19970
19981
|
agent: step,
|
|
19971
19982
|
enabled: true,
|
|
19983
|
+
optional: false,
|
|
19972
19984
|
produces: [],
|
|
19973
19985
|
produces_contains: [],
|
|
19974
19986
|
requires: [],
|
|
@@ -19994,6 +20006,7 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
19994
20006
|
name: typeof obj.name === "string" ? obj.name : void 0,
|
|
19995
20007
|
skills,
|
|
19996
20008
|
enabled: typeof obj.enabled === "boolean" ? obj.enabled : true,
|
|
20009
|
+
optional: obj.optional === true,
|
|
19997
20010
|
produces,
|
|
19998
20011
|
produces_contains,
|
|
19999
20012
|
requires,
|
|
@@ -20752,6 +20765,83 @@ var require_RunState = __commonJS({
|
|
|
20752
20765
|
}
|
|
20753
20766
|
});
|
|
20754
20767
|
|
|
20768
|
+
// ../core/dist/runs/runProgress.js
|
|
20769
|
+
var require_runProgress = __commonJS({
|
|
20770
|
+
"../core/dist/runs/runProgress.js"(exports2) {
|
|
20771
|
+
"use strict";
|
|
20772
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
20773
|
+
exports2.isActiveStatus = isActiveStatus;
|
|
20774
|
+
exports2.isStepOptional = isStepOptional;
|
|
20775
|
+
exports2.deriveRunProgress = deriveRunProgress;
|
|
20776
|
+
exports2.isRunComplete = isRunComplete;
|
|
20777
|
+
var WorkspaceSchema_1 = require_WorkspaceSchema();
|
|
20778
|
+
var ACTIVE = /* @__PURE__ */ new Set([
|
|
20779
|
+
"awaiting_work",
|
|
20780
|
+
"awaiting_auto_review",
|
|
20781
|
+
"awaiting_review"
|
|
20782
|
+
]);
|
|
20783
|
+
function isActiveStatus(status) {
|
|
20784
|
+
return ACTIVE.has(status);
|
|
20785
|
+
}
|
|
20786
|
+
function isStepOptional(pipeline, idx) {
|
|
20787
|
+
const cfg = pipeline?.steps?.[idx];
|
|
20788
|
+
return cfg === void 0 ? false : (0, WorkspaceSchema_1.normalizeStep)(cfg).optional;
|
|
20789
|
+
}
|
|
20790
|
+
function usesDag(pipeline) {
|
|
20791
|
+
return pipeline.steps.some((s) => (0, WorkspaceSchema_1.normalizeStep)(s).depends_on.length > 0);
|
|
20792
|
+
}
|
|
20793
|
+
function deriveRunProgress(state, pipeline) {
|
|
20794
|
+
const dag = pipeline ? usesDag(pipeline) : false;
|
|
20795
|
+
const approvedDagIds = /* @__PURE__ */ new Set();
|
|
20796
|
+
if (pipeline && dag) {
|
|
20797
|
+
state.steps.forEach((s, i) => {
|
|
20798
|
+
if (s.status !== "approved") {
|
|
20799
|
+
return;
|
|
20800
|
+
}
|
|
20801
|
+
const norm = (0, WorkspaceSchema_1.normalizeStep)(pipeline.steps[i] ?? { agent: s.agent });
|
|
20802
|
+
approvedDagIds.add(norm.name ?? norm.agent);
|
|
20803
|
+
});
|
|
20804
|
+
}
|
|
20805
|
+
const actionable = [];
|
|
20806
|
+
const rejected = [];
|
|
20807
|
+
const blocking = [];
|
|
20808
|
+
state.steps.forEach((s, i) => {
|
|
20809
|
+
if (isActiveStatus(s.status)) {
|
|
20810
|
+
actionable.push(i);
|
|
20811
|
+
return;
|
|
20812
|
+
}
|
|
20813
|
+
if (s.status === "rejected") {
|
|
20814
|
+
rejected.push(i);
|
|
20815
|
+
if (!isStepOptional(pipeline, i)) {
|
|
20816
|
+
blocking.push(i);
|
|
20817
|
+
}
|
|
20818
|
+
return;
|
|
20819
|
+
}
|
|
20820
|
+
if (s.status === "pending" && pipeline && dag) {
|
|
20821
|
+
const deps = (0, WorkspaceSchema_1.normalizeStep)(pipeline.steps[i] ?? { agent: s.agent }).depends_on;
|
|
20822
|
+
if (deps.length > 0 && deps.every((d) => approvedDagIds.has(d))) {
|
|
20823
|
+
actionable.push(i);
|
|
20824
|
+
}
|
|
20825
|
+
}
|
|
20826
|
+
});
|
|
20827
|
+
const stuck = blocking.length > 0 && actionable.length === 0;
|
|
20828
|
+
const status = state.status === "completed" ? "done" : stuck ? "failed" : "in_progress";
|
|
20829
|
+
return { actionable, rejected, blocking, stuck, status };
|
|
20830
|
+
}
|
|
20831
|
+
function isRunComplete(state, pipeline) {
|
|
20832
|
+
return state.steps.every((s, i) => {
|
|
20833
|
+
if (s.status === "approved") {
|
|
20834
|
+
return true;
|
|
20835
|
+
}
|
|
20836
|
+
if (!isStepOptional(pipeline, i)) {
|
|
20837
|
+
return false;
|
|
20838
|
+
}
|
|
20839
|
+
return s.status === "rejected" || s.status === "pending";
|
|
20840
|
+
});
|
|
20841
|
+
}
|
|
20842
|
+
}
|
|
20843
|
+
});
|
|
20844
|
+
|
|
20755
20845
|
// ../core/dist/runs/reconcileRun.js
|
|
20756
20846
|
var require_reconcileRun = __commonJS({
|
|
20757
20847
|
"../core/dist/runs/reconcileRun.js"(exports2) {
|
|
@@ -20911,6 +21001,7 @@ var require_PipelineRunner = __commonJS({
|
|
|
20911
21001
|
exports2.canStartStep = canStartStep;
|
|
20912
21002
|
exports2.markStepDone = markStepDone3;
|
|
20913
21003
|
exports2.submitAutoReviewVerdict = submitAutoReviewVerdict2;
|
|
21004
|
+
exports2.retryAutoReview = retryAutoReview;
|
|
20914
21005
|
exports2.approveStep = approveStep3;
|
|
20915
21006
|
exports2.rejectStep = rejectStep3;
|
|
20916
21007
|
exports2.rerunStep = rerunStep3;
|
|
@@ -20919,6 +21010,7 @@ var require_PipelineRunner = __commonJS({
|
|
|
20919
21010
|
var path17 = __importStar(require("path"));
|
|
20920
21011
|
var WorkspaceSchema_1 = require_WorkspaceSchema();
|
|
20921
21012
|
var RunState_1 = require_RunState();
|
|
21013
|
+
var runProgress_1 = require_runProgress();
|
|
20922
21014
|
var reconcileRun_1 = require_reconcileRun();
|
|
20923
21015
|
var PipelineRunError3 = class extends Error {
|
|
20924
21016
|
missing;
|
|
@@ -21098,6 +21190,7 @@ var require_PipelineRunner = __commonJS({
|
|
|
21098
21190
|
sentBackToIdx: idx
|
|
21099
21191
|
});
|
|
21100
21192
|
next.status = "running";
|
|
21193
|
+
settleOptionalRejection(next, idx, pipeline);
|
|
21101
21194
|
return next;
|
|
21102
21195
|
}
|
|
21103
21196
|
if (norm.human_review) {
|
|
@@ -21107,6 +21200,37 @@ var require_PipelineRunner = __commonJS({
|
|
|
21107
21200
|
}
|
|
21108
21201
|
return advance(next, idx, pipeline);
|
|
21109
21202
|
}
|
|
21203
|
+
function retryAutoReview(args) {
|
|
21204
|
+
const { pipeline } = args;
|
|
21205
|
+
const state = alignedOrThrow(args.state, pipeline);
|
|
21206
|
+
const idx = args.stepIdx ?? state.currentStepIdx;
|
|
21207
|
+
const step = state.steps[idx];
|
|
21208
|
+
if (!step) {
|
|
21209
|
+
throw new PipelineRunError3(`No step at index ${idx}`);
|
|
21210
|
+
}
|
|
21211
|
+
if (step.status !== "rejected") {
|
|
21212
|
+
throw new PipelineRunError3(`Cannot re-run auto-review for step "${step.agent}": status is "${step.status}", expected "rejected"`);
|
|
21213
|
+
}
|
|
21214
|
+
if (step.autoReviewVerdict?.decision !== "reject") {
|
|
21215
|
+
throw new PipelineRunError3(`Step "${step.agent}" was not rejected by its auto-reviewer \u2014 rerun it instead.`);
|
|
21216
|
+
}
|
|
21217
|
+
const stepConfig = pipeline.steps[idx];
|
|
21218
|
+
if (!stepConfig) {
|
|
21219
|
+
throw new PipelineRunError3(`Pipeline mismatch \u2014 step "${(0, RunState_1.stepIdentity)(step)}" is at index ${idx}, which pipeline "${pipeline.id}" does not have.`);
|
|
21220
|
+
}
|
|
21221
|
+
if (!(0, WorkspaceSchema_1.normalizeStep)(stepConfig).auto_review) {
|
|
21222
|
+
throw new PipelineRunError3(`Step "${step.agent}" no longer has auto_review enabled in pipeline "${pipeline.id}".`);
|
|
21223
|
+
}
|
|
21224
|
+
const next = clone(state);
|
|
21225
|
+
next.steps[idx] = {
|
|
21226
|
+
...step,
|
|
21227
|
+
status: "awaiting_auto_review",
|
|
21228
|
+
rejectReason: void 0,
|
|
21229
|
+
autoReviewVerdict: void 0
|
|
21230
|
+
};
|
|
21231
|
+
next.status = "running";
|
|
21232
|
+
return next;
|
|
21233
|
+
}
|
|
21110
21234
|
function approveStep3(args) {
|
|
21111
21235
|
const { pipeline } = args;
|
|
21112
21236
|
const state = alignedOrThrow(args.state, pipeline);
|
|
@@ -21207,6 +21331,9 @@ var require_PipelineRunner = __commonJS({
|
|
|
21207
21331
|
})
|
|
21208
21332
|
};
|
|
21209
21333
|
next.status = "running";
|
|
21334
|
+
if (pipeline) {
|
|
21335
|
+
settleOptionalRejection(next, idx, pipeline);
|
|
21336
|
+
}
|
|
21210
21337
|
return next;
|
|
21211
21338
|
}
|
|
21212
21339
|
function rerunStep3(args) {
|
|
@@ -21325,7 +21452,7 @@ var require_PipelineRunner = __commonJS({
|
|
|
21325
21452
|
}
|
|
21326
21453
|
const dagId = (i) => normalized[i].name ?? normalized[i].agent;
|
|
21327
21454
|
const approvedDagIds = new Set(next.steps.filter((s) => s.status === "approved").map((s) => dagId(s.stepIdx)));
|
|
21328
|
-
|
|
21455
|
+
const opened = [];
|
|
21329
21456
|
for (let i = 0; i < normalized.length; i++) {
|
|
21330
21457
|
const sStep = next.steps[i];
|
|
21331
21458
|
if (sStep.status !== "pending") {
|
|
@@ -21344,25 +21471,47 @@ var require_PipelineRunner = __commonJS({
|
|
|
21344
21471
|
status: "awaiting_work",
|
|
21345
21472
|
startedAt: finishedAt
|
|
21346
21473
|
};
|
|
21347
|
-
|
|
21348
|
-
if (next.currentStepIdx === idx) {
|
|
21349
|
-
next.currentStepIdx = i;
|
|
21350
|
-
}
|
|
21474
|
+
opened.push(i);
|
|
21351
21475
|
}
|
|
21352
|
-
|
|
21353
|
-
if (allApproved) {
|
|
21476
|
+
if ((0, runProgress_1.isRunComplete)(next, pipeline)) {
|
|
21354
21477
|
next.status = "completed";
|
|
21355
21478
|
return next;
|
|
21356
21479
|
}
|
|
21357
|
-
|
|
21358
|
-
const stillActive = next.steps.findIndex((s) => s.status === "awaiting_work" || s.status === "awaiting_auto_review" || s.status === "awaiting_review");
|
|
21359
|
-
if (stillActive >= 0) {
|
|
21360
|
-
next.currentStepIdx = stillActive;
|
|
21361
|
-
}
|
|
21362
|
-
}
|
|
21480
|
+
refocusCursor(next, opened);
|
|
21363
21481
|
next.status = "running";
|
|
21364
21482
|
return next;
|
|
21365
21483
|
}
|
|
21484
|
+
function refocusCursor(next, opened) {
|
|
21485
|
+
const cur = next.steps[next.currentStepIdx];
|
|
21486
|
+
if (cur && cur.status !== "approved" && cur.status !== "rejected") {
|
|
21487
|
+
return;
|
|
21488
|
+
}
|
|
21489
|
+
const target = opened.length > 0 ? Math.min(...opened) : next.steps.findIndex((s) => (0, runProgress_1.isActiveStatus)(s.status));
|
|
21490
|
+
if (target >= 0) {
|
|
21491
|
+
next.currentStepIdx = target;
|
|
21492
|
+
}
|
|
21493
|
+
}
|
|
21494
|
+
function settleOptionalRejection(next, idx, pipeline) {
|
|
21495
|
+
if (!(0, runProgress_1.isStepOptional)(pipeline, idx)) {
|
|
21496
|
+
return;
|
|
21497
|
+
}
|
|
21498
|
+
const normalized = pipeline.steps.map(WorkspaceSchema_1.normalizeStep);
|
|
21499
|
+
const usesDag = normalized.some((s) => s.depends_on.length > 0);
|
|
21500
|
+
if (!usesDag) {
|
|
21501
|
+
const follower = next.steps[idx + 1];
|
|
21502
|
+
if (follower && follower.status === "pending") {
|
|
21503
|
+
next.steps[idx + 1] = {
|
|
21504
|
+
...follower,
|
|
21505
|
+
status: "awaiting_work",
|
|
21506
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21507
|
+
};
|
|
21508
|
+
}
|
|
21509
|
+
}
|
|
21510
|
+
refocusCursor(next, []);
|
|
21511
|
+
if ((0, runProgress_1.isRunComplete)(next, pipeline)) {
|
|
21512
|
+
next.status = "completed";
|
|
21513
|
+
}
|
|
21514
|
+
}
|
|
21366
21515
|
function clone(value) {
|
|
21367
21516
|
return JSON.parse(JSON.stringify(value));
|
|
21368
21517
|
}
|
|
@@ -25053,6 +25202,7 @@ var require_EpicScaffold = __commonJS({
|
|
|
25053
25202
|
var fs14 = __importStar(require("fs"));
|
|
25054
25203
|
var path17 = __importStar(require("path"));
|
|
25055
25204
|
var PipelineRunner_1 = require_PipelineRunner();
|
|
25205
|
+
var runProgress_1 = require_runProgress();
|
|
25056
25206
|
var RunStateStore_1 = require_RunStateStore();
|
|
25057
25207
|
var EpicPipelineStore_1 = require_EpicPipelineStore();
|
|
25058
25208
|
var epicTags_1 = require_epicTags();
|
|
@@ -25100,7 +25250,9 @@ var require_EpicScaffold = __commonJS({
|
|
|
25100
25250
|
} catch {
|
|
25101
25251
|
return;
|
|
25102
25252
|
}
|
|
25103
|
-
const
|
|
25253
|
+
const pipelines = Array.isArray(doc?.pipelines) ? doc.pipelines : [];
|
|
25254
|
+
const pipeline = pipelines.find((p) => p.id === runState.pipelineId);
|
|
25255
|
+
const epicStatus = (0, runProgress_1.deriveRunProgress)(runState, pipeline).status;
|
|
25104
25256
|
const stepStates = runState.steps.map((s) => ({
|
|
25105
25257
|
agent: s.agent,
|
|
25106
25258
|
// The step's identity, mirrored alongside its agent so state.json says
|
|
@@ -29409,6 +29561,7 @@ var require_execEngine = __commonJS({
|
|
|
29409
29561
|
var AutoReviewer_1 = require_AutoReviewer();
|
|
29410
29562
|
var EpicArtifactCommit_1 = require_EpicArtifactCommit();
|
|
29411
29563
|
var EpicScaffold_1 = require_EpicScaffold();
|
|
29564
|
+
var runProgress_1 = require_runProgress();
|
|
29412
29565
|
var budget_1 = require_budget();
|
|
29413
29566
|
var pricing_1 = require_pricing();
|
|
29414
29567
|
var models_1 = require_models();
|
|
@@ -29473,9 +29626,34 @@ var require_execEngine = __commonJS({
|
|
|
29473
29626
|
return { kind: "awaiting_review" };
|
|
29474
29627
|
}
|
|
29475
29628
|
if (step.status === "rejected") {
|
|
29629
|
+
const skippable = (0, runProgress_1.isStepOptional)(initialPipeline, state.currentStepIdx) || initialPipeline.on_failure === "continue";
|
|
29630
|
+
const openElsewhere = state.steps.findIndex((s, i) => i !== state.currentStepIdx && (0, runProgress_1.isActiveStatus)(s.status));
|
|
29631
|
+
if (skippable && openElsewhere >= 0) {
|
|
29632
|
+
hooks.onStepSkipped?.({
|
|
29633
|
+
stepIdx: state.currentStepIdx,
|
|
29634
|
+
agent: step.agent,
|
|
29635
|
+
reason: step.rejectReason ?? step.autoReviewVerdict?.reason ?? "rejected",
|
|
29636
|
+
nextStepIdx: openElsewhere,
|
|
29637
|
+
runId
|
|
29638
|
+
});
|
|
29639
|
+
RunStateStore_1.RunStateStore.save(root, { ...state, currentStepIdx: openElsewhere });
|
|
29640
|
+
continue;
|
|
29641
|
+
}
|
|
29476
29642
|
hooks.onRejected?.({ agent: step.agent, runId });
|
|
29477
29643
|
return { kind: "rejected" };
|
|
29478
29644
|
}
|
|
29645
|
+
if (step.status === "approved") {
|
|
29646
|
+
const openElsewhere = state.steps.findIndex((s) => (0, runProgress_1.isActiveStatus)(s.status));
|
|
29647
|
+
if (openElsewhere >= 0) {
|
|
29648
|
+
RunStateStore_1.RunStateStore.save(root, { ...state, currentStepIdx: openElsewhere });
|
|
29649
|
+
continue;
|
|
29650
|
+
}
|
|
29651
|
+
const parked = state.steps.find((s) => s.status === "rejected");
|
|
29652
|
+
if (parked) {
|
|
29653
|
+
hooks.onRejected?.({ agent: parked.agent, runId });
|
|
29654
|
+
return { kind: "rejected" };
|
|
29655
|
+
}
|
|
29656
|
+
}
|
|
29479
29657
|
if (step.status !== "awaiting_work") {
|
|
29480
29658
|
hooks.onRunFailed?.(`Unexpected step status "${step.status}" \u2014 cannot exec.`);
|
|
29481
29659
|
return { kind: "error" };
|
|
@@ -31320,6 +31498,7 @@ var require_commandModel = __commonJS({
|
|
|
31320
31498
|
var strictMode_1 = require_strictMode();
|
|
31321
31499
|
var commandBodyFreshness_1 = require_commandBodyFreshness();
|
|
31322
31500
|
var WorkspaceSchema_1 = require_WorkspaceSchema();
|
|
31501
|
+
var runProgress_1 = require_runProgress();
|
|
31323
31502
|
exports2.CANONICAL_PHASES = [
|
|
31324
31503
|
{ id: "plan", name: "Plan", description: "Scaffold the epic and write the PRD.", artifact: "PRD.md" },
|
|
31325
31504
|
{ id: "prototype", name: "Prototype", description: "Propose the UI visually with multiple design options.", artifact: "PROTOTYPE.md" },
|
|
@@ -31386,14 +31565,14 @@ var require_commandModel = __commonJS({
|
|
|
31386
31565
|
};
|
|
31387
31566
|
const statusByDagId = /* @__PURE__ */ new Map();
|
|
31388
31567
|
state.steps.forEach((s, idx) => statusByDagId.set(dagId(idx), s.status));
|
|
31389
|
-
|
|
31390
|
-
|
|
31391
|
-
|
|
31392
|
-
|
|
31393
|
-
|
|
31394
|
-
|
|
31395
|
-
|
|
31396
|
-
}
|
|
31568
|
+
const open = state.steps.findIndex((s) => s.status === "awaiting_work");
|
|
31569
|
+
if (open >= 0) {
|
|
31570
|
+
return { index: open, phaseId: dagId(open), reason: "awaiting_work" };
|
|
31571
|
+
}
|
|
31572
|
+
const optional = (i) => (0, runProgress_1.isStepOptional)(pipeline, i);
|
|
31573
|
+
const blocked = state.steps.findIndex((s, i) => s.status === "rejected" && !optional(i));
|
|
31574
|
+
if (blocked >= 0) {
|
|
31575
|
+
return { index: blocked, phaseId: dagId(blocked), reason: "rejected" };
|
|
31397
31576
|
}
|
|
31398
31577
|
for (let i = 0; i < state.steps.length; i++) {
|
|
31399
31578
|
if (state.steps[i].status !== "pending") {
|
|
@@ -31406,6 +31585,10 @@ var require_commandModel = __commonJS({
|
|
|
31406
31585
|
return { index: i, phaseId: dagId(i), reason: "unblocked" };
|
|
31407
31586
|
}
|
|
31408
31587
|
}
|
|
31588
|
+
const skipped = state.steps.findIndex((s, i) => s.status === "rejected" && optional(i));
|
|
31589
|
+
if (skipped >= 0) {
|
|
31590
|
+
return { index: skipped, phaseId: dagId(skipped), reason: "rejected" };
|
|
31591
|
+
}
|
|
31409
31592
|
return null;
|
|
31410
31593
|
}
|
|
31411
31594
|
function unprovisionedPhases(config, canonical = exports2.CANONICAL_PHASE_IDS) {
|
|
@@ -31445,10 +31628,12 @@ The first token is the **epic id**; an optional second token is the **phase**.
|
|
|
31445
31628
|
- **If a phase was given**, use it. Validate it is a step in the epic's
|
|
31446
31629
|
pipeline (see step 3). If it isn't, tell the user which phases the pipeline
|
|
31447
31630
|
*does* have and stop.
|
|
31448
|
-
- **If no phase was given**, pick the **next eligible phase
|
|
31449
|
-
|
|
31450
|
-
\`
|
|
31451
|
-
|
|
31631
|
+
- **If no phase was given**, pick the **next eligible phase**, checking each
|
|
31632
|
+
rule against every step before moving to the next rule: any step that is
|
|
31633
|
+
\`awaiting_work\`, else any \`rejected\` step *not* marked \`optional: true\`,
|
|
31634
|
+
else the first \`pending\` step whose every \`depends_on\` is \`approved\`, else
|
|
31635
|
+
a \`rejected\` \`optional\` step. If none is actionable (all approved or
|
|
31636
|
+
paused for review), say so and stop.
|
|
31452
31637
|
|
|
31453
31638
|
## 3. Resolve composition from the pipeline (never from the command name)
|
|
31454
31639
|
|
|
@@ -32037,9 +32222,9 @@ var require_dist = __commonJS({
|
|
|
32037
32222
|
exports2.parseFollowUps = exports2.FollowUpsParseError = exports2.FollowUpManifestSchema = exports2.FollowUpItemSchema = exports2.SIGNAL_FILE = exports2.FOLLOW_UP_ARTIFACT = exports2.readEpicSignal = exports2.existingEpicIds = exports2.followUpIdFor = exports2.followUpEpicId = exports2.renderIntentMarkdown = exports2.openFollowUpEpic = exports2.openIncidentEpic = exports2.SignalParseError = exports2.isSignal = exports2.parseSignal = exports2.SignalSchema = exports2.EpicStepEditError = exports2.resolveStepRef = exports2.describeGateEffect = exports2.commitEpicStepEdit = exports2.planSetEpicStepGates = exports2.planRemoveEpicStep = exports2.planAddEpicStep = exports2.EpicScaffoldError = exports2.epicsRoot = exports2.mapStepStatusToEpic = exports2.mirrorRunStateToEpic = exports2.scaffoldEpic = exports2.resolveArtifactCommitConfig = exports2.commitApprovedArtifacts = exports2.PipelineAdaptError = exports2.applyAdaptation = exports2.parseAdaptationVerdict = exports2.buildAdaptationPrompt = exports2.buildPhaseCatalog = exports2.slugEpicId = exports2.parseClassificationVerdict = exports2.buildClassificationPrompt = exports2.heuristicClassify = exports2.PipelineAssembleError = exports2.recipePipelineId = exports2.assemblePipeline = exports2.collectWorkspaceRefIssues = exports2.stepDagId = exports2.stepAgentId = exports2.normalizeStep = exports2.WorkspaceValidationError = exports2.validateWorkspace = exports2.WorkspaceSchema = void 0;
|
|
32038
32223
|
exports2.composeAgentPrompt = exports2.PROJECT_INSTRUCTION_FILES = exports2.findProjectInstructions = exports2.stripPersonaMetadata = exports2.PersonaLoader = exports2.SkillNotFoundError = exports2.SkillLoader = exports2.EnvVarMissingError = exports2.EnvResolver = exports2.epicPipelineReport = exports2.planEpicPipelineExtraction = exports2.epicOwningPipeline = exports2.unstageEpicPipeline = exports2.stageEpicPipeline = exports2.writeEpicPipelines = exports2.splitEpicPipelines = exports2.mergeEpicPipelines = exports2.epicPipelinePath = exports2.EPIC_PIPELINE_FILENAME = exports2.WORKSPACE_DIR = exports2.WORKSPACE_FILENAME = exports2.WorkspaceParseError = exports2.WorkspaceNotFoundError = exports2.WorkspaceLoader = exports2.renderPlanMarkdown = exports2.generatePlan = exports2.collectContext = exports2.followUpHookFailures = exports2.pendingFollowUpDone = exports2.applyFollowUpHookRun = exports2.trackFollowUpChildren = exports2.writeFollowUpHookLedger = exports2.readFollowUpHookLedger = exports2.followUpHookLedgerPath = exports2.runFollowUpHook = exports2.fillFollowUpHookCommand = exports2.resolveFollowUpHooks = exports2.epicPipelineId = exports2.FOLLOW_UP_HOOK_TIMEOUT_MS = exports2.FOLLOW_UP_HOOKS_LEDGER = exports2.stepProducesFollowUps = exports2.collectFollowUpHookIssues = exports2.FOLLOW_UP_HOOK_PLACEHOLDERS = exports2.FOLLOW_UP_HOOK_KEYS = exports2.FOLLOW_UP_INTENT = exports2.FOLLOW_UPS_FILE = exports2.openManifestFollowUp = exports2.followUpChildId = exports2.followUpsOf = exports2.readEpicFollowUps = void 0;
|
|
32039
32224
|
exports2.buildClaudeSpawnEnv = exports2.hasClaudeLogin = exports2.isInsideClaudeCodeSession = exports2.createJsonSink = exports2.createLineSink = exports2.isCodexMcpConfigured = exports2.codexConfigPath = exports2.readProjectMcpServer = exports2.mcpRegistrarFor = exports2.codexMcpRegistrar = exports2.claudeMcpRegistrar = exports2.CodexRunner = exports2.DefaultRunner = exports2.RunnerRegistry = exports2.targetPath = exports2.scopePaths = exports2.discoverAssets = exports2.commandBodyIsStale = exports2.readEpicTags = exports2.normalizeTags = exports2.normalizeTag = exports2.epicMatchesTags = exports2.applyTagEdit = exports2.MAX_TAG_LENGTH = exports2.EPIC_TAGS_KEY = exports2.strictModeSection = exports2.resolveEpicStrictMode = exports2.epicStrictMode = exports2.commandBodyPredatesStrictMode = exports2.STRICT_MODE_KEY = exports2.STRICT_MODE_HEADING = exports2.writeUserEpicIdPrefix = exports2.userConfigPath = exports2.readUserConfig = exports2.readGitUserName = exports2.ensureUserConfigIgnored = exports2.USER_CONFIG_RELPATH = exports2.USER_CONFIG_IGNORE_LINE = exports2.suggestEpicId = exports2.resolveEpicIdPrefixChain = exports2.resolveEpicIdPrefix = exports2.epicIdDateStamp = exports2.deriveEpicIdPrefix = exports2.EPIC_ID_PREFIX_PATTERN = exports2.EPIC_ID_PREFIX_KEY = exports2.resolveArtifactLanguage = exports2.commandBodyPredatesArtifactLanguage = exports2.artifactLanguageSection = exports2.ARTIFACT_LANGUAGE_HEADING = exports2.stripPersonaDirectives = void 0;
|
|
32040
|
-
exports2.
|
|
32041
|
-
exports2.
|
|
32042
|
-
exports2.AIDLC_CORE_VERSION = exports2.AIDLC_CLI_GUIDE_TEXT = exports2.AIDLC_KNOWLEDGE = exports2.clearResolveCommandCache = exports2.resolveCommand = exports2.remapClaudePath = exports2.claudeConfigEnv = exports2.claudeJsonPath = exports2.isDefaultClaudeConfigDir = exports2.claudeConfigDir = exports2.resolveClaudeConfigDir = exports2.defaultClaudeConfigDir = exports2.getClaudeConfigDirOverride = exports2.setClaudeConfigDir = exports2.resolveDeclaredPath = exports2.expandHome = exports2.ProfileLoadError = exports2.UnknownStandardError = exports2.builtinProfiles = exports2.loadActiveProfile = exports2.loadProfile = exports2.listProfileManifests = exports2.resolveStandard = exports2.workspaceStandard = exports2.isBuiltinProfileId = exports2.ProfileSchema = void 0;
|
|
32225
|
+
exports2.getBuiltinWorkflow = exports2.workflowSlug = exports2.builtinTemplatesRoot = exports2.pipelineCommandId = exports2.PHASES = exports2.BUILTIN_WORKFLOWS = exports2.withBackfilledStepNames = exports2.describeDrift = exports2.reconcileRunSteps = exports2.RUN_STATE_SCHEMA_VERSION = exports2.migrateRunState = exports2.stepIdentity = exports2.resolvePath = exports2.AutoReviewerError = exports2.runAutoReview = exports2.renderRunReport = exports2.verifyRun = exports2.runExecLoop = exports2.estimateCostUsd = exports2.providerAliases = exports2.ratesFromConfig = exports2.mergeRates = exports2.BUILTIN_RATES = exports2.checkBudget = exports2.isActiveStatus = exports2.isStepOptional = exports2.isRunComplete = exports2.deriveRunProgress = exports2.PipelineRunError = exports2.retryAutoReview = exports2.submitAutoReviewVerdict = exports2.requestStepUpdate = exports2.rerunStep = exports2.rejectStep = exports2.approveStep = exports2.markStepDone = exports2.canStartStep = exports2.startRun = exports2.activateBackendFromWorkspace = exports2.activateRunStateBackend = exports2.resolveRunStateBackend = exports2.GitRunStateStore = exports2.RUN_ID_PATTERN = exports2.FileRunStateStore = exports2.RunStateStore = exports2.harnessCapabilities = exports2.NO_HARNESS_CAPABILITIES = exports2.RunnerValidationError = exports2.validateRunnerExport = exports2.CustomRunnerLoader = void 0;
|
|
32226
|
+
exports2.isEpicMemoryHookEnabled = exports2.installAnnotationTools = exports2.relativeEpicRoot = exports2.provisionDeclaredWorkflows = exports2.provisionWorkflowFiles = exports2.writeWorkflowArtifactTemplates = exports2.writeWorkflowCommands = exports2.provisionShortcutDocs = exports2.writeTwoLayerCommands = exports2.shortcutCommandDoc = exports2.backboneCommandDoc = exports2.unprovisionedPhases = exports2.nextEligiblePhase = exports2.resolveComposition = exports2.shortcutCommandId = exports2.getCanonicalPhase = exports2.isCanonicalPhase = exports2.BACKBONE_COMMAND_ID = exports2.CANONICAL_PHASE_IDS = exports2.CANONICAL_PHASES = exports2.renderTemplate = exports2.DEFAULT_GLOBAL_WORKFLOW_IDS = exports2.detectGlobalBuiltinSource = exports2.uninstallWorkflowGlobalsByIds = exports2.isWorkflowGloballyInstalled = exports2.installWorkflowGlobalsByIds = exports2.installGlobalDefaults = exports2.resolveProviderModel = exports2.isClaudeTierAlias = exports2.CLAUDE_TIER_ALIASES = exports2.FAST_MODEL = exports2.CODING_MODEL = exports2.PLANNING_MODEL = exports2.isBuiltinPreset = exports2.BUILTIN_PRESET_IDS = exports2.writeBuiltinAutoReviewValidators = exports2.resolvePrimaryStack = exports2.getSdlcArtifactTemplates = exports2.getBuiltinArtifactTemplates = exports2.phaseArtifactFileName = exports2.sdlcClaudeCommand = exports2.builtinClaudeCommand = exports2.loadAllBuiltinPresets = exports2.loadBuiltinPreset = exports2.planRecipeMigration = exports2.getBuiltinRecipeSummaries = exports2.getAllBuiltinPipelineSummaries = exports2.getSdlcBuiltinPipelineSummary = exports2.getBuiltinPipelineSummary = exports2.getBuiltinWorkflowByPipelineId = void 0;
|
|
32227
|
+
exports2.AIDLC_CORE_VERSION = exports2.AIDLC_CLI_GUIDE_TEXT = exports2.AIDLC_KNOWLEDGE = exports2.clearResolveCommandCache = exports2.resolveCommand = exports2.remapClaudePath = exports2.claudeConfigEnv = exports2.claudeJsonPath = exports2.isDefaultClaudeConfigDir = exports2.claudeConfigDir = exports2.resolveClaudeConfigDir = exports2.defaultClaudeConfigDir = exports2.getClaudeConfigDirOverride = exports2.setClaudeConfigDir = exports2.resolveDeclaredPath = exports2.expandHome = exports2.ProfileLoadError = exports2.UnknownStandardError = exports2.builtinProfiles = exports2.loadActiveProfile = exports2.loadProfile = exports2.listProfileManifests = exports2.resolveStandard = exports2.workspaceStandard = exports2.isBuiltinProfileId = exports2.ProfileSchema = exports2.TRACE_RULES = exports2.PROFILES_DIR = exports2.DEFAULT_PROFILE_ID = exports2.BUILTIN_PROFILE_IDS = exports2.setEpicMemoryHook = void 0;
|
|
32043
32228
|
var WorkspaceSchema_1 = require_WorkspaceSchema();
|
|
32044
32229
|
Object.defineProperty(exports2, "WorkspaceSchema", { enumerable: true, get: function() {
|
|
32045
32230
|
return WorkspaceSchema_1.WorkspaceSchema;
|
|
@@ -32590,9 +32775,25 @@ var require_dist = __commonJS({
|
|
|
32590
32775
|
Object.defineProperty(exports2, "submitAutoReviewVerdict", { enumerable: true, get: function() {
|
|
32591
32776
|
return PipelineRunner_1.submitAutoReviewVerdict;
|
|
32592
32777
|
} });
|
|
32778
|
+
Object.defineProperty(exports2, "retryAutoReview", { enumerable: true, get: function() {
|
|
32779
|
+
return PipelineRunner_1.retryAutoReview;
|
|
32780
|
+
} });
|
|
32593
32781
|
Object.defineProperty(exports2, "PipelineRunError", { enumerable: true, get: function() {
|
|
32594
32782
|
return PipelineRunner_1.PipelineRunError;
|
|
32595
32783
|
} });
|
|
32784
|
+
var runProgress_1 = require_runProgress();
|
|
32785
|
+
Object.defineProperty(exports2, "deriveRunProgress", { enumerable: true, get: function() {
|
|
32786
|
+
return runProgress_1.deriveRunProgress;
|
|
32787
|
+
} });
|
|
32788
|
+
Object.defineProperty(exports2, "isRunComplete", { enumerable: true, get: function() {
|
|
32789
|
+
return runProgress_1.isRunComplete;
|
|
32790
|
+
} });
|
|
32791
|
+
Object.defineProperty(exports2, "isStepOptional", { enumerable: true, get: function() {
|
|
32792
|
+
return runProgress_1.isStepOptional;
|
|
32793
|
+
} });
|
|
32794
|
+
Object.defineProperty(exports2, "isActiveStatus", { enumerable: true, get: function() {
|
|
32795
|
+
return runProgress_1.isActiveStatus;
|
|
32796
|
+
} });
|
|
32596
32797
|
var budget_1 = require_budget();
|
|
32597
32798
|
Object.defineProperty(exports2, "checkBudget", { enumerable: true, get: function() {
|
|
32598
32799
|
return budget_1.checkBudget;
|
|
@@ -41595,7 +41796,7 @@ var require_package = __commonJS({
|
|
|
41595
41796
|
"package.json"(exports2, module2) {
|
|
41596
41797
|
module2.exports = {
|
|
41597
41798
|
name: "@delete101020/aidlc",
|
|
41598
|
-
version: "4.0.
|
|
41799
|
+
version: "4.0.10",
|
|
41599
41800
|
description: "AIDLC Native CLI, a fork of AIDLC \u2014 drive Claude through the six-stage AI-Native SDLC Playbook: Plan \u2192 Design \u2192 Build \u2192 Test \u2192 Deploy \u2192 Maintain, with artifact gates, requirements traceability, an incident loop back to Plan, and Spec Kit support.",
|
|
41600
41801
|
license: "MIT",
|
|
41601
41802
|
repository: {
|
|
@@ -46412,9 +46613,10 @@ function registerRun(program3) {
|
|
|
46412
46613
|
cmd.command("reject <runId>").description("Reject the current awaiting_review step").requiredOption("--reason <text>", "Why the step was rejected").action((runId, opts, actionCmd) => {
|
|
46413
46614
|
const root = resolveWorkspaceRoot(actionCmd);
|
|
46414
46615
|
const state = requireRun(root, runId);
|
|
46616
|
+
const pipeline = requirePipelineForRun(root, state);
|
|
46415
46617
|
let next;
|
|
46416
46618
|
try {
|
|
46417
|
-
next = (0, import_core13.rejectStep)({ state, reason: opts.reason });
|
|
46619
|
+
next = (0, import_core13.rejectStep)({ state, reason: opts.reason, pipeline });
|
|
46418
46620
|
} catch (err) {
|
|
46419
46621
|
console.error(import_chalk10.default.red(err instanceof Error ? err.message : String(err)));
|
|
46420
46622
|
process.exit(1);
|
|
@@ -46425,18 +46627,23 @@ function registerRun(program3) {
|
|
|
46425
46627
|
console.log(import_chalk10.default.dim(` Reason: ${opts.reason}`));
|
|
46426
46628
|
console.log(import_chalk10.default.dim(` Rerun: aidlc run rerun ${runId} [--feedback "..."]`));
|
|
46427
46629
|
});
|
|
46428
|
-
cmd.command("rerun <runId>").description("Retry
|
|
46630
|
+
cmd.command("rerun <runId>").description("Retry a rejected step (bumps revision, resets to awaiting_work)").option("--feedback <text>", "Notes for the next attempt (stored on the step)").option("--step <idx>", "0-based step index (default: the run's current step)").action((runId, opts, actionCmd) => {
|
|
46429
46631
|
const root = resolveWorkspaceRoot(actionCmd);
|
|
46430
46632
|
const state = requireRun(root, runId);
|
|
46633
|
+
const stepIdx = opts.step === void 0 ? void 0 : Number(opts.step);
|
|
46634
|
+
if (stepIdx !== void 0 && !Number.isInteger(stepIdx)) {
|
|
46635
|
+
console.error(import_chalk10.default.red(`--step must be an integer, got "${opts.step}"`));
|
|
46636
|
+
process.exit(1);
|
|
46637
|
+
}
|
|
46431
46638
|
let next;
|
|
46432
46639
|
try {
|
|
46433
|
-
next = (0, import_core13.rerunStep)({ state, feedback: opts.feedback });
|
|
46640
|
+
next = (0, import_core13.rerunStep)({ state, feedback: opts.feedback, stepIdx });
|
|
46434
46641
|
} catch (err) {
|
|
46435
46642
|
console.error(import_chalk10.default.red(err instanceof Error ? err.message : String(err)));
|
|
46436
46643
|
process.exit(1);
|
|
46437
46644
|
}
|
|
46438
46645
|
saveRunState(root, next, state);
|
|
46439
|
-
const step = next.steps[next.currentStepIdx];
|
|
46646
|
+
const step = next.steps[stepIdx ?? next.currentStepIdx];
|
|
46440
46647
|
console.log(import_chalk10.default.yellow("\u21BA") + ` Rerunning "${step.agent}" (rev ${step.revision})`);
|
|
46441
46648
|
if (opts.feedback) {
|
|
46442
46649
|
console.log(import_chalk10.default.dim(` Feedback: ${opts.feedback}`));
|
|
@@ -46694,6 +46901,11 @@ ${reason}`)),
|
|
|
46694
46901
|
\u2718 Step "${e.agent}" was rejected.`));
|
|
46695
46902
|
info(import_chalk10.default.dim(` Rerun: aidlc run rerun ${e.runId} [--feedback "..."]`));
|
|
46696
46903
|
},
|
|
46904
|
+
onStepSkipped: (e) => {
|
|
46905
|
+
info(import_chalk10.default.yellow(`
|
|
46906
|
+
\u2933 Step "${e.agent}" was rejected \u2014 carrying on.`) + import_chalk10.default.dim(` ${e.reason}`));
|
|
46907
|
+
info(import_chalk10.default.dim(` Want it back? aidlc run rerun ${e.runId} --step ${e.stepIdx}`));
|
|
46908
|
+
},
|
|
46697
46909
|
onAutoReviewStart: (e) => info(import_chalk10.default.bold(`
|
|
46698
46910
|
\u{1F50D} Auto-review: "${e.agent}"`)),
|
|
46699
46911
|
onAutoReviewResult: (e) => {
|
|
@@ -23,33 +23,45 @@
|
|
|
23
23
|
* which can't resolve the package). Built-in profile rules are embedded; a
|
|
24
24
|
* custom profile is read from .aidlc/profiles/<id>.yaml when js-yaml is
|
|
25
25
|
* importable, else it is treated as enforce-nothing with a logged note.
|
|
26
|
+
*
|
|
27
|
+
* A profile carries its own section requirements: the built-ins embed theirs
|
|
28
|
+
* below, a custom profile declares them as `artifacts.<NAME>.mandatory_sections`
|
|
29
|
+
* in its manifest. The `mandatory-sections` rule checks the ACTIVE profile's
|
|
30
|
+
* list — never another profile's.
|
|
26
31
|
*/
|
|
27
32
|
|
|
28
33
|
import * as fs from 'node:fs';
|
|
29
34
|
import * as path from 'node:path';
|
|
30
35
|
|
|
36
|
+
// Sections the built-in `iso-ieee` profile requires, keyed by artifact file —
|
|
37
|
+
// mirrors its `artifacts:` block in StandardProfile.ts. No other built-in turns
|
|
38
|
+
// `mandatory-sections` on, so no other built-in needs a list.
|
|
39
|
+
const ISO_IEEE_SECTIONS = {
|
|
40
|
+
'PRD.md': ['Problem & Goal', 'User Flow', 'Acceptance Criteria', 'Non-Functional Requirements', 'Dependencies'],
|
|
41
|
+
'TECH-DESIGN.md': ['Architecture', 'API', 'Data Model'],
|
|
42
|
+
'TEST-CASES.md': ['Test Cases'],
|
|
43
|
+
};
|
|
44
|
+
|
|
31
45
|
// Built-in profile traceability config — mirrors
|
|
32
46
|
// packages/core/src/profiles/StandardProfile.ts. Keep in sync.
|
|
33
47
|
const BUILTIN_TRACE = {
|
|
34
|
-
none: { enforce: false, rules: [] },
|
|
35
|
-
'agile-lite': { enforce: true, rules: ['ac-testable', 'ac-has-test'] },
|
|
36
|
-
hybrid: {
|
|
48
|
+
none: { enforce: false, rules: [], sections: {} },
|
|
49
|
+
'agile-lite': { enforce: true, rules: ['ac-testable', 'ac-has-test'], sections: {} },
|
|
50
|
+
hybrid: {
|
|
51
|
+
enforce: true,
|
|
52
|
+
rules: ['ac-testable', 'ac-has-test', 'tc-has-result', 'rtm-no-dangling'],
|
|
53
|
+
sections: {},
|
|
54
|
+
},
|
|
37
55
|
'iso-ieee': {
|
|
38
56
|
enforce: true,
|
|
39
57
|
rules: ['ac-testable', 'ac-has-test', 'tc-has-result', 'rtm-no-dangling', 'mandatory-sections'],
|
|
58
|
+
sections: ISO_IEEE_SECTIONS,
|
|
40
59
|
},
|
|
41
60
|
};
|
|
42
61
|
|
|
43
62
|
// Vague phrases that make an acceptance criterion untestable (ac-testable).
|
|
44
63
|
const VAGUE = [/should work well/i, /good ux/i, /feels fast/i, /as expected/i, /etc\.?$/im];
|
|
45
64
|
|
|
46
|
-
// Mandatory sections checked under `mandatory-sections`, keyed by artifact file.
|
|
47
|
-
const MANDATORY_SECTIONS = {
|
|
48
|
-
'PRD.md': ['Problem & Goal', 'User Flow', 'Acceptance Criteria', 'Non-Functional Requirements', 'Dependencies'],
|
|
49
|
-
'TECH-DESIGN.md': ['Architecture', 'API', 'Data Model'],
|
|
50
|
-
'TEST-CASES.md': ['Test Cases'],
|
|
51
|
-
};
|
|
52
|
-
|
|
53
65
|
// ── helpers ────────────────────────────────────────────────────────
|
|
54
66
|
|
|
55
67
|
function readIfExists(p) {
|
|
@@ -83,6 +95,24 @@ function resolveStandardId(workspaceRoot, state) {
|
|
|
83
95
|
return 'none';
|
|
84
96
|
}
|
|
85
97
|
|
|
98
|
+
/**
|
|
99
|
+
* A manifest's `artifacts:` block as this validator wants it — keyed by the
|
|
100
|
+
* artifact FILE name, since that is what we look for on disk. Manifests name
|
|
101
|
+
* artifacts without the extension (`PRD`, `TECH-DESIGN`), so add it; a key
|
|
102
|
+
* that already carries `.md` is left alone. An entry with no sections is
|
|
103
|
+
* dropped so an empty declaration can't masquerade as a real one.
|
|
104
|
+
*/
|
|
105
|
+
function sectionsFromManifest(doc) {
|
|
106
|
+
const artifacts = doc && typeof doc.artifacts === 'object' && doc.artifacts ? doc.artifacts : {};
|
|
107
|
+
const out = {};
|
|
108
|
+
for (const [name, rule] of Object.entries(artifacts)) {
|
|
109
|
+
const sections = rule && Array.isArray(rule.mandatory_sections) ? rule.mandatory_sections : [];
|
|
110
|
+
if (sections.length === 0) { continue; }
|
|
111
|
+
out[/\.md$/i.test(name) ? name : `${name}.md`] = sections;
|
|
112
|
+
}
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
|
|
86
116
|
/** Traceability config for an id — built-in embedded, custom via optional js-yaml read. */
|
|
87
117
|
async function traceConfigFor(id, workspaceRoot, notes) {
|
|
88
118
|
if (Object.prototype.hasOwnProperty.call(BUILTIN_TRACE, id)) { return BUILTIN_TRACE[id]; }
|
|
@@ -90,16 +120,29 @@ async function traceConfigFor(id, workspaceRoot, notes) {
|
|
|
90
120
|
const text = readIfExists(manifest);
|
|
91
121
|
if (!text) {
|
|
92
122
|
notes.push(`custom profile "${id}" has no manifest at ${manifest} — enforcing nothing`);
|
|
93
|
-
return { enforce: false, rules: [] };
|
|
123
|
+
return { enforce: false, rules: [], sections: {} };
|
|
94
124
|
}
|
|
95
125
|
try {
|
|
96
126
|
const yaml = await import('js-yaml');
|
|
97
127
|
const doc = yaml.load(text) || {};
|
|
98
128
|
const t = doc.traceability || {};
|
|
99
|
-
|
|
129
|
+
const cfg = {
|
|
130
|
+
enforce: t.enforce === true,
|
|
131
|
+
rules: Array.isArray(t.rules) ? t.rules : [],
|
|
132
|
+
sections: sectionsFromManifest(doc),
|
|
133
|
+
};
|
|
134
|
+
// Turning the rule on with nothing to check is silently vacuous — say so
|
|
135
|
+
// rather than let the profile look enforced when it isn't.
|
|
136
|
+
if (cfg.rules.includes('mandatory-sections') && Object.keys(cfg.sections).length === 0) {
|
|
137
|
+
notes.push(
|
|
138
|
+
`custom profile "${id}" enables mandatory-sections but declares no ` +
|
|
139
|
+
'artifacts.<NAME>.mandatory_sections — no sections checked',
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
return cfg;
|
|
100
143
|
} catch {
|
|
101
144
|
notes.push(`custom profile "${id}" present but js-yaml unavailable — enforcing nothing`);
|
|
102
|
-
return { enforce: false, rules: [] };
|
|
145
|
+
return { enforce: false, rules: [], sections: {} };
|
|
103
146
|
}
|
|
104
147
|
}
|
|
105
148
|
|
|
@@ -218,7 +261,7 @@ export default async function traceability(ctx) {
|
|
|
218
261
|
|
|
219
262
|
// mandatory-sections — each present artifact carries the profile's required headings.
|
|
220
263
|
if (trace.rules.includes('mandatory-sections')) {
|
|
221
|
-
for (const [file, sections] of Object.entries(
|
|
264
|
+
for (const [file, sections] of Object.entries(trace.sections || {})) {
|
|
222
265
|
const found = firstExisting(artifactsDir, [file]);
|
|
223
266
|
if (!found) { continue; }
|
|
224
267
|
for (const s of sections) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@delete101020/aidlc",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.10",
|
|
4
4
|
"description": "AIDLC Native CLI, a fork of AIDLC — drive Claude through the six-stage AI-Native SDLC Playbook: Plan → Design → Build → Test → Deploy → Maintain, with artifact gates, requirements traceability, an incident loop back to Plan, and Spec Kit support.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|