@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 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
- let openedAny = false;
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
- openedAny = true;
21348
- if (next.currentStepIdx === idx) {
21349
- next.currentStepIdx = i;
21350
- }
21474
+ opened.push(i);
21351
21475
  }
21352
- const allApproved = next.steps.every((s) => s.status === "approved");
21353
- if (allApproved) {
21476
+ if ((0, runProgress_1.isRunComplete)(next, pipeline)) {
21354
21477
  next.status = "completed";
21355
21478
  return next;
21356
21479
  }
21357
- if (!openedAny) {
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 epicStatus = runState.status === "completed" ? "done" : runState.steps.some((s) => s.status === "rejected") ? "failed" : "in_progress";
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
- for (let i = 0; i < state.steps.length; i++) {
31390
- const st = state.steps[i].status;
31391
- if (st === "awaiting_work") {
31392
- return { index: i, phaseId: dagId(i), reason: "awaiting_work" };
31393
- }
31394
- if (st === "rejected") {
31395
- return { index: i, phaseId: dagId(i), reason: "rejected" };
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**: the first step
31449
- that is \`awaiting_work\`, else the first \`rejected\` step, else the first
31450
- \`pending\` step whose every \`depends_on\` is \`approved\`. If none is
31451
- actionable (all approved or paused for review), say so and stop.
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.getBuiltinRecipeSummaries = exports2.getAllBuiltinPipelineSummaries = exports2.getSdlcBuiltinPipelineSummary = exports2.getBuiltinPipelineSummary = exports2.getBuiltinWorkflowByPipelineId = 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.PipelineRunError = 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;
32041
- exports2.TRACE_RULES = exports2.PROFILES_DIR = exports2.DEFAULT_PROFILE_ID = exports2.BUILTIN_PROFILE_IDS = exports2.setEpicMemoryHook = 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 = void 0;
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.7",
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 the current rejected step (bumps revision, resets to awaiting_work)").option("--feedback <text>", "Notes for the next attempt (stored on the step)").action((runId, opts, actionCmd) => {
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: { enforce: true, rules: ['ac-testable', 'ac-has-test', 'tc-has-result', 'rtm-no-dangling'] },
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
- return { enforce: t.enforce === true, rules: Array.isArray(t.rules) ? t.rules : [] };
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(MANDATORY_SECTIONS)) {
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.7",
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": {