moflo 4.9.10 → 4.9.12

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 (37) hide show
  1. package/.claude/commands/simplify.md +78 -30
  2. package/.claude/guidance/shipped/moflo-cli-reference.md +201 -0
  3. package/.claude/guidance/shipped/moflo-core-guidance.md +30 -391
  4. package/.claude/guidance/shipped/moflo-cross-platform.md +20 -1
  5. package/.claude/guidance/shipped/moflo-guidance-rules.md +144 -0
  6. package/.claude/guidance/shipped/moflo-memory-strategy.md +1 -0
  7. package/.claude/guidance/shipped/moflo-memorydb-maintenance.md +33 -6
  8. package/.claude/guidance/shipped/moflo-session-start.md +154 -0
  9. package/.claude/guidance/shipped/moflo-settings-injection.md +124 -0
  10. package/.claude/guidance/shipped/moflo-source-hygiene.md +1 -1
  11. package/.claude/guidance/shipped/moflo-spell-custom-steps.md +126 -0
  12. package/.claude/guidance/shipped/moflo-spell-engine.md +4 -101
  13. package/.claude/guidance/shipped/moflo-subagents.md +10 -0
  14. package/.claude/guidance/shipped/moflo-task-icons.md +9 -0
  15. package/.claude/guidance/shipped/moflo-user-facing-language.md +8 -0
  16. package/.claude/guidance/shipped/moflo-yaml-reference.md +191 -0
  17. package/.claude/skills/connector-builder/SKILL.md +1 -1
  18. package/.claude/skills/guidance/SKILL.md +158 -0
  19. package/.claude/skills/publish/SKILL.md +16 -0
  20. package/.claude/skills/simplify/SKILL.md +90 -21
  21. package/.claude/skills/spell-builder/SKILL.md +2 -2
  22. package/.claude/skills/spell-builder/architecture.md +1 -1
  23. package/.claude/skills/spell-schedule/SKILL.md +167 -0
  24. package/bin/session-start-launcher.mjs +164 -11
  25. package/dist/src/cli/commands/doctor-checks-deep.js +62 -0
  26. package/dist/src/cli/commands/doctor.js +34 -1
  27. package/dist/src/cli/config/moflo-config.js +14 -3
  28. package/dist/src/cli/index.js +18 -0
  29. package/dist/src/cli/init/moflo-init.js +19 -4
  30. package/dist/src/cli/init/settings-generator.js +18 -3
  31. package/dist/src/cli/services/daemon-readiness.js +12 -0
  32. package/dist/src/cli/services/hook-block-hash.js +320 -0
  33. package/dist/src/cli/services/hook-wiring.js +54 -1
  34. package/dist/src/cli/services/index.js +2 -0
  35. package/dist/src/cli/services/process-registry.js +58 -0
  36. package/dist/src/cli/version.js +1 -1
  37. package/package.json +2 -2
@@ -38,7 +38,10 @@ export const HOOK_ENTRY_MAP = {
38
38
  'check-dangerous-command': { event: 'PreToolUse', matcher: '^Bash$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-dangerous-command', timeout: 2000 } },
39
39
  'check-before-pr': { event: 'PreToolUse', matcher: '^Bash$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-before-pr', timeout: 2000 } },
40
40
  'record-task-created': { event: 'PostToolUse', matcher: '^TaskCreate$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" record-task-created', timeout: 2000 } },
41
- 'record-memory-searched': { event: 'PostToolUse', matcher: 'mcp__moflo__memory_', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" record-memory-searched', timeout: 3000 } },
41
+ // record-memory-searched MUST go through gate-hook.mjs (not gate.cjs directly)
42
+ // — the wrapper forwards Claude Code's session_id as HOOK_SESSION_ID, which
43
+ // markMemorySearched needs to stamp the per-actor map (#879).
44
+ 'record-memory-searched': { event: 'PostToolUse', matcher: 'mcp__moflo__memory_', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" record-memory-searched', timeout: 3000 } },
42
45
  'check-task-transition': { event: 'PostToolUse', matcher: '^TaskUpdate$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" check-task-transition', timeout: 2000 } },
43
46
  'record-learnings-stored': { event: 'PostToolUse', matcher: '^mcp__moflo__memory_store$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" record-learnings-stored', timeout: 2000 } },
