substrate-ai 0.20.87 → 0.20.89

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 CHANGED
@@ -157,7 +157,7 @@ Stories run in parallel across your available agents, each in its own git worktr
157
157
 
158
158
  #### Per-Story Worktree Lifecycle
159
159
 
160
- Each dispatched story runs in a dedicated git worktree at `.substrate-worktrees/story-<key>` on branch `substrate/story-<key>`. The dev agent's auto-commit (e.g., `feat(story-N-M): ...`) lands on the branch, not main. After verification produces a SHIP_IT verdict, the branch is merged back to the base branch (typically main) and the worktree is removed automatically. After a verification failure, the worktree and branch are preserved so you can inspect the partial implementation via `substrate reconcile-from-disk`. Use `--no-worktree` if your project does not support worktrees (e.g., submodules, bare repos).
160
+ Each dispatched story runs in a dedicated git worktree at `.substrate-worktrees/story-<key>` on branch `substrate/story-<key>`. After verification produces a SHIP_IT verdict, **substrate auto-commits the dispatched agent's output** to the story branch with a `feat(story-N-M): <title>` message (v0.20.86+ — substrate does NOT rely on the agent running `git commit` itself, since empirical audit found agents don't reliably do so). Pre-commit hooks run on the substrate commit. The branch then merges to the base branch (typically main) and the worktree is removed. If the commit fails (e.g., a pre-commit hook rejects) or the agent's run produced no committable changes, the story escalates with `dev-story-commit-failed` or `dev-story-no-commit` instead of merging an empty branch. After a verification failure, the worktree and branch are preserved so you can inspect the partial implementation via `substrate reconcile-from-disk`. Use `--no-worktree` if your project does not support worktrees (e.g., submodules, bare repos).
161
161
 
162
162
  ### Verification Pipeline
163
163
 
package/dist/cli/index.js CHANGED
@@ -3,7 +3,7 @@ import { FileStateStore, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipel
3
3
  import { createLogger } from "../logger-KeHncl-f.js";
4
4
  import { createEventBus } from "../helpers-CElYrONe.js";
5
5
  import { AdapterRegistry, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, ConfigError, CostTrackerConfigSchema, DEFAULT_CONFIG, DoltClient, DoltNotInstalled, GlobalSettingsSchema, InMemoryDatabaseAdapter, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createDoltClient, createPipelineRun, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, swallowDebug, tagRunAsBaseline, updatePipelineRun } from "../dist-DCBSXUiX.js";
6
- import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-9rTq4ngR.js";
6
+ import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GLOBSTAR, GitClient, GrammarLoader, Minimatch, Minipass, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createGitWorktreeManager, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, escape, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runProbeAuthor, runSolutioningPhase, unescape, validateStopAfterFromConflict } from "../run-CVmkAQxu.js";
7
7
  import "../adapter-registry-DIcrxjH8.js";
8
8
  import { RunManifest, SupervisorLock, ZERO_FINDINGS_BY_AUTHOR, ZERO_FINDING_COUNTS, ZERO_PROBE_AUTHOR_METRICS, aggregateProbeAuthorMetrics, parseRuntimeProbes, readCurrentRunId, resolveMainRepoRoot, resolveRunManifest, rollupFindingCounts, rollupFindingsByAuthor, rollupProbeAuthorByClass, rollupProbeAuthorMetrics, runAcTraceabilityCheck } from "../manifest-read-Boipz5aP.js";
9
9
  import "../errors-D7xD-utp.js";
