moflo 4.9.21 → 4.9.23
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/analysis/analyze-code-quality.md +0 -121
- package/.claude/agents/analysis/code-analyzer.md +5 -26
- package/.claude/agents/architecture/system-design/arch-system-design.md +0 -119
- package/.claude/agents/base-template-generator.md +0 -1
- package/.claude/agents/core/coder.md +0 -22
- package/.claude/agents/core/planner.md +0 -16
- package/.claude/agents/core/researcher.md +0 -16
- package/.claude/agents/core/reviewer.md +0 -17
- package/.claude/agents/core/tester.md +0 -19
- package/.claude/agents/custom/test-long-runner.md +0 -2
- package/.claude/agents/development/dev-backend-api.md +0 -167
- package/.claude/agents/development/dev-database.md +43 -0
- package/.claude/agents/development/dev-frontend.md +42 -0
- package/.claude/agents/devops/ci-cd/ops-cicd-github.md +0 -112
- package/.claude/agents/documentation/api-docs/docs-api-openapi.md +0 -111
- package/.claude/agents/security/security-auditor.md +45 -0
- package/.claude/guidance/shipped/moflo-cli-reference.md +19 -16
- package/.claude/guidance/shipped/moflo-core-guidance.md +0 -2
- package/.claude/guidance/shipped/moflo-guidance-rules.md +5 -5
- package/.claude/guidance/shipped/moflo-spell-runner.md +1 -0
- package/.claude/guidance/shipped/moflo-spell-scheduling.md +225 -0
- package/.claude/guidance/shipped/moflo-spell-troubleshooting.md +1 -0
- package/.claude/helpers/gate.cjs +70 -3
- package/.claude/skills/fl/execution-modes.md +38 -15
- package/.claude/skills/fl/phases.md +67 -0
- package/.claude/skills/spell-schedule/SKILL.md +18 -5
- package/README.md +1 -1
- package/bin/gate.cjs +70 -3
- package/bin/index-guidance.mjs +32 -6
- package/bin/lib/retired-files.mjs +146 -0
- package/bin/session-start-launcher.mjs +116 -8
- package/dist/src/cli/appliance/rvfa-builder.js +1 -1
- package/dist/src/cli/commands/agent.js +3 -9
- package/dist/src/cli/commands/daemon.js +13 -17
- package/dist/src/cli/commands/hooks.js +4 -9
- package/dist/src/cli/commands/index.js +2 -0
- package/dist/src/cli/commands/retire.js +111 -0
- package/dist/src/cli/commands/spell-schedule.js +237 -49
- package/dist/src/cli/hooks/reasoningbank/index.js +7 -7
- package/dist/src/cli/init/executor.js +26 -54
- package/dist/src/cli/init/helpers-generator.js +66 -3
- package/dist/src/cli/init/settings-generator.js +17 -6
- package/dist/src/cli/mcp-tools/agent-tools.js +9 -27
- package/dist/src/cli/mcp-tools/hooks-tools.js +23 -21
- package/dist/src/cli/mcp-tools/memory-tools.js +16 -5
- package/dist/src/cli/memory/bridge-embedder.js +26 -6
- package/dist/src/cli/memory/bridge-entries.js +33 -15
- package/dist/src/cli/memory/controllers/semantic-router.js +18 -12
- package/dist/src/cli/memory/sona-optimizer.js +6 -6
- package/dist/src/cli/neural/domain/services/learning-service.js +3 -3
- package/dist/src/cli/services/agent-router.js +2 -5
- package/dist/src/cli/services/daemon-autostart-lifecycle.js +62 -0
- package/dist/src/cli/services/daemon-dashboard.js +187 -18
- package/dist/src/cli/services/daemon-readiness.js +19 -31
- package/dist/src/cli/services/ephemeral-namespace-purge.js +61 -33
- package/dist/src/cli/services/headless-worker-executor.js +7 -94
- package/dist/src/cli/services/hook-block-hash.js +4 -0
- package/dist/src/cli/services/worker-daemon.js +40 -66
- package/dist/src/cli/shared/events/example-usage.js +6 -6
- package/dist/src/cli/shared/hooks/task-hooks.js +8 -8
- package/dist/src/cli/spells/core/runner.js +12 -0
- package/dist/src/cli/spells/scheduler/scheduler.js +24 -9
- package/dist/src/cli/spells/schema/validator.js +2 -1
- package/dist/src/cli/spells/schema/validators/top-level.js +18 -0
- package/dist/src/cli/version.js +1 -1
- package/package.json +5 -2
- package/retired-files.json +1989 -0
- package/src/cli/data/model-registry.json +2 -2
- package/.claude/agents/consensus/byzantine-coordinator.md +0 -63
- package/.claude/agents/consensus/crdt-synchronizer.md +0 -997
- package/.claude/agents/consensus/gossip-coordinator.md +0 -63
- package/.claude/agents/consensus/performance-benchmarker.md +0 -851
- package/.claude/agents/consensus/quorum-manager.md +0 -823
- package/.claude/agents/consensus/raft-manager.md +0 -63
- package/.claude/agents/consensus/security-manager.md +0 -622
- package/.claude/agents/data/ml/data-ml-model.md +0 -193
- package/.claude/agents/github/code-review-swarm.md +0 -538
- package/.claude/agents/github/github-modes.md +0 -172
- package/.claude/agents/github/issue-tracker.md +0 -311
- package/.claude/agents/github/multi-repo-swarm.md +0 -551
- package/.claude/agents/github/pr-manager.md +0 -183
- package/.claude/agents/github/project-board-sync.md +0 -508
- package/.claude/agents/github/release-manager.md +0 -360
- package/.claude/agents/github/release-swarm.md +0 -580
- package/.claude/agents/github/repo-architect.md +0 -391
- package/.claude/agents/github/swarm-issue.md +0 -566
- package/.claude/agents/github/swarm-pr.md +0 -414
- package/.claude/agents/github/sync-coordinator.md +0 -426
- package/.claude/agents/github/workflow-automation.md +0 -606
- package/.claude/agents/goal/code-goal-planner.md +0 -440
- package/.claude/agents/goal/goal-planner.md +0 -168
- package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +0 -127
- package/.claude/agents/hive-mind/queen-coordinator.md +0 -198
- package/.claude/agents/hive-mind/scout-explorer.md +0 -233
- package/.claude/agents/hive-mind/swarm-memory-manager.md +0 -184
- package/.claude/agents/hive-mind/worker-specialist.md +0 -208
- package/.claude/agents/neural/safla-neural.md +0 -73
- package/.claude/agents/optimization/benchmark-suite.md +0 -665
- package/.claude/agents/optimization/load-balancer.md +0 -431
- package/.claude/agents/optimization/performance-monitor.md +0 -672
- package/.claude/agents/optimization/resource-allocator.md +0 -674
- package/.claude/agents/optimization/topology-optimizer.md +0 -808
- package/.claude/agents/reasoning/goal-planner.md +0 -67
- package/.claude/agents/sona/sona-learning-optimizer.md +0 -74
- package/.claude/agents/sparc/architecture.md +0 -472
- package/.claude/agents/sparc/pseudocode.md +0 -318
- package/.claude/agents/sparc/refinement.md +0 -525
- package/.claude/agents/sparc/specification.md +0 -276
- package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +0 -225
- package/.claude/agents/swarm/adaptive-coordinator.md +0 -391
- package/.claude/agents/swarm/hierarchical-coordinator.md +0 -321
- package/.claude/agents/swarm/mesh-coordinator.md +0 -383
- package/.claude/agents/testing/production-validator.md +0 -395
- package/.claude/agents/testing/tdd-london-swarm.md +0 -244
- package/.claude/agents/v3/adr-architect.md +0 -184
- package/.claude/agents/v3/aidefence-guardian.md +0 -277
- package/.claude/agents/v3/claims-authorizer.md +0 -208
- package/.claude/agents/v3/collective-intelligence-coordinator.md +0 -988
- package/.claude/agents/v3/ddd-domain-expert.md +0 -220
- package/.claude/agents/v3/injection-analyst.md +0 -232
- package/.claude/agents/v3/memory-specialist.md +0 -987
- package/.claude/agents/v3/performance-engineer.md +0 -1225
- package/.claude/agents/v3/pii-detector.md +0 -146
- package/.claude/agents/v3/reasoningbank-learner.md +0 -213
- package/.claude/agents/v3/security-architect-aidefence.md +0 -405
- package/.claude/agents/v3/security-architect.md +0 -865
- package/.claude/agents/v3/security-auditor.md +0 -771
- package/.claude/agents/v3/sparc-orchestrator.md +0 -182
- package/.claude/agents/v3/swarm-memory-manager.md +0 -142
- package/.claude/agents/v3/v3-integration-architect.md +0 -205
- package/.claude/commands/claude-flow-help.md +0 -103
- package/.claude/commands/claude-flow-memory.md +0 -107
- package/.claude/commands/claude-flow-swarm.md +0 -205
- package/.claude/commands/flo-simplify.md +0 -101
- package/.claude/commands/github/README.md +0 -11
- package/.claude/commands/github/code-review-swarm.md +0 -514
- package/.claude/commands/github/code-review.md +0 -25
- package/.claude/commands/github/github-modes.md +0 -146
- package/.claude/commands/github/github-swarm.md +0 -113
- package/.claude/commands/github/issue-tracker.md +0 -284
- package/.claude/commands/github/issue-triage.md +0 -25
- package/.claude/commands/github/multi-repo-swarm.md +0 -519
- package/.claude/commands/github/pr-enhance.md +0 -26
- package/.claude/commands/github/pr-manager.md +0 -164
- package/.claude/commands/github/project-board-sync.md +0 -471
- package/.claude/commands/github/release-manager.md +0 -332
- package/.claude/commands/github/release-swarm.md +0 -544
- package/.claude/commands/github/repo-analyze.md +0 -25
- package/.claude/commands/github/repo-architect.md +0 -361
- package/.claude/commands/github/swarm-issue.md +0 -482
- package/.claude/commands/github/swarm-pr.md +0 -285
- package/.claude/commands/github/sync-coordinator.md +0 -294
- package/.claude/commands/github/workflow-automation.md +0 -442
- package/.claude/commands/hooks/README.md +0 -11
- package/.claude/commands/hooks/overview.md +0 -58
- package/.claude/commands/hooks/post-edit.md +0 -117
- package/.claude/commands/hooks/post-task.md +0 -112
- package/.claude/commands/hooks/pre-edit.md +0 -113
- package/.claude/commands/hooks/pre-task.md +0 -111
- package/.claude/commands/hooks/session-end.md +0 -118
- package/.claude/commands/hooks/setup.md +0 -103
- package/.claude/commands/sparc/analyzer.md +0 -42
- package/.claude/commands/sparc/architect.md +0 -43
- package/.claude/commands/sparc/ask.md +0 -86
- package/.claude/commands/sparc/batch-executor.md +0 -44
- package/.claude/commands/sparc/code.md +0 -78
- package/.claude/commands/sparc/coder.md +0 -44
- package/.claude/commands/sparc/debug.md +0 -72
- package/.claude/commands/sparc/debugger.md +0 -44
- package/.claude/commands/sparc/designer.md +0 -43
- package/.claude/commands/sparc/devops.md +0 -98
- package/.claude/commands/sparc/docs-writer.md +0 -69
- package/.claude/commands/sparc/documenter.md +0 -44
- package/.claude/commands/sparc/innovator.md +0 -44
- package/.claude/commands/sparc/integration.md +0 -72
- package/.claude/commands/sparc/mcp.md +0 -106
- package/.claude/commands/sparc/memory-manager.md +0 -44
- package/.claude/commands/sparc/optimizer.md +0 -44
- package/.claude/commands/sparc/orchestrator.md +0 -116
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +0 -72
- package/.claude/commands/sparc/refinement-optimization-mode.md +0 -72
- package/.claude/commands/sparc/researcher.md +0 -44
- package/.claude/commands/sparc/reviewer.md +0 -44
- package/.claude/commands/sparc/security-review.md +0 -69
- package/.claude/commands/sparc/sparc-modes.md +0 -139
- package/.claude/commands/sparc/sparc.md +0 -99
- package/.claude/commands/sparc/spec-pseudocode.md +0 -69
- package/.claude/commands/sparc/spell-manager.md +0 -44
- package/.claude/commands/sparc/supabase-admin.md +0 -337
- package/.claude/commands/sparc/swarm-coordinator.md +0 -44
- package/.claude/commands/sparc/tdd.md +0 -44
- package/.claude/commands/sparc/tester.md +0 -44
- package/.claude/commands/sparc/tutorial.md +0 -68
- package/.claude/commands/sparc.md +0 -151
|
@@ -105,9 +105,11 @@ export function generateSettings(options) {
|
|
|
105
105
|
daemon: {
|
|
106
106
|
autoStart: true,
|
|
107
107
|
// Note: this list is documentation for the user — the daemon's actual
|
|
108
|
-
// worker registry lives in src/cli/services/worker-daemon.ts
|
|
109
|
-
//
|
|
110
|
-
//
|
|
108
|
+
// worker registry lives in src/cli/services/worker-daemon.ts
|
|
109
|
+
// DEFAULT_WORKERS. The `audit`/`predict`/`document` workers were
|
|
110
|
+
// removed in #970 (no surfacing layer for findings + dashboard
|
|
111
|
+
// pollution); restore them as opt-in `flo doctor` one-shots if their
|
|
112
|
+
// value is ever re-established.
|
|
111
113
|
workers: [
|
|
112
114
|
'map', // Codebase mapping
|
|
113
115
|
'optimize', // Performance optimization (high priority)
|
|
@@ -115,15 +117,12 @@ export function generateSettings(options) {
|
|
|
115
117
|
'testgaps', // Test coverage gaps
|
|
116
118
|
'ultralearn', // Deep knowledge acquisition
|
|
117
119
|
'deepdive', // Deep code analysis
|
|
118
|
-
'document', // Auto-documentation for ADRs
|
|
119
120
|
'refactor', // Refactoring suggestions (DDD alignment)
|
|
120
121
|
'benchmark', // Performance benchmarking
|
|
121
122
|
],
|
|
122
123
|
schedules: {
|
|
123
|
-
audit: { interval: '1h', priority: 'critical' },
|
|
124
124
|
optimize: { interval: '30m', priority: 'high' },
|
|
125
125
|
consolidate: { interval: '2h', priority: 'low' },
|
|
126
|
-
document: { interval: '1h', priority: 'normal', triggers: ['adr-update', 'api-change'] },
|
|
127
126
|
deepdive: { interval: '4h', priority: 'normal', triggers: ['complex-change'] },
|
|
128
127
|
ultralearn: { interval: '1h', priority: 'normal' },
|
|
129
128
|
},
|
|
@@ -302,6 +301,18 @@ function generateHooksConfig(config) {
|
|
|
302
301
|
matcher: '^mcp__moflo__memory_store$',
|
|
303
302
|
hooks: [{ type: 'command', command: gateCmd('record-learnings-stored'), timeout: 2000 }],
|
|
304
303
|
},
|
|
304
|
+
{
|
|
305
|
+
// #952 — when /fl is invoked with -s/--swarm, the gate blocks Agent
|
|
306
|
+
// spawns until mcp__moflo__swarm_init runs. Record the call here so
|
|
307
|
+
// the hard block in check-before-agent passes for legitimate /fl runs.
|
|
308
|
+
matcher: '^mcp__moflo__swarm_init$',
|
|
309
|
+
hooks: [{ type: 'command', command: gateCmd('record-swarm-init'), timeout: 2000 }],
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
// #952 — symmetric record for /fl -h/--hive runs.
|
|
313
|
+
matcher: '^mcp__moflo__hive-mind_init$',
|
|
314
|
+
hooks: [{ type: 'command', command: gateCmd('record-hive-init'), timeout: 2000 }],
|
|
315
|
+
},
|
|
305
316
|
];
|
|
306
317
|
}
|
|
307
318
|
// UserPromptSubmit — per-prompt state reset + Context warnings.
|
|
@@ -27,33 +27,16 @@ const CANONICAL_AGENT_TYPES = [
|
|
|
27
27
|
];
|
|
28
28
|
const ALLOWED_AGENT_TYPES = new Set([
|
|
29
29
|
...CANONICAL_AGENT_TYPES,
|
|
30
|
-
//
|
|
31
|
-
'
|
|
30
|
+
// Claude Code built-ins
|
|
31
|
+
'claude-code-guide', 'general-purpose',
|
|
32
|
+
// Shipped Claude Code agent definitions (.claude/agents/**) — both the
|
|
33
|
+
// canonical `name:` slug and the file basename are accepted.
|
|
32
34
|
'analyze-code-quality', 'api-docs', 'arch-system-design',
|
|
33
|
-
'backend-dev', 'base-template-generator', '
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'dev-backend-api', 'docs-api-openapi', 'general-purpose',
|
|
39
|
-
'github-modes', 'goal-planner', 'gossip-coordinator',
|
|
40
|
-
'hierarchical-coordinator', 'injection-analyst', 'issue-tracker',
|
|
41
|
-
'load-balancer', 'memory-specialist', 'mesh-coordinator',
|
|
42
|
-
'ml-developer', 'mobile-dev', 'multi-repo-swarm',
|
|
43
|
-
'ops-cicd-github', 'performance-benchmarker', 'performance-engineer',
|
|
44
|
-
'performance-monitor', 'pii-detector', 'planner',
|
|
45
|
-
'pr-manager', 'production-validator', 'project-board-sync',
|
|
46
|
-
'pseudocode', 'quorum-manager', 'queen-coordinator',
|
|
47
|
-
'raft-manager', 'reasoningbank-learner', 'refinement',
|
|
48
|
-
'release-manager', 'release-swarm', 'repo-architect',
|
|
49
|
-
'resource-allocator', 'safla-neural', 'scout-explorer',
|
|
50
|
-
'security-architect', 'security-architect-aidefence',
|
|
51
|
-
'security-auditor', 'security-manager', 'sona-learning-optimizer',
|
|
52
|
-
'sparc-orchestrator', 'spec-mobile-react-native', 'specification',
|
|
53
|
-
'swarm-issue', 'swarm-memory-manager', 'swarm-pr',
|
|
54
|
-
'sync-coordinator', 'system-architect', 'tdd-london-swarm',
|
|
55
|
-
'test-long-runner', 'topology-optimizer', 'v3-integration-architect',
|
|
56
|
-
'workflow-automation', 'worker-specialist',
|
|
35
|
+
'backend-dev', 'base-template-generator', 'cicd-engineer',
|
|
36
|
+
'code-analyzer', 'database-dev', 'dev-backend-api',
|
|
37
|
+
'dev-database', 'dev-frontend', 'docs-api-openapi',
|
|
38
|
+
'frontend-dev', 'ops-cicd-github', 'planner',
|
|
39
|
+
'security-auditor', 'system-architect', 'test-long-runner',
|
|
57
40
|
]);
|
|
58
41
|
const AGENT_TYPE_SLUG_RE = /^[a-z][a-z0-9-]*$/;
|
|
59
42
|
export function toNonNegativeInt(value, fallback) {
|
|
@@ -78,7 +61,6 @@ export function validateAgentType(value) {
|
|
|
78
61
|
const AGENT_TYPE_MODEL_DEFAULTS = {
|
|
79
62
|
// Complex agents → opus
|
|
80
63
|
'architect': 'opus',
|
|
81
|
-
'security-architect': 'opus',
|
|
82
64
|
'system-architect': 'opus',
|
|
83
65
|
'core-architect': 'opus',
|
|
84
66
|
// Medium complexity → sonnet
|
|
@@ -211,7 +211,7 @@ function learnedPatternsFromOutcomes() {
|
|
|
211
211
|
const TASK_PATTERNS = {
|
|
212
212
|
'security-task': {
|
|
213
213
|
keywords: ['authentication', 'security', 'auth', 'password', 'encryption', 'vulnerability', 'cve', 'audit'],
|
|
214
|
-
agents: ['security-
|
|
214
|
+
agents: ['security-auditor', 'reviewer'],
|
|
215
215
|
},
|
|
216
216
|
'testing-task': {
|
|
217
217
|
keywords: ['test', 'testing', 'spec', 'coverage', 'unit test', 'integration test', 'e2e'],
|
|
@@ -223,7 +223,7 @@ const TASK_PATTERNS = {
|
|
|
223
223
|
},
|
|
224
224
|
'performance-task': {
|
|
225
225
|
keywords: ['performance', 'optimize', 'speed', 'memory', 'benchmark', 'profiling', 'bottleneck'],
|
|
226
|
-
agents: ['
|
|
226
|
+
agents: ['reviewer', 'coder', 'tester'],
|
|
227
227
|
},
|
|
228
228
|
'refactor-task': {
|
|
229
229
|
keywords: ['refactor', 'restructure', 'clean', 'organize', 'modular', 'decouple'],
|
|
@@ -239,23 +239,25 @@ const TASK_PATTERNS = {
|
|
|
239
239
|
},
|
|
240
240
|
'database-task': {
|
|
241
241
|
keywords: ['database', 'sql', 'query', 'schema', 'migration', 'orm'],
|
|
242
|
-
agents: ['
|
|
242
|
+
agents: ['database-dev', 'coder', 'tester'],
|
|
243
243
|
},
|
|
244
244
|
'frontend-task': {
|
|
245
|
-
keywords: ['frontend', 'ui', 'component', 'react', 'css', 'style', 'layout'],
|
|
246
|
-
agents: ['
|
|
245
|
+
keywords: ['frontend', 'ui', 'component', 'react', 'vue', 'svelte', 'css', 'tailwind', 'style', 'layout', 'accessibility'],
|
|
246
|
+
agents: ['frontend-dev', 'reviewer', 'tester'],
|
|
247
247
|
},
|
|
248
248
|
'devops-task': {
|
|
249
249
|
keywords: ['deploy', 'ci', 'cd', 'pipeline', 'docker', 'kubernetes', 'infrastructure'],
|
|
250
|
-
agents: ['
|
|
250
|
+
agents: ['cicd-engineer', 'coder', 'tester'],
|
|
251
251
|
},
|
|
252
|
+
// (github-task intent removed — github work routes to generic coder/reviewer
|
|
253
|
+
// with the gh CLI; specialized github-* agents were retired in #932)
|
|
252
254
|
'swarm-task': {
|
|
253
255
|
keywords: ['swarm', 'agent', 'coordinator', 'hive', 'mesh', 'topology'],
|
|
254
|
-
agents: ['
|
|
256
|
+
agents: ['coordinator', 'architect'],
|
|
255
257
|
},
|
|
256
258
|
'memory-task': {
|
|
257
259
|
keywords: ['memory', 'cache', 'store', 'vector', 'embedding', 'persistence'],
|
|
258
|
-
agents: ['
|
|
260
|
+
agents: ['researcher', 'architect', 'coder'],
|
|
259
261
|
},
|
|
260
262
|
};
|
|
261
263
|
/**
|
|
@@ -436,30 +438,30 @@ const AGENT_PATTERNS = {
|
|
|
436
438
|
'.yaml': ['coder', 'devops'],
|
|
437
439
|
'.yml': ['coder', 'devops'],
|
|
438
440
|
'.sh': ['devops', 'coder'],
|
|
439
|
-
'.py': ['coder', '
|
|
441
|
+
'.py': ['coder', 'researcher'],
|
|
440
442
|
'.sql': ['coder', 'architect'],
|
|
441
443
|
'.css': ['coder', 'designer'],
|
|
442
444
|
'.scss': ['coder', 'designer'],
|
|
443
445
|
};
|
|
444
446
|
// Keyword patterns for fallback routing (when semantic routing doesn't match)
|
|
445
447
|
const KEYWORD_PATTERNS = {
|
|
446
|
-
'authentication': { agents: ['security-
|
|
447
|
-
'auth': { agents: ['security-
|
|
448
|
+
'authentication': { agents: ['security-auditor', 'coder', 'tester'], confidence: 0.9 },
|
|
449
|
+
'auth': { agents: ['security-auditor', 'coder', 'tester'], confidence: 0.85 },
|
|
448
450
|
'api': { agents: ['architect', 'coder', 'tester'], confidence: 0.85 },
|
|
449
451
|
'test': { agents: ['tester', 'reviewer'], confidence: 0.95 },
|
|
450
452
|
'refactor': { agents: ['architect', 'coder', 'reviewer'], confidence: 0.9 },
|
|
451
|
-
'performance': { agents: ['
|
|
452
|
-
'security': { agents: ['security-
|
|
453
|
-
'database': { agents: ['
|
|
454
|
-
'frontend': { agents: ['
|
|
455
|
-
'backend': { agents: ['architect', 'coder', 'tester'], confidence: 0.
|
|
453
|
+
'performance': { agents: ['reviewer', 'coder', 'tester'], confidence: 0.88 },
|
|
454
|
+
'security': { agents: ['security-auditor', 'reviewer'], confidence: 0.92 },
|
|
455
|
+
'database': { agents: ['database-dev', 'coder', 'tester'], confidence: 0.9 },
|
|
456
|
+
'frontend': { agents: ['frontend-dev', 'reviewer', 'tester'], confidence: 0.9 },
|
|
457
|
+
'backend': { agents: ['backend-dev', 'architect', 'coder', 'tester'], confidence: 0.9 },
|
|
456
458
|
'bug': { agents: ['coder', 'tester', 'reviewer'], confidence: 0.88 },
|
|
457
459
|
'fix': { agents: ['coder', 'tester', 'reviewer'], confidence: 0.85 },
|
|
458
460
|
'feature': { agents: ['architect', 'coder', 'tester'], confidence: 0.8 },
|
|
459
|
-
'swarm': { agents: ['
|
|
460
|
-
'memory': { agents: ['
|
|
461
|
-
'deploy': { agents: ['
|
|
462
|
-
'ci/cd': { agents: ['
|
|
461
|
+
'swarm': { agents: ['coordinator', 'architect'], confidence: 0.9 },
|
|
462
|
+
'memory': { agents: ['researcher', 'architect', 'coder'], confidence: 0.88 },
|
|
463
|
+
'deploy': { agents: ['cicd-engineer', 'coder', 'tester'], confidence: 0.85 },
|
|
464
|
+
'ci/cd': { agents: ['cicd-engineer', 'coder'], confidence: 0.9 },
|
|
463
465
|
};
|
|
464
466
|
function getFileExtension(filePath) {
|
|
465
467
|
const match = filePath.match(/\.[a-zA-Z0-9]+$/);
|
|
@@ -1675,7 +1677,7 @@ export const hooksBuildAgents = {
|
|
|
1675
1677
|
{ type: 'coder', configFile: join(outputDir, `coder.${format}`), capabilities: ['code-generation', 'refactoring', 'debugging'], optimizations: ['flash-attention', 'token-reduction'] },
|
|
1676
1678
|
{ type: 'architect', configFile: join(outputDir, `architect.${format}`), capabilities: ['system-design', 'api-design', 'documentation'], optimizations: ['context-caching', 'memory-persistence'] },
|
|
1677
1679
|
{ type: 'tester', configFile: join(outputDir, `tester.${format}`), capabilities: ['unit-testing', 'integration-testing', 'coverage'], optimizations: ['parallel-execution'] },
|
|
1678
|
-
{ type: 'security-
|
|
1680
|
+
{ type: 'security-auditor', configFile: join(outputDir, `security-auditor.${format}`), capabilities: ['threat-modeling', 'vulnerability-analysis', 'security-review'], optimizations: ['pattern-matching'] },
|
|
1679
1681
|
{ type: 'reviewer', configFile: join(outputDir, `reviewer.${format}`), capabilities: ['code-review', 'quality-analysis', 'best-practices'], optimizations: ['incremental-analysis'] },
|
|
1680
1682
|
];
|
|
1681
1683
|
const filteredAgents = focus === 'all' ? agents :
|
|
@@ -154,7 +154,7 @@ async function ensureInitialized() {
|
|
|
154
154
|
export const memoryTools = [
|
|
155
155
|
{
|
|
156
156
|
name: 'memory_store',
|
|
157
|
-
description: 'Store a value in memory with vector embedding for semantic search (sql.js + HNSW backend).
|
|
157
|
+
description: 'Store a value in memory with vector embedding for semantic search (sql.js + HNSW backend). Upserts by default — pass upsert:false to fail on duplicate keys.',
|
|
158
158
|
category: 'memory',
|
|
159
159
|
inputSchema: {
|
|
160
160
|
type: 'object',
|
|
@@ -168,7 +168,7 @@ export const memoryTools = [
|
|
|
168
168
|
description: 'Optional tags for filtering',
|
|
169
169
|
},
|
|
170
170
|
ttl: { type: 'number', description: 'Time-to-live in seconds (optional)' },
|
|
171
|
-
upsert: { type: 'boolean', description: 'If
|
|
171
|
+
upsert: { type: 'boolean', description: 'If false, fail on duplicate keys instead of replacing (default: true)' },
|
|
172
172
|
},
|
|
173
173
|
required: ['key', 'value'],
|
|
174
174
|
},
|
|
@@ -180,7 +180,9 @@ export const memoryTools = [
|
|
|
180
180
|
const value = typeof input.value === 'string' ? input.value : JSON.stringify(input.value);
|
|
181
181
|
const tags = input.tags || [];
|
|
182
182
|
const ttl = input.ttl;
|
|
183
|
-
|
|
183
|
+
// #962: default upsert=true — silent UNIQUE-constraint failures on update
|
|
184
|
+
// were dropping schedule cancels and similar updates on the floor.
|
|
185
|
+
const upsert = input.upsert === false ? false : true;
|
|
184
186
|
validateMemoryInput(key, value);
|
|
185
187
|
const startTime = performance.now();
|
|
186
188
|
try {
|
|
@@ -364,12 +366,21 @@ export const memoryTools = [
|
|
|
364
366
|
const namespace = input.namespace || 'default';
|
|
365
367
|
try {
|
|
366
368
|
const result = await deleteEntry({ key, namespace });
|
|
369
|
+
// Issue #963: surface the underlying reason when delete fails.
|
|
370
|
+
// `result.success` reflects whether the call itself succeeded; we
|
|
371
|
+
// require `deleted === true` for the MCP-level success boolean,
|
|
372
|
+
// and pass `result.error` through whenever the delete didn't take.
|
|
373
|
+
const deleted = result.deleted === true;
|
|
374
|
+
const errorReason = !deleted
|
|
375
|
+
? (result.error ?? `No entry deleted (key='${key}', namespace='${namespace}'); reason not reported by storage layer`)
|
|
376
|
+
: undefined;
|
|
367
377
|
return {
|
|
368
|
-
success: result.deleted,
|
|
378
|
+
success: result.success === true && deleted,
|
|
369
379
|
key,
|
|
370
380
|
namespace,
|
|
371
|
-
deleted
|
|
381
|
+
deleted,
|
|
372
382
|
backend: 'sql.js + HNSW',
|
|
383
|
+
...(errorReason ? { error: errorReason } : {}),
|
|
373
384
|
};
|
|
374
385
|
}
|
|
375
386
|
catch (error) {
|
|
@@ -44,11 +44,9 @@ export const EMBEDDING_MODEL_OPT_OUT = 'none';
|
|
|
44
44
|
*/
|
|
45
45
|
export const EMBEDDING_MODEL_LEGACY_DEFAULT = 'local';
|
|
46
46
|
/**
|
|
47
|
-
* Namespaces that
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* tags rows with `'none'`. Existing rows in these namespaces are hard-deleted
|
|
51
|
-
* on upgrade by `services/ephemeral-namespace-purge.ts`.
|
|
47
|
+
* Namespaces that skip embedding generation in the bridge write path. Rows
|
|
48
|
+
* land with both `embedding` and `embedding_model` NULL (distinct from the
|
|
49
|
+
* opt-out path which still tags rows with `'none'`).
|
|
52
50
|
*
|
|
53
51
|
* Members:
|
|
54
52
|
* - `hive-mind` — MCP broadcast traffic (msg:*, agent_join, consensus_propose)
|
|
@@ -56,7 +54,11 @@ export const EMBEDDING_MODEL_LEGACY_DEFAULT = 'local';
|
|
|
56
54
|
* - `epic-state` — Epic progress (epic-N, story-M) written by commands/epic.ts
|
|
57
55
|
* - `test-bridge-fix` — Single 2026-04-23 row left over from a one-off test
|
|
58
56
|
*
|
|
59
|
-
* See story #729 for the source-trace and rationale.
|
|
57
|
+
* See story #729 for the source-trace and rationale. The session-start
|
|
58
|
+
* launcher only purges {@link PURGE_ON_SESSION_START_NAMESPACES} — a strict
|
|
59
|
+
* subset that *excludes* `tasklist`, because the dashboard's Flo Runs tab
|
|
60
|
+
* (`daemon-dashboard.ts handleSpells`) reads tasklist; purging it on every
|
|
61
|
+
* session would empty the tab between sessions (#968).
|
|
60
62
|
*/
|
|
61
63
|
export const EPHEMERAL_NAMESPACES = new Set([
|
|
62
64
|
'hive-mind',
|
|
@@ -64,6 +66,24 @@ export const EPHEMERAL_NAMESPACES = new Set([
|
|
|
64
66
|
'epic-state',
|
|
65
67
|
'test-bridge-fix',
|
|
66
68
|
]);
|
|
69
|
+
/**
|
|
70
|
+
* Subset of {@link EPHEMERAL_NAMESPACES} that the session-start launcher
|
|
71
|
+
* hard-purges via `services/ephemeral-namespace-purge.ts`. Excludes
|
|
72
|
+
* `tasklist` — those rows back the dashboard's "Flo Runs" tab and are
|
|
73
|
+
* trimmed by row-count retention instead of bulk purge (#968).
|
|
74
|
+
*/
|
|
75
|
+
export const PURGE_ON_SESSION_START_NAMESPACES = new Set([
|
|
76
|
+
'hive-mind',
|
|
77
|
+
'epic-state',
|
|
78
|
+
'test-bridge-fix',
|
|
79
|
+
]);
|
|
80
|
+
/**
|
|
81
|
+
* Maximum number of `tasklist` rows kept across session restarts. The
|
|
82
|
+
* session-start retention pass deletes oldest rows beyond this cap, so the
|
|
83
|
+
* dashboard's "Flo Runs" tab shows recent history without unbounded growth
|
|
84
|
+
* (#968). Sized for ~2 weeks of /flo activity at typical use.
|
|
85
|
+
*/
|
|
86
|
+
export const TASKLIST_RETENTION_CAP = 200;
|
|
67
87
|
let cachedEmbedder = null;
|
|
68
88
|
let testOverride = null;
|
|
69
89
|
class LazyFastembedBridgeEmbedder {
|
|
@@ -435,14 +435,30 @@ export async function bridgeGetEntry(options) {
|
|
|
435
435
|
});
|
|
436
436
|
}
|
|
437
437
|
/**
|
|
438
|
-
*
|
|
438
|
+
* Hard-delete an entry. Guarded, cache-invalidated, attested.
|
|
439
|
+
*
|
|
440
|
+
* Failure modes (issue #963): every non-success path now carries a
|
|
441
|
+
* human-readable `error` so MCP callers can surface the reason instead
|
|
442
|
+
* of seeing a silent `{ deleted: false }`.
|
|
439
443
|
*/
|
|
440
444
|
export async function bridgeDeleteEntry(options) {
|
|
441
445
|
return withDb(options.dbPath, async (ctx, registry) => {
|
|
442
446
|
const { key, namespace = 'default' } = options;
|
|
447
|
+
const deleteFail = (error) => ({ success: false, deleted: false, key, namespace, remainingEntries: 0, error });
|
|
443
448
|
const guardResult = await guardValidate(registry, 'delete', { key, namespace });
|
|
444
449
|
if (!guardResult.allowed) {
|
|
445
|
-
return
|
|
450
|
+
return deleteFail(`MutationGuard rejected: ${guardResult.reason}`);
|
|
451
|
+
}
|
|
452
|
+
let existed = false;
|
|
453
|
+
try {
|
|
454
|
+
const existsRows = execRows(ctx.db, `SELECT 1 as found FROM memory_entries WHERE key = ? AND namespace = ? AND status = 'active' LIMIT 1`, [key, namespace]);
|
|
455
|
+
existed = existsRows.length > 0;
|
|
456
|
+
}
|
|
457
|
+
catch (err) {
|
|
458
|
+
return deleteFail(`DB read failed during delete pre-check: ${errorDetail(err)}`);
|
|
459
|
+
}
|
|
460
|
+
if (!existed) {
|
|
461
|
+
return deleteFail(`Key '${key}' not found in namespace '${namespace}'`);
|
|
446
462
|
}
|
|
447
463
|
let changes = 0;
|
|
448
464
|
try {
|
|
@@ -454,28 +470,30 @@ export async function bridgeDeleteEntry(options) {
|
|
|
454
470
|
// db.getRowsModified() to read the row count from the last statement.
|
|
455
471
|
changes = ctx.db.getRowsModified?.() ?? 0;
|
|
456
472
|
}
|
|
457
|
-
catch {
|
|
458
|
-
return
|
|
473
|
+
catch (err) {
|
|
474
|
+
return deleteFail(`DELETE failed: ${errorDetail(err)}`);
|
|
459
475
|
}
|
|
460
|
-
if (changes
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
476
|
+
if (changes === 0) {
|
|
477
|
+
// SELECT found the row but DELETE removed nothing. Most likely cause:
|
|
478
|
+
// bridge holds an in-memory snapshot that diverged from disk
|
|
479
|
+
// (sql.js writeback semantics — see feedback_sqljs_writeback_clobber.md).
|
|
480
|
+
return deleteFail(`Internal inconsistency: row matched SELECT but DELETE removed 0 rows (key='${key}', namespace='${namespace}'). Possible bridge cache staleness — restart the daemon and retry.`);
|
|
465
481
|
}
|
|
482
|
+
persistBridgeDb(ctx.db, options.dbPath);
|
|
483
|
+
await cacheInvalidate(registry, makeEntryCacheKey(namespace, key));
|
|
484
|
+
await logAttestation(registry, 'delete', key, { namespace });
|
|
466
485
|
let remaining = 0;
|
|
467
486
|
try {
|
|
468
|
-
const
|
|
469
|
-
remaining =
|
|
487
|
+
const countRows = execRows(ctx.db, `SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active'`);
|
|
488
|
+
remaining = Number(countRows[0]?.cnt ?? 0);
|
|
470
489
|
}
|
|
471
490
|
catch {
|
|
472
|
-
// Non-fatal
|
|
491
|
+
// Non-fatal — count is informational
|
|
473
492
|
}
|
|
474
|
-
|
|
475
|
-
refreshVectorStatsCache();
|
|
493
|
+
refreshVectorStatsCache();
|
|
476
494
|
return {
|
|
477
495
|
success: true,
|
|
478
|
-
deleted:
|
|
496
|
+
deleted: true,
|
|
479
497
|
key,
|
|
480
498
|
namespace,
|
|
481
499
|
remainingEntries: remaining,
|
|
@@ -27,43 +27,49 @@ const DEFAULT_INTENTS = [
|
|
|
27
27
|
name: 'memory',
|
|
28
28
|
category: 'storage',
|
|
29
29
|
keywords: ['memory', 'store', 'retrieve', 'search', 'embedding', 'vector', 'recall', 'persist'],
|
|
30
|
-
agents: ['
|
|
30
|
+
agents: ['researcher', 'coder'],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'frontend',
|
|
34
|
+
category: 'development',
|
|
35
|
+
keywords: ['frontend', 'ui', 'component', 'react', 'vue', 'svelte', 'css', 'tailwind', 'style', 'layout', 'accessibility', 'responsive'],
|
|
36
|
+
agents: ['frontend-dev', 'reviewer'],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'database',
|
|
40
|
+
category: 'development',
|
|
41
|
+
keywords: ['database', 'sql', 'query', 'schema', 'migration', 'orm', 'index', 'postgres', 'mysql', 'sqlite', 'transaction'],
|
|
42
|
+
agents: ['database-dev', 'reviewer'],
|
|
31
43
|
},
|
|
32
44
|
{
|
|
33
45
|
name: 'spell',
|
|
34
46
|
category: 'workflow',
|
|
35
47
|
keywords: ['spell', 'workflow', 'orchestrate', 'cast', 'pipeline', 'step'],
|
|
36
|
-
agents: ['planner'
|
|
48
|
+
agents: ['planner'],
|
|
37
49
|
},
|
|
38
50
|
{
|
|
39
51
|
name: 'hooks',
|
|
40
52
|
category: 'automation',
|
|
41
53
|
keywords: ['hook', 'pre-task', 'post-task', 'event', 'trigger', 'automation'],
|
|
42
|
-
agents: ['cicd-engineer', '
|
|
54
|
+
agents: ['cicd-engineer', 'coder'],
|
|
43
55
|
},
|
|
44
56
|
{
|
|
45
57
|
name: 'security',
|
|
46
58
|
category: 'security',
|
|
47
59
|
keywords: ['security', 'vulnerability', 'cve', 'audit', 'threat', 'permission', 'auth'],
|
|
48
|
-
agents: ['security-auditor', '
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: 'neural',
|
|
52
|
-
category: 'ml',
|
|
53
|
-
keywords: ['neural', 'train', 'model', 'learning', 'reinforcement', 'sona', 'reasoningbank'],
|
|
54
|
-
agents: ['ml-developer', 'safla-neural'],
|
|
60
|
+
agents: ['security-auditor', 'reviewer'],
|
|
55
61
|
},
|
|
56
62
|
{
|
|
57
63
|
name: 'test',
|
|
58
64
|
category: 'quality',
|
|
59
65
|
keywords: ['test', 'vitest', 'unit', 'integration', 'tdd', 'coverage', 'assertion'],
|
|
60
|
-
agents: ['tester'
|
|
66
|
+
agents: ['tester'],
|
|
61
67
|
},
|
|
62
68
|
{
|
|
63
69
|
name: 'github',
|
|
64
70
|
category: 'integration',
|
|
65
71
|
keywords: ['github', 'pr', 'pull request', 'issue', 'release', 'commit', 'branch'],
|
|
66
|
-
agents: ['
|
|
72
|
+
agents: ['coder', 'reviewer'],
|
|
67
73
|
},
|
|
68
74
|
];
|
|
69
75
|
export class SemanticRouter {
|
|
@@ -38,8 +38,8 @@ const AGENT_TYPES = [
|
|
|
38
38
|
'optimizer',
|
|
39
39
|
'debugger',
|
|
40
40
|
'documenter',
|
|
41
|
-
'security-
|
|
42
|
-
'
|
|
41
|
+
'security-auditor',
|
|
42
|
+
'planner',
|
|
43
43
|
];
|
|
44
44
|
/**
|
|
45
45
|
* Task keywords for pattern extraction
|
|
@@ -77,13 +77,13 @@ const KEYWORD_CATEGORIES = {
|
|
|
77
77
|
'document', 'docs', 'readme', 'comment', 'explain', 'guide',
|
|
78
78
|
'tutorial', 'api-docs', 'specification', 'jsdoc',
|
|
79
79
|
],
|
|
80
|
-
'security-
|
|
80
|
+
'security-auditor': [
|
|
81
81
|
'security', 'auth', 'authentication', 'authorization', 'encrypt',
|
|
82
82
|
'vulnerability', 'cve', 'secure', 'permission', 'role',
|
|
83
83
|
],
|
|
84
|
-
|
|
85
|
-
'
|
|
86
|
-
'
|
|
84
|
+
planner: [
|
|
85
|
+
'plan', 'breakdown', 'sequencing', 'estimate', 'milestone', 'roadmap',
|
|
86
|
+
'task', 'dependency', 'goal',
|
|
87
87
|
],
|
|
88
88
|
};
|
|
89
89
|
// ============================================================================
|
|
@@ -118,9 +118,9 @@ export class LearningDomainService {
|
|
|
118
118
|
review: 'reviewer',
|
|
119
119
|
plan: 'planner',
|
|
120
120
|
research: 'researcher',
|
|
121
|
-
security: 'security-
|
|
122
|
-
performance: '
|
|
123
|
-
memory: '
|
|
121
|
+
security: 'security-auditor',
|
|
122
|
+
performance: 'reviewer',
|
|
123
|
+
memory: 'researcher',
|
|
124
124
|
};
|
|
125
125
|
for (const [keyword, role] of Object.entries(keywordMap)) {
|
|
126
126
|
if (taskLower.includes(keyword)) {
|
|
@@ -19,9 +19,7 @@ export const AGENT_CAPABILITIES = {
|
|
|
19
19
|
'backend-dev': ['api', 'database', 'server', 'authentication'],
|
|
20
20
|
'frontend-dev': ['ui', 'react', 'css', 'components'],
|
|
21
21
|
devops: ['ci-cd', 'docker', 'deployment', 'infrastructure'],
|
|
22
|
-
'security-
|
|
23
|
-
'security-auditor': ['vulnerability-scan', 'dependency-audit', 'compliance'],
|
|
24
|
-
'memory-specialist': ['memory-management', 'caching', 'persistence'],
|
|
22
|
+
'security-auditor': ['security-design', 'threat-modeling', 'auth-flow', 'vulnerability-scan', 'dependency-audit', 'compliance'],
|
|
25
23
|
coordinator: ['task-distribution', 'orchestration', 'scheduling'],
|
|
26
24
|
analyst: ['data-analysis', 'metrics', 'reporting', 'monitoring'],
|
|
27
25
|
optimizer: ['performance', 'profiling', 'optimization', 'benchmarking'],
|
|
@@ -41,8 +39,7 @@ const TASK_PATTERNS = [
|
|
|
41
39
|
{ regex: /ui|frontend|component|react|css|style/i, agentType: 'frontend-dev' },
|
|
42
40
|
{ regex: /deploy|docker|ci|cd|pipeline|infrastructure/i, agentType: 'devops' },
|
|
43
41
|
// Specialized patterns
|
|
44
|
-
{ regex: /security|auth|permission|rbac|oauth/i, agentType: 'security-
|
|
45
|
-
{ regex: /vulnerability|cve|dependency.*update|npm audit/i, agentType: 'security-auditor' },
|
|
42
|
+
{ regex: /security|auth|permission|rbac|oauth|vulnerability|cve|dependency.*update|npm audit/i, agentType: 'security-auditor' },
|
|
46
43
|
{ regex: /performance|optimize|profile|benchmark|speed/i, agentType: 'optimizer' },
|
|
47
44
|
{ regex: /analyz|metric|report|monitor|dashboard/i, agentType: 'analyst' },
|
|
48
45
|
];
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon Autostart Lifecycle
|
|
3
|
+
*
|
|
4
|
+
* Reconciles the OS-native daemon login service against the count of enabled
|
|
5
|
+
* scheduled spells. Replaces the old prompt-based flow in `daemon-readiness.ts`
|
|
6
|
+
* (which left users with stale autostart entries when their last schedule was
|
|
7
|
+
* cancelled — see #960, #961).
|
|
8
|
+
*
|
|
9
|
+
* Idempotent: callers invoke `reconcileDaemonAutostart` after every mutation
|
|
10
|
+
* to `scheduled-spells`. It installs once, uninstalls once, and is a no-op
|
|
11
|
+
* for every other transition.
|
|
12
|
+
*/
|
|
13
|
+
import { isDaemonInstalled as defaultIsDaemonInstalled, installDaemonService as defaultInstallDaemonService, uninstallDaemonService as defaultUninstallDaemonService, } from './daemon-service.js';
|
|
14
|
+
const NOOP = { transition: 'noop', message: null, warning: null };
|
|
15
|
+
/**
|
|
16
|
+
* Reconcile OS-native daemon autostart against schedule count.
|
|
17
|
+
*
|
|
18
|
+
* - count ≥ 1 + not installed → install
|
|
19
|
+
* - count = 0 + installed → uninstall
|
|
20
|
+
* - all other states → noop
|
|
21
|
+
*
|
|
22
|
+
* Never throws. Install/uninstall failures are returned as non-fatal warnings
|
|
23
|
+
* — the caller decides whether to print them. The schedule mutation itself is
|
|
24
|
+
* always considered the primary operation; autostart is best-effort.
|
|
25
|
+
*/
|
|
26
|
+
export function reconcileDaemonAutostart(options) {
|
|
27
|
+
if (options.skip)
|
|
28
|
+
return NOOP;
|
|
29
|
+
const isInstalled = (options.isDaemonInstalled ?? defaultIsDaemonInstalled)(options.projectRoot);
|
|
30
|
+
if (options.enabledScheduleCount >= 1 && !isInstalled) {
|
|
31
|
+
const result = (options.installDaemonService ?? defaultInstallDaemonService)(options.projectRoot);
|
|
32
|
+
if (result.success) {
|
|
33
|
+
return {
|
|
34
|
+
transition: 'installed',
|
|
35
|
+
message: 'Daemon registered as OS login service so this schedule survives reboot.',
|
|
36
|
+
warning: null,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
transition: 'noop',
|
|
41
|
+
message: null,
|
|
42
|
+
warning: `Could not register daemon as OS login service: ${result.message}`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (options.enabledScheduleCount === 0 && isInstalled) {
|
|
46
|
+
const result = (options.uninstallDaemonService ?? defaultUninstallDaemonService)(options.projectRoot);
|
|
47
|
+
if (result.success) {
|
|
48
|
+
return {
|
|
49
|
+
transition: 'uninstalled',
|
|
50
|
+
message: 'No enabled schedules remain — daemon unregistered from OS login services.',
|
|
51
|
+
warning: null,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
transition: 'noop',
|
|
56
|
+
message: null,
|
|
57
|
+
warning: `Could not unregister daemon from OS login services: ${result.message}`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return NOOP;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=daemon-autostart-lifecycle.js.map
|