44
47
  'check-bash-memory': { event: 'PostToolUse', matcher: '^Bash$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-bash-memory', timeout: 2000 } },
@@ -84,4 +87,54 @@ export function repairHookWiring(settings) {
84
87
  settings.hooks = hooks;
85
88
  return { settings, repaired };
86
89
  }
90
+ export const HOOK_REWRITE_RULES = [
91
+ // Issue #879 — record-memory-searched MUST use gate-hook.mjs so Claude Code's
92
+ // session_id is forwarded as HOOK_SESSION_ID. Without it, the per-actor map
93
+ // stays empty and the gate blocks every Read forever within a turn.
94
+ {
95
+ name: '#879: record-memory-searched → gate-hook.mjs',
96
+ from: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" record-memory-searched',
97
+ to: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" record-memory-searched',
98
+ },
99
+ // Symmetry hardening — same fix shape for check-bash-memory. The shipped
100
+ // settings.json already wires this through gate-hook.mjs in current versions,
101
+ // but a stale consumer settings.json may have it wrong.
102
+ {
103
+ name: '#879: check-bash-memory → gate-hook.mjs',
104
+ from: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" check-bash-memory',
105
+ to: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-bash-memory',
106
+ },
107
+ ];
108
+ /**
109
+ * Apply HOOK_REWRITE_RULES to every hook command in `settings.hooks.*`.
110
+ * Idempotent: a hook already at the `to` form won't match `from`.
111
+ *
112
+ * @returns The (potentially mutated) settings and a list of rewrites that fired.
113
+ */
114
+ export function rewriteIncorrectHookWiring(settings) {
115
+ const hooks = (settings.hooks ?? {});
116
+ const rewrites = [];
117
+ for (const rule of HOOK_REWRITE_RULES) {
118
+ let count = 0;
119
+ for (const eventName of Object.keys(hooks)) {
120
+ const eventArray = hooks[eventName];
121
+ if (!Array.isArray(eventArray))
122
+ continue;
123
+ for (const block of eventArray) {
124
+ const blockHooks = block.hooks;
125
+ if (!Array.isArray(blockHooks))
126
+ continue;
127
+ for (const h of blockHooks) {
128
+ if (typeof h.command === 'string' && h.command.includes(rule.from)) {
129
+ h.command = h.command.split(rule.from).join(rule.to);
130
+ count++;
131
+ }
132
+ }
133
+ }
134
+ }
135
+ if (count > 0)
136
+ rewrites.push({ name: rule.name, count });
137
+ }
138
+ return { settings, rewrites };
139
+ }
87
140
  //# sourceMappingURL=hook-wiring.js.map
@@ -15,6 +15,8 @@ export { AgentRouter, getAgentRouter, routeTask, AGENT_CAPABILITIES, } from './a
15
15
  export { startDashboard, createDashboardMemoryAccessor, DEFAULT_DASHBOARD_PORT, } from './daemon-dashboard.js';
16
16
  // Hook Wiring (shared between doctor, upgrade, and session-start)
17
17
  export { repairHookWiring, HOOK_ENTRY_MAP, REQUIRED_HOOK_WIRING, } from './hook-wiring.js';
18
+ // Hook Block Drift Detection (#881 — hash-based reconciliation)
19
+ export { computeHookBlockHash, computeHookBlockDrift, formatDriftReport, getReferenceHookBlock, normaliseHooks, isHookBlockLocked, applyAdditiveRegeneration, DRIFT_MODES, } from './hook-block-hash.js';
18
20
  // Subagent Bootstrap Directive (single-source for SubagentStart + agent_spawn surfaces)
19
21
  export { SUBAGENT_BOOTSTRAP_DIRECTIVE } from './subagent-bootstrap.js';
