mover-os 4.7.7 → 4.7.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.
Files changed (107) hide show
  1. package/install.js +688 -68
  2. package/package.json +15 -3
  3. package/src/dashboard/build.js +1503 -0
  4. package/src/dashboard/dashboard.js +276 -0
  5. package/src/dashboard/index.js +319 -0
  6. package/src/dashboard/lib/activation-log.js +297 -0
  7. package/src/dashboard/lib/active-context-parser.js +177 -0
  8. package/src/dashboard/lib/agent-command.js +93 -0
  9. package/src/dashboard/lib/agent-detect.js +255 -0
  10. package/src/dashboard/lib/agent-detector.js +92 -0
  11. package/src/dashboard/lib/agent-session.js +462 -0
  12. package/src/dashboard/lib/anti-identity-detector.js +116 -0
  13. package/src/dashboard/lib/auto-learnings-parser.js +183 -0
  14. package/src/dashboard/lib/cli-usage-parser.js +92 -0
  15. package/src/dashboard/lib/config-parser.js +109 -0
  16. package/src/dashboard/lib/connect-recommender.js +131 -0
  17. package/src/dashboard/lib/correlations-parser.js +231 -0
  18. package/src/dashboard/lib/daily-note-resolver.js +211 -0
  19. package/src/dashboard/lib/date-utils.js +35 -0
  20. package/src/dashboard/lib/distribution-parser.js +78 -0
  21. package/src/dashboard/lib/dossier-parser.js +64 -0
  22. package/src/dashboard/lib/drift-history.js +83 -0
  23. package/src/dashboard/lib/drift-score.js +119 -0
  24. package/src/dashboard/lib/engine-health.js +170 -0
  25. package/src/dashboard/lib/engine-writer.js +1685 -0
  26. package/src/dashboard/lib/execution-plan.js +125 -0
  27. package/src/dashboard/lib/experiments-parser.js +429 -0
  28. package/src/dashboard/lib/feed-parser.js +294 -0
  29. package/src/dashboard/lib/forked-future.js +60 -0
  30. package/src/dashboard/lib/goal-forecast.js +304 -0
  31. package/src/dashboard/lib/goals-parser.js +67 -0
  32. package/src/dashboard/lib/health-protocols-parser.js +133 -0
  33. package/src/dashboard/lib/hook-activity.js +48 -0
  34. package/src/dashboard/lib/hook-indexer.js +169 -0
  35. package/src/dashboard/lib/hourly-activity-parser.js +143 -0
  36. package/src/dashboard/lib/identity-parser.js +85 -0
  37. package/src/dashboard/lib/ingestion.js +418 -0
  38. package/src/dashboard/lib/library-indexer-v2.js +212 -0
  39. package/src/dashboard/lib/library-indexer.js +105 -0
  40. package/src/dashboard/lib/log-activation.sh +61 -0
  41. package/src/dashboard/lib/memory-curator.js +97 -0
  42. package/src/dashboard/lib/memory-gardener.js +177 -0
  43. package/src/dashboard/lib/memory-gepa.js +102 -0
  44. package/src/dashboard/lib/memory-index.js +470 -0
  45. package/src/dashboard/lib/memory-rerank.js +72 -0
  46. package/src/dashboard/lib/memory-text.js +136 -0
  47. package/src/dashboard/lib/metrics-log-parser.js +76 -0
  48. package/src/dashboard/lib/moves-usage-parser.js +184 -0
  49. package/src/dashboard/lib/onboarding-forge.js +70 -0
  50. package/src/dashboard/lib/override-outcome-parser.js +68 -0
  51. package/src/dashboard/lib/override-summary.js +73 -0
  52. package/src/dashboard/lib/paths.js +192 -0
  53. package/src/dashboard/lib/pattern-manifest-loader.js +29 -0
  54. package/src/dashboard/lib/phantom-strategy.js +129 -0
  55. package/src/dashboard/lib/project-scanner.js +121 -0
  56. package/src/dashboard/lib/promise-wall.js +88 -0
  57. package/src/dashboard/lib/record-score.js +173 -0
  58. package/src/dashboard/lib/redaction.js +140 -0
  59. package/src/dashboard/lib/refusal-parser.js +44 -0
  60. package/src/dashboard/lib/regenerate-manifest.js +206 -0
  61. package/src/dashboard/lib/rewind-snapshots.js +689 -0
  62. package/src/dashboard/lib/roast-wall-parser.js +200 -0
  63. package/src/dashboard/lib/run-registry.js +226 -0
  64. package/src/dashboard/lib/safe-write.js +63 -0
  65. package/src/dashboard/lib/session-log-parser.js +145 -0
  66. package/src/dashboard/lib/session-time-parser.js +158 -0
  67. package/src/dashboard/lib/skill-index.js +171 -0
  68. package/src/dashboard/lib/skill-indexer.js +118 -0
  69. package/src/dashboard/lib/skill-recommender.js +689 -0
  70. package/src/dashboard/lib/strategy-parser.js +245 -0
  71. package/src/dashboard/lib/strategy-protocol-parser.js +135 -0
  72. package/src/dashboard/lib/streak-parser.js +95 -0
  73. package/src/dashboard/lib/suggested-now.js +254 -0
  74. package/src/dashboard/lib/tool-awareness.js +125 -0
  75. package/src/dashboard/lib/transcript-parser.js +331 -0
  76. package/src/dashboard/lib/vault-graph-parser.js +205 -0
  77. package/src/dashboard/lib/view-generator.js +163 -0
  78. package/src/dashboard/lib/voice-dna-parser.js +57 -0
  79. package/src/dashboard/lib/walkthrough-script.js +140 -0
  80. package/src/dashboard/lib/workflow-graph-parser.js +170 -0
  81. package/src/dashboard/lib/workflow-library-parser.js +146 -0
  82. package/src/dashboard/server.js +2024 -0
  83. package/src/dashboard/shortcut.js +0 -0
  84. package/src/dashboard/static/setup-poc.html +306 -0
  85. package/src/dashboard/static/walkthrough-poc.html +580 -0
  86. package/src/dashboard/styles.css +1201 -0
  87. package/src/dashboard/templates/index.html +278 -0
  88. package/src/dashboard/ui/dist/assets/hanken-grotesk-latin-ext-wght-normal-Dg-wlmqe.woff2 +0 -0
  89. package/src/dashboard/ui/dist/assets/hanken-grotesk-latin-wght-normal-CaVRRdDk.woff2 +0 -0
  90. package/src/dashboard/ui/dist/assets/hanken-grotesk-vietnamese-wght-normal-CHiFlh_0.woff2 +0 -0
  91. package/src/dashboard/ui/dist/assets/hero.png +0 -0
  92. package/src/dashboard/ui/dist/assets/index-598CSGOZ.js +157 -0
  93. package/src/dashboard/ui/dist/assets/index-BP--M69H.css +1 -0
  94. package/src/dashboard/ui/dist/assets/index-CidzmwSW.js +34 -0
  95. package/src/dashboard/ui/dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  96. package/src/dashboard/ui/dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  97. package/src/dashboard/ui/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  98. package/src/dashboard/ui/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  99. package/src/dashboard/ui/dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  100. package/src/dashboard/ui/dist/assets/mover-system.css +62 -0
  101. package/src/dashboard/ui/dist/assets/xterm-CqkleIqs.js +1 -0
  102. package/src/dashboard/ui/dist/icon.svg +4 -0
  103. package/src/dashboard/ui/dist/index.html +18 -0
  104. package/src/dashboard/ui/dist/manifest.webmanifest +1 -0
  105. package/src/dashboard/ui/dist/registerSW.js +1 -0
  106. package/src/dashboard/ui/dist/sw.js +1 -0
  107. package/src/dashboard/ui/dist/workbox-39fa566e.js +1 -0
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const os = require("os");
5
+ const path = require("path");
6
+
7
+ // refusal-parser.js — F38. Reads ~/.mover/refusals.jsonl appended by the
8
+ // friction-enforcer skill. Each line: { ts, message, level, accepted }.
9
+ // Used for the "AI refused me N times this week" share artifact + StatsStrip tile.
10
+
11
+ function compute({ daysLookback = 30 } = {}) {
12
+ const p = path.join(os.homedir(), ".mover", "refusals.jsonl");
13
+ if (!fs.existsSync(p)) return { available: false, count: 0, count7d: 0, recent: [] };
14
+ let lines;
15
+ try {
16
+ lines = fs.readFileSync(p, "utf8").split("\n").filter(Boolean);
17
+ } catch (_) {
18
+ return { available: false, count: 0, count7d: 0, recent: [] };
19
+ }
20
+ const now = Date.now();
21
+ const dayMs = 24 * 3600 * 1000;
22
+ const entries = [];
23
+ for (const line of lines) {
24
+ try {
25
+ const j = JSON.parse(line);
26
+ const ts = j.ts ? Date.parse(j.ts) : null;
27
+ if (ts && Number.isFinite(ts)) {
28
+ const ageDays = (now - ts) / dayMs;
29
+ if (ageDays <= daysLookback) entries.push({ ts: j.ts, level: j.level || 1, message: j.message || '', accepted: !!j.accepted, ageDays });
30
+ }
31
+ } catch (_) { /* skip malformed lines */ }
32
+ }
33
+ const count7d = entries.filter(e => e.ageDays <= 7).length;
34
+ const count30d = entries.length;
35
+ return {
36
+ available: true,
37
+ count: count30d,
38
+ count7d,
39
+ delta7d: count7d - entries.filter(e => e.ageDays > 7 && e.ageDays <= 14).length,
40
+ recent: entries.slice(-10).reverse()
41
+ };
42
+ }
43
+
44
+ module.exports = { compute };
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // regenerate-manifest.js — V5 Phase 41.0.8.
5
+ //
6
+ // Auto-regenerates ~/.mover/pattern-manifest.json after /pivot-strategy
7
+ // writes a new Strategy.md. Without this step, the session-start hook
8
+ // + dashboard hero continue to inject the V3 cached strings until the
9
+ // next manual `moveros doctor --rebuild-manifest` (which doesn't exist).
10
+ //
11
+ // Usage:
12
+ // node regenerate-manifest.js [vaultPath]
13
+ //
14
+ // Vault path defaults to:
15
+ // - first argv
16
+ // - ~/.mover/config.json vaultPath
17
+ // - walks up from cwd looking for 02_Areas/Engine/
18
+ //
19
+ // Preserves these fields from the existing manifest (append-only):
20
+ // override_history, recent_wins, active_patterns (if newer than file mtime),
21
+ // zombie_tasks (the workflow updates these via a different path)
22
+ //
23
+ // Re-derived from Strategy.md:
24
+ // single_test, single_test_status, single_test_deadline, sacrifice,
25
+ // sacrifice_status, friction_level, friction_level_reason
26
+ //
27
+ // Safe to call from /pivot-strategy workflow Bash step. Best-effort —
28
+ // failures print to stderr but exit 1 only on truly fatal errors
29
+ // (no Strategy.md found, no vault path resolvable).
30
+
31
+ const fs = require("fs");
32
+ const path = require("path");
33
+ const os = require("os");
34
+
35
+ function resolveVaultPath(argv) {
36
+ if (argv && argv.length > 2) {
37
+ const p = argv[2];
38
+ if (fs.existsSync(path.join(p, "02_Areas", "Engine"))) return p;
39
+ }
40
+ const cfgPath = path.join(os.homedir(), ".mover", "config.json");
41
+ if (fs.existsSync(cfgPath)) {
42
+ try {
43
+ const cfg = JSON.parse(fs.readFileSync(cfgPath, "utf8"));
44
+ if (cfg.vaultPath && fs.existsSync(path.join(cfg.vaultPath, "02_Areas", "Engine"))) {
45
+ return cfg.vaultPath;
46
+ }
47
+ } catch (_) { /* fall through */ }
48
+ }
49
+ let cur = process.cwd();
50
+ for (let i = 0; i < 6; i++) {
51
+ if (fs.existsSync(path.join(cur, "02_Areas", "Engine"))) return cur;
52
+ const next = path.dirname(cur);
53
+ if (next === cur) break;
54
+ cur = next;
55
+ }
56
+ return null;
57
+ }
58
+
59
+ function readSection(text, sectionRegex) {
60
+ // Extract from "## N. <heading>" until next "## " or end of file.
61
+ const startMatch = text.match(sectionRegex);
62
+ if (!startMatch) return null;
63
+ const startIdx = startMatch.index + startMatch[0].length;
64
+ const tail = text.slice(startIdx);
65
+ const endMatch = tail.match(/\n##\s/);
66
+ return endMatch ? tail.slice(0, endMatch.index) : tail;
67
+ }
68
+
69
+ function extractField(section, labelRegex) {
70
+ if (!section) return null;
71
+ // Match "**Label:** value" lines OR "* **Label:** value" bullets.
72
+ const m = section.match(new RegExp(`\\*?\\*?${labelRegex}:?\\*?\\*?\\s+(.+?)(?=\\n\\*?\\*?\\w+:|\\n\\n|$)`, "is"));
73
+ if (m) return m[1].trim().replace(/\s+/g, " ");
74
+ return null;
75
+ }
76
+
77
+ function extractSingleTest(strategy) {
78
+ // Pass 4 BLOCKER fix: parser was looking for "**The Bet:**" / "**Single Test:**"
79
+ // headers that V4 Strategy.md doesn't use. Actual V4 format:
80
+ // **Mid-term Milestone:** <N activated installs + M referrals by date>...
81
+ // **The Positioning (V4):**
82
+ // - **Hero:** "..."
83
+ // Prefer Mid-term Milestone (machine-stable measurable target), fall back
84
+ // to legacy headers if found.
85
+ const milestoneMatch = strategy.match(/\*\*Mid-term Milestone:\*\*\s+(.+?)(?=\n\*\*|\n##|$)/is);
86
+ if (milestoneMatch) return milestoneMatch[1].trim().replace(/\s+/g, " ");
87
+
88
+ // Legacy header support (older Strategy.md versions still parse).
89
+ const sec = readSection(strategy, /##\s*1\.\s*(BUSINESS\s+)?HYPOTHESIS/i) ||
90
+ readSection(strategy, /##\s*1\./);
91
+ if (sec) {
92
+ const betMatch = sec.match(/\*\*(?:The Bet|Single Test):\*\*\s+(.+?)(?=\n\*\*\w|\n\n##|\n>\s|$)/is);
93
+ if (betMatch) return betMatch[1].trim().replace(/\s+/g, " ");
94
+ const hypoMatch = sec.match(/\*\*Hypothesis:\*\*\s+(.+?)(?=\n\*\*\w|\n\n##|$)/is);
95
+ if (hypoMatch) return hypoMatch[1].trim().replace(/\s+/g, " ");
96
+ }
97
+ return null;
98
+ }
99
+
100
+ function extractSacrifice(strategy) {
101
+ // Pass 4 BLOCKER fix: V4 uses "**The Sacrifice (V4 — hardened past V3.0):**"
102
+ // which has a parenthetical that the old regex didn't match. The header
103
+ // can also be followed by a bulleted list rather than inline text.
104
+ // Strategy: find the header anywhere (Section 1 or 2), then capture the
105
+ // first bullet point OR inline text until the next bold header / next section.
106
+ //
107
+ // First try: full bullet list under the header (V4 actual structure).
108
+ const sacrHeaderMatch = strategy.match(/\*\*The Sacrifice[^*]*\*\*\s*\n([\s\S]+?)(?=\n\*\*\w[^*]*\*\*|\n##\s|$)/i);
109
+ if (sacrHeaderMatch) {
110
+ // Collapse the bullet list into a single human-readable string.
111
+ // Take first 2-3 bullets, strip markdown bullet markers.
112
+ const bullets = sacrHeaderMatch[1]
113
+ .split(/\n/)
114
+ .map(l => l.replace(/^\s*[*-]\s+/, "").trim())
115
+ .filter(l => l && !l.startsWith("**"))
116
+ .slice(0, 4);
117
+ if (bullets.length) return bullets.join(" · ").replace(/\s+/g, " ").slice(0, 400);
118
+ }
119
+
120
+ // Fall back: legacy inline format.
121
+ const sec = readSection(strategy, /##\s*2\./);
122
+ if (sec) {
123
+ return extractField(sec, "(?:The Sacrifice|Sacrifice)") ||
124
+ extractField(sec, "What I am NOT doing");
125
+ }
126
+ return null;
127
+ }
128
+
129
+ function extractFrictionLevel(strategy) {
130
+ // Pass 4 BLOCKER fix: V4 uses prose like "L3 friction floor active from Day 1"
131
+ // — not a labeled "Friction Level: L3" line. Accept both formats.
132
+ // First try labeled form, then prose "L<N> friction" / "friction L<N>".
133
+ const labeled = strategy.match(/Friction\s+Level\s*[:=]\s*L?(\d)/i);
134
+ if (labeled) return parseInt(labeled[1], 10);
135
+ const proseFloor = strategy.match(/\bL([0-5])\s+friction\s+(?:floor|level|active)/i);
136
+ if (proseFloor) return parseInt(proseFloor[1], 10);
137
+ const proseLevel = strategy.match(/\bfriction\s+(?:level|floor)\s+L?([0-5])/i);
138
+ if (proseLevel) return parseInt(proseLevel[1], 10);
139
+ return null;
140
+ }
141
+
142
+ function extractStrategyVersion(strategy) {
143
+ const m = strategy.match(/^\*\*Version:\*\*\s*(.+)$/m);
144
+ return m ? m[1].trim() : null;
145
+ }
146
+
147
+ function regenerate(vaultPath) {
148
+ const strategyPath = path.join(vaultPath, "02_Areas", "Engine", "Strategy.md");
149
+ if (!fs.existsSync(strategyPath)) {
150
+ console.error(`[regenerate-manifest] Strategy.md not found at ${strategyPath}`);
151
+ process.exit(1);
152
+ }
153
+ const strategy = fs.readFileSync(strategyPath, "utf8");
154
+ const manifestPath = path.join(os.homedir(), ".mover", "pattern-manifest.json");
155
+
156
+ let existing = {};
157
+ if (fs.existsSync(manifestPath)) {
158
+ try { existing = JSON.parse(fs.readFileSync(manifestPath, "utf8")); }
159
+ catch (_) { existing = {}; }
160
+ }
161
+
162
+ const singleTest = extractSingleTest(strategy);
163
+ const sacrifice = extractSacrifice(strategy);
164
+ const frictionLevel = extractFrictionLevel(strategy);
165
+ const strategyVersion = extractStrategyVersion(strategy);
166
+
167
+ if (!singleTest && !sacrifice) {
168
+ console.error(`[regenerate-manifest] could not extract Single Test or Sacrifice from Strategy.md — manifest unchanged`);
169
+ process.exit(1);
170
+ }
171
+
172
+ const next = {
173
+ ...existing,
174
+ version: 1,
175
+ last_updated: new Date().toISOString().slice(0, 16),
176
+ updated_by: "regenerate-manifest.js",
177
+ strategy_version: strategyVersion || existing.strategy_version || null,
178
+ // Re-derived fields
179
+ ...(singleTest ? { single_test: singleTest } : {}),
180
+ ...(sacrifice ? { sacrifice: sacrifice } : {}),
181
+ ...(frictionLevel != null ? { friction_level: frictionLevel } : {}),
182
+ // Preserved fields (append-only)
183
+ override_history: Array.isArray(existing.override_history) ? existing.override_history : [],
184
+ recent_wins: Array.isArray(existing.recent_wins) ? existing.recent_wins : [],
185
+ active_patterns: Array.isArray(existing.active_patterns) ? existing.active_patterns : [],
186
+ zombie_tasks: Array.isArray(existing.zombie_tasks) ? existing.zombie_tasks : [],
187
+ };
188
+
189
+ // Atomic tmp+rename
190
+ const tmp = `${manifestPath}.tmp-${process.pid}-${Date.now()}`;
191
+ fs.writeFileSync(tmp, JSON.stringify(next, null, 2), "utf8");
192
+ fs.renameSync(tmp, manifestPath);
193
+
194
+ console.log(`Pattern manifest regenerated: single_test="${(next.single_test || "—").slice(0, 60)}…", sacrifice="${(next.sacrifice || "—").slice(0, 60)}…", friction_level=L${next.friction_level || 0}`);
195
+ }
196
+
197
+ if (require.main === module) {
198
+ const vault = resolveVaultPath(process.argv);
199
+ if (!vault) {
200
+ console.error(`[regenerate-manifest] could not resolve vault path. Pass as first arg or set vaultPath in ~/.mover/config.json`);
201
+ process.exit(1);
202
+ }
203
+ regenerate(vault);
204
+ }
205
+
206
+ module.exports = { regenerate, extractSingleTest, extractSacrifice, extractFrictionLevel };