@@ -8436,7 +8436,7 @@ async function runSupervisorAction(options, deps = {}) {
8436
8436
  await initSchema(expAdapter);
8437
8437
  const { runRunAction: runPipeline } = await import(
8438
8438
  /* @vite-ignore */
8439
- "../run-80GC8leA.js"
8439
+ "../run-CsXM3tl6.js"
8440
8440
  );
8441
8441
  const runStoryFn = async (opts) => {
8442
8442
  const exitCode = await runPipeline({
@@ -1472,8 +1472,8 @@ const PIPELINE_EVENT_METADATA = [
1472
1472
  },
1473
1473
  {
1474
1474
  type: "story:escalation",
1475
- description: "Story escalated after exhausting review cycles.",
1476
- when: "When max review cycles exceeded.",
1475
+ description: "Story escalated either max review cycles exceeded or a precondition for SHIP_IT was not met.",
1476
+ when: "When max review cycles exceeded, OR when substrate detects a hard precondition failure (e.g., auto-commit failed, branch did not advance).",
1477
1477
  fields: [
1478
1478
  {
1479
1479
  name: "ts",
@@ -1488,7 +1488,7 @@ const PIPELINE_EVENT_METADATA = [
1488
1488
  {
1489
1489
  name: "reason",
1490
1490
  type: "string",
1491
- description: "Escalation reason."
1491
+ 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). v0.20.87+."
1492
1492
  },
1493
1493
  {
1494
1494
  name: "cycles",
@@ -2722,7 +2722,7 @@ These on-disk files back the new autonomy commands. External monitors (dashboard
2722
2722
  - \`.substrate/current-run-id\` — plain text file containing the latest run ID; consulted by the canonical run-discovery chain.
2723
2723
  - \`.substrate/notifications/<run-id>-<timestamp>.json\` — operator halt notifications written by the Recovery Engine when \`--halt-on\` triggers; deleted by \`substrate report\` after read.
2724
2724
  - \`pending_proposals[]\` field in the run manifest — Recovery Engine Tier B re-scope proposals collected here for next-morning operator review. Back-pressure pauses dispatching at \`>= 2\` proposals (work-graph-aware) or \`>= 5\` (safety valve).
2725
- - \`.substrate-worktrees/story-<key>/\` — per-story git worktree directories created during dispatch. Removed on successful merge; preserved on failure for \`substrate reconcile-from-disk\` inspection. Use \`--no-worktree\` to disable.
2725
+ - \`.substrate-worktrees/story-<key>/\` — per-story git worktree directories created during dispatch on branch \`substrate/story-<key>\`. **Substrate auto-commits** the dispatched agent's output to the branch after SHIP_IT with a \`feat(story-N-M): <title>\` message (v0.20.86+ substrate does not rely on the agent committing). Pre-commit hooks fire on the substrate commit. The branch is then merged to the base branch and the worktree is removed. On verification failure or auto-commit failure, the worktree and branch are preserved for \`substrate reconcile-from-disk\` inspection. Use \`--no-worktree\` (or \`SUBSTRATE_NO_WORKTREE=1\`) to disable per-story worktrees entirely; dispatch then runs against the parent project tree.
2726
2726
 
2727
2727
  ## Environment Variables
2728
2728
 
@@ -9253,39 +9253,18 @@ function tryThreeWayMerge(branchName, projectRoot) {
9253
9253
  * @param worktreeManager - Manager for removing the worktree directory
9254
9254
  * @param projectRoot - Working directory for git branch deletion
9255
9255
  */
9256
- async function cleanupAfterSuccessfulMerge(storyKey, branchName, worktreeManager, projectRoot) {
9256
+ async function cleanupAfterSuccessfulMerge(storyKey, branchName, worktreeManager, _projectRoot) {
9257
9257
  try {
9258
9258
  await worktreeManager.cleanupWorktree(storyKey);
9259
- logger$16.info({ storyKey }, "Worktree removed after successful merge");
9260
- } catch (worktreeErr) {
9261
- logger$16.warn({
9262
- storyKey,
9263
- err: worktreeErr
9264
- }, "Failed to remove worktree (best-effort)");
9265
- }
9266
- try {
9267
- execFileSync("git", [
9268
- "branch",
9269
- "-d",
9270
- branchName
9271
- ], {
9272
- cwd: projectRoot,
9273
- stdio: [
9274
- "ignore",
9275
- "pipe",
9276
- "pipe"
9277
- ]
9278
- });
9279
9259
  logger$16.info({
9280
9260
  storyKey,
9281
9261
  branchName
9282
- }, "Merged branch deleted");
9283
- } catch (branchErr) {
9262
+ }, "Worktree + branch removed after successful merge");
9263
+ } catch (worktreeErr) {
9284
9264
  logger$16.warn({
9285
9265
  storyKey,
9286
- branchName,
9287
- err: branchErr
9288
- }, "Failed to delete merged branch (best-effort)");
9266
+ err: worktreeErr
9267
+ }, "Failed to remove worktree (best-effort)");
9289
9268
  }
9290
9269
  }
9291
9270
  /**
@@ -47382,4 +47361,4 @@ function registerRunCommand(program, version = "0.0.0", projectRoot = process.cw
47382
47361
 
47383
47362
  //#endregion
47384
47363
  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, createGitWorktreeManager, 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 };
47385
- //# sourceMappingURL=run-9rTq4ngR.js.map
47364
+ //# sourceMappingURL=run-CVmkAQxu.js.map
@@ -2,7 +2,7 @@ import "./health-CuKzY0Fn.js";
2
2
  import "./logger-KeHncl-f.js";
3
3
  import "./helpers-CElYrONe.js";
4
4
  import "./dist-DCBSXUiX.js";
5
- import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-9rTq4ngR.js";
5
+ import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, resolveProbeAuthorStateIntegrating, runRunAction, wireNdjsonEmitter } from "./run-CVmkAQxu.js";
6
6
  import "./manifest-read-Boipz5aP.js";
7
7
  import "./routing-DFxoKHDt.js";
8
8
  import "./work-graph-repository-DZyJv5pV.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.20.87",
3
+ "version": "0.20.89",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -71,7 +71,9 @@ If the story artifact contains a `## Runtime Probes` section, your implementatio
71
71
 
72
72
  ## Output Contract
73
73
 
74
- After completing all tasks (or hitting a HALT condition), emit ONLY this YAML block — no other text:
74
+ After completing all tasks (or hitting a HALT condition), emit ONLY this YAML block — no other text.
75
+
76
+ **Do NOT run `git commit` yourself.** Substrate auto-commits your changes (v0.20.86+) using your declared `files_modified` list — your job is to write the files and report which ones, not to commit them. The substrate-side commit composes the message as `feat(story-X-Y): <title>` and runs the operator's pre-commit hooks. If you DID commit (e.g., for an interactive iteration), substrate's commit step short-circuits when there are no uncommitted changes — but it's cleaner to leave commit responsibility entirely to substrate.
75
77
 
76
78
  ```yaml
77
79
  result: success