@monoes/monomindcli 2.9.6 → 2.9.8
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/.claude/agents/design/design-monodesign.md +1 -2
- package/.claude/agents/engineering/engineering-ai-data-remediation-engineer.md +1 -2
- package/.claude/agents/engineering/engineering-ai-engineer.md +1 -2
- package/.claude/agents/engineering/engineering-autonomous-optimization-architect.md +0 -1
- package/.claude/agents/engineering/engineering-backend-architect.md +1 -2
- package/.claude/agents/engineering/engineering-code-reviewer.md +1 -2
- package/.claude/agents/engineering/engineering-data-engineer.md +1 -2
- package/.claude/agents/engineering/engineering-database-optimizer.md +1 -2
- package/.claude/agents/engineering/engineering-devops-automator.md +1 -2
- package/.claude/agents/engineering/engineering-embedded-firmware-engineer.md +1 -2
- package/.claude/agents/engineering/engineering-feishu-integration-developer.md +1 -2
- package/.claude/agents/engineering/engineering-frontend-developer.md +1 -2
- package/.claude/agents/engineering/engineering-git-workflow-master.md +1 -2
- package/.claude/agents/engineering/engineering-incident-response-commander.md +0 -1
- package/.claude/agents/engineering/engineering-mobile-app-builder.md +1 -2
- package/.claude/agents/engineering/engineering-rapid-prototyper.md +1 -2
- package/.claude/agents/engineering/engineering-security-engineer.md +1 -2
- package/.claude/agents/engineering/engineering-senior-developer.md +1 -2
- package/.claude/agents/engineering/engineering-software-architect.md +1 -2
- package/.claude/agents/engineering/engineering-solidity-smart-contract-engineer.md +1 -2
- package/.claude/agents/engineering/engineering-sre.md +0 -1
- package/.claude/agents/engineering/engineering-technical-writer.md +1 -2
- package/.claude/agents/engineering/engineering-threat-detection-engineer.md +0 -1
- package/.claude/agents/engineering/engineering-wechat-mini-program-developer.md +1 -2
- package/.claude/agents/github/code-review-swarm.md +0 -1
- package/.claude/agents/github/github-modes.md +0 -1
- package/.claude/agents/github/issue-tracker.md +0 -1
- package/.claude/agents/github/multi-repo-swarm.md +0 -1
- package/.claude/agents/github/pr-manager.md +0 -1
- package/.claude/agents/github/project-board-sync.md +0 -1
- package/.claude/agents/github/release-manager.md +0 -1
- package/.claude/agents/github/repo-architect.md +0 -1
- package/.claude/agents/github/swarm-issue.md +0 -1
- package/.claude/agents/github/swarm-pr.md +0 -1
- package/.claude/agents/github/sync-coordinator.md +0 -1
- package/.claude/agents/github/workflow-automation.md +0 -1
- package/.claude/agents/marketing/marketing-competitive-content.md +1 -2
- package/.claude/agents/marketing/marketing-cro-specialist.md +1 -2
- package/.claude/agents/marketing/marketing-email-specialist.md +1 -2
- package/.claude/agents/marketing/marketing-launch-strategist.md +1 -2
- package/.claude/agents/marketing/marketing-pricing-strategist.md +1 -2
- package/.claude/agents/specialized/agentic-identity-trust.md +0 -1
- package/.claude/agents/specialized/agents-orchestrator.md +1 -2
- package/.claude/agents/specialized/automation-governance-architect.md +1 -2
- package/.claude/agents/specialized/blockchain-security-auditor.md +1 -2
- package/.claude/agents/specialized/compliance-auditor.md +1 -2
- package/.claude/agents/specialized/identity-graph-operator.md +0 -1
- package/.claude/agents/specialized/lsp-index-engineer.md +1 -2
- package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +0 -1
- package/.claude/agents/specialized/specialized-cultural-intelligence-strategist.md +0 -1
- package/.claude/agents/specialized/specialized-developer-advocate.md +1 -2
- package/.claude/agents/specialized/specialized-document-generator.md +1 -2
- package/.claude/agents/specialized/specialized-mcp-builder.md +1 -2
- package/.claude/agents/specialized/specialized-model-qa.md +0 -1
- package/.claude/agents/specialized/specialized-workflow-architect.md +1 -2
- package/.claude/agents/specialized/zk-steward.md +1 -2
- package/.claude/agents/testing/production-validator.md +0 -1
- package/.claude/agents/testing/tdd-london-swarm.md +0 -1
- package/.claude/agents/testing/testing-accessibility-auditor.md +0 -1
- package/.claude/agents/testing/testing-api-tester.md +1 -2
- package/.claude/agents/testing/testing-evidence-collector.md +1 -2
- package/.claude/agents/testing/testing-performance-benchmarker.md +1 -2
- package/.claude/agents/testing/testing-test-results-analyzer.md +1 -2
- package/.claude/agents/testing/testing-tool-evaluator.md +1 -2
- package/.claude/agents/testing/testing-workflow-optimizer.md +1 -2
- package/.claude/commands/hooks/README.md +1 -1
- package/.claude/commands/memory/README.md +6 -7
- package/.claude/commands/monitoring/README.md +1 -1
- package/.claude/helpers/control-start.cjs +27 -7
- package/.claude/helpers/handlers/route-handler.cjs +22 -3
- package/.claude/helpers/handlers/session-handler.cjs +43 -0
- package/.claude/helpers/intelligence.cjs +27 -6
- package/.claude/helpers/statusline.cjs +45 -11
- package/.claude/skills/agentic-jujutsu/SKILL.md +17 -15
- package/.claude/skills/hive-mind-advanced/SKILL.md +212 -559
- package/.claude/skills/hooks-automation/SKILL.md +1 -1
- package/.claude/skills/mastermind-adapters/SKILL.md +0 -11
- package/.claude/skills/mastermind-agents/SKILL.md +0 -11
- package/.claude/skills/mastermind-backup/SKILL.md +0 -11
- package/.claude/skills/mastermind-bootstrap/SKILL.md +0 -11
- package/.claude/skills/mastermind-delegation/SKILL.md +14 -12
- package/.claude/skills/mastermind-idea/SKILL.md +0 -5
- package/.claude/skills/mastermind-monitor/SKILL.md +0 -15
- package/.claude/skills/mastermind-org-settings/SKILL.md +0 -11
- package/.claude/skills/mastermind-plugins/SKILL.md +0 -11
- package/.claude/skills/mastermind-protocol/SKILL.md +6 -124
- package/.claude/skills/mastermind-repeat/SKILL.md +0 -25
- package/.claude/skills/mastermind-review/SKILL.md +1 -1
- package/.claude/skills/mastermind-stoporg/SKILL.md +0 -19
- package/.claude/skills/memory-toolkit/SKILL.md +12 -11
- package/.claude/skills/monodesign/scripts/detector/engines/browser/drivers.mjs +8 -1
- package/.claude/skills/pair-programming/SKILL.md +1 -1
- package/.claude/skills/performance-analysis/SKILL.md +228 -484
- package/.claude/skills/specialagent/SKILL.md +31 -133
- package/.claude/skills/swarm-advanced/SKILL.md +2 -2
- package/.claude/skills/swarm-orchestration/SKILL.md +220 -150
- package/.claude/skills/verification-quality/SKILL.md +247 -571
- package/README.md +3 -3
- package/dist/src/commands/agent-lifecycle.js +3 -3
- package/dist/src/commands/agent-lifecycle.js.map +1 -1
- package/dist/src/commands/autopilot.d.ts.map +1 -1
- package/dist/src/commands/autopilot.js +7 -1
- package/dist/src/commands/autopilot.js.map +1 -1
- package/dist/src/commands/doc.d.ts.map +1 -1
- package/dist/src/commands/doc.js +14 -3
- package/dist/src/commands/doc.js.map +1 -1
- package/dist/src/commands/doctor-env-checks.d.ts +1 -1
- package/dist/src/commands/doctor-env-checks.d.ts.map +1 -1
- package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
- package/dist/src/commands/doctor-project-checks.js +3 -37
- package/dist/src/commands/doctor-project-checks.js.map +1 -1
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +30 -1
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/commands/hooks-coverage-commands.d.ts.map +1 -1
- package/dist/src/commands/hooks-coverage-commands.js +75 -67
- package/dist/src/commands/hooks-coverage-commands.js.map +1 -1
- package/dist/src/commands/hooks-workers.d.ts.map +1 -1
- package/dist/src/commands/hooks-workers.js +41 -10
- package/dist/src/commands/hooks-workers.js.map +1 -1
- package/dist/src/commands/hooks.js +1 -1
- package/dist/src/commands/index.d.ts +1 -1
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +20 -4
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +80 -7
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/mcp.d.ts.map +1 -1
- package/dist/src/commands/mcp.js +78 -2
- package/dist/src/commands/mcp.js.map +1 -1
- package/dist/src/commands/neural-optimize.d.ts.map +1 -1
- package/dist/src/commands/neural-optimize.js +27 -5
- package/dist/src/commands/neural-optimize.js.map +1 -1
- package/dist/src/commands/org-observe.d.ts.map +1 -1
- package/dist/src/commands/org-observe.js +1 -0
- package/dist/src/commands/org-observe.js.map +1 -1
- package/dist/src/commands/org.d.ts.map +1 -1
- package/dist/src/commands/org.js +129 -2
- package/dist/src/commands/org.js.map +1 -1
- package/dist/src/commands/performance.js +1 -1
- package/dist/src/commands/performance.js.map +1 -1
- package/dist/src/commands/security-cve.d.ts.map +1 -1
- package/dist/src/commands/security-cve.js +1 -11
- package/dist/src/commands/security-cve.js.map +1 -1
- package/dist/src/commands/security-misc.d.ts +0 -9
- package/dist/src/commands/security-misc.d.ts.map +1 -1
- package/dist/src/commands/security-misc.js +33 -54
- package/dist/src/commands/security-misc.js.map +1 -1
- package/dist/src/commands/security-scan.d.ts.map +1 -1
- package/dist/src/commands/security-scan.js +3 -11
- package/dist/src/commands/security-scan.js.map +1 -1
- package/dist/src/commands/swarm.d.ts.map +1 -1
- package/dist/src/commands/swarm.js +7 -2
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/commands/ui.d.ts +8 -0
- package/dist/src/commands/ui.d.ts.map +1 -0
- package/dist/src/commands/ui.js +94 -0
- package/dist/src/commands/ui.js.map +1 -0
- package/dist/src/init/claudemd-generator.d.ts.map +1 -1
- package/dist/src/init/claudemd-generator.js +7 -9
- package/dist/src/init/claudemd-generator.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +13 -3
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/kimi-generator.d.ts +3 -2
- package/dist/src/init/kimi-generator.d.ts.map +1 -1
- package/dist/src/init/kimi-generator.js +45 -13
- package/dist/src/init/kimi-generator.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts +1 -1
- package/dist/src/init/statusline-generator.js +1 -1
- package/dist/src/init/write-capabilities.js +7 -7
- package/dist/src/init/write-capabilities.js.map +1 -1
- package/dist/src/knowledge/document-pipeline.d.ts.map +1 -1
- package/dist/src/knowledge/document-pipeline.js +1 -0
- package/dist/src/knowledge/document-pipeline.js.map +1 -1
- package/dist/src/knowledge/eval/golden-set.d.ts.map +1 -1
- package/dist/src/knowledge/eval/golden-set.js +21 -32
- package/dist/src/knowledge/eval/golden-set.js.map +1 -1
- package/dist/src/mcp-tools/embeddings-tools.js +2 -2
- package/dist/src/mcp-tools/embeddings-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-intelligence.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-intelligence.js +29 -3
- package/dist/src/mcp-tools/hooks-intelligence.js.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.js +32 -19
- package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
- package/dist/src/mcp-tools/monograph/query-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph/query-tools.js +48 -18
- package/dist/src/mcp-tools/monograph/query-tools.js.map +1 -1
- package/dist/src/mcp-tools/performance-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/performance-tools.js +15 -10
- package/dist/src/mcp-tools/performance-tools.js.map +1 -1
- package/dist/src/memory/embedding-operations.d.ts +4 -0
- package/dist/src/memory/embedding-operations.d.ts.map +1 -1
- package/dist/src/memory/embedding-operations.js +125 -32
- package/dist/src/memory/embedding-operations.js.map +1 -1
- package/dist/src/memory/hnsw-operations.d.ts +1 -1
- package/dist/src/memory/hnsw-operations.js +1 -1
- package/dist/src/memory/memory-bridge.d.ts +8 -0
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +37 -8
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/memory/memory-read.d.ts +1 -1
- package/dist/src/memory/memory-read.js +2 -2
- package/dist/src/memory/memory-read.js.map +1 -1
- package/dist/src/orgrt/antigravity-runner.d.ts.map +1 -1
- package/dist/src/orgrt/antigravity-runner.js +6 -6
- package/dist/src/orgrt/antigravity-runner.js.map +1 -1
- package/dist/src/orgrt/checkpoint-ops.d.ts +11 -1
- package/dist/src/orgrt/checkpoint-ops.d.ts.map +1 -1
- package/dist/src/orgrt/checkpoint-ops.js +18 -86
- package/dist/src/orgrt/checkpoint-ops.js.map +1 -1
- package/dist/src/orgrt/checkpoint.d.ts +1 -1
- package/dist/src/orgrt/checkpoint.d.ts.map +1 -1
- package/dist/src/orgrt/checkpoint.js +3 -3
- package/dist/src/orgrt/checkpoint.js.map +1 -1
- package/dist/src/orgrt/daemon.d.ts +9 -1
- package/dist/src/orgrt/daemon.d.ts.map +1 -1
- package/dist/src/orgrt/daemon.js +267 -139
- package/dist/src/orgrt/daemon.js.map +1 -1
- package/dist/src/orgrt/decisions.d.ts +13 -0
- package/dist/src/orgrt/decisions.d.ts.map +1 -1
- package/dist/src/orgrt/decisions.js +95 -0
- package/dist/src/orgrt/decisions.js.map +1 -1
- package/dist/src/orgrt/forwarder.d.ts.map +1 -1
- package/dist/src/orgrt/forwarder.js +148 -15
- package/dist/src/orgrt/forwarder.js.map +1 -1
- package/dist/src/orgrt/kimicode-runner.js +1 -1
- package/dist/src/orgrt/kimicode-runner.js.map +1 -1
- package/dist/src/orgrt/opencode-runner.js +1 -1
- package/dist/src/orgrt/opencode-runner.js.map +1 -1
- package/dist/src/orgrt/session.d.ts +27 -1
- package/dist/src/orgrt/session.d.ts.map +1 -1
- package/dist/src/orgrt/session.js +67 -6
- package/dist/src/orgrt/session.js.map +1 -1
- package/dist/src/orgrt/task-dag.d.ts +11 -1
- package/dist/src/orgrt/task-dag.d.ts.map +1 -1
- package/dist/src/orgrt/task-dag.js +93 -2
- package/dist/src/orgrt/task-dag.js.map +1 -1
- package/dist/src/orgrt/templates.d.ts.map +1 -1
- package/dist/src/orgrt/templates.js +26 -2
- package/dist/src/orgrt/templates.js.map +1 -1
- package/dist/src/orgrt/types.d.ts +77 -1
- package/dist/src/orgrt/types.d.ts.map +1 -1
- package/dist/src/orgrt/types.js +28 -2
- package/dist/src/orgrt/types.js.map +1 -1
- package/dist/src/orgrt/vercel-providers.d.ts.map +1 -1
- package/dist/src/orgrt/vercel-providers.js +9 -4
- package/dist/src/orgrt/vercel-providers.js.map +1 -1
- package/dist/src/orgrt/vercel-runner.d.ts +0 -23
- package/dist/src/orgrt/vercel-runner.d.ts.map +1 -1
- package/dist/src/orgrt/vercel-runner.js +38 -7
- package/dist/src/orgrt/vercel-runner.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/.claude/commands/mastermind/approvev1.md +0 -94
- package/.claude/commands/mastermind/architect.md +0 -52
- package/.claude/commands/mastermind/autodev.md +0 -28
- package/.claude/commands/mastermind/build.md +0 -23
- package/.claude/commands/mastermind/finish.md +0 -17
- package/.claude/commands/mastermind/runorgv1.md +0 -159
- package/.claude/commands/mastermind/taskdev.md +0 -23
- package/.claude/commands/mastermind/tdd.md +0 -19
- package/.claude/commands/mastermind/verify.md +0 -19
- package/.claude/skills/mastermind-approvev1/SKILL.md +0 -191
- package/.claude/skills/mastermind-architect/SKILL.md +0 -862
- package/.claude/skills/mastermind-autodev/SKILL.md +0 -360
- package/.claude/skills/mastermind-build/SKILL.md +0 -169
- package/.claude/skills/mastermind-companies/SKILL.md +0 -256
- package/.claude/skills/mastermind-content/SKILL.md +0 -197
- package/.claude/skills/mastermind-costs/SKILL.md +0 -151
- package/.claude/skills/mastermind-finance/SKILL.md +0 -166
- package/.claude/skills/mastermind-finish/SKILL.md +0 -251
- package/.claude/skills/mastermind-heartbeatv1/SKILL.md +0 -167
- package/.claude/skills/mastermind-instance-settings/SKILL.md +0 -315
- package/.claude/skills/mastermind-marketing/SKILL.md +0 -228
- package/.claude/skills/mastermind-marketing/references/copywriting-frameworks.md +0 -181
- package/.claude/skills/mastermind-marketing/references/persuasion-psychology.md +0 -158
- package/.claude/skills/mastermind-ops/SKILL.md +0 -168
- package/.claude/skills/mastermind-org-chart/SKILL.md +0 -209
- package/.claude/skills/mastermind-project-detail/SKILL.md +0 -249
- package/.claude/skills/mastermind-project-workspace/SKILL.md +0 -244
- package/.claude/skills/mastermind-projects/SKILL.md +0 -167
- package/.claude/skills/mastermind-runorgv1/SKILL.md +0 -731
- package/.claude/skills/mastermind-sales/SKILL.md +0 -170
- package/.claude/skills/mastermind-taskdev/SKILL.md +0 -377
- package/.claude/skills/mastermind-taskdev/code-quality-reviewer-prompt.md +0 -60
- package/.claude/skills/mastermind-taskdev/final-reviewer-prompt.md +0 -144
- package/.claude/skills/mastermind-taskdev/implementer-prompt.md +0 -114
- package/.claude/skills/mastermind-taskdev/spec-reviewer-prompt.md +0 -80
- package/.claude/skills/mastermind-tdd/SKILL.md +0 -424
- package/.claude/skills/mastermind-verify/SKILL.md +0 -196
- package/.claude/skills/mastermind-wiki/SKILL.md +0 -314
- package/.claude/skills/monolean-review/SKILL.md +0 -57
package/dist/src/orgrt/daemon.js
CHANGED
|
@@ -21,7 +21,7 @@ import { KimiCodeAgentRunner } from './kimicode-runner.js';
|
|
|
21
21
|
import { VercelAgentRunner } from './vercel-runner.js';
|
|
22
22
|
import { CodexAgentRunner } from './codex-runner.js';
|
|
23
23
|
import { AntigravityAgentRunner } from './antigravity-runner.js';
|
|
24
|
-
import { captureCheckpoint } from './checkpoint.js';
|
|
24
|
+
import { captureCheckpoint, generateChecksum, validateCheckpoint, isCheckpointExpired, restoreMailboxQueue, } from './checkpoint.js';
|
|
25
25
|
import { loadGlobalFenceConfig, mergeFenceConfigs, createFenceForRole, } from './fence.js';
|
|
26
26
|
// ── Extracted module imports ────────────────────────────────────────────
|
|
27
27
|
import * as approvalOps from './approvals.js';
|
|
@@ -263,7 +263,7 @@ export class OrgDaemon {
|
|
|
263
263
|
return ws;
|
|
264
264
|
return isAbsolute(ws) ? ws : join(this.root, ws);
|
|
265
265
|
}
|
|
266
|
-
async startOrg(name, taskOverride) {
|
|
266
|
+
async startOrg(name, taskOverride, options) {
|
|
267
267
|
// A restart-driven start (scheduleBossRestart) keeps its crash counter so the
|
|
268
268
|
// cap holds; any other (explicit) start resets it so a manual re-run gets a
|
|
269
269
|
// fresh budget.
|
|
@@ -279,9 +279,31 @@ export class OrgDaemon {
|
|
|
279
279
|
throw new Error(`org ${name} already running`);
|
|
280
280
|
const defPath = join(this.root, ORG_DIR, `${name}.json`);
|
|
281
281
|
const def = OrgDefSchema.parse(JSON.parse(readFileSync(defPath, 'utf8')));
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
282
|
+
let run;
|
|
283
|
+
let checkpoint;
|
|
284
|
+
if (options?.resume) {
|
|
285
|
+
const rtPath = join(this.root, ORG_DIR, name, 'runtime.json');
|
|
286
|
+
if (!existsSync(rtPath))
|
|
287
|
+
throw new Error(`cannot resume org "${name}": runtime.json not found`);
|
|
288
|
+
const rt = JSON.parse(readFileSync(rtPath, 'utf8'));
|
|
289
|
+
if (!rt?.run || !rt?.checkpoint)
|
|
290
|
+
throw new Error(`cannot resume org "${name}": no valid checkpoint found`);
|
|
291
|
+
if (isCheckpointExpired(rt.checkpoint))
|
|
292
|
+
throw new Error(`cannot resume org "${name}": checkpoint expired`);
|
|
293
|
+
if (!validateCheckpoint(rt.checkpoint))
|
|
294
|
+
throw new Error(`cannot resume org "${name}": checkpoint validation failed`);
|
|
295
|
+
run = rt.run;
|
|
296
|
+
checkpoint = rt.checkpoint;
|
|
297
|
+
if (rt.abandonedRoles) {
|
|
298
|
+
this.abandoned.set(name, new Set(rt.abandonedRoles));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
this.abandoned.delete(name); // a previous run's missing roles say nothing about this one
|
|
303
|
+
// random suffix: second-precision stamps collide across processes (two CLI
|
|
304
|
+
// invocations in the same second would share a run dir and its bus.jsonl)
|
|
305
|
+
run = `run-${new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14)}-${Math.random().toString(36).slice(2, 6)}`;
|
|
306
|
+
}
|
|
285
307
|
const dir = join(this.root, ORG_DIR, name, run);
|
|
286
308
|
mkdirSync(dir, { recursive: true });
|
|
287
309
|
// Role sessions run at the project root by default. They used to run in an
|
|
@@ -292,7 +314,6 @@ export class OrgDaemon {
|
|
|
292
314
|
// not path-scoped, meaning the sandbox blocked the safe tools and let the
|
|
293
315
|
// unrestricted one through. Opt back in with run_config.workspace:
|
|
294
316
|
// 'isolated', or pin an absolute path.
|
|
295
|
-
this.abandoned.delete(name); // a previous run's missing roles say nothing about this one
|
|
296
317
|
const ws = this.workspaceSetting(def);
|
|
297
318
|
let cwd;
|
|
298
319
|
let worktreePath;
|
|
@@ -483,7 +504,9 @@ export class OrgDaemon {
|
|
|
483
504
|
// Extracted so a role that fails its gate check can be spawned later by
|
|
484
505
|
// scheduleDeferredSpawn() once resources free up, without re-running the
|
|
485
506
|
// gate logic or duplicating the session-wiring below.
|
|
486
|
-
const spawnRole = (role) => {
|
|
507
|
+
const spawnRole = (role, roleCheckpoint) => {
|
|
508
|
+
if (running.agents.has(role.id))
|
|
509
|
+
return;
|
|
487
510
|
let roleCwd = cwd;
|
|
488
511
|
if (ws === 'worktree-per-role' && role.id !== bossRole.id) {
|
|
489
512
|
const wtPath = join(this.root, ORG_DIR, name, `worktree-${role.id}`);
|
|
@@ -517,16 +540,32 @@ export class OrgDaemon {
|
|
|
517
540
|
}
|
|
518
541
|
}
|
|
519
542
|
const mailbox = new Mailbox();
|
|
543
|
+
if (roleCheckpoint?.mailboxQueue?.length) {
|
|
544
|
+
restoreMailboxQueue({ mailbox }, roleCheckpoint.mailboxQueue);
|
|
545
|
+
}
|
|
546
|
+
if (roleCheckpoint?.mailboxClosed) {
|
|
547
|
+
mailbox.close();
|
|
548
|
+
}
|
|
520
549
|
const policy = new PolicyEngine(role.id, { maxTokens: role.budget_tokens ?? perRoleBudget, ...(role.policy ?? {}) }, bus, roleCwd);
|
|
550
|
+
if (roleCheckpoint?.tokensUsed) {
|
|
551
|
+
policy.setUsage(roleCheckpoint.tokensUsed);
|
|
552
|
+
}
|
|
521
553
|
const runtime = {
|
|
522
554
|
mailbox,
|
|
523
555
|
policy,
|
|
524
|
-
status: 'running',
|
|
556
|
+
status: roleCheckpoint?.status ?? 'running',
|
|
525
557
|
done: Promise.resolve(),
|
|
526
|
-
metrics: { tokens: 0, costUsd: 0 },
|
|
558
|
+
metrics: { tokens: roleCheckpoint?.tokensUsed ?? 0, costUsd: roleCheckpoint?.costUsd ?? 0 },
|
|
559
|
+
lastMessageId: roleCheckpoint?.lastMessageId,
|
|
560
|
+
error: roleCheckpoint?.error,
|
|
561
|
+
sessionId: roleCheckpoint?.sessionId,
|
|
527
562
|
worktreePath: roleCwd !== cwd ? roleCwd : undefined,
|
|
528
563
|
scrollback: new ScrollbackBuffer(),
|
|
529
564
|
};
|
|
565
|
+
if (roleCheckpoint?.scrollback?.length) {
|
|
566
|
+
for (const line of roleCheckpoint.scrollback)
|
|
567
|
+
runtime.scrollback.push(line);
|
|
568
|
+
}
|
|
530
569
|
const sessionOpts = {
|
|
531
570
|
org: name,
|
|
532
571
|
role,
|
|
@@ -540,8 +579,10 @@ export class OrgDaemon {
|
|
|
540
579
|
// instead of polluting the workspace cwd.
|
|
541
580
|
orgDir: join(this.root, ORG_DIR, name),
|
|
542
581
|
maxTurns: role.max_turns_per_message ?? def.run_config.max_turns_per_message,
|
|
582
|
+
resumeSessionId: roleCheckpoint?.sessionId,
|
|
543
583
|
lastMessageId: () => runtime.lastMessageId,
|
|
544
584
|
onOutput: (line) => runtime.scrollback.push(line),
|
|
585
|
+
onSessionId: (id) => { runtime.sessionId = id; },
|
|
545
586
|
deliver: (from, to, subject, body) => this.deliver(name, from, to, subject, body),
|
|
546
587
|
askHuman: (r, question) => this.askHuman(name, r, question),
|
|
547
588
|
onGate: (r, gateName, gateDesc) => this.createGate(name, r, gateName, gateDesc),
|
|
@@ -628,6 +669,18 @@ export class OrgDaemon {
|
|
|
628
669
|
const running = this.orgs.get(name);
|
|
629
670
|
return JSON.stringify(running?.taskDag?.all() ?? [], null, 2);
|
|
630
671
|
},
|
|
672
|
+
splitTask: (r, parentId, children) => {
|
|
673
|
+
return this.dagSplitTask(name, r, parentId, children);
|
|
674
|
+
},
|
|
675
|
+
mergeTask: (r, sourceId, targetId) => {
|
|
676
|
+
return this.dagMergeTask(name, r, sourceId, targetId);
|
|
677
|
+
},
|
|
678
|
+
cancelTask: (r, taskId, reason) => {
|
|
679
|
+
return this.dagCancelTask(name, r, taskId, reason);
|
|
680
|
+
},
|
|
681
|
+
planGraph: (r, specs) => {
|
|
682
|
+
return this.dagPlanGraph(name, r, specs);
|
|
683
|
+
},
|
|
631
684
|
queryFn: this.opts.queryFn,
|
|
632
685
|
// Runner resolution: explicit opts.runner > role `runtime` field >
|
|
633
686
|
// org def `runtime` field > MONOMIND_RUNTIME env (opencode/kimicode) >
|
|
@@ -646,133 +699,172 @@ export class OrgDaemon {
|
|
|
646
699
|
// status chatter) so a dead agent surfaces instead of a run that
|
|
647
700
|
// silently never progresses.
|
|
648
701
|
const BACKOFFS_MS = this.opts.crashBackoffsMs ?? [1000, 5000, 15000];
|
|
649
|
-
runtime.
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
702
|
+
if (!mailbox.isClosed && runtime.status !== 'crashed') {
|
|
703
|
+
runtime.done = (async () => {
|
|
704
|
+
for (let attempt = 0;; attempt++) {
|
|
705
|
+
try {
|
|
706
|
+
await runAgentSession(sessionOpts);
|
|
707
|
+
runtime.status = 'ended';
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
catch (err) {
|
|
711
|
+
// Drop the crashed session's stale waker immediately: a push()
|
|
712
|
+
// during the backoff window must queue for the NEXT session, not
|
|
713
|
+
// wake the dead generator to swallow it.
|
|
714
|
+
mailbox.detach();
|
|
715
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
716
|
+
const isTurnLimit = /Reached maximum number of turns|error_max_turns/i.test(message);
|
|
717
|
+
// Bounded like every other recovery: attempt counts every pass
|
|
718
|
+
// through this loop, so a role that keeps surfacing max-turns
|
|
719
|
+
// errors here (session.ts already swallows the normal ones)
|
|
720
|
+
// falls through to crash handling instead of looping forever.
|
|
721
|
+
if (isTurnLimit && !mailbox.isClosed && attempt < BACKOFFS_MS.length) {
|
|
722
|
+
sessionOpts.resumeSessionId = undefined;
|
|
723
|
+
mailbox.push(`${Mailbox.CONTINUE_PREFIX} You reached the turn limit on your task. Continue your in-progress work from where you left off; if finished, end your turn.`);
|
|
668
724
|
bus.emit({
|
|
669
725
|
type: 'status',
|
|
670
726
|
from: role.id,
|
|
671
|
-
|
|
672
|
-
|
|
727
|
+
reason: 'turn-limit-recover',
|
|
728
|
+
msg: `agent "${role.id}" hit turn limit error — continuing with fresh session`,
|
|
673
729
|
});
|
|
674
|
-
|
|
730
|
+
continue;
|
|
675
731
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
const isContextLimit = OrgDaemon.CONTEXT_LIMIT_RE.test(message);
|
|
683
|
-
bus.emit({
|
|
684
|
-
type: 'audit',
|
|
685
|
-
from: role.id,
|
|
686
|
-
msg: `agent "${role.id}" crashed: ${message}`,
|
|
687
|
-
reason: isContextLimit ? 'agent-context-limit' : 'agent-session-crash',
|
|
688
|
-
data: {
|
|
689
|
-
agentId: role.id,
|
|
690
|
-
error: message,
|
|
691
|
-
restarts: attempt,
|
|
692
|
-
contextLimit: isContextLimit,
|
|
693
|
-
},
|
|
694
|
-
});
|
|
695
|
-
if (role.id !== bossRole.id) {
|
|
696
|
-
// #2/#3: a worker is gone for the rest of this run. Without this
|
|
697
|
-
// notice the coordinator keeps messaging a corpse (observed: four
|
|
698
|
-
// unanswered org_send calls to a developer that had crashed on a
|
|
699
|
-
// context-window limit). Tell the boss to reassign — and if the
|
|
700
|
-
// crash was a context overflow, tell it to chunk smaller, since
|
|
701
|
-
// re-dispatching the same task verbatim fails the same way.
|
|
702
|
-
const bossRt = running.agents.get(bossRole.id);
|
|
703
|
-
if (bossRt && !bossRt.mailbox.isClosed) {
|
|
704
|
-
const guidance = isContextLimit
|
|
705
|
-
? ' This was a context-window overflow — re-dispatching the same task verbatim will fail identically. Break the work into smaller pieces (one file or section at a time) and do not paste large file contents in a single message.'
|
|
706
|
-
: '';
|
|
707
|
-
bossRt.mailbox.push(`[system] Worker "${role.id}" crashed and will not recover this run (${message}). It can no longer receive messages — stop messaging it. Reassign its outstanding work to another agent or take it on yourself.${guidance}`);
|
|
732
|
+
// Exit 143 = SIGTERM. If the mailbox is already closed, we
|
|
733
|
+
// sent the signal ourselves during stop — not a crash.
|
|
734
|
+
const killedByStop = mailbox.isClosed && /exit(?:ed)? with code 143/.test(message);
|
|
735
|
+
const crash = () => {
|
|
736
|
+
if (killedByStop) {
|
|
737
|
+
runtime.status = 'ended';
|
|
708
738
|
bus.emit({
|
|
709
|
-
type: '
|
|
710
|
-
from:
|
|
711
|
-
|
|
712
|
-
|
|
739
|
+
type: 'status',
|
|
740
|
+
from: role.id,
|
|
741
|
+
msg: `agent "${role.id}" terminated by stop (was still working when drain window expired)`,
|
|
742
|
+
reason: 'terminated-by-stop',
|
|
713
743
|
});
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
runtime.status = 'crashed';
|
|
747
|
+
runtime.error = message;
|
|
748
|
+
// Close the mailbox so deliver()/receiveRemote() report a real
|
|
749
|
+
// error instead of pushing into a queue no session will read
|
|
750
|
+
// (and returning a false "delivered" receipt to the sender).
|
|
751
|
+
mailbox.close();
|
|
752
|
+
const isContextLimit = OrgDaemon.CONTEXT_LIMIT_RE.test(message);
|
|
753
|
+
bus.emit({
|
|
754
|
+
type: 'audit',
|
|
755
|
+
from: role.id,
|
|
756
|
+
msg: `agent "${role.id}" crashed: ${message}`,
|
|
757
|
+
reason: isContextLimit ? 'agent-context-limit' : 'agent-session-crash',
|
|
758
|
+
data: {
|
|
759
|
+
agentId: role.id,
|
|
760
|
+
error: message,
|
|
761
|
+
restarts: attempt,
|
|
762
|
+
contextLimit: isContextLimit,
|
|
763
|
+
},
|
|
764
|
+
});
|
|
765
|
+
if (role.id !== bossRole.id) {
|
|
766
|
+
// #2/#3: a worker is gone for the rest of this run. Without this
|
|
767
|
+
// notice the coordinator keeps messaging a corpse (observed: four
|
|
768
|
+
// unanswered org_send calls to a developer that had crashed on a
|
|
769
|
+
// context-window limit). Tell the boss to reassign — and if the
|
|
770
|
+
// crash was a context overflow, tell it to chunk smaller, since
|
|
771
|
+
// re-dispatching the same task verbatim fails the same way.
|
|
772
|
+
const bossRt = running.agents.get(bossRole.id);
|
|
773
|
+
if (bossRt && !bossRt.mailbox.isClosed) {
|
|
774
|
+
const guidance = isContextLimit
|
|
775
|
+
? ' This was a context-window overflow — re-dispatching the same task verbatim will fail identically. Break the work into smaller pieces (one file or section at a time) and do not paste large file contents in a single message.'
|
|
776
|
+
: '';
|
|
777
|
+
bossRt.mailbox.push(`[system] Worker "${role.id}" crashed and will not recover this run (${message}). It can no longer receive messages — stop messaging it. Reassign its outstanding work to another agent or take it on yourself.${guidance}`);
|
|
778
|
+
bus.emit({
|
|
779
|
+
type: 'audit',
|
|
780
|
+
from: bossRole.id,
|
|
781
|
+
reason: 'worker-crashed',
|
|
782
|
+
msg: `worker "${role.id}" crashed (contextLimit=${isContextLimit}); coordinator notified to reassign`,
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
else {
|
|
787
|
+
// #4: the coordinator itself died. Don't go silent and wait for a
|
|
788
|
+
// human — attempt a bounded whole-org restart with fresh sessions
|
|
789
|
+
// (which also sheds whatever bloated context caused the crash).
|
|
790
|
+
this.scheduleBossRestart(name);
|
|
714
791
|
}
|
|
792
|
+
};
|
|
793
|
+
// Fatal errors (provider auth/quota/billing — tagged with
|
|
794
|
+
// err.fatal by the runner) can NEVER be fixed by a restart: the
|
|
795
|
+
// same call fails identically or hangs. Skip the backoff loop
|
|
796
|
+
// and go straight to terminal crash handling instead of burning
|
|
797
|
+
// the retry budget and wall-clock on a guaranteed failure.
|
|
798
|
+
const fatal = err?.fatal === true;
|
|
799
|
+
if (fatal) {
|
|
800
|
+
bus.emit({
|
|
801
|
+
type: 'status',
|
|
802
|
+
from: role.id,
|
|
803
|
+
reason: 'agent-fatal',
|
|
804
|
+
msg: `agent "${role.id}" hit a fatal (non-retryable) error — not restarting`,
|
|
805
|
+
});
|
|
806
|
+
crash();
|
|
807
|
+
return;
|
|
715
808
|
}
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
// (which also sheds whatever bloated context caused the crash).
|
|
720
|
-
this.scheduleBossRestart(name);
|
|
809
|
+
if (mailbox.isClosed || attempt >= BACKOFFS_MS.length) {
|
|
810
|
+
crash();
|
|
811
|
+
return;
|
|
721
812
|
}
|
|
722
|
-
};
|
|
723
|
-
// Fatal errors (provider auth/quota/billing — tagged with
|
|
724
|
-
// err.fatal by the runner) can NEVER be fixed by a restart: the
|
|
725
|
-
// same call fails identically or hangs. Skip the backoff loop
|
|
726
|
-
// and go straight to terminal crash handling instead of burning
|
|
727
|
-
// the retry budget and wall-clock on a guaranteed failure.
|
|
728
|
-
const fatal = err?.fatal === true;
|
|
729
|
-
if (fatal) {
|
|
730
813
|
bus.emit({
|
|
731
814
|
type: 'status',
|
|
732
815
|
from: role.id,
|
|
733
|
-
reason: 'agent-
|
|
734
|
-
msg: `agent "${role.id}"
|
|
816
|
+
reason: 'agent-restart',
|
|
817
|
+
msg: `agent "${role.id}" crashed (${message}) — restarting in ${BACKOFFS_MS[attempt]}ms (attempt ${attempt + 1}/${BACKOFFS_MS.length})`,
|
|
735
818
|
});
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
819
|
+
await new Promise((r) => {
|
|
820
|
+
const t = setTimeout(r, BACKOFFS_MS[attempt]);
|
|
821
|
+
t.unref?.();
|
|
822
|
+
});
|
|
823
|
+
if (mailbox.isClosed) {
|
|
824
|
+
crash();
|
|
825
|
+
return;
|
|
826
|
+
} // org stopped during backoff — never recovered
|
|
742
827
|
}
|
|
743
|
-
bus.emit({
|
|
744
|
-
type: 'status',
|
|
745
|
-
from: role.id,
|
|
746
|
-
reason: 'agent-restart',
|
|
747
|
-
msg: `agent "${role.id}" crashed (${message}) — restarting in ${BACKOFFS_MS[attempt]}ms (attempt ${attempt + 1}/${BACKOFFS_MS.length})`,
|
|
748
|
-
});
|
|
749
|
-
await new Promise((r) => {
|
|
750
|
-
const t = setTimeout(r, BACKOFFS_MS[attempt]);
|
|
751
|
-
t.unref?.();
|
|
752
|
-
});
|
|
753
|
-
if (mailbox.isClosed) {
|
|
754
|
-
crash();
|
|
755
|
-
return;
|
|
756
|
-
} // org stopped during backoff — never recovered
|
|
757
828
|
}
|
|
758
|
-
}
|
|
759
|
-
}
|
|
829
|
+
})();
|
|
830
|
+
}
|
|
760
831
|
running.agents.set(role.id, runtime);
|
|
761
832
|
};
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
pendingRoles
|
|
833
|
+
if (options?.resume && checkpoint) {
|
|
834
|
+
const restoredRoles = new Set(Object.keys(checkpoint.roleState));
|
|
835
|
+
for (const [roleId, roleState] of Object.entries(checkpoint.roleState)) {
|
|
836
|
+
const role = def.roles.find((r) => r.id === roleId);
|
|
837
|
+
if (role)
|
|
838
|
+
spawnRole(role, roleState);
|
|
839
|
+
}
|
|
840
|
+
const pendingRoles = new Map();
|
|
841
|
+
for (const role of def.roles) {
|
|
842
|
+
if (!restoredRoles.has(role.id)) {
|
|
843
|
+
pendingRoles.set(role.id, role);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
running.pendingRoles = pendingRoles;
|
|
847
|
+
running.spawnRole = spawnRole;
|
|
848
|
+
running.taskDag = new TaskDag();
|
|
849
|
+
if (worktreePath)
|
|
850
|
+
running.worktreePath = worktreePath;
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
spawnRole(bossRole); // always, ungated — see comment above
|
|
854
|
+
// Lazy spawn: register non-boss roles as pending. They spawn on first
|
|
855
|
+
// message (see deliver()), avoiding the memory gate stampede at startup.
|
|
856
|
+
const pendingRoles = new Map();
|
|
857
|
+
for (const role of def.roles) {
|
|
858
|
+
if (role.id === bossRole.id)
|
|
859
|
+
continue;
|
|
860
|
+
pendingRoles.set(role.id, role);
|
|
861
|
+
}
|
|
862
|
+
running.pendingRoles = pendingRoles;
|
|
863
|
+
running.spawnRole = spawnRole;
|
|
864
|
+
running.taskDag = new TaskDag();
|
|
865
|
+
if (worktreePath)
|
|
866
|
+
running.worktreePath = worktreePath;
|
|
770
867
|
}
|
|
771
|
-
running.pendingRoles = pendingRoles;
|
|
772
|
-
running.spawnRole = spawnRole;
|
|
773
|
-
running.taskDag = new TaskDag();
|
|
774
|
-
if (worktreePath)
|
|
775
|
-
running.worktreePath = worktreePath;
|
|
776
868
|
// Crash cleanup: reap SDK children if this process exits abnormally.
|
|
777
869
|
// monolean: process-scoped listener — upgrade path = per-org tracking
|
|
778
870
|
const crashCleanup = () => {
|
|
@@ -816,25 +908,40 @@ export class OrgDaemon {
|
|
|
816
908
|
}
|
|
817
909
|
}
|
|
818
910
|
const boss = bossRole;
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
911
|
+
if (options?.resume) {
|
|
912
|
+
if (running.agents.get(boss.id)?.mailbox.serialize().queue.length === 0) {
|
|
913
|
+
running.agents
|
|
914
|
+
.get(boss.id)
|
|
915
|
+
?.mailbox.push(`Org "${name}" resumed from checkpoint (run ${run}).\nGoal: ${taskOverride ?? def.goal}\n` +
|
|
916
|
+
`Outstanding tasks and role states have been restored. Continue coordinating your team.`);
|
|
917
|
+
}
|
|
918
|
+
bus.emit({
|
|
919
|
+
type: 'status',
|
|
920
|
+
msg: `org resumed from checkpoint (${run})`,
|
|
921
|
+
data: { goal: taskOverride ?? def.goal },
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
else {
|
|
925
|
+
// Cross-run memory: brief the coordinator on the previous run so scheduled
|
|
926
|
+
// orgs accumulate instead of starting cold every interval.
|
|
927
|
+
const prev = readHistory(this.root, name).at(-1);
|
|
928
|
+
const prevBrief = prev
|
|
929
|
+
? `\n\nPrevious run (${prev.run}${prev.endedAt ? `, ${new Date(prev.endedAt).toISOString()}` : ''}): ` +
|
|
930
|
+
(prev.outcome
|
|
931
|
+
? `outcome "${prev.outcome.status}" — ${prev.outcome.summary}`
|
|
932
|
+
: `no recorded outcome (${prev.messages} messages, ${prev.assets.length} assets${prev.crashes.length ? `, ${prev.crashes.length} crashed agent(s)` : ''})`) +
|
|
933
|
+
`\nBuild on that work — do not redo what is already done.`
|
|
934
|
+
: '';
|
|
935
|
+
running.agents
|
|
936
|
+
.get(boss.id)
|
|
937
|
+
.mailbox.push(`Org "${name}" started (run ${run}).\nGoal: ${taskOverride ?? def.goal}\n` +
|
|
938
|
+
`Coordinate your team via org_send. When the goal is achieved (or clearly can't be), record it with org_complete, then end your turn.${prevBrief}`);
|
|
939
|
+
bus.emit({
|
|
940
|
+
type: 'status',
|
|
941
|
+
msg: `org started (${def.roles.length} agents)`,
|
|
942
|
+
data: { goal: taskOverride ?? def.goal },
|
|
943
|
+
});
|
|
944
|
+
}
|
|
838
945
|
this.persistState(name, 'running', run);
|
|
839
946
|
// Idle watchdog: a hung tool call (or a run that quietly finished without
|
|
840
947
|
// org_complete) produces no bus events, and every agent just waits. After
|
|
@@ -966,7 +1073,7 @@ export class OrgDaemon {
|
|
|
966
1073
|
// Snapshot checkpoint BEFORE closing mailboxes / draining sessions — the
|
|
967
1074
|
// queue is emptied during the drain, so capturing afterwards loses all
|
|
968
1075
|
// unconsumed messages (the whole point of checkpoint-resume).
|
|
969
|
-
const stopCheckpoint = captureCheckpoint(org);
|
|
1076
|
+
const stopCheckpoint = captureCheckpoint(org, 'stopped');
|
|
970
1077
|
// Capture THIS run's forwarder now: an autoWake-restart of the same org
|
|
971
1078
|
// during the long tail below (agent wait, flush, history write) would
|
|
972
1079
|
// register a NEW forwarder under the same name — settling/unsubscribing
|
|
@@ -1112,12 +1219,21 @@ export class OrgDaemon {
|
|
|
1112
1219
|
const p = join(this.root, ORG_DIR, name, 'runtime.json');
|
|
1113
1220
|
const missing = [...(this.abandoned.get(name) ?? [])];
|
|
1114
1221
|
const running = org ?? this.orgs.get(name);
|
|
1222
|
+
const validStatus = status === 'stopped' || status === 'crashed' ? status : 'running';
|
|
1115
1223
|
// Pattern 3: Capture full checkpoint state for resume. On stop, finishStop
|
|
1116
1224
|
// passes a snapshot captured BEFORE mailboxes close and sessions drain —
|
|
1117
1225
|
// otherwise the queue is always empty by persist time.
|
|
1118
1226
|
let checkpoint = checkpointOverride ?? null;
|
|
1119
|
-
if (running) {
|
|
1120
|
-
checkpoint = captureCheckpoint(running);
|
|
1227
|
+
if (!checkpoint && running) {
|
|
1228
|
+
checkpoint = captureCheckpoint(running, validStatus);
|
|
1229
|
+
}
|
|
1230
|
+
else if (checkpoint && checkpoint.status !== validStatus) {
|
|
1231
|
+
const { checksum: _, ...state } = checkpoint;
|
|
1232
|
+
checkpoint = {
|
|
1233
|
+
...state,
|
|
1234
|
+
status: validStatus,
|
|
1235
|
+
checksum: generateChecksum({ ...state, status: validStatus }),
|
|
1236
|
+
};
|
|
1121
1237
|
}
|
|
1122
1238
|
// C4: writeJsonFileAtomic (tmp + rename) — a direct writeFileSync here
|
|
1123
1239
|
// could leave runtime.json truncated on Ctrl-C during `org stop`, which
|
|
@@ -1216,6 +1332,18 @@ export class OrgDaemon {
|
|
|
1216
1332
|
dagCompleteTask(org, role, taskId, result) {
|
|
1217
1333
|
return decisionOps.dagCompleteTask(this, org, role, taskId, result);
|
|
1218
1334
|
}
|
|
1335
|
+
dagSplitTask(org, role, parentId, children) {
|
|
1336
|
+
return decisionOps.dagSplitTask(this, org, role, parentId, children);
|
|
1337
|
+
}
|
|
1338
|
+
dagMergeTask(org, role, sourceId, targetId) {
|
|
1339
|
+
return decisionOps.dagMergeTask(this, org, role, sourceId, targetId);
|
|
1340
|
+
}
|
|
1341
|
+
dagCancelTask(org, role, taskId, reason) {
|
|
1342
|
+
return decisionOps.dagCancelTask(this, org, role, taskId, reason);
|
|
1343
|
+
}
|
|
1344
|
+
dagPlanGraph(org, role, specs) {
|
|
1345
|
+
return decisionOps.dagPlanGraph(this, org, role, specs);
|
|
1346
|
+
}
|
|
1219
1347
|
recordDecision(org, role, decision) {
|
|
1220
1348
|
decisionOps.recordDecision(this, org, role, decision);
|
|
1221
1349
|
}
|