substrate-ai 0.21.1 → 0.21.3
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/README.md +32 -3
- package/dist/adapter-registry-BSig1zpx.js +4 -0
- package/dist/cli/index.js +114 -19
- package/dist/cli/templates/agents-md-substrate-section.md +12 -1
- package/dist/cli/templates/claude-md-substrate-section.md +6 -0
- package/dist/cli/templates/gemini-md-substrate-section.md +12 -1
- package/dist/{decisions-BPwrDCTx.js → decisions-lxU14pNh.js} +1 -1
- package/dist/{dist-BkhYgJWo.js → dist-CpnLJuVw.js} +13 -3
- package/dist/{errors-C7pY6_yQ.js → errors-8tVEwG6v.js} +2 -2
- package/dist/{experimenter-BYqALeaE.js → experimenter-C7swe92R.js} +1 -1
- package/dist/{health-Cfkv6XoQ.js → health-Dnzblihr.js} +3 -3
- package/dist/{health-Coh3BG8W.js → health-bhMCTYDO.js} +3 -3
- package/dist/{index-CnV5PcSR.d.ts → index-C31XtSMn.d.ts} +8 -1
- package/dist/index.d.ts +45 -2
- package/dist/index.js +2 -2
- package/dist/{interactive-prompt-BBfPSxyJ.js → interactive-prompt-BM5RaXYG.js} +2 -2
- package/dist/{manifest-read-BhNRIiqm.js → manifest-read-B3gE46DX.js} +369 -4
- package/dist/modules/interactive-prompt/index.js +3 -3
- package/dist/{routing-BS-Q8_2L.js → routing-CGO2UZyA.js} +1 -1
- package/dist/{run-CKM-5T34.js → run-ChZFveqv.js} +5 -5
- package/dist/{run-JrEnvaB0.js → run-ZxFHQyE_.js} +219 -8
- package/dist/src/modules/recovery-engine/index.d.ts +16 -2
- package/dist/{upgrade-S1oUMH5P.js → upgrade-BUSzXgnd.js} +2 -2
- package/dist/{upgrade-BOWLlLbD.js → upgrade-M0UkDCeg.js} +2 -2
- package/dist/{version-manager-impl-BVcsgUtN.js → version-manager-impl-DeEPhQlA.js} +1 -1
- package/package.json +1 -1
- package/packs/bmad/prompts/create-story.md +22 -0
- package/dist/adapter-registry-CZn__637.js +0 -4
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { BMAD_BASELINE_TOKENS_FULL, FileKvStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, validateStoryKey } from "./health-
|
|
1
|
+
import { BMAD_BASELINE_TOKENS_FULL, FileKvStore, STOP_AFTER_VALID_PHASES, STORY_KEY_PATTERN, VALID_PHASES, __commonJS, __require, __toESM, buildPipelineStatusOutput, createDatabaseAdapter, formatOutput, formatPipelineSummary, formatTokenTelemetry, inspectProcessTree, parseDbTimestampAsUtc, validateStoryKey } from "./health-Dnzblihr.js";
|
|
2
2
|
import { createLogger } from "./logger-KeHncl-f.js";
|
|
3
3
|
import { TypedEventBusImpl, createEventBus, createTuiApp, isTuiCapable, printNonTtyWarning, sleep } from "./helpers-CElYrONe.js";
|
|
4
|
-
import { ADVISORY_NOTES, BRANCH_PREFIX, CLAUDE_AUTH_FAILURE_HINT, CODEX_SANDBOX_BLOCK_HINT, Categorizer, ConsumerAnalyzer, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, IngestionServer, LogTurnAnalyzer, OPERATIONAL_FINDING, Recommender, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, callLLM, classifyVersionGap, createConfigSystem, createDatabaseAdapter$1, createDecision, createGitWorktreeManager, createPipelineRun, createRequirement, detectClaudeAuthFailure, detectCodexSandboxBlock, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunMetrics, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, swallowDebug, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-
|
|
5
|
-
import { FindingsInjector, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, parseRuntimeProbes, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery } from "./manifest-read-
|
|
4
|
+
import { ADVISORY_NOTES, BRANCH_PREFIX, CLAUDE_AUTH_FAILURE_HINT, CODEX_SANDBOX_BLOCK_HINT, Categorizer, ConsumerAnalyzer, DEFAULT_GLOBAL_SETTINGS, DispatcherImpl, DoltClient, ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, EfficiencyScorer, IngestionServer, LogTurnAnalyzer, OPERATIONAL_FINDING, Recommender, RoutingRecommender, RoutingResolver, RoutingTelemetry, RoutingTokenAccumulator, RoutingTuner, STORY_METRICS, STORY_OUTCOME, SubstrateConfigSchema, TEST_EXPANSION_FINDING, TEST_PLAN, TelemetryNormalizer, TelemetryPipeline, TurnAnalyzer, addTokenUsage, aggregateTokenUsageForRun, aggregateTokenUsageForStory, callLLM, classifyVersionGap, createConfigSystem, createDatabaseAdapter$1, createDecision, createGitWorktreeManager, createPipelineRun, createRequirement, detectClaudeAuthFailure, detectCodexSandboxBlock, detectInterfaceChanges, getArtifactByTypeForRun, getArtifactsByRun, getDecisionsByCategory, getDecisionsByPhase, getDecisionsByPhaseForRun, getLatestRun, getPipelineRunById, getRunMetrics, getRunningPipelineRuns, getStoryMetricsForRun, getTokenUsageSummary, initSchema, listRequirements, loadModelRoutingConfig, registerArtifact, swallowDebug, updatePipelineRun, updatePipelineRunConfig, upsertDecision, writeRunMetrics, writeStoryMetrics } from "./dist-CpnLJuVw.js";
|
|
5
|
+
import { FindingsInjector, JOURNEY_DEFERRALS_PATH, RunManifest, RuntimeProbeListSchema, applyConfigToGraph, computeJourneyCoverage, createDefaultVerificationPipeline, createGraphOrchestrator, createSdlcCodeReviewHandler, createSdlcCreateStoryHandler, createSdlcDevStoryHandler, createSdlcPhaseHandler, detectsEventDrivenAC, detectsStateIntegratingAC, extractTargetFilesFromStoryContent, loadJourneyDeferralsFromTrustedTree, loadJourneyRegistryFromTrustedTree, parseRuntimeProbes, parseStoryFrontmatter, renderFindings, resolveGraphPath, resolveMainRepoRoot, runAcTraceabilityCheck, runStaleVerificationRecovery, summarizeCoverage } from "./manifest-read-B3gE46DX.js";
|
|
6
6
|
import { WorkGraphRepository, detectCycles } from "./work-graph-repository-DZyJv5pV.js";
|
|
7
7
|
import { deriveExitCode, routeDecision } from "./decision-router-BAPpON_C.js";
|
|
8
|
-
import { runInteractivePrompt } from "./interactive-prompt-
|
|
8
|
+
import { runInteractivePrompt } from "./interactive-prompt-BM5RaXYG.js";
|
|
9
9
|
import { runRecoveryEngine } from "./recovery-engine-BKGBeBnW.js";
|
|
10
10
|
import { basename, dirname, extname, join } from "path";
|
|
11
11
|
import { access, readFile, readdir, stat } from "fs/promises";
|
|
@@ -933,6 +933,38 @@ const PIPELINE_EVENT_METADATA = [
|
|
|
933
933
|
}
|
|
934
934
|
]
|
|
935
935
|
},
|
|
936
|
+
{
|
|
937
|
+
type: "acceptance:coverage",
|
|
938
|
+
description: "Journey coverage audit result (acceptance gate, A0.3). Every registered journey in scope lands in exactly one state: walked-pass, walked-fail, deferred, unclaimed (NO story claims it — the never-wired-journey class), or unwalked (claimed but never walked). Advisory mode warns; blocking mode escalates the last story of the epic.",
|
|
939
|
+
when: "At each epic close and once at run end (scope: \"final\").",
|
|
940
|
+
fields: [
|
|
941
|
+
{
|
|
942
|
+
name: "ts",
|
|
943
|
+
type: "string",
|
|
944
|
+
description: "Timestamp."
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
name: "scope",
|
|
948
|
+
type: "string",
|
|
949
|
+
description: "Audited boundary: epic-<n> or final."
|
|
950
|
+
},
|
|
951
|
+
{
|
|
952
|
+
name: "mode",
|
|
953
|
+
type: "advisory|blocking",
|
|
954
|
+
description: "Audit posture (acceptance.mode config)."
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
name: "entries",
|
|
958
|
+
type: "array",
|
|
959
|
+
description: "Per-journey {journeyId, criticality, state, ownerStories}."
|
|
960
|
+
},
|
|
961
|
+
{
|
|
962
|
+
name: "summary",
|
|
963
|
+
type: "object",
|
|
964
|
+
description: "State counts across entries."
|
|
965
|
+
}
|
|
966
|
+
]
|
|
967
|
+
},
|
|
936
968
|
{
|
|
937
969
|
type: "story:escalation",
|
|
938
970
|
description: "Story escalated — either max review cycles exceeded or a precondition for SHIP_IT was not met.",
|
|
@@ -951,7 +983,7 @@ const PIPELINE_EVENT_METADATA = [
|
|
|
951
983
|
{
|
|
952
984
|
name: "reason",
|
|
953
985
|
type: "string",
|
|
954
|
-
description: "Escalation reason. Common values: review-cycles-exhausted (default review-loop max hit); create-story-no-file (create-story phase did not write a story artifact); dev-story-no-commit (substrate auto-commit found no committable changes — agent produced nothing or all changes were outside the worktree); dev-story-commit-failed (substrate auto-commit failed — typically a pre-commit hook rejected the commit; stderr captured in issues); merge-to-main-error (unexpected error in the merge-to-main phase); merge-conflict-detected (story branch could not be merged due to conflicts); parent-tree-dirtied-by-run (uncommitted parent changes intersect the story diff — merge refused, H3.3); ff-only-merge-not-possible (base moved and merge_strategy is ff-only — set finalization.merge_strategy: three-way or integrate manually, H3.3); epic-gate-failed (finalization.epic_gate_command exited non-zero before the last story of an epic integrated, H3.4); story-file-missing (story artifact gone from working tree AND branch HEAD — check wip/feat commits on the story branch, H5.5). v0.20.87+."
|
|
986
|
+
description: "Escalation reason. Common values: review-cycles-exhausted (default review-loop max hit); create-story-no-file (create-story phase did not write a story artifact); dev-story-no-commit (substrate auto-commit found no committable changes — agent produced nothing or all changes were outside the worktree); dev-story-commit-failed (substrate auto-commit failed — typically a pre-commit hook rejected the commit; stderr captured in issues); merge-to-main-error (unexpected error in the merge-to-main phase); merge-conflict-detected (story branch could not be merged due to conflicts); parent-tree-dirtied-by-run (uncommitted parent changes intersect the story diff — merge refused, H3.3); ff-only-merge-not-possible (base moved and merge_strategy is ff-only — set finalization.merge_strategy: three-way or integrate manually, H3.3); epic-gate-failed (finalization.epic_gate_command exited non-zero before the last story of an epic integrated, H3.4); story-file-missing (story artifact gone from working tree AND branch HEAD — check wip/feat commits on the story branch, H5.5); undisclosed-files-in-merge (a committed implementation file was never in the dev agent's files_modified, so no review cycle inspected it — inspect the branch, then re-dispatch with accurate files_modified or merge manually, H7); journey-unclaimed (acceptance.mode: blocking — a registered journey has NO story claiming it at epic close; wire it or defer via `substrate acceptance defer`, A0.3); journey-unwalked (acceptance.mode: blocking — a claimed journey was never walked by the acceptance gate at epic close, A0.3). v0.20.87+."
|
|
955
987
|
},
|
|
956
988
|
{
|
|
957
989
|
name: "cycles",
|
|
@@ -6138,6 +6170,21 @@ async function runCreateStory(deps, params) {
|
|
|
6138
6170
|
} catch {}
|
|
6139
6171
|
const archConstraintsContent = await getArchConstraints$3(deps);
|
|
6140
6172
|
const storyTemplateContent = await getStoryTemplate(deps);
|
|
6173
|
+
const trustedRoot = deps.parentProjectRoot ?? deps.projectRoot;
|
|
6174
|
+
let journeyRegistry;
|
|
6175
|
+
if (trustedRoot !== void 0) {
|
|
6176
|
+
const registryLoad = await loadJourneyRegistryFromTrustedTree(trustedRoot);
|
|
6177
|
+
if (registryLoad.status === "ok" && registryLoad.registry.journeys.length > 0) journeyRegistry = registryLoad.registry;
|
|
6178
|
+
else if (registryLoad.status === "invalid") logger$21.warn({
|
|
6179
|
+
storyKey,
|
|
6180
|
+
issues: registryLoad.issues
|
|
6181
|
+
}, "A0.2: journey registry present but invalid — stories will be untagged (registry validity is escalated at epic close)");
|
|
6182
|
+
else if (registryLoad.status === "error") logger$21.warn({
|
|
6183
|
+
storyKey,
|
|
6184
|
+
error: registryLoad.message
|
|
6185
|
+
}, "A0.2: journey registry read failed — stories will be untagged");
|
|
6186
|
+
}
|
|
6187
|
+
const journeyRegistryContent = journeyRegistry !== void 0 ? journeyRegistry.journeys.map((j$1) => `- ${j$1.id} [${j$1.criticality}]: ${j$1.title}`).join("\n") : "";
|
|
6141
6188
|
const { prompt, tokenCount, truncated } = assemblePrompt(template, [
|
|
6142
6189
|
{
|
|
6143
6190
|
name: "story_key",
|
|
@@ -6182,6 +6229,15 @@ async function runCreateStory(deps, params) {
|
|
|
6182
6229
|
name: "prior_drift_feedback",
|
|
6183
6230
|
content: "",
|
|
6184
6231
|
priority: "optional"
|
|
6232
|
+
}],
|
|
6233
|
+
...journeyRegistryContent.length > 0 ? [{
|
|
6234
|
+
name: "journey_registry",
|
|
6235
|
+
content: journeyRegistryContent,
|
|
6236
|
+
priority: "required"
|
|
6237
|
+
}] : [{
|
|
6238
|
+
name: "journey_registry",
|
|
6239
|
+
content: "",
|
|
6240
|
+
priority: "optional"
|
|
6185
6241
|
}]
|
|
6186
6242
|
], TOKEN_CEILING);
|
|
6187
6243
|
logger$21.debug({
|
|
@@ -6295,6 +6351,42 @@ async function runCreateStory(deps, params) {
|
|
|
6295
6351
|
};
|
|
6296
6352
|
}
|
|
6297
6353
|
const parsed = parseResult.data;
|
|
6354
|
+
let validatedJourneys;
|
|
6355
|
+
if (journeyRegistry !== void 0 && parsed.story_file !== void 0) {
|
|
6356
|
+
let artifactContent;
|
|
6357
|
+
try {
|
|
6358
|
+
artifactContent = await readFile$1(parsed.story_file, "utf-8");
|
|
6359
|
+
} catch {
|
|
6360
|
+
artifactContent = void 0;
|
|
6361
|
+
}
|
|
6362
|
+
if (artifactContent !== void 0) {
|
|
6363
|
+
const taggedJourneys = parseStoryFrontmatter(artifactContent).journeys;
|
|
6364
|
+
const knownIds = new Set(journeyRegistry.journeys.map((j$1) => j$1.id));
|
|
6365
|
+
const unknown = taggedJourneys.filter((id) => !knownIds.has(id));
|
|
6366
|
+
if (unknown.length > 0) {
|
|
6367
|
+
const details = `story artifact declares unknown journey id(s): ${unknown.join(", ")} — registry v${String(journeyRegistry.version)} defines: ${[...knownIds].join(", ")}`;
|
|
6368
|
+
logger$21.warn({
|
|
6369
|
+
epicId,
|
|
6370
|
+
storyKey,
|
|
6371
|
+
unknown
|
|
6372
|
+
}, "A0.2: journey tag validation failed");
|
|
6373
|
+
return {
|
|
6374
|
+
result: "failed",
|
|
6375
|
+
error: "schema_validation_failed",
|
|
6376
|
+
details,
|
|
6377
|
+
tokenUsage
|
|
6378
|
+
};
|
|
6379
|
+
}
|
|
6380
|
+
if (taggedJourneys.length > 0) {
|
|
6381
|
+
logger$21.info({
|
|
6382
|
+
epicId,
|
|
6383
|
+
storyKey,
|
|
6384
|
+
journeys: taggedJourneys
|
|
6385
|
+
}, "A0.2: story tagged with journeys");
|
|
6386
|
+
validatedJourneys = taggedJourneys;
|
|
6387
|
+
}
|
|
6388
|
+
}
|
|
6389
|
+
}
|
|
6298
6390
|
logger$21.info({
|
|
6299
6391
|
epicId,
|
|
6300
6392
|
storyKey,
|
|
@@ -6307,6 +6399,7 @@ async function runCreateStory(deps, params) {
|
|
|
6307
6399
|
story_key: parsed.story_key,
|
|
6308
6400
|
story_title: parsed.story_title,
|
|
6309
6401
|
tokenUsage,
|
|
6402
|
+
...validatedJourneys !== void 0 ? { journeys: validatedJourneys } : {},
|
|
6310
6403
|
...dispatchResult.model !== void 0 ? { model: dispatchResult.model } : {}
|
|
6311
6404
|
};
|
|
6312
6405
|
}
|
|
@@ -13859,6 +13952,40 @@ function createImplementationOrchestrator(deps) {
|
|
|
13859
13952
|
_lastProgressTs = Date.now();
|
|
13860
13953
|
_stalledStories.clear();
|
|
13861
13954
|
}
|
|
13955
|
+
async function auditJourneyCoverage(scope, opts) {
|
|
13956
|
+
const mode = config.acceptanceMode ?? "advisory";
|
|
13957
|
+
if (mode === "off" || projectRoot === void 0) return void 0;
|
|
13958
|
+
const registryLoad = await loadJourneyRegistryFromTrustedTree(projectRoot);
|
|
13959
|
+
if (registryLoad.status === "absent") return void 0;
|
|
13960
|
+
if (registryLoad.status !== "ok") {
|
|
13961
|
+
logger$27.warn({ detail: registryLoad.status === "invalid" ? registryLoad.issues : registryLoad.message }, "A0.3: journey registry unreadable/invalid — coverage audit skipped (loud escalation for this is A1 acceptance-unrunnable scope)");
|
|
13962
|
+
return void 0;
|
|
13963
|
+
}
|
|
13964
|
+
const deferralsLoad = await loadJourneyDeferralsFromTrustedTree(projectRoot);
|
|
13965
|
+
if (deferralsLoad.status !== "ok") logger$27.warn({ detail: deferralsLoad.status === "invalid" ? deferralsLoad.issues : deferralsLoad.message }, `A0.3: ${JOURNEY_DEFERRALS_PATH} unreadable/invalid — treating as no deferrals`);
|
|
13966
|
+
const deferredJourneyIds = deferralsLoad.status === "ok" ? deferralsLoad.deferrals.map((d) => d.journey) : [];
|
|
13967
|
+
const claims = [];
|
|
13968
|
+
for (const [key, st] of _stories.entries()) for (const journeyId of st.journeys ?? []) claims.push({
|
|
13969
|
+
journeyId,
|
|
13970
|
+
storyKey: key
|
|
13971
|
+
});
|
|
13972
|
+
const entries = computeJourneyCoverage({
|
|
13973
|
+
registry: registryLoad.registry,
|
|
13974
|
+
claims,
|
|
13975
|
+
verdicts: [],
|
|
13976
|
+
deferredJourneyIds,
|
|
13977
|
+
scope
|
|
13978
|
+
});
|
|
13979
|
+
const scopeLabel = "final" in scope ? "final" : `epic-${String(scope.epic)}`;
|
|
13980
|
+
eventBus.emit("orchestrator:acceptance-coverage", {
|
|
13981
|
+
scope: scopeLabel,
|
|
13982
|
+
mode,
|
|
13983
|
+
entries,
|
|
13984
|
+
summary: summarizeCoverage(entries)
|
|
13985
|
+
});
|
|
13986
|
+
if (opts?.persist === true && runManifest !== null) await runManifest.update({ journeys: entries }).catch((err) => logger$27.warn({ err }, "A0.3: manifest journeys ledger write failed — pipeline continues"));
|
|
13987
|
+
return entries;
|
|
13988
|
+
}
|
|
13862
13989
|
function getStallThresholdMs(phase) {
|
|
13863
13990
|
return phase === "IN_DEV" ? DEV_STORY_STALL_THRESHOLD_MS : DEFAULT_STALL_THRESHOLD_MS;
|
|
13864
13991
|
}
|
|
@@ -14085,6 +14212,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
14085
14212
|
storyKey,
|
|
14086
14213
|
storyFilePath
|
|
14087
14214
|
}, "Found existing story file — skipping create-story");
|
|
14215
|
+
try {
|
|
14216
|
+
const reusedContent = await readFile$1(candidatePath, "utf-8");
|
|
14217
|
+
const reusedJourneys = parseStoryFrontmatter(reusedContent).journeys;
|
|
14218
|
+
if (reusedJourneys.length > 0) updateStory(storyKey, { journeys: reusedJourneys });
|
|
14219
|
+
} catch {}
|
|
14088
14220
|
endPhase(storyKey, "create-story");
|
|
14089
14221
|
eventBus.emit("orchestrator:story-phase-complete", {
|
|
14090
14222
|
storyKey,
|
|
@@ -14379,6 +14511,13 @@ function createImplementationOrchestrator(deps) {
|
|
|
14379
14511
|
}
|
|
14380
14512
|
}
|
|
14381
14513
|
storyFilePath = createResult.story_file;
|
|
14514
|
+
if (createResult.journeys !== void 0 && createResult.journeys.length > 0) {
|
|
14515
|
+
updateStory(storyKey, { journeys: createResult.journeys });
|
|
14516
|
+
if (runManifest !== null) runManifest.patchStoryState(storyKey, { journeys: createResult.journeys }).catch((err) => logger$27.warn({
|
|
14517
|
+
err,
|
|
14518
|
+
storyKey
|
|
14519
|
+
}, "A0.3: patchStoryState(journeys) failed — pipeline continues"));
|
|
14520
|
+
}
|
|
14382
14521
|
_capturedStoryTitle = sanitizeStoryTitle(createResult.story_title);
|
|
14383
14522
|
if (createResult.story_title) try {
|
|
14384
14523
|
const epicId = storyKey.split("-")[0] ?? storyKey;
|
|
@@ -16231,6 +16370,53 @@ function createImplementationOrchestrator(deps) {
|
|
|
16231
16370
|
}
|
|
16232
16371
|
}
|
|
16233
16372
|
const finalizationMode = config.finalizationMode ?? "merge";
|
|
16373
|
+
{
|
|
16374
|
+
const acceptanceModeCfg = config.acceptanceMode ?? "advisory";
|
|
16375
|
+
if (acceptanceModeCfg !== "off") {
|
|
16376
|
+
const epicOfA = (key) => key.includes("-") ? key.slice(0, key.lastIndexOf("-")) : key;
|
|
16377
|
+
const epicIdA = epicOfA(storyKey);
|
|
16378
|
+
const TERMINAL_A = ["COMPLETE", "ESCALATED"];
|
|
16379
|
+
const isLastOfEpicA = [..._stories.entries()].filter(([key]) => key !== storyKey && epicOfA(key) === epicIdA).every(([, st]) => TERMINAL_A.includes(st.phase));
|
|
16380
|
+
const epicNum = Number(epicIdA);
|
|
16381
|
+
if (isLastOfEpicA && Number.isInteger(epicNum)) {
|
|
16382
|
+
const entries = await auditJourneyCoverage({ epic: epicNum });
|
|
16383
|
+
const violations = (entries ?? []).filter((e) => e.state === "unclaimed" || e.state === "unwalked");
|
|
16384
|
+
if (violations.length > 0) {
|
|
16385
|
+
const issueLines = violations.map((v) => `journey ${v.journeyId} [${v.criticality}] "${v.title}" is ${v.state}` + (v.ownerStories.length > 0 ? ` (claimed by ${v.ownerStories.join(", ")} but never walked)` : " — NO story claims it"));
|
|
16386
|
+
if (acceptanceModeCfg === "blocking") {
|
|
16387
|
+
const verdict = violations.some((v) => v.state === "unclaimed") ? "journey-unclaimed" : "journey-unwalked";
|
|
16388
|
+
logger$27.error({
|
|
16389
|
+
storyKey,
|
|
16390
|
+
epicId: epicIdA,
|
|
16391
|
+
journeys: violations.map((v) => v.journeyId)
|
|
16392
|
+
}, "A0.3: journey coverage violation at epic close — blocking finalization; branch preserved");
|
|
16393
|
+
updateStory(storyKey, {
|
|
16394
|
+
phase: "ESCALATED",
|
|
16395
|
+
error: verdict,
|
|
16396
|
+
completedAt: new Date().toISOString()
|
|
16397
|
+
});
|
|
16398
|
+
await emitEscalation({
|
|
16399
|
+
storyKey,
|
|
16400
|
+
lastVerdict: verdict,
|
|
16401
|
+
reviewCycles: completedReviewCycles,
|
|
16402
|
+
issues: [
|
|
16403
|
+
`epic ${epicIdA} closes with ${String(violations.length)} journey coverage violation(s) — the never-wired-journey class:`,
|
|
16404
|
+
...issueLines,
|
|
16405
|
+
"Wire the journey in a story tagged with its id, or defer it explicitly: `substrate acceptance defer <id> --reason \"<why>\"` (commit the deferral file)."
|
|
16406
|
+
]
|
|
16407
|
+
});
|
|
16408
|
+
await persistState();
|
|
16409
|
+
return "terminal";
|
|
16410
|
+
}
|
|
16411
|
+
logger$27.warn({
|
|
16412
|
+
storyKey,
|
|
16413
|
+
epicId: epicIdA,
|
|
16414
|
+
violations: issueLines
|
|
16415
|
+
}, "A0.3 (advisory): journey coverage violations at epic close — not blocking (acceptance.mode: advisory)");
|
|
16416
|
+
}
|
|
16417
|
+
}
|
|
16418
|
+
}
|
|
16419
|
+
}
|
|
16234
16420
|
const epicGateCommand = config.epicGateCommand;
|
|
16235
16421
|
if (epicGateCommand !== void 0 && epicGateCommand.trim() !== "" && finalizationMode !== "branch") {
|
|
16236
16422
|
const epicOf = (key) => key.includes("-") ? key.slice(0, key.lastIndexOf("-")) : key;
|
|
@@ -18008,6 +18194,11 @@ function createImplementationOrchestrator(deps) {
|
|
|
18008
18194
|
} catch (err) {
|
|
18009
18195
|
logger$27.debug({ err }, "Profile staleness check failed (best-effort)");
|
|
18010
18196
|
}
|
|
18197
|
+
try {
|
|
18198
|
+
await auditJourneyCoverage({ final: true }, { persist: true });
|
|
18199
|
+
} catch (err) {
|
|
18200
|
+
logger$27.warn({ err }, "A0.3: run-end coverage sweep failed (best-effort)");
|
|
18201
|
+
}
|
|
18011
18202
|
let completed = 0;
|
|
18012
18203
|
let escalated = 0;
|
|
18013
18204
|
let failed = 0;
|
|
@@ -46243,6 +46434,21 @@ function wireNdjsonEmitter(eventBus, ndjsonEmitter) {
|
|
|
46243
46434
|
...payload.prUrl !== void 0 ? { pr_url: payload.prUrl } : {}
|
|
46244
46435
|
});
|
|
46245
46436
|
});
|
|
46437
|
+
eventBus.on("orchestrator:acceptance-coverage", (payload) => {
|
|
46438
|
+
ndjsonEmitter.emit({
|
|
46439
|
+
type: "acceptance:coverage",
|
|
46440
|
+
ts: new Date().toISOString(),
|
|
46441
|
+
scope: payload.scope,
|
|
46442
|
+
mode: payload.mode,
|
|
46443
|
+
entries: payload.entries.map((e) => ({
|
|
46444
|
+
journeyId: e.journeyId,
|
|
46445
|
+
criticality: e.criticality,
|
|
46446
|
+
state: e.state,
|
|
46447
|
+
ownerStories: e.ownerStories
|
|
46448
|
+
})),
|
|
46449
|
+
summary: payload.summary
|
|
46450
|
+
});
|
|
46451
|
+
});
|
|
46246
46452
|
eventBus.on("orchestrator:story-escalated", (payload) => {
|
|
46247
46453
|
const rawIssues = Array.isArray(payload.issues) ? payload.issues : [];
|
|
46248
46454
|
const issues = rawIssues.map((issue) => {
|
|
@@ -46575,6 +46781,7 @@ async function runRunAction(options) {
|
|
|
46575
46781
|
let configFinalizationMode;
|
|
46576
46782
|
let configMergeStrategy;
|
|
46577
46783
|
let configEpicGateCommand;
|
|
46784
|
+
let configAcceptanceMode;
|
|
46578
46785
|
let configPermissionProfile;
|
|
46579
46786
|
let configWorktreeCopyFiles;
|
|
46580
46787
|
try {
|
|
@@ -46605,6 +46812,7 @@ async function runRunAction(options) {
|
|
|
46605
46812
|
if (cfg.finalization?.mode !== void 0) configFinalizationMode = cfg.finalization.mode;
|
|
46606
46813
|
if (cfg.finalization?.merge_strategy !== void 0) configMergeStrategy = cfg.finalization.merge_strategy;
|
|
46607
46814
|
if (cfg.finalization?.epic_gate_command !== void 0) configEpicGateCommand = cfg.finalization.epic_gate_command;
|
|
46815
|
+
if (cfg.acceptance?.mode !== void 0) configAcceptanceMode = cfg.acceptance.mode;
|
|
46608
46816
|
if (cfg.dispatch?.permission_profile !== void 0) configPermissionProfile = cfg.dispatch.permission_profile;
|
|
46609
46817
|
if (Array.isArray(cfg.worktree?.copy_files) && cfg.worktree.copy_files.length > 0) {
|
|
46610
46818
|
configWorktreeCopyFiles = [...cfg.worktree.copy_files];
|
|
@@ -46708,6 +46916,7 @@ async function runRunAction(options) {
|
|
|
46708
46916
|
...finalization !== void 0 ? { finalizationMode: finalization } : configFinalizationMode !== void 0 ? { finalizationMode: configFinalizationMode } : {},
|
|
46709
46917
|
...configMergeStrategy !== void 0 ? { mergeStrategy: configMergeStrategy } : {},
|
|
46710
46918
|
...configEpicGateCommand !== void 0 ? { epicGateCommand: configEpicGateCommand } : {},
|
|
46919
|
+
...configAcceptanceMode !== void 0 ? { acceptanceMode: configAcceptanceMode } : {},
|
|
46711
46920
|
...configPermissionProfile !== void 0 ? { permissionProfile: configPermissionProfile } : {},
|
|
46712
46921
|
...configWorktreeCopyFiles !== void 0 ? { worktreeCopyFiles: configWorktreeCopyFiles } : {}
|
|
46713
46922
|
});
|
|
@@ -47276,6 +47485,7 @@ async function runRunAction(options) {
|
|
|
47276
47485
|
...finalization !== void 0 ? { finalizationMode: finalization } : configFinalizationMode !== void 0 ? { finalizationMode: configFinalizationMode } : {},
|
|
47277
47486
|
...configMergeStrategy !== void 0 ? { mergeStrategy: configMergeStrategy } : {},
|
|
47278
47487
|
...configEpicGateCommand !== void 0 ? { epicGateCommand: configEpicGateCommand } : {},
|
|
47488
|
+
...configAcceptanceMode !== void 0 ? { acceptanceMode: configAcceptanceMode } : {},
|
|
47279
47489
|
...configWorktreeCopyFiles !== void 0 ? { worktreeCopyFiles: configWorktreeCopyFiles } : {}
|
|
47280
47490
|
},
|
|
47281
47491
|
projectRoot,
|
|
@@ -47499,7 +47709,7 @@ async function runRunAction(options) {
|
|
|
47499
47709
|
}
|
|
47500
47710
|
}
|
|
47501
47711
|
async function runFullPipeline(options) {
|
|
47502
|
-
const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, projectRoot, events: eventsFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, skipVerification, maxReviewCycles = 2, retryBudget, registry: injectedRegistry, tokenCeilings, stories: explicitStories, telemetryEnabled: fullTelemetryEnabled, telemetryPort: fullTelemetryPort, agentId, meshUrl: fpMeshUrl, meshProjectId: fpMeshProjectId, engineType: fpEngineType, probeAuthor, probeAuthorStateIntegrating: fpProbeAuthorStateIntegrating, noWorktree, worktreeCopyFiles: fpWorktreeCopyFiles, finalizationMode: fpFinalizationMode, mergeStrategy: fpMergeStrategy, epicGateCommand: fpEpicGateCommand, permissionProfile: fpPermissionProfile } = options;
|
|
47712
|
+
const { packName, packPath, dbDir, dbPath, startPhase, stopAfter, concept, concurrency, outputFormat, projectRoot, events: eventsFlag, skipUx, research: researchFlag, skipResearch: skipResearchFlag, skipPreflight, skipVerification, maxReviewCycles = 2, retryBudget, registry: injectedRegistry, tokenCeilings, stories: explicitStories, telemetryEnabled: fullTelemetryEnabled, telemetryPort: fullTelemetryPort, agentId, meshUrl: fpMeshUrl, meshProjectId: fpMeshProjectId, engineType: fpEngineType, probeAuthor, probeAuthorStateIntegrating: fpProbeAuthorStateIntegrating, noWorktree, worktreeCopyFiles: fpWorktreeCopyFiles, finalizationMode: fpFinalizationMode, mergeStrategy: fpMergeStrategy, epicGateCommand: fpEpicGateCommand, acceptanceMode: fpAcceptanceMode, permissionProfile: fpPermissionProfile } = options;
|
|
47503
47713
|
if (!existsSync$1(dbDir)) mkdirSync$1(dbDir, { recursive: true });
|
|
47504
47714
|
let doltServerFull = null;
|
|
47505
47715
|
try {
|
|
@@ -47815,6 +48025,7 @@ async function runFullPipeline(options) {
|
|
|
47815
48025
|
...fpFinalizationMode !== void 0 ? { finalizationMode: fpFinalizationMode } : {},
|
|
47816
48026
|
...fpMergeStrategy !== void 0 ? { mergeStrategy: fpMergeStrategy } : {},
|
|
47817
48027
|
...fpEpicGateCommand !== void 0 ? { epicGateCommand: fpEpicGateCommand } : {},
|
|
48028
|
+
...fpAcceptanceMode !== void 0 ? { acceptanceMode: fpAcceptanceMode } : {},
|
|
47818
48029
|
...fpWorktreeCopyFiles !== void 0 ? { worktreeCopyFiles: fpWorktreeCopyFiles } : {}
|
|
47819
48030
|
},
|
|
47820
48031
|
projectRoot,
|
|
@@ -47985,7 +48196,7 @@ async function runFullPipeline(options) {
|
|
|
47985
48196
|
*/
|
|
47986
48197
|
async function emitPreDispatchVersionAdvisory(currentVersion) {
|
|
47987
48198
|
if (process.env["SUBSTRATE_NO_UPDATE_CHECK"] === "1") return;
|
|
47988
|
-
const { createVersionManager } = await import("./version-manager-impl-
|
|
48199
|
+
const { createVersionManager } = await import("./version-manager-impl-DeEPhQlA.js");
|
|
47989
48200
|
const vm = createVersionManager();
|
|
47990
48201
|
const result = await vm.checkForUpdates(true);
|
|
47991
48202
|
const gap = classifyVersionGap(currentVersion, result.latestVersion);
|
|
@@ -48092,4 +48303,4 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
|
|
|
48092
48303
|
|
|
48093
48304
|
//#endregion
|
|
48094
48305
|
export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR$1 as GLOBSTAR, GitClient, GrammarLoader, Minimatch$1 as Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape$1 as escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runRunAction, runSolutioningPhase, unescape$1 as unescape, validateStopAfterFromConflict, wireNdjsonEmitter };
|
|
48095
|
-
//# sourceMappingURL=run-
|
|
48306
|
+
//# sourceMappingURL=run-ZxFHQyE_.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CoreEvents, DatabaseAdapter, TypedEventBus } from "../../../index-
|
|
1
|
+
import { CoreEvents, DatabaseAdapter, TypedEventBus } from "../../../index-C31XtSMn.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
4
|
//#region packages/sdlc/dist/verification/findings.d.ts
|
|
@@ -582,6 +582,7 @@ declare const PerStoryStateSchema: z.ZodObject<{
|
|
|
582
582
|
escalation_detail: z.ZodOptional<z.ZodString>;
|
|
583
583
|
commit_sha: z.ZodOptional<z.ZodString>;
|
|
584
584
|
baseline_sha: z.ZodOptional<z.ZodString>;
|
|
585
|
+
journeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
585
586
|
checkpoint_sha: z.ZodOptional<z.ZodString>;
|
|
586
587
|
finalization: z.ZodOptional<z.ZodObject<{
|
|
587
588
|
mode: z.ZodUnion<readonly [z.ZodLiteral<"merge">, z.ZodLiteral<"branch">, z.ZodLiteral<"pr">]>;
|
|
@@ -717,6 +718,19 @@ interface RunManifestData {
|
|
|
717
718
|
* Optional for backward-compatibility with pre-75-2 manifests.
|
|
718
719
|
*/
|
|
719
720
|
orchestrator_start_branch?: string;
|
|
721
|
+
/**
|
|
722
|
+
* A0.3 (acceptance-gate): journey coverage ledger from the most recent
|
|
723
|
+
* audit (epic-close or run-end). Absent on registry-less projects and
|
|
724
|
+
* pre-A0.3 manifests.
|
|
725
|
+
*/
|
|
726
|
+
journeys?: {
|
|
727
|
+
journeyId: string;
|
|
728
|
+
title: string;
|
|
729
|
+
criticality: 'critical' | 'standard';
|
|
730
|
+
epic?: number;
|
|
731
|
+
state: 'walked-pass' | 'walked-fail' | 'deferred' | 'unclaimed' | 'unwalked';
|
|
732
|
+
ownerStories: string[];
|
|
733
|
+
}[];
|
|
720
734
|
/**
|
|
721
735
|
* Human-readable reason the run was stopped (e.g. 'killed_by_user').
|
|
722
736
|
* Set by the SIGTERM/SIGINT handler (Story 58-7). Absent on pre-58-7 manifests.
|
|
@@ -751,8 +765,8 @@ declare const CliFlagsSchema: z.ZodObject<{
|
|
|
751
765
|
stories: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
752
766
|
halt_on: z.ZodOptional<z.ZodEnum<{
|
|
753
767
|
none: "none";
|
|
754
|
-
all: "all";
|
|
755
768
|
critical: "critical";
|
|
769
|
+
all: "all";
|
|
756
770
|
}>>;
|
|
757
771
|
cost_ceiling: z.ZodOptional<z.ZodNumber>;
|
|
758
772
|
agent: z.ZodOptional<z.ZodString>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createVersionManager } from "./dist-
|
|
1
|
+
import { createVersionManager } from "./dist-CpnLJuVw.js";
|
|
2
2
|
import { execSync, spawn } from "child_process";
|
|
3
3
|
import * as readline from "readline";
|
|
4
4
|
|
|
@@ -123,4 +123,4 @@ function registerUpgradeCommand(program) {
|
|
|
123
123
|
|
|
124
124
|
//#endregion
|
|
125
125
|
export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
|
|
126
|
-
//# sourceMappingURL=upgrade-
|
|
126
|
+
//# sourceMappingURL=upgrade-BUSzXgnd.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./dist-
|
|
1
|
+
import "./dist-CpnLJuVw.js";
|
|
2
2
|
import "./version-manager-impl-qFBiO4Eh.js";
|
|
3
|
-
import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-
|
|
3
|
+
import { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand } from "./upgrade-BUSzXgnd.js";
|
|
4
4
|
|
|
5
5
|
export { isGlobalInstall, registerUpgradeCommand, runUpgradeCommand };
|
package/package.json
CHANGED
|
@@ -191,6 +191,28 @@ Suggested values (use as many as apply):
|
|
|
191
191
|
|
|
192
192
|
**Omit the field (or leave it empty) only for purely-algorithmic modules** where you also omit `## Runtime Probes` — parse/format/sort/score/calculate transforms, type-only refactors, documentation edits, build-config changes, and unit-test-only stories.
|
|
193
193
|
|
|
194
|
+
### Journey tags (acceptance gate)
|
|
195
|
+
|
|
196
|
+
This project's journey registry (empty when the project has none):
|
|
197
|
+
|
|
198
|
+
{{journey_registry}}
|
|
199
|
+
|
|
200
|
+
If the registry above is non-empty, decide which journeys this story's acceptance criteria deliver or materially advance, and declare them in the SAME YAML frontmatter block at the top of the story file:
|
|
201
|
+
|
|
202
|
+
```text
|
|
203
|
+
---
|
|
204
|
+
external_state_dependencies:
|
|
205
|
+
- subprocess
|
|
206
|
+
journeys:
|
|
207
|
+
- UJ-2
|
|
208
|
+
---
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Rules:
|
|
212
|
+
- Use ONLY journey ids that appear in the registry above — an unknown id fails the story artifact's schema validation.
|
|
213
|
+
- Tag a journey when the story wires, extends, or completes any part of that journey's user-facing path — not merely because it touches nearby code.
|
|
214
|
+
- If no registered journey applies (or the registry above is empty), OMIT the `journeys:` field entirely. Untagged stories are legal; unclaimed journeys are audited separately at epic close.
|
|
215
|
+
|
|
194
216
|
### Probe YAML shape
|
|
195
217
|
|
|
196
218
|
Declare probes as a YAML list inside a single fenced `yaml` block directly under the `## Runtime Probes` heading. Each entry has this shape:
|