@delete101020/aidlc 4.0.25 → 4.0.26

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.
Files changed (3) hide show
  1. package/README.md +13 -1
  2. package/dist/bundle.js +256 -57
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -299,7 +299,19 @@ aidlc epic start <id> --pipeline <pipelineId> # or use an existing pipeline as
299
299
  aidlc epic start <id> … --tag payment --tag "thanh toán" # tag it at creation
300
300
  aidlc epic tag <id> # print this epic's tags
301
301
  aidlc epic tag <id> payment "release q3" # add tags (also --add/--remove/--set/--clear)
302
- ```
302
+ aidlc epic follow-up <parent> --title "…" [--desc "…"] # park work found mid-epic as <parent>-F<n>
303
+ ```
304
+
305
+ **Follow-ups opened by hand.** Work that turns up while an epic is in flight —
306
+ a CR in build finds a second screen that needs the same change — goes into
307
+ `epic follow-up <parent>`. It scaffolds `<parent>-F1` (then `F2`, …) with
308
+ `from_epic` and `follow_up_key` in its `inputs.json`, so the parent's card links
309
+ to it exactly as it does to manifest and incident follow-ups. The child runs
310
+ the way the parent does (the recipe that assembled the parent's pipeline, else
311
+ the pipeline it was derived from) and inherits its tags; override with
312
+ `--recipe` / `--pipeline`, `--tag`, `--no-inherit-tags`, `--epic <id>`. Nothing
313
+ runs: the child waits at its first step until someone starts it. The
314
+ extension's card offers the same as **New follow-up epic**.
303
315
 
304
316
  **Tags** are free text in and one canonical form on disk: uppercase, ASCII,
305
317
  dash-separated — `"thanh toán VNPay"` is stored as `THANH-TOAN-VNPAY`, and the
package/dist/bundle.js CHANGED
@@ -27017,14 +27017,18 @@ var require_FollowUps = __commonJS({
27017
27017
  };
27018
27018
  }();
27019
27019
  Object.defineProperty(exports2, "__esModule", { value: true });
27020
- exports2.FollowUpsParseError = exports2.FollowUpManifestSchema = exports2.FollowUpItemSchema = exports2.FOLLOW_UP_INTENT = exports2.FOLLOW_UPS_FILE = void 0;
27020
+ exports2.MANUAL_FOLLOW_UP_KEY_PREFIX = exports2.FollowUpsParseError = exports2.FollowUpManifestSchema = exports2.FollowUpItemSchema = exports2.FOLLOW_UP_INTENT = exports2.FOLLOW_UPS_FILE = void 0;
27021
27021
  exports2.parseFollowUps = parseFollowUps;
27022
27022
  exports2.readEpicFollowUps = readEpicFollowUps;
27023
27023
  exports2.followUpsOf = followUpsOf;
27024
27024
  exports2.followUpChildId = followUpChildId;
27025
27025
  exports2.openManifestFollowUp = openManifestFollowUp;
27026
+ exports2.withFollowUpProvenance = withFollowUpProvenance2;
27027
+ exports2.nextManualFollowUpKey = nextManualFollowUpKey;
27028
+ exports2.followUpDefaults = followUpDefaults2;
27026
27029
  var fs14 = __importStar(require("fs"));
27027
27030
  var path17 = __importStar(require("path"));
27031
+ var yaml = __importStar(require_js_yaml());
27028
27032
  var zod_1 = require_zod();
27029
27033
  var WorkspaceSchema_1 = require_WorkspaceSchema();
27030
27034
  var EpicScaffold_1 = require_EpicScaffold();
@@ -27032,6 +27036,8 @@ var require_FollowUps = __commonJS({
27032
27036
  Object.defineProperty(exports2, "FOLLOW_UPS_FILE", { enumerable: true, get: function() {
27033
27037
  return FollowUpHookSchema_1.FOLLOW_UPS_FILE;
27034
27038
  } });
27039
+ var EpicPipelineStore_1 = require_EpicPipelineStore();
27040
+ var epicTags_1 = require_epicTags();
27035
27041
  exports2.FOLLOW_UP_INTENT = "intent.md";
27036
27042
  var nonEmpty = (field) => zod_1.z.string().trim().min(1, `\`${field}\` is required`);
27037
27043
  exports2.FollowUpItemSchema = zod_1.z.object({
@@ -27158,11 +27164,7 @@ var require_FollowUps = __commonJS({
27158
27164
  target: { kind: "pipeline", id: pipeline.id },
27159
27165
  agents,
27160
27166
  // Provenance last, so a manifest cannot overwrite the edge it is drawn from.
27161
- inputs: {
27162
- ...item.inputs,
27163
- from_epic: parentEpicId,
27164
- follow_up_key: item.key
27165
- },
27167
+ inputs: withFollowUpProvenance2(item.inputs, parentEpicId, item.key),
27166
27168
  pipeline,
27167
27169
  seedArtifacts: { [exports2.FOLLOW_UP_INTENT]: item.intent.endsWith("\n") ? item.intent : `${item.intent}
27168
27170
  ` },
@@ -27174,6 +27176,91 @@ var require_FollowUps = __commonJS({
27174
27176
  intentPath: path17.join(result.artifactsDir, exports2.FOLLOW_UP_INTENT)
27175
27177
  };
27176
27178
  }
27179
+ function withFollowUpProvenance2(inputs, parentEpicId, key) {
27180
+ return { ...inputs, from_epic: parentEpicId, follow_up_key: key };
27181
+ }
27182
+ exports2.MANUAL_FOLLOW_UP_KEY_PREFIX = "F";
27183
+ function nextManualFollowUpKey(taken) {
27184
+ const used = new Set([...taken].map((k) => k.toUpperCase()));
27185
+ for (let n = 1; n < 1e4; n++) {
27186
+ const key = `${exports2.MANUAL_FOLLOW_UP_KEY_PREFIX}${n}`;
27187
+ if (!used.has(key)) {
27188
+ return key;
27189
+ }
27190
+ }
27191
+ throw new EpicScaffold_1.EpicScaffoldError("Could not find a free follow-up key.");
27192
+ }
27193
+ function stepIds(steps) {
27194
+ if (!Array.isArray(steps)) {
27195
+ return [];
27196
+ }
27197
+ return steps.map((s) => {
27198
+ if (typeof s === "string") {
27199
+ return s;
27200
+ }
27201
+ const o = s ?? {};
27202
+ return String(o.name ?? o.agent ?? "");
27203
+ });
27204
+ }
27205
+ function parentTarget(own, pipelines, recipes) {
27206
+ if (!own) {
27207
+ return void 0;
27208
+ }
27209
+ const source = typeof own.derived_from === "string" ? own.derived_from : "";
27210
+ if (!source) {
27211
+ return typeof own.id === "string" && own.id ? { kind: "pipeline", id: own.id } : void 0;
27212
+ }
27213
+ const steps = stepIds(own.steps).join("\n");
27214
+ const recipe = recipes.find((r) => (r.from === void 0 || r.from === source) && stepIds(r.steps).join("\n") === steps);
27215
+ if (recipe && typeof recipe.id === "string") {
27216
+ return { kind: "recipe", id: recipe.id };
27217
+ }
27218
+ if (pipelines.some((p) => p.id === source)) {
27219
+ return { kind: "pipeline", id: source };
27220
+ }
27221
+ return void 0;
27222
+ }
27223
+ function followUpDefaults2(workspaceRoot, doc, parentEpicId) {
27224
+ const root = (0, EpicScaffold_1.epicsRoot)(workspaceRoot, doc);
27225
+ const dir = path17.join(root, parentEpicId);
27226
+ const stateFile = path17.join(dir, "state.json");
27227
+ if (!fs14.existsSync(stateFile)) {
27228
+ throw new EpicScaffold_1.EpicScaffoldError(`Epic "${parentEpicId}" not found \u2014 no state.json in ${dir}.`);
27229
+ }
27230
+ let state;
27231
+ try {
27232
+ state = JSON.parse(fs14.readFileSync(stateFile, "utf8"));
27233
+ } catch (err) {
27234
+ throw new EpicScaffold_1.EpicScaffoldError(`Epic "${parentEpicId}" has an unreadable state.json: ${err instanceof Error ? err.message : String(err)}`);
27235
+ }
27236
+ const pipelines = Array.isArray(doc?.pipelines) ? doc.pipelines : [];
27237
+ const recipes = Array.isArray(doc?.recipes) ? doc.recipes : [];
27238
+ let own = null;
27239
+ const ownFile = path17.join(dir, EpicPipelineStore_1.EPIC_PIPELINE_FILENAME);
27240
+ if (fs14.existsSync(ownFile)) {
27241
+ try {
27242
+ const parsed = yaml.load(fs14.readFileSync(ownFile, "utf8"));
27243
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
27244
+ own = parsed;
27245
+ }
27246
+ } catch {
27247
+ }
27248
+ }
27249
+ if (!own && typeof state.pipeline === "string") {
27250
+ own = pipelines.find((p) => p.id === state.pipeline) ?? null;
27251
+ }
27252
+ const key = nextManualFollowUpKey(followUpsOf(workspaceRoot, doc, parentEpicId).map((f) => f.key ?? ""));
27253
+ const taken = fs14.existsSync(root) ? fs14.readdirSync(root) : [];
27254
+ const target = parentTarget(own, pipelines, recipes);
27255
+ return {
27256
+ parentEpicId,
27257
+ parentTitle: typeof state.title === "string" ? state.title : "",
27258
+ key,
27259
+ epicId: followUpChildId(parentEpicId, key, taken),
27260
+ tags: (0, epicTags_1.normalizeTags)(state.tags),
27261
+ ...target ? { target } : {}
27262
+ };
27263
+ }
27177
27264
  }
27178
27265
  });
27179
27266
 
@@ -33448,12 +33535,12 @@ var require_dist = __commonJS({
33448
33535
  "use strict";
33449
33536
  Object.defineProperty(exports2, "__esModule", { value: true });
33450
33537
  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.EpicWorkflowSwitchError = exports2.canSwitchEpicWorkflow = exports2.epicWorkflowLock = exports2.applyEpicWorkflowSwitch = exports2.stageEpicWorkflowSwitch = exports2.planEpicWorkflowSwitch = exports2.EpicDescriptionError = exports2.setEpicDescription = exports2.lockedEpicDirError = 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.resolveStepSkills = exports2.stepSkillAlternatives = exports2.stepDagId = exports2.stepAgentId = exports2.producesEntries = exports2.normalizeStep = exports2.WorkspaceValidationError = exports2.validateWorkspace = exports2.WorkspaceSchema = void 0;
33451
- exports2.skillReferences = exports2.agentReferences = exports2.renameSkillRefs = exports2.renameAgentRefs = exports2.dropRecipesForPipeline = exports2.dropRecipeStep = exports2.recipesDrawingFrom = 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 = 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 = void 0;
33452
- 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 = 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.unusedAfterStepRemoval = void 0;
33453
- exports2.deriveRunProgress = exports2.PipelineRunError = exports2.retryAutoReview = exports2.submitAutoReviewVerdict = exports2.dirtyUpstreamOf = exports2.rerunApprovedStep = exports2.canRerunApprovedStep = exports2.chooseStepSkill = exports2.requestStepUpdate = exports2.rerunStep = exports2.rejectStep = exports2.approveStep = exports2.undoStepDone = exports2.canUndoStepDone = 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 = 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.claudeModelArg = exports2.DefaultRunner = exports2.RunnerRegistry = exports2.targetPath = exports2.scopePaths = exports2.discoverAssets = exports2.commandBodyIsStale = exports2.readEpicTags = exports2.normalizeTags = void 0;
33454
- 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 = 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.weighStepProgress = exports2.isActiveStatus = exports2.isStepOptional = exports2.isRunComplete = void 0;
33455
- 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 = 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 = void 0;
33456
- exports2.AIDLC_CORE_VERSION = exports2.AIDLC_CLI_GUIDE_TEXT = exports2.AIDLC_KNOWLEDGE = exports2.clearResolveCommandCache = exports2.resolveCommand = exports2.remapClaudePath = exports2.claudeConfigEnv = exports2.claudeJsonPath = exports2.isDefaultClaudeConfigDir = void 0;
33538
+ exports2.dropRecipesForPipeline = exports2.dropRecipeStep = exports2.recipesDrawingFrom = 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.MANUAL_FOLLOW_UP_KEY_PREFIX = exports2.followUpDefaults = exports2.nextManualFollowUpKey = exports2.withFollowUpProvenance = exports2.openManifestFollowUp = exports2.followUpChildId = exports2.followUpsOf = exports2.readEpicFollowUps = 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 = void 0;
33539
+ 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 = 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.unusedAfterStepRemoval = exports2.skillReferences = exports2.agentReferences = exports2.renameSkillRefs = exports2.renameAgentRefs = void 0;
33540
+ exports2.dirtyUpstreamOf = exports2.rerunApprovedStep = exports2.canRerunApprovedStep = exports2.chooseStepSkill = exports2.requestStepUpdate = exports2.rerunStep = exports2.rejectStep = exports2.approveStep = exports2.undoStepDone = exports2.canUndoStepDone = 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 = 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.claudeModelArg = 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 = void 0;
33541
+ 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 = 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.weighStepProgress = exports2.isActiveStatus = exports2.isStepOptional = exports2.isRunComplete = exports2.deriveRunProgress = exports2.PipelineRunError = exports2.retryAutoReview = exports2.submitAutoReviewVerdict = void 0;
33542
+ 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 = 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 = void 0;
33543
+ 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 = void 0;
33457
33544
  var WorkspaceSchema_1 = require_WorkspaceSchema();
33458
33545
  Object.defineProperty(exports2, "WorkspaceSchema", { enumerable: true, get: function() {
33459
33546
  return WorkspaceSchema_1.WorkspaceSchema;
@@ -33664,6 +33751,18 @@ var require_dist = __commonJS({
33664
33751
  Object.defineProperty(exports2, "openManifestFollowUp", { enumerable: true, get: function() {
33665
33752
  return FollowUps_1.openManifestFollowUp;
33666
33753
  } });
33754
+ Object.defineProperty(exports2, "withFollowUpProvenance", { enumerable: true, get: function() {
33755
+ return FollowUps_1.withFollowUpProvenance;
33756
+ } });
33757
+ Object.defineProperty(exports2, "nextManualFollowUpKey", { enumerable: true, get: function() {
33758
+ return FollowUps_1.nextManualFollowUpKey;
33759
+ } });
33760
+ Object.defineProperty(exports2, "followUpDefaults", { enumerable: true, get: function() {
33761
+ return FollowUps_1.followUpDefaults;
33762
+ } });
33763
+ Object.defineProperty(exports2, "MANUAL_FOLLOW_UP_KEY_PREFIX", { enumerable: true, get: function() {
33764
+ return FollowUps_1.MANUAL_FOLLOW_UP_KEY_PREFIX;
33765
+ } });
33667
33766
  Object.defineProperty(exports2, "FOLLOW_UPS_FILE", { enumerable: true, get: function() {
33668
33767
  return FollowUps_1.FOLLOW_UPS_FILE;
33669
33768
  } });
@@ -43113,7 +43212,7 @@ var require_package = __commonJS({
43113
43212
  "package.json"(exports2, module2) {
43114
43213
  module2.exports = {
43115
43214
  name: "@delete101020/aidlc",
43116
- version: "4.0.25",
43215
+ version: "4.0.26",
43117
43216
  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.",
43118
43217
  license: "MIT",
43119
43218
  repository: {
@@ -49752,22 +49851,14 @@ ${epics.length} epic${epics.length !== 1 ? "s" : ""}`));
49752
49851
  console.error(import_chalk15.default.dim(err instanceof Error ? err.message : String(err)));
49753
49852
  process.exit(1);
49754
49853
  }
49755
- let pipelineCfg;
49756
- if (opts.pipeline) {
49757
- const found = doc.pipelines.find((p) => String(p.id) === opts.pipeline);
49758
- if (!found) {
49759
- console.error(import_chalk15.default.red(`Pipeline "${opts.pipeline}" not found in workspace.yaml.`));
49760
- process.exit(1);
49761
- }
49762
- pipelineCfg = found;
49763
- } else {
49854
+ let recipeId = opts.recipe;
49855
+ if (!opts.pipeline) {
49764
49856
  if (config.recipes.length === 0) {
49765
49857
  console.error(import_chalk15.default.red("No recipes defined \u2014 task-type suggestion needs them."));
49766
49858
  console.error(import_chalk15.default.dim(" Back-fill from your existing pipeline: aidlc recipe init"));
49767
49859
  console.error(import_chalk15.default.dim(" Or apply the preset that ships them: aidlc preset apply sdlc"));
49768
49860
  process.exit(1);
49769
49861
  }
49770
- let recipeId = opts.recipe;
49771
49862
  if (!recipeId) {
49772
49863
  const brief = (opts.brief ?? []).join(" ").trim();
49773
49864
  const heur = (0, import_core19.heuristicClassify)(brief, config.recipes);
@@ -49779,34 +49870,12 @@ ${epics.length} epic${epics.length !== 1 ? "s" : ""}`));
49779
49870
  recipeId = verdict.recipeId;
49780
49871
  console.log(import_chalk15.default.dim(`Classified \u2192 ${import_chalk15.default.bold(recipeId)} (${verdict.confidence}, ${verdict.source})`));
49781
49872
  }
49782
- if (opts.from) {
49783
- const recipe = config.recipes.find((r) => r.id === recipeId);
49784
- if (recipe) {
49785
- recipe.from = opts.from;
49786
- }
49787
- }
49788
- const pipelineId = (0, import_core19.recipePipelineId)({ recipeId, epicId, taken: existingIds(doc.pipelines) });
49789
- try {
49790
- pipelineCfg = (0, import_core19.assemblePipeline)(config, { recipeId, pipelineId });
49791
- } catch (err) {
49792
- if (err instanceof import_core19.PipelineAssembleError) {
49793
- console.error(import_chalk15.default.red("Could not assemble pipeline: ") + import_chalk15.default.dim(err.message));
49794
- process.exit(1);
49795
- }
49796
- throw err;
49797
- }
49798
- doc.pipelines.push(pipelineCfg);
49799
- (0, import_core19.stageEpicPipeline)(doc, pipelineCfg.id, epicId);
49800
- try {
49801
- (0, import_core19.validateWorkspace)(doc, ".aidlc/workspace.yaml");
49802
- } catch (err) {
49803
- console.error(import_chalk15.default.red("Assembled pipeline failed validation \u2014 not written:"));
49804
- console.error(import_chalk15.default.dim(err instanceof Error ? err.message : String(err)));
49805
- process.exit(1);
49806
- }
49807
- writeYaml(root, doc);
49808
- console.log(import_chalk15.default.dim(`Assembled pipeline ${import_chalk15.default.bold(pipelineCfg.id)} from recipe ${import_chalk15.default.bold(recipeId)}`));
49809
49873
  }
49874
+ const pipelineCfg = resolveEpicPipeline(root, doc, config, {
49875
+ pipeline: opts.pipeline,
49876
+ recipe: recipeId,
49877
+ from: opts.from
49878
+ }, epicId);
49810
49879
  const agents = Array.isArray(pipelineCfg.steps) ? pipelineCfg.steps.map(import_core19.stepAgentId) : [];
49811
49880
  const inputs = {};
49812
49881
  for (const kv of opts.input) {
@@ -49841,13 +49910,7 @@ ${epics.length} epic${epics.length !== 1 ? "s" : ""}`));
49841
49910
  if (!opts.strict) {
49842
49911
  console.log(import_chalk15.default.dim(" Depth: strict_mode: false \u2014 phases stay proportional to the work"));
49843
49912
  }
49844
- const firstStep = Array.isArray(pipelineCfg.steps) ? pipelineCfg.steps[0] : void 0;
49845
- const firstName = firstStep?.name ?? firstStep?.agent ?? agents[0];
49846
- const slashCmds = Array.isArray(doc.slash_commands) ? doc.slash_commands : [];
49847
- const match = slashCmds.find(
49848
- (c) => typeof c.name === "string" && c.name.endsWith(`-${firstName}`) && c.agent === agents[0]
49849
- ) ?? slashCmds.find((c) => typeof c.name === "string" && c.name.endsWith(`-${firstName}`));
49850
- const runCmd = match?.name ?? `/${firstName}`;
49913
+ const runCmd = firstStepCommand(doc, pipelineCfg, agents);
49851
49914
  console.log(`
49852
49915
  Run ${import_chalk15.default.cyan(`${runCmd} ${epicId}`)} in Claude to begin.`);
49853
49916
  } catch (err) {
@@ -49858,6 +49921,87 @@ Run ${import_chalk15.default.cyan(`${runCmd} ${epicId}`)} in Claude to begin.`);
49858
49921
  throw err;
49859
49922
  }
49860
49923
  });
49924
+ cmd.command("follow-up <parentEpic>").description("Open a follow-up epic of <parentEpic> to park work found while doing it \u2014 nothing runs yet").requiredOption("--title <title>", "what the follow-up is").option("--desc <description>", "the note: what turned up, and why it is not part of the parent").option("--recipe <id>", "recipe for the follow-up (default: the one the parent runs on)").option("--pipeline <id>", "use an existing pipeline as-is (default: the parent's workflow)").option("--from <pipelineId>", "override the recipe's source pipeline").option("--epic <id>", "id for the follow-up (default: <parentEpic>-F<n>)").option("--input <kv>", "capability input as key=value (repeatable)", collectKv, []).option("--tag <tag>", "extra tag (repeatable) \u2014 added to the ones inherited from the parent", collectKv, []).option("--no-inherit-tags", "do not copy the parent's tags").option("--no-strict", "work to the size of this epic \u2014 no invented NFR / risk / alternatives sections").option("--json", "output the result as JSON").action((parentEpic, opts, actionCmd) => {
49925
+ const root = resolveWorkspaceRoot(actionCmd);
49926
+ const doc = requireYaml(root);
49927
+ if (opts.recipe && opts.pipeline) {
49928
+ console.error(import_chalk15.default.red("Pick at most one of --recipe <id> or --pipeline <id>."));
49929
+ process.exit(1);
49930
+ }
49931
+ let config;
49932
+ try {
49933
+ config = (0, import_core19.validateWorkspace)(doc, ".aidlc/workspace.yaml");
49934
+ } catch (err) {
49935
+ console.error(import_chalk15.default.red("workspace.yaml is invalid \u2014 fix it before opening a follow-up:"));
49936
+ console.error(import_chalk15.default.dim(err instanceof Error ? err.message : String(err)));
49937
+ process.exit(1);
49938
+ }
49939
+ let defaults;
49940
+ try {
49941
+ defaults = (0, import_core19.followUpDefaults)(root, doc, parentEpic);
49942
+ } catch (err) {
49943
+ console.error(import_chalk15.default.red(err instanceof Error ? err.message : String(err)));
49944
+ process.exit(1);
49945
+ }
49946
+ const epicId = opts.epic?.trim() || defaults.epicId;
49947
+ const target = opts.pipeline ? { pipeline: opts.pipeline } : opts.recipe ? { recipe: opts.recipe } : defaults.target?.kind === "pipeline" ? { pipeline: defaults.target.id } : defaults.target ? { recipe: defaults.target.id } : void 0;
49948
+ if (!target) {
49949
+ console.error(import_chalk15.default.red(`Could not tell which workflow "${parentEpic}" runs on.`));
49950
+ console.error(import_chalk15.default.dim(" Pass one: --recipe <id> or --pipeline <id>"));
49951
+ process.exit(1);
49952
+ }
49953
+ const pipelineCfg = resolveEpicPipeline(root, doc, config, { ...target, from: opts.from, quiet: opts.json }, epicId);
49954
+ const agents = Array.isArray(pipelineCfg.steps) ? pipelineCfg.steps.map(import_core19.stepAgentId) : [];
49955
+ const inputs = {};
49956
+ for (const kv of opts.input) {
49957
+ const eq = kv.indexOf("=");
49958
+ if (eq > 0) {
49959
+ inputs[kv.slice(0, eq).trim()] = kv.slice(eq + 1).trim();
49960
+ }
49961
+ }
49962
+ const tags = (0, import_core19.normalizeTags)([...opts.inheritTags ? defaults.tags : [], ...opts.tag]);
49963
+ try {
49964
+ const { epicDir } = (0, import_core19.scaffoldEpic)({
49965
+ workspaceRoot: root,
49966
+ doc,
49967
+ epicId,
49968
+ title: opts.title.trim(),
49969
+ description: opts.desc?.trim() ?? "",
49970
+ target: { kind: "pipeline", id: pipelineCfg.id },
49971
+ agents,
49972
+ inputs: (0, import_core19.withFollowUpProvenance)(inputs, parentEpic, defaults.key),
49973
+ pipeline: pipelineCfg,
49974
+ strictMode: opts.strict,
49975
+ tags
49976
+ });
49977
+ if (opts.json) {
49978
+ console.log(JSON.stringify({
49979
+ epicId,
49980
+ epicDir,
49981
+ pipeline: pipelineCfg.id,
49982
+ fromEpic: parentEpic,
49983
+ followUpKey: defaults.key,
49984
+ tags
49985
+ }, null, 2));
49986
+ return;
49987
+ }
49988
+ console.log(import_chalk15.default.green("\u2714") + ` Opened follow-up ${import_chalk15.default.bold(epicId)} of ${import_chalk15.default.bold(parentEpic)}`);
49989
+ console.log(import_chalk15.default.dim(` Pipeline: ${pipelineCfg.id}`));
49990
+ console.log(import_chalk15.default.dim(` Steps: ${agents.join(" \u2192 ")}`));
49991
+ console.log(import_chalk15.default.dim(` Dir: ${epicDir}`));
49992
+ if (tags.length > 0) {
49993
+ console.log(import_chalk15.default.dim(" Tags: ") + import_chalk15.default.cyan(tags.join(" ")));
49994
+ }
49995
+ console.log(`
49996
+ Parked \u2014 nothing runs yet. When it is time: ${import_chalk15.default.cyan(`${firstStepCommand(doc, pipelineCfg, agents)} ${epicId}`)}`);
49997
+ } catch (err) {
49998
+ if (err instanceof import_core19.EpicScaffoldError) {
49999
+ console.error(import_chalk15.default.red(err.message));
50000
+ process.exit(1);
50001
+ }
50002
+ throw err;
50003
+ }
50004
+ });
49861
50005
  cmd.command("tag <id> [tags...]").description("Show or edit an epic's tags. Bare `tag <id>` prints them; extra words are added.").option("--add <tag>", "add a tag (repeatable) \u2014 same as passing it positionally", collectKv, []).option("--remove <tag>", "remove a tag (repeatable)", collectKv, []).option("--set <tag>", "replace every tag with these (repeatable)", collectKv, []).option("--clear", "remove every tag").option("--json", "Output the resulting tags as JSON").action((id, positional, opts, actionCmd) => {
49862
50006
  const root = resolveWorkspaceRoot(actionCmd);
49863
50007
  const doc = readYaml(root);
@@ -50260,6 +50404,61 @@ function collectKv(value, acc) {
50260
50404
  acc.push(value);
50261
50405
  return acc;
50262
50406
  }
50407
+ function firstStepCommand(doc, pipelineCfg, agents) {
50408
+ const firstStep = Array.isArray(pipelineCfg.steps) ? pipelineCfg.steps[0] : void 0;
50409
+ const firstName = firstStep?.name ?? firstStep?.agent ?? agents[0];
50410
+ const slashCmds = Array.isArray(doc.slash_commands) ? doc.slash_commands : [];
50411
+ const match = slashCmds.find(
50412
+ (c) => typeof c.name === "string" && c.name.endsWith(`-${firstName}`) && c.agent === agents[0]
50413
+ ) ?? slashCmds.find((c) => typeof c.name === "string" && c.name.endsWith(`-${firstName}`));
50414
+ return match?.name ?? `/${firstName}`;
50415
+ }
50416
+ function resolveEpicPipeline(root, doc, config, opts, epicId) {
50417
+ if (opts.pipeline) {
50418
+ const found = doc.pipelines.find((p) => String(p.id) === opts.pipeline);
50419
+ if (!found) {
50420
+ console.error(import_chalk15.default.red(`Pipeline "${opts.pipeline}" not found in workspace.yaml.`));
50421
+ process.exit(1);
50422
+ }
50423
+ return found;
50424
+ }
50425
+ const recipeId = opts.recipe ?? "";
50426
+ if (!config.recipes.some((r) => r.id === recipeId)) {
50427
+ console.error(import_chalk15.default.red(`Recipe "${recipeId}" is not defined in this workspace.`));
50428
+ process.exit(1);
50429
+ }
50430
+ if (opts.from) {
50431
+ const recipe = config.recipes.find((r) => r.id === recipeId);
50432
+ if (recipe) {
50433
+ recipe.from = opts.from;
50434
+ }
50435
+ }
50436
+ const pipelineId = (0, import_core19.recipePipelineId)({ recipeId, epicId, taken: existingIds(doc.pipelines) });
50437
+ let pipelineCfg;
50438
+ try {
50439
+ pipelineCfg = (0, import_core19.assemblePipeline)(config, { recipeId, pipelineId });
50440
+ } catch (err) {
50441
+ if (err instanceof import_core19.PipelineAssembleError) {
50442
+ console.error(import_chalk15.default.red("Could not assemble pipeline: ") + import_chalk15.default.dim(err.message));
50443
+ process.exit(1);
50444
+ }
50445
+ throw err;
50446
+ }
50447
+ doc.pipelines.push(pipelineCfg);
50448
+ (0, import_core19.stageEpicPipeline)(doc, pipelineCfg.id, epicId);
50449
+ try {
50450
+ (0, import_core19.validateWorkspace)(doc, ".aidlc/workspace.yaml");
50451
+ } catch (err) {
50452
+ console.error(import_chalk15.default.red("Assembled pipeline failed validation \u2014 not written:"));
50453
+ console.error(import_chalk15.default.dim(err instanceof Error ? err.message : String(err)));
50454
+ process.exit(1);
50455
+ }
50456
+ writeYaml(root, doc);
50457
+ if (!opts.quiet) {
50458
+ console.log(import_chalk15.default.dim(`Assembled pipeline ${import_chalk15.default.bold(pipelineCfg.id)} from recipe ${import_chalk15.default.bold(recipeId)}`));
50459
+ }
50460
+ return pipelineCfg;
50461
+ }
50263
50462
  function printEpicDetail(epic) {
50264
50463
  console.log();
50265
50464
  console.log(import_chalk15.default.bold(epic.id) + " " + colorEpicStatus(epic.status));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delete101020/aidlc",
3
- "version": "4.0.25",
3
+ "version": "4.0.26",
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": {