substrate-ai 0.20.60 → 0.20.61

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 (2) hide show
  1. package/dist/cli/index.js +35 -44
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -13172,30 +13172,30 @@ function tailWindow(s, maxBytes = MAX_OUTPUT_BYTES) {
13172
13172
  return buf.slice(buf.length - maxBytes).toString("utf-8");
13173
13173
  }
13174
13174
  /**
13175
- * Read and parse the reconcile manifest index from .substrate/runs/manifest.json.
13176
- * Returns null if the file doesn't exist or fails to parse.
13175
+ * Materialize a ReconcileRunEntry from a per-run manifest at
13176
+ * `.substrate/runs/<run-id>.json`. Returns null if the manifest is absent or
13177
+ * malformed.
13177
13178
  */
13178
- async function readReconcileManifest(dbRoot) {
13179
- const manifestPath = join(dbRoot, ".substrate", "runs", "manifest.json");
13179
+ async function readRunEntry(dbRoot, resolvedRunId) {
13180
+ const { manifest: fullManifest } = await resolveRunManifest(dbRoot, resolvedRunId);
13181
+ if (!fullManifest) return null;
13180
13182
  try {
13181
- const content = await readFile(manifestPath, "utf-8");
13182
- const parsed = JSON.parse(content);
13183
- if (parsed !== null && typeof parsed === "object" && "runs" in parsed && Array.isArray(parsed.runs)) return parsed;
13184
- return null;
13183
+ const data = await fullManifest.read();
13184
+ const stories = Object.entries(data.per_story_state).map(([key, state]) => ({
13185
+ storyKey: key,
13186
+ status: state.status
13187
+ }));
13188
+ return {
13189
+ runId: resolvedRunId,
13190
+ started_at: data.created_at,
13191
+ stories
13192
+ };
13185
13193
  } catch {
13194
+ logger$1.debug({ runId: resolvedRunId }, "failed to read individual run manifest");
13186
13195
  return null;
13187
13196
  }
13188
13197
  }
13189
13198
  /**
13190
- * Find a specific run entry from the manifest by runId.
13191
- * When runId is not provided, returns the last (most recent) entry.
13192
- */
13193
- function findRunEntry(manifest, runId) {
13194
- if (manifest.runs.length === 0) return null;
13195
- if (runId) return manifest.runs.find((r) => r.runId === runId) ?? null;
13196
- return manifest.runs[manifest.runs.length - 1] ?? null;
13197
- }
13198
- /**
13199
13199
  * Detect an auto-committed SHA for a story using git log.
13200
13200
  *
13201
13201
  * Searches commits matching `feat(story-<storyKey>)` since started_at using
@@ -13312,39 +13312,30 @@ async function runReconcileFromDiskAction(options) {
13312
13312
  const { runId, dryRun = false, yes = false, outputFormat, projectRoot, _dbRoot, _skipGates = false } = options;
13313
13313
  const startMs = Date.now();
13314
13314
  const dbRoot = _dbRoot ?? await resolveMainRepoRoot(projectRoot);
13315
- const indexManifest = await readReconcileManifest(dbRoot);
13316
- let resolvedRunId = null;
13317
- let runEntry = null;
13318
- if (runId) {
13319
- resolvedRunId = runId;
13320
- if (indexManifest) runEntry = findRunEntry(indexManifest, runId);
13321
- } else if (indexManifest && indexManifest.runs.length > 0) {
13322
- runEntry = findRunEntry(indexManifest);
13323
- resolvedRunId = runEntry?.runId ?? null;
13324
- } else resolvedRunId = await readCurrentRunId(dbRoot);
13315
+ let resolvedRunId = runId ?? null;
13316
+ if (!resolvedRunId) resolvedRunId = await readCurrentRunId(dbRoot);
13317
+ if (!resolvedRunId) {
13318
+ const probeAdapter = createDatabaseAdapter({
13319
+ backend: "auto",
13320
+ basePath: dbRoot
13321
+ });
13322
+ try {
13323
+ await initSchema(probeAdapter);
13324
+ const latestRun = await getLatestRun(probeAdapter);
13325
+ if (latestRun?.id) resolvedRunId = latestRun.id;
13326
+ } catch {
13327
+ logger$1.debug("Dolt fallback failed during run-id resolution");
13328
+ } finally {
13329
+ await probeAdapter.close().catch(() => {});
13330
+ }
13331
+ }
13325
13332
  if (!resolvedRunId) {
13326
13333
  const errorMsg = "No runs found. Use `substrate metrics --output-format json` for run history.";
13327
13334
  if (outputFormat === "json") process.stdout.write(JSON.stringify({ error: errorMsg }) + "\n");
13328
13335
  else process.stderr.write(`Error: ${errorMsg}\n`);
13329
13336
  return 1;
13330
13337
  }
13331
- if (!runEntry) {
13332
- const { manifest: fullManifest } = await resolveRunManifest(dbRoot, resolvedRunId);
13333
- if (fullManifest) try {
13334
- const data = await fullManifest.read();
13335
- const stories = Object.entries(data.per_story_state).map(([key, state]) => ({
13336
- storyKey: key,
13337
- status: state.status
13338
- }));
13339
- runEntry = {
13340
- runId: resolvedRunId,
13341
- started_at: data.created_at,
13342
- stories
13343
- };
13344
- } catch {
13345
- logger$1.debug({ runId: resolvedRunId }, "failed to read individual run manifest");
13346
- }
13347
- }
13338
+ const runEntry = await readRunEntry(dbRoot, resolvedRunId);
13348
13339
  if (!runEntry) {
13349
13340
  const errorMsg = runId ? `Run '${runId}' not found. Use \`substrate metrics --output-format json\` for run history.` : "No runs found. Use `substrate metrics --output-format json` for run history.";
13350
13341
  if (outputFormat === "json") process.stdout.write(JSON.stringify({ error: errorMsg }) + "\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "substrate-ai",
3
- "version": "0.20.60",
3
+ "version": "0.20.61",
4
4
  "description": "Substrate — multi-agent orchestration daemon for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",