20
22
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Shared write side of the moflo background-process registry.
3
+ *
4
+ * Mirrors `bin/lib/process-manager.mjs`'s atomic write logic so TS spawn
5
+ * sites (auto-start daemon in src/cli/index.ts and daemon-readiness.ts) can
6
+ * register their PIDs alongside the ones written by bin/hooks.mjs's
7
+ * spawnWindowless helper. Without registry parity, doctor's zombie scan
8
+ * (src/cli/commands/doctor.ts) flags every TS-spawned background process as
9
+ * an orphan, because they are detached:true so their immediate parent dies.
10
+ *
11
+ * The .mjs module remains the canonical reader/writer with full read+killAll
12
+ * semantics; this TS helper only covers the registration we need from compiled
13
+ * paths. Both write to the same JSON file (`<projectRoot>/.moflo/background-pids.json`),
14
+ * so a process registered here is reapable via pm.killAll() at session-end.
15
+ */
16
+ import { join } from 'path';
17
+ import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync } from 'fs';
18
+ const REGISTRY_FILENAME = 'background-pids.json';
19
+ function registryPath(projectRoot) {
20
+ return join(projectRoot, '.moflo', REGISTRY_FILENAME);
21
+ }
22
+ function readRegistry(projectRoot) {
23
+ const path = registryPath(projectRoot);
24
+ if (!existsSync(path))
25
+ return [];
26
+ try {
27
+ const parsed = JSON.parse(readFileSync(path, 'utf-8'));
28
+ return Array.isArray(parsed) ? parsed : [];
29
+ }
30
+ catch {
31
+ return [];
32
+ }
33
+ }
34
+ function writeRegistry(projectRoot, entries) {
35
+ const path = registryPath(projectRoot);
36
+ mkdirSync(join(projectRoot, '.moflo'), { recursive: true });
37
+ const tmp = `${path}.tmp.${process.pid}`;
38
+ writeFileSync(tmp, JSON.stringify(entries, null, 2));
39
+ renameSync(tmp, path);
40
+ }
41
+ /**
42
+ * Register a spawned background PID under the given label. Replaces any
43
+ * pre-existing entry with the same label so a stale dead-PID row doesn't
44
+ * accumulate when a daemon crashes and is restarted.
45
+ */
46
+ export function registerBackgroundPid(projectRoot, pid, label, cmd) {
47
+ if (!Number.isInteger(pid) || pid <= 0)
48
+ return;
49
+ const fresh = readRegistry(projectRoot).filter(e => e && e.label !== label);
50
+ fresh.push({
51
+ pid,
52
+ label,
53
+ cmd: cmd.slice(0, 200),
54
+ startedAt: new Date().toISOString(),
55
+ });
56
+ writeRegistry(projectRoot, fresh);
57
+ }
58
+ //# sourceMappingURL=process-registry.js.map
@@ -2,5 +2,5 @@
2
2
  * Auto-generated by build. Do not edit manually.
3
3
  * Source of truth: root package.json → scripts/sync-version.mjs
4
4
  */
5
- export const VERSION = '4.9.10';
5
+ export const VERSION = '4.9.12';
6
6
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moflo",
3
- "version": "4.9.10",
3
+ "version": "4.9.12",
4
4
  "description": "MoFlo — AI agent orchestration for Claude Code. A standalone, opinionated toolkit with semantic memory, learned routing, gates, spells, and the /flo issue-execution skill.",
5
5
  "main": "dist/src/cli/index.js",
6
6
  "type": "module",
@@ -81,7 +81,7 @@
81
81
  "@typescript-eslint/eslint-plugin": "^7.18.0",
82
82
  "@typescript-eslint/parser": "^7.18.0",
83
83
  "eslint": "^8.0.0",
84
- "moflo": "^4.9.9",
84
+ "moflo": "^4.9.11",
85
85
  "tsx": "^4.21.0",
86
86
  "typescript": "^5.9.3",
87
87
  "vitest": "^4.0.0"