@delete101020/aidlc 4.0.7 → 4.0.9

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
@@ -20911,6 +20911,7 @@ var require_PipelineRunner = __commonJS({
20911
20911
  exports2.canStartStep = canStartStep;
20912
20912
  exports2.markStepDone = markStepDone3;
20913
20913
  exports2.submitAutoReviewVerdict = submitAutoReviewVerdict2;
20914
+ exports2.retryAutoReview = retryAutoReview;
20914
20915
  exports2.approveStep = approveStep3;
20915
20916
  exports2.rejectStep = rejectStep3;
20916
20917
  exports2.rerunStep = rerunStep3;
@@ -21107,6 +21108,37 @@ var require_PipelineRunner = __commonJS({
21107
21108
  }
21108
21109
  return advance(next, idx, pipeline);
21109
21110
  }
21111
+ function retryAutoReview(args) {
21112
+ const { pipeline } = args;
21113
+ const state = alignedOrThrow(args.state, pipeline);
21114
+ const idx = args.stepIdx ?? state.currentStepIdx;
21115
+ const step = state.steps[idx];
21116
+ if (!step) {
21117
+ throw new PipelineRunError3(`No step at index ${idx}`);
21118
+ }
21119
+ if (step.status !== "rejected") {
21120
+ throw new PipelineRunError3(`Cannot re-run auto-review for step "${step.agent}": status is "${step.status}", expected "rejected"`);
21121
+ }
21122
+ if (step.autoReviewVerdict?.decision !== "reject") {
21123
+ throw new PipelineRunError3(`Step "${step.agent}" was not rejected by its auto-reviewer \u2014 rerun it instead.`);
21124
+ }
21125
+ const stepConfig = pipeline.steps[idx];
21126
+ if (!stepConfig) {
21127
+ throw new PipelineRunError3(`Pipeline mismatch \u2014 step "${(0, RunState_1.stepIdentity)(step)}" is at index ${idx}, which pipeline "${pipeline.id}" does not have.`);
21128
+ }
21129
+ if (!(0, WorkspaceSchema_1.normalizeStep)(stepConfig).auto_review) {
21130
+ throw new PipelineRunError3(`Step "${step.agent}" no longer has auto_review enabled in pipeline "${pipeline.id}".`);
21131
+ }
21132
+ const next = clone(state);
21133
+ next.steps[idx] = {
21134
+ ...step,
21135
+ status: "awaiting_auto_review",
21136
+ rejectReason: void 0,
21137
+ autoReviewVerdict: void 0
21138
+ };
21139
+ next.status = "running";
21140
+ return next;
21141
+ }
21110
21142
  function approveStep3(args) {
21111
21143
  const { pipeline } = args;
21112
21144
  const state = alignedOrThrow(args.state, pipeline);
@@ -32037,9 +32069,9 @@ var require_dist = __commonJS({
32037
32069
  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
32070
  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
32071
  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;
32072
+ 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.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;
32073
+ 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 = exports2.getBuiltinRecipeSummaries = void 0;
32074
+ 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 = void 0;
32043
32075
  var WorkspaceSchema_1 = require_WorkspaceSchema();
32044
32076
  Object.defineProperty(exports2, "WorkspaceSchema", { enumerable: true, get: function() {
32045
32077
  return WorkspaceSchema_1.WorkspaceSchema;
@@ -32590,6 +32622,9 @@ var require_dist = __commonJS({
32590
32622
  Object.defineProperty(exports2, "submitAutoReviewVerdict", { enumerable: true, get: function() {
32591
32623
  return PipelineRunner_1.submitAutoReviewVerdict;
32592
32624
  } });
32625
+ Object.defineProperty(exports2, "retryAutoReview", { enumerable: true, get: function() {
32626
+ return PipelineRunner_1.retryAutoReview;
32627
+ } });
32593
32628
  Object.defineProperty(exports2, "PipelineRunError", { enumerable: true, get: function() {
32594
32629
  return PipelineRunner_1.PipelineRunError;
32595
32630
  } });
@@ -41595,7 +41630,7 @@ var require_package = __commonJS({
41595
41630
  "package.json"(exports2, module2) {
41596
41631
  module2.exports = {
41597
41632
  name: "@delete101020/aidlc",
41598
- version: "4.0.7",
41633
+ version: "4.0.9",
41599
41634
  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
41635
  license: "MIT",
41601
41636
  repository: {
@@ -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.9",
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": {