mop-flow 0.1.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 (390) hide show
  1. package/.MOP/PROTOCOL.md +579 -0
  2. package/.MOP/STATE.json +668 -0
  3. package/.MOP/config/defaults.json +55 -0
  4. package/.MOP/config/team.json +8 -0
  5. package/.MOP/flow/ROADMAP.md +51 -0
  6. package/.MOP/flow/skill-manifest.json +645 -0
  7. package/.MOP/scripts/burhan-mop.mjs +291 -0
  8. package/.MOP/scripts/mop-auto-deploy.mjs +152 -0
  9. package/.MOP/scripts/mop-autosycn.mjs +790 -0
  10. package/.MOP/scripts/mop-core.mjs +1206 -0
  11. package/.MOP/scripts/mop-flow.mjs +396 -0
  12. package/.MOP/scripts/mop-smoke-test.mjs +76 -0
  13. package/.MOP/scripts/mop-workflow.mjs +348 -0
  14. package/.MOP/templates/artifacts/adversarial-review.md +33 -0
  15. package/.MOP/templates/artifacts/architecture.md +28 -0
  16. package/.MOP/templates/artifacts/decision-log.md +21 -0
  17. package/.MOP/templates/artifacts/handoff.md +21 -0
  18. package/.MOP/templates/artifacts/implementation-notes.md +21 -0
  19. package/.MOP/templates/artifacts/prd.md +29 -0
  20. package/.MOP/templates/artifacts/product-brief.md +30 -0
  21. package/.MOP/templates/artifacts/readiness-report.md +25 -0
  22. package/.MOP/templates/artifacts/release-notes.md +21 -0
  23. package/.MOP/templates/artifacts/review.md +21 -0
  24. package/.MOP/templates/artifacts/story.md +25 -0
  25. package/.MOP/templates/artifacts/ux-spec.md +32 -0
  26. package/.agents/AGENTS.md +85 -0
  27. package/.agents/skills/auto-deploy/SKILL.md +48 -0
  28. package/.agents/skills/autosycn/SKILL.md +75 -0
  29. package/.agents/skills/mop-flow/SKILL.md +53 -0
  30. package/.agents/skills/mop-help/SKILL.md +35 -0
  31. package/.agents/skills/ruflo-core/SKILL.md +36 -0
  32. package/.claude/agents/analysis/analyze-code-quality.md +179 -0
  33. package/.claude/agents/analysis/code-analyzer.md +210 -0
  34. package/.claude/agents/analysis/code-review/analyze-code-quality.md +179 -0
  35. package/.claude/agents/architecture/arch-system-design.md +157 -0
  36. package/.claude/agents/architecture/system-design/arch-system-design.md +155 -0
  37. package/.claude/agents/browser/browser-agent.yaml +182 -0
  38. package/.claude/agents/consensus/byzantine-coordinator.md +63 -0
  39. package/.claude/agents/consensus/crdt-synchronizer.md +997 -0
  40. package/.claude/agents/consensus/gossip-coordinator.md +63 -0
  41. package/.claude/agents/consensus/performance-benchmarker.md +851 -0
  42. package/.claude/agents/consensus/quorum-manager.md +823 -0
  43. package/.claude/agents/consensus/raft-manager.md +63 -0
  44. package/.claude/agents/consensus/security-manager.md +622 -0
  45. package/.claude/agents/core/planner.md +375 -0
  46. package/.claude/agents/custom/test-long-runner.md +44 -0
  47. package/.claude/agents/data/data-ml-model.md +445 -0
  48. package/.claude/agents/data/ml/data-ml-model.md +193 -0
  49. package/.claude/agents/development/backend/dev-backend-api.md +142 -0
  50. package/.claude/agents/development/dev-backend-api.md +345 -0
  51. package/.claude/agents/devops/ci-cd/ops-cicd-github.md +164 -0
  52. package/.claude/agents/devops/ops-cicd-github.md +165 -0
  53. package/.claude/agents/documentation/api-docs/docs-api-openapi.md +174 -0
  54. package/.claude/agents/documentation/docs-api-openapi.md +355 -0
  55. package/.claude/agents/flow-nexus/app-store.md +88 -0
  56. package/.claude/agents/flow-nexus/authentication.md +69 -0
  57. package/.claude/agents/flow-nexus/challenges.md +81 -0
  58. package/.claude/agents/flow-nexus/neural-network.md +88 -0
  59. package/.claude/agents/flow-nexus/payments.md +83 -0
  60. package/.claude/agents/flow-nexus/sandbox.md +76 -0
  61. package/.claude/agents/flow-nexus/swarm.md +76 -0
  62. package/.claude/agents/flow-nexus/user-tools.md +96 -0
  63. package/.claude/agents/flow-nexus/workflow.md +84 -0
  64. package/.claude/agents/github/code-review-swarm.md +377 -0
  65. package/.claude/agents/github/github-modes.md +173 -0
  66. package/.claude/agents/github/issue-tracker.md +576 -0
  67. package/.claude/agents/github/multi-repo-swarm.md +553 -0
  68. package/.claude/agents/github/pr-manager.md +438 -0
  69. package/.claude/agents/github/project-board-sync.md +509 -0
  70. package/.claude/agents/github/release-manager.md +605 -0
  71. package/.claude/agents/github/release-swarm.md +583 -0
  72. package/.claude/agents/github/repo-architect.md +398 -0
  73. package/.claude/agents/github/swarm-issue.md +573 -0
  74. package/.claude/agents/github/swarm-pr.md +428 -0
  75. package/.claude/agents/github/sync-coordinator.md +452 -0
  76. package/.claude/agents/github/workflow-automation.md +903 -0
  77. package/.claude/agents/goal/agent.md +816 -0
  78. package/.claude/agents/optimization/benchmark-suite.md +665 -0
  79. package/.claude/agents/optimization/load-balancer.md +431 -0
  80. package/.claude/agents/optimization/performance-monitor.md +672 -0
  81. package/.claude/agents/optimization/resource-allocator.md +674 -0
  82. package/.claude/agents/optimization/topology-optimizer.md +808 -0
  83. package/.claude/agents/payments/agentic-payments.md +126 -0
  84. package/.claude/agents/sona/sona-learning-optimizer.md +74 -0
  85. package/.claude/agents/sparc/architecture.md +699 -0
  86. package/.claude/agents/sparc/pseudocode.md +520 -0
  87. package/.claude/agents/sparc/refinement.md +802 -0
  88. package/.claude/agents/sparc/specification.md +478 -0
  89. package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +225 -0
  90. package/.claude/agents/specialized/spec-mobile-react-native.md +227 -0
  91. package/.claude/agents/sublinear/consensus-coordinator.md +338 -0
  92. package/.claude/agents/sublinear/matrix-optimizer.md +185 -0
  93. package/.claude/agents/sublinear/pagerank-analyzer.md +299 -0
  94. package/.claude/agents/sublinear/performance-optimizer.md +368 -0
  95. package/.claude/agents/sublinear/trading-predictor.md +246 -0
  96. package/.claude/agents/swarm/adaptive-coordinator.md +1127 -0
  97. package/.claude/agents/swarm/hierarchical-coordinator.md +710 -0
  98. package/.claude/agents/swarm/mesh-coordinator.md +963 -0
  99. package/.claude/agents/templates/automation-smart-agent.md +205 -0
  100. package/.claude/agents/templates/base-template-generator.md +289 -0
  101. package/.claude/agents/templates/coordinator-swarm-init.md +90 -0
  102. package/.claude/agents/templates/github-pr-manager.md +177 -0
  103. package/.claude/agents/templates/implementer-sparc-coder.md +259 -0
  104. package/.claude/agents/templates/memory-coordinator.md +187 -0
  105. package/.claude/agents/templates/orchestrator-task.md +139 -0
  106. package/.claude/agents/templates/performance-analyzer.md +199 -0
  107. package/.claude/agents/templates/sparc-coordinator.md +514 -0
  108. package/.claude/agents/testing/production-validator.md +395 -0
  109. package/.claude/agents/testing/tdd-london-swarm.md +244 -0
  110. package/.claude/agents/v3/aidefence-guardian.md +282 -0
  111. package/.claude/agents/v3/claims-authorizer.md +208 -0
  112. package/.claude/agents/v3/collective-intelligence-coordinator.md +993 -0
  113. package/.claude/agents/v3/ddd-domain-expert.md +220 -0
  114. package/.claude/agents/v3/injection-analyst.md +236 -0
  115. package/.claude/agents/v3/performance-engineer.md +1233 -0
  116. package/.claude/agents/v3/pii-detector.md +151 -0
  117. package/.claude/agents/v3/reasoningbank-learner.md +213 -0
  118. package/.claude/agents/v3/security-architect-aidefence.md +410 -0
  119. package/.claude/agents/v3/security-architect.md +867 -0
  120. package/.claude/agents/v3/swarm-memory-manager.md +157 -0
  121. package/.claude/agents/v3/v3-integration-architect.md +205 -0
  122. package/.claude/commands/agents/README.md +50 -0
  123. package/.claude/commands/agents/agent-capabilities.md +140 -0
  124. package/.claude/commands/agents/agent-coordination.md +28 -0
  125. package/.claude/commands/agents/agent-spawning.md +28 -0
  126. package/.claude/commands/agents/agent-types.md +216 -0
  127. package/.claude/commands/agents/health.md +139 -0
  128. package/.claude/commands/agents/list.md +100 -0
  129. package/.claude/commands/agents/logs.md +130 -0
  130. package/.claude/commands/agents/metrics.md +122 -0
  131. package/.claude/commands/agents/pool.md +127 -0
  132. package/.claude/commands/agents/spawn.md +140 -0
  133. package/.claude/commands/agents/status.md +115 -0
  134. package/.claude/commands/agents/stop.md +102 -0
  135. package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +54 -0
  136. package/.claude/commands/analysis/README.md +9 -0
  137. package/.claude/commands/analysis/bottleneck-detect.md +162 -0
  138. package/.claude/commands/analysis/performance-bottlenecks.md +59 -0
  139. package/.claude/commands/analysis/performance-report.md +25 -0
  140. package/.claude/commands/analysis/token-efficiency.md +45 -0
  141. package/.claude/commands/analysis/token-usage.md +25 -0
  142. package/.claude/commands/automation/README.md +9 -0
  143. package/.claude/commands/automation/auto-agent.md +122 -0
  144. package/.claude/commands/automation/self-healing.md +106 -0
  145. package/.claude/commands/automation/session-memory.md +90 -0
  146. package/.claude/commands/automation/smart-agents.md +73 -0
  147. package/.claude/commands/automation/smart-spawn.md +25 -0
  148. package/.claude/commands/automation/workflow-select.md +25 -0
  149. package/.claude/commands/claude-flow-help.md +103 -0
  150. package/.claude/commands/claude-flow-memory.md +107 -0
  151. package/.claude/commands/claude-flow-swarm.md +205 -0
  152. package/.claude/commands/coordination/README.md +9 -0
  153. package/.claude/commands/coordination/agent-spawn.md +25 -0
  154. package/.claude/commands/coordination/init.md +44 -0
  155. package/.claude/commands/coordination/orchestrate.md +43 -0
  156. package/.claude/commands/coordination/spawn.md +45 -0
  157. package/.claude/commands/coordination/swarm-init.md +85 -0
  158. package/.claude/commands/coordination/task-orchestrate.md +25 -0
  159. package/.claude/commands/github/README.md +11 -0
  160. package/.claude/commands/github/code-review-swarm.md +514 -0
  161. package/.claude/commands/github/code-review.md +25 -0
  162. package/.claude/commands/github/github-modes.md +147 -0
  163. package/.claude/commands/github/github-swarm.md +121 -0
  164. package/.claude/commands/github/issue-tracker.md +292 -0
  165. package/.claude/commands/github/issue-triage.md +25 -0
  166. package/.claude/commands/github/multi-repo-swarm.md +519 -0
  167. package/.claude/commands/github/pr-enhance.md +26 -0
  168. package/.claude/commands/github/pr-manager.md +170 -0
  169. package/.claude/commands/github/project-board-sync.md +471 -0
  170. package/.claude/commands/github/release-manager.md +340 -0
  171. package/.claude/commands/github/release-swarm.md +544 -0
  172. package/.claude/commands/github/repo-analyze.md +25 -0
  173. package/.claude/commands/github/repo-architect.md +367 -0
  174. package/.claude/commands/github/swarm-issue.md +485 -0
  175. package/.claude/commands/github/swarm-pr.md +288 -0
  176. package/.claude/commands/github/sync-coordinator.md +303 -0
  177. package/.claude/commands/github/workflow-automation.md +442 -0
  178. package/.claude/commands/hive-mind/README.md +17 -0
  179. package/.claude/commands/hive-mind/hive-mind-consensus.md +8 -0
  180. package/.claude/commands/hive-mind/hive-mind-init.md +18 -0
  181. package/.claude/commands/hive-mind/hive-mind-memory.md +8 -0
  182. package/.claude/commands/hive-mind/hive-mind-metrics.md +8 -0
  183. package/.claude/commands/hive-mind/hive-mind-resume.md +8 -0
  184. package/.claude/commands/hive-mind/hive-mind-sessions.md +8 -0
  185. package/.claude/commands/hive-mind/hive-mind-spawn.md +21 -0
  186. package/.claude/commands/hive-mind/hive-mind-status.md +8 -0
  187. package/.claude/commands/hive-mind/hive-mind-stop.md +8 -0
  188. package/.claude/commands/hive-mind/hive-mind-wizard.md +8 -0
  189. package/.claude/commands/hive-mind/hive-mind.md +27 -0
  190. package/.claude/commands/hooks/README.md +11 -0
  191. package/.claude/commands/hooks/overview.md +58 -0
  192. package/.claude/commands/hooks/post-edit.md +117 -0
  193. package/.claude/commands/hooks/post-task.md +112 -0
  194. package/.claude/commands/hooks/pre-edit.md +113 -0
  195. package/.claude/commands/hooks/pre-task.md +111 -0
  196. package/.claude/commands/hooks/session-end.md +118 -0
  197. package/.claude/commands/hooks/setup.md +103 -0
  198. package/.claude/commands/memory/README.md +9 -0
  199. package/.claude/commands/memory/memory-persist.md +25 -0
  200. package/.claude/commands/memory/memory-search.md +25 -0
  201. package/.claude/commands/memory/memory-usage.md +25 -0
  202. package/.claude/commands/memory/neural.md +47 -0
  203. package/.claude/commands/monitoring/README.md +9 -0
  204. package/.claude/commands/monitoring/agent-metrics.md +25 -0
  205. package/.claude/commands/monitoring/agents.md +44 -0
  206. package/.claude/commands/monitoring/real-time-view.md +25 -0
  207. package/.claude/commands/monitoring/status.md +46 -0
  208. package/.claude/commands/monitoring/swarm-monitor.md +25 -0
  209. package/.claude/commands/optimization/README.md +9 -0
  210. package/.claude/commands/optimization/auto-topology.md +62 -0
  211. package/.claude/commands/optimization/cache-manage.md +25 -0
  212. package/.claude/commands/optimization/parallel-execute.md +25 -0
  213. package/.claude/commands/optimization/parallel-execution.md +50 -0
  214. package/.claude/commands/optimization/topology-optimize.md +25 -0
  215. package/.claude/commands/pair/README.md +261 -0
  216. package/.claude/commands/pair/commands.md +546 -0
  217. package/.claude/commands/pair/config.md +510 -0
  218. package/.claude/commands/pair/examples.md +512 -0
  219. package/.claude/commands/pair/modes.md +348 -0
  220. package/.claude/commands/pair/session.md +407 -0
  221. package/.claude/commands/pair/start.md +209 -0
  222. package/.claude/commands/sparc/analyzer.md +52 -0
  223. package/.claude/commands/sparc/architect.md +53 -0
  224. package/.claude/commands/sparc/ask.md +97 -0
  225. package/.claude/commands/sparc/batch-executor.md +54 -0
  226. package/.claude/commands/sparc/code.md +89 -0
  227. package/.claude/commands/sparc/coder.md +54 -0
  228. package/.claude/commands/sparc/debug.md +83 -0
  229. package/.claude/commands/sparc/debugger.md +54 -0
  230. package/.claude/commands/sparc/designer.md +53 -0
  231. package/.claude/commands/sparc/devops.md +109 -0
  232. package/.claude/commands/sparc/docs-writer.md +80 -0
  233. package/.claude/commands/sparc/documenter.md +54 -0
  234. package/.claude/commands/sparc/innovator.md +54 -0
  235. package/.claude/commands/sparc/integration.md +83 -0
  236. package/.claude/commands/sparc/mcp.md +117 -0
  237. package/.claude/commands/sparc/memory-manager.md +54 -0
  238. package/.claude/commands/sparc/optimizer.md +54 -0
  239. package/.claude/commands/sparc/orchestrator.md +132 -0
  240. package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -0
  241. package/.claude/commands/sparc/refinement-optimization-mode.md +83 -0
  242. package/.claude/commands/sparc/researcher.md +54 -0
  243. package/.claude/commands/sparc/reviewer.md +54 -0
  244. package/.claude/commands/sparc/security-review.md +80 -0
  245. package/.claude/commands/sparc/sparc-modes.md +174 -0
  246. package/.claude/commands/sparc/sparc.md +111 -0
  247. package/.claude/commands/sparc/spec-pseudocode.md +80 -0
  248. package/.claude/commands/sparc/supabase-admin.md +348 -0
  249. package/.claude/commands/sparc/swarm-coordinator.md +54 -0
  250. package/.claude/commands/sparc/tdd.md +54 -0
  251. package/.claude/commands/sparc/tester.md +54 -0
  252. package/.claude/commands/sparc/tutorial.md +79 -0
  253. package/.claude/commands/sparc/workflow-manager.md +54 -0
  254. package/.claude/commands/stream-chain/pipeline.md +121 -0
  255. package/.claude/commands/stream-chain/run.md +70 -0
  256. package/.claude/commands/swarm/README.md +15 -0
  257. package/.claude/commands/swarm/analysis.md +95 -0
  258. package/.claude/commands/swarm/development.md +96 -0
  259. package/.claude/commands/swarm/examples.md +168 -0
  260. package/.claude/commands/swarm/maintenance.md +102 -0
  261. package/.claude/commands/swarm/optimization.md +117 -0
  262. package/.claude/commands/swarm/research.md +136 -0
  263. package/.claude/commands/swarm/swarm-analysis.md +8 -0
  264. package/.claude/commands/swarm/swarm-background.md +8 -0
  265. package/.claude/commands/swarm/swarm-init.md +19 -0
  266. package/.claude/commands/swarm/swarm-modes.md +8 -0
  267. package/.claude/commands/swarm/swarm-monitor.md +8 -0
  268. package/.claude/commands/swarm/swarm-spawn.md +19 -0
  269. package/.claude/commands/swarm/swarm-status.md +8 -0
  270. package/.claude/commands/swarm/swarm-strategies.md +8 -0
  271. package/.claude/commands/swarm/swarm.md +87 -0
  272. package/.claude/commands/swarm/testing.md +131 -0
  273. package/.claude/commands/training/README.md +9 -0
  274. package/.claude/commands/training/model-update.md +25 -0
  275. package/.claude/commands/training/neural-patterns.md +108 -0
  276. package/.claude/commands/training/neural-train.md +75 -0
  277. package/.claude/commands/training/pattern-learn.md +25 -0
  278. package/.claude/commands/training/specialization.md +63 -0
  279. package/.claude/commands/truth/start.md +143 -0
  280. package/.claude/commands/verify/check.md +50 -0
  281. package/.claude/commands/verify/start.md +128 -0
  282. package/.claude/commands/workflows/README.md +9 -0
  283. package/.claude/commands/workflows/development.md +78 -0
  284. package/.claude/commands/workflows/research.md +63 -0
  285. package/.claude/commands/workflows/workflow-create.md +25 -0
  286. package/.claude/commands/workflows/workflow-execute.md +25 -0
  287. package/.claude/commands/workflows/workflow-export.md +25 -0
  288. package/.claude/helpers/README.md +97 -0
  289. package/.claude/helpers/adr-compliance.sh +186 -0
  290. package/.claude/helpers/auto-commit.sh +178 -0
  291. package/.claude/helpers/auto-memory-hook.mjs +368 -0
  292. package/.claude/helpers/checkpoint-manager.sh +251 -0
  293. package/.claude/helpers/daemon-manager.sh +252 -0
  294. package/.claude/helpers/ddd-tracker.sh +144 -0
  295. package/.claude/helpers/github-safe.js +156 -0
  296. package/.claude/helpers/github-setup.sh +45 -0
  297. package/.claude/helpers/guidance-hook.sh +13 -0
  298. package/.claude/helpers/guidance-hooks.sh +102 -0
  299. package/.claude/helpers/health-monitor.sh +108 -0
  300. package/.claude/helpers/hook-handler.cjs +286 -0
  301. package/.claude/helpers/intelligence.cjs +1031 -0
  302. package/.claude/helpers/learning-hooks.sh +329 -0
  303. package/.claude/helpers/learning-optimizer.sh +127 -0
  304. package/.claude/helpers/learning-service.mjs +1144 -0
  305. package/.claude/helpers/memory.js +83 -0
  306. package/.claude/helpers/metrics-db.mjs +488 -0
  307. package/.claude/helpers/pattern-consolidator.sh +86 -0
  308. package/.claude/helpers/perf-worker.sh +160 -0
  309. package/.claude/helpers/post-commit +16 -0
  310. package/.claude/helpers/pre-commit +26 -0
  311. package/.claude/helpers/quick-start.sh +19 -0
  312. package/.claude/helpers/router.js +105 -0
  313. package/.claude/helpers/ruflo-hook.cjs +59 -0
  314. package/.claude/helpers/security-scanner.sh +127 -0
  315. package/.claude/helpers/session.js +157 -0
  316. package/.claude/helpers/setup-mcp.sh +18 -0
  317. package/.claude/helpers/standard-checkpoint-hooks.sh +189 -0
  318. package/.claude/helpers/statusline-hook.sh +21 -0
  319. package/.claude/helpers/statusline.cjs +693 -0
  320. package/.claude/helpers/statusline.js +352 -0
  321. package/.claude/helpers/swarm-comms.sh +353 -0
  322. package/.claude/helpers/swarm-hooks.sh +761 -0
  323. package/.claude/helpers/swarm-monitor.sh +211 -0
  324. package/.claude/helpers/sync-v3-metrics.sh +245 -0
  325. package/.claude/helpers/update-v3-progress.sh +166 -0
  326. package/.claude/helpers/v3-quick-status.sh +58 -0
  327. package/.claude/helpers/v3.sh +111 -0
  328. package/.claude/helpers/validate-v3-config.sh +216 -0
  329. package/.claude/helpers/worker-manager.sh +170 -0
  330. package/.claude/settings.json +305 -0
  331. package/.claude/skills/agentdb-advanced/SKILL.md +550 -0
  332. package/.claude/skills/agentdb-learning/SKILL.md +545 -0
  333. package/.claude/skills/agentdb-memory-patterns/SKILL.md +339 -0
  334. package/.claude/skills/agentdb-optimization/SKILL.md +509 -0
  335. package/.claude/skills/agentdb-vector-search/SKILL.md +339 -0
  336. package/.claude/skills/auto-deploy/SKILL.md +31 -0
  337. package/.claude/skills/autosycn/SKILL.md +30 -0
  338. package/.claude/skills/browser/SKILL.md +204 -0
  339. package/.claude/skills/dual-mode/README.md +71 -0
  340. package/.claude/skills/dual-mode/dual-collect.md +103 -0
  341. package/.claude/skills/dual-mode/dual-coordinate.md +85 -0
  342. package/.claude/skills/dual-mode/dual-spawn.md +81 -0
  343. package/.claude/skills/flow-nexus-neural/SKILL.md +727 -0
  344. package/.claude/skills/flow-nexus-platform/SKILL.md +1154 -0
  345. package/.claude/skills/flow-nexus-swarm/SKILL.md +604 -0
  346. package/.claude/skills/github-code-review/SKILL.md +1125 -0
  347. package/.claude/skills/github-multi-repo/SKILL.md +862 -0
  348. package/.claude/skills/github-project-management/SKILL.md +1262 -0
  349. package/.claude/skills/github-release-management/SKILL.md +1064 -0
  350. package/.claude/skills/github-workflow-automation/SKILL.md +1047 -0
  351. package/.claude/skills/hooks-automation/SKILL.md +1201 -0
  352. package/.claude/skills/mop-flow/SKILL.md +53 -0
  353. package/.claude/skills/mop-help/SKILL.md +35 -0
  354. package/.claude/skills/pair-programming/SKILL.md +1202 -0
  355. package/.claude/skills/reasoningbank-agentdb/SKILL.md +446 -0
  356. package/.claude/skills/reasoningbank-intelligence/SKILL.md +201 -0
  357. package/.claude/skills/skill-builder/SKILL.md +910 -0
  358. package/.claude/skills/sparc-methodology/SKILL.md +1106 -0
  359. package/.claude/skills/stream-chain/SKILL.md +560 -0
  360. package/.claude/skills/swarm-advanced/SKILL.md +970 -0
  361. package/.claude/skills/swarm-orchestration/SKILL.md +179 -0
  362. package/.claude/skills/v3-cli-modernization/SKILL.md +872 -0
  363. package/.claude/skills/v3-core-implementation/SKILL.md +797 -0
  364. package/.claude/skills/v3-ddd-architecture/SKILL.md +442 -0
  365. package/.claude/skills/v3-integration-deep/SKILL.md +241 -0
  366. package/.claude/skills/v3-mcp-optimization/SKILL.md +777 -0
  367. package/.claude/skills/v3-memory-unification/SKILL.md +174 -0
  368. package/.claude/skills/v3-performance-optimization/SKILL.md +390 -0
  369. package/.claude/skills/v3-security-overhaul/SKILL.md +82 -0
  370. package/.claude/skills/v3-swarm-coordination/SKILL.md +340 -0
  371. package/.claude/skills/verification-quality/SKILL.md +691 -0
  372. package/.claude-flow/CAPABILITIES.md +406 -0
  373. package/.claude-flow/config.yaml +45 -0
  374. package/.claude-flow/metrics/learning.json +17 -0
  375. package/.claude-flow/metrics/swarm-activity.json +18 -0
  376. package/.claude-flow/metrics/v3-progress.json +26 -0
  377. package/.claude-flow/security/audit-status.json +8 -0
  378. package/.codex/config.toml +42 -0
  379. package/.gemini/settings.json +51 -0
  380. package/.mcp.json +58 -0
  381. package/AGENTS.md +180 -0
  382. package/CLAUDE.md +277 -0
  383. package/GEMINI.md +48 -0
  384. package/README.bm.md +171 -0
  385. package/README.md +170 -0
  386. package/bin/burhan-mop.mjs +2 -0
  387. package/bin/mop-core.mjs +2 -0
  388. package/bin/mop-flow.mjs +2 -0
  389. package/bin/mop-workflow.mjs +2 -0
  390. package/package.json +72 -0
@@ -0,0 +1,1206 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from 'node:fs';
3
+ import { dirname, join, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { randomBytes, scryptSync, timingSafeEqual } from 'node:crypto';
6
+ import { spawnSync } from 'node:child_process';
7
+
8
+ const here = dirname(fileURLToPath(import.meta.url));
9
+ const coreDir = resolve(here, '..');
10
+ const rootDir = resolve(coreDir, '..');
11
+ const statePath = join(coreDir, 'STATE.json');
12
+
13
+ function now() {
14
+ return new Date().toISOString();
15
+ }
16
+
17
+ function readState() {
18
+ return JSON.parse(readFileSync(statePath, 'utf8'));
19
+ }
20
+
21
+ function writeState(state) {
22
+ mkdirSync(coreDir, { recursive: true });
23
+ const tmp = `${statePath}.tmp`;
24
+ writeFileSync(tmp, `${JSON.stringify(state, null, 2)}\n`, 'utf8');
25
+ renameSync(tmp, statePath);
26
+ }
27
+
28
+ function parseArgs(argv) {
29
+ const out = { _: [] };
30
+ for (let i = 0; i < argv.length; i += 1) {
31
+ const item = argv[i];
32
+ if (!item.startsWith('--')) {
33
+ out._.push(item);
34
+ continue;
35
+ }
36
+ const key = item.slice(2);
37
+ const next = argv[i + 1];
38
+ if (!next || next.startsWith('--')) {
39
+ out[key] = true;
40
+ } else {
41
+ out[key] = next;
42
+ i += 1;
43
+ }
44
+ }
45
+ return out;
46
+ }
47
+
48
+ function requireArg(args, key) {
49
+ const value = args[key];
50
+ if (!value || value === true) {
51
+ throw new Error(`Missing --${key}`);
52
+ }
53
+ return String(value);
54
+ }
55
+
56
+ function slug(value) {
57
+ return String(value)
58
+ .trim()
59
+ .toLowerCase()
60
+ .replace(/[^a-z0-9]+/g, '-')
61
+ .replace(/^-+|-+$/g, '');
62
+ }
63
+
64
+ function hashPassword(password, salt = randomBytes(16).toString('hex')) {
65
+ const passwordHash = scryptSync(password, salt, 64).toString('hex');
66
+ return { passwordHash, passwordSalt: salt };
67
+ }
68
+
69
+ function verifyPassword(password, salt, expectedHex) {
70
+ const actual = scryptSync(password, salt, 64);
71
+ const expected = Buffer.from(expectedHex, 'hex');
72
+ return expected.length === actual.length && timingSafeEqual(actual, expected);
73
+ }
74
+
75
+ function currentGhUser() {
76
+ const result = spawnSync('gh', ['api', 'user', '--jq', '{login:.login,id:.id,email:.email}'], {
77
+ cwd: rootDir,
78
+ encoding: 'utf8'
79
+ });
80
+ if (result.status !== 0) return null;
81
+ try {
82
+ return JSON.parse(result.stdout || '{}');
83
+ } catch {
84
+ return null;
85
+ }
86
+ }
87
+
88
+ function githubNoreplyEmail(user) {
89
+ if (!user?.login || !user?.id) return '';
90
+ return `${user.id}+${user.login}@users.noreply.github.com`;
91
+ }
92
+
93
+ function resolveGitIdentityInput(state, actor, name, emailInput, githubUsernameInput) {
94
+ const policy = state.autosync?.githubIdentity || {};
95
+ const preferNoreply = policy.useNoreplyForMemberCommits !== false;
96
+ const gh = currentGhUser();
97
+ const githubUsername = githubUsernameInput || gh?.login || '';
98
+ if (gh?.login && githubUsername && policy.requireMatchedGhUser !== false && gh.login.toLowerCase() !== githubUsername.toLowerCase()) {
99
+ throw new Error(`GitHub CLI authenticated as ${gh.login}, expected ${githubUsername}. Run gh auth login as the real user.`);
100
+ }
101
+
102
+ let email = String(emailInput || '').trim();
103
+ const wantsNoreply = !email || ['auto', 'github', 'github-noreply', 'noreply'].includes(email.toLowerCase());
104
+ if (preferNoreply && wantsNoreply) {
105
+ email = githubNoreplyEmail(gh);
106
+ if (!email) {
107
+ throw new Error('Cannot derive GitHub noreply email. Run gh auth login or provide --git-email "<github-verified-email>".');
108
+ }
109
+ }
110
+ if (!email && state.autosync?.requireUserGitEmail !== false) {
111
+ throw new Error('Git email is required. Use --git-email github-noreply after gh auth login, or provide a GitHub-verified email.');
112
+ }
113
+ return {
114
+ name,
115
+ email,
116
+ githubUsername,
117
+ githubUserId: gh?.login?.toLowerCase() === githubUsername.toLowerCase() ? gh.id : undefined,
118
+ emailSource: wantsNoreply && email ? 'github-noreply' : 'manual'
119
+ };
120
+ }
121
+
122
+ function activeAgentFor(state, actor) {
123
+ const activeId = state.activeAgents?.[actor];
124
+ if (!activeId) return null;
125
+ const agent = (state.agentRoster || []).find((item) => item.id === activeId || item.name === activeId);
126
+ if (!agent || !(agent.owners || []).includes(actor)) return null;
127
+ return agent;
128
+ }
129
+
130
+ function agentLedgerFields(agent) {
131
+ return agent ? {
132
+ agent: agent.name,
133
+ agentRole: agent.role,
134
+ agentId: agent.id
135
+ } : {};
136
+ }
137
+
138
+ function memoryPolicy(state) {
139
+ return state.memoryPolicy || {
140
+ enabled: true,
141
+ directory: '.MOP/memory',
142
+ sessionBrief: '.MOP/memory/SESSION_BRIEF.md',
143
+ monthlyPattern: 'YYYY-MM.jsonl',
144
+ recentLimit: 20
145
+ };
146
+ }
147
+
148
+ function answerPolicy(state) {
149
+ return state.answerPolicy || {
150
+ requireVisibleAgent: true,
151
+ visibleAgentFormat: 'agent: <agent-name> (<agent-role>) to <user>',
152
+ requireMemoryRestore: true,
153
+ requireMemorySave: true
154
+ };
155
+ }
156
+
157
+ function monthKey(date = new Date()) {
158
+ return date.toISOString().slice(0, 7);
159
+ }
160
+
161
+ function relativeFromRoot(path) {
162
+ return path.replace(rootDir, '').replace(/^[\\/]/, '').replaceAll('\\', '/');
163
+ }
164
+
165
+ function memoryDirFor(state) {
166
+ return join(rootDir, memoryPolicy(state).directory || '.MOP/memory');
167
+ }
168
+
169
+ function monthlyMemoryPath(state, month = monthKey()) {
170
+ const policy = memoryPolicy(state);
171
+ const filename = (policy.monthlyPattern || 'YYYY-MM.jsonl').replace('YYYY-MM', month);
172
+ return join(memoryDirFor(state), filename);
173
+ }
174
+
175
+ function sessionBriefPath(state) {
176
+ return join(rootDir, memoryPolicy(state).sessionBrief || '.MOP/memory/SESSION_BRIEF.md');
177
+ }
178
+
179
+ function readJsonl(path) {
180
+ if (!existsSync(path)) return [];
181
+ return readFileSync(path, 'utf8')
182
+ .split(/\r?\n/)
183
+ .filter(Boolean)
184
+ .map((line) => {
185
+ try {
186
+ return JSON.parse(line);
187
+ } catch {
188
+ return null;
189
+ }
190
+ })
191
+ .filter(Boolean);
192
+ }
193
+
194
+ function memoryMonths(state) {
195
+ const dir = memoryDirFor(state);
196
+ if (!existsSync(dir)) return [];
197
+ return readdirSync(dir)
198
+ .filter((name) => /^\d{4}-\d{2}\.jsonl$/.test(name))
199
+ .map((name) => name.replace(/\.jsonl$/, ''))
200
+ .sort();
201
+ }
202
+
203
+ function latestMemoryEntries(state, limit = memoryPolicy(state).recentLimit || 20) {
204
+ const months = memoryMonths(state);
205
+ const selected = months.length ? months.slice(-3) : [monthKey()];
206
+ return selected
207
+ .flatMap((month) => readJsonl(monthlyMemoryPath(state, month)))
208
+ .sort((a, b) => String(a.at || '').localeCompare(String(b.at || '')))
209
+ .slice(-limit);
210
+ }
211
+
212
+ function answerContractFor(state, actor, agent = activeAgentFor(state, actor)) {
213
+ const policy = answerPolicy(state);
214
+ const format = policy.visibleAgentFormat || 'agent: <agent-name> (<agent-role>) to <user>';
215
+ const firstLine = agent
216
+ ? format
217
+ .replace('<agent-name>', agent.name)
218
+ .replace('<agent-role>', agent.role)
219
+ .replace('<agent-title>', agent.title || agent.role)
220
+ .replace('<user>', actor || 'user')
221
+ : '';
222
+ return {
223
+ required: policy.requireVisibleAgent !== false,
224
+ firstLine,
225
+ beforeAnswer: `node .MOP/scripts/mop-core.mjs memory brief --actor ${actor || '<codename>'}`,
226
+ afterAnswer: `node .MOP/scripts/mop-core.mjs memory add --actor ${actor || '<codename>'} --kind conversation --summary "<one-line outcome>"`,
227
+ rules: [
228
+ 'Do not answer authenticated work without an active named agent.',
229
+ 'Every user-facing answer must show the active agent line first.',
230
+ 'Restore monthly memory before answering and save a one-line memory after meaningful work.'
231
+ ]
232
+ };
233
+ }
234
+
235
+ function browserPolicy(state) {
236
+ return state.browserPolicy || {
237
+ requirePreflightBeforeBrowserWork: true,
238
+ requireDefaultBrowserCheck: true,
239
+ directModeBrowsers: ['brave', 'edge', 'opera'],
240
+ builtinChromeBrowsers: ['chrome', 'chromium'],
241
+ supportedChoices: ['Chrome', 'Edge', 'Brave', 'Opera']
242
+ };
243
+ }
244
+
245
+ function browserFamilyFromValue(raw) {
246
+ const value = String(raw || '').toLowerCase();
247
+ if (/(google-chrome|chromehtml|chrome)/.test(value) && !/chromium/.test(value)) return 'chrome';
248
+ if (/chromium/.test(value)) return 'chromium';
249
+ if (/brave/.test(value)) return 'brave';
250
+ if (/(microsoft-edge|mseedge|edge)/.test(value)) return 'edge';
251
+ if (/opera/.test(value)) return 'opera';
252
+ if (/firefox/.test(value)) return 'firefox';
253
+ return 'unknown';
254
+ }
255
+
256
+ function detectWindowsDefaultBrowser() {
257
+ const script = [
258
+ '$ErrorActionPreference = "SilentlyContinue";',
259
+ '$keys = @(',
260
+ '"HKCU:\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\https\\UserChoice",',
261
+ '"HKCU:\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice"',
262
+ ');',
263
+ 'foreach ($key in $keys) {',
264
+ ' $item = Get-ItemProperty -Path $key -Name ProgId;',
265
+ ' if ($item.ProgId) { Write-Output $item.ProgId; break }',
266
+ '}'
267
+ ].join('\n');
268
+ const result = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', script], {
269
+ cwd: rootDir,
270
+ encoding: 'utf8'
271
+ });
272
+ const raw = result.status === 0 ? (result.stdout || '').trim().split(/\r?\n/)[0] : '';
273
+ return raw ? { raw, source: 'windows-registry' } : null;
274
+ }
275
+
276
+ function detectDefaultBrowser() {
277
+ let detected = process.platform === 'win32' ? detectWindowsDefaultBrowser() : null;
278
+ if (!detected) {
279
+ const xdg = spawnSync('xdg-settings', ['get', 'default-web-browser'], {
280
+ cwd: rootDir,
281
+ encoding: 'utf8'
282
+ });
283
+ const raw = (xdg.status === 0 ? xdg.stdout : '').trim();
284
+ if (raw) detected = { raw, source: 'xdg-settings' };
285
+ }
286
+ if (!detected && process.env.BROWSER) {
287
+ detected = { raw: process.env.BROWSER, source: 'BROWSER' };
288
+ }
289
+ const raw = detected?.raw || '';
290
+ return {
291
+ raw: raw || null,
292
+ family: browserFamilyFromValue(raw),
293
+ source: detected?.source || 'not-detected'
294
+ };
295
+ }
296
+
297
+ function browserPreflightFor(state) {
298
+ const policy = browserPolicy(state);
299
+ const detected = detectDefaultBrowser();
300
+ const direct = (policy.directModeBrowsers || []).includes(detected.family);
301
+ const builtin = (policy.builtinChromeBrowsers || []).includes(detected.family);
302
+ const supported = direct || builtin;
303
+ const mode = builtin ? 'chrome' : direct ? 'chrome-direct' : 'ask-user-browser';
304
+ const needsQuestion = !supported;
305
+ return {
306
+ required: policy.requirePreflightBeforeBrowserWork !== false,
307
+ defaultBrowser: detected,
308
+ mode,
309
+ ready: supported,
310
+ needsQuestion,
311
+ question: needsQuestion
312
+ ? `Saya tak dapat kesan Chrome/Edge/Brave/Opera sebagai browser default. Awak guna browser apa? Pilih: ${(policy.supportedChoices || ['Chrome', 'Edge', 'Brave', 'Opera']).join(', ')}.`
313
+ : '',
314
+ instructions: direct
315
+ ? [
316
+ `Use browser-act chrome-direct for ${detected.family}.`,
317
+ 'Guide the user to start that browser with --remote-debugging-port before scraping or form automation.',
318
+ 'Do not create a default chrome session first.'
319
+ ]
320
+ : builtin
321
+ ? ['Use normal Chrome-compatible browser automation.', 'Do not ask the user again unless automation fails.']
322
+ : ['Ask the user which browser they use before scraping or browser automation.']
323
+ };
324
+ }
325
+
326
+ function requireActiveAgent(state, actor, role = 'core', title = 'Core Agent') {
327
+ const agent = activeAgentFor(state, actor);
328
+ if (agent) return agent;
329
+ throw new Error([
330
+ `Agent diperlukan sebelum sambung kerja untuk ${actor}.`,
331
+ `Task ini perlukan ${title}. Agent ini belum ada nama lagi atau belum dipilih.`,
332
+ `Jalankan: node .MOP/scripts/mop-core.mjs agent activate --actor ${actor} --role ${role} --title "${title}" --name "<agent-name>"`
333
+ ].join(' '));
334
+ }
335
+
336
+ function appendLedger(state, actor, kind, summary, agent = activeAgentFor(state, actor)) {
337
+ state.ledger ||= [];
338
+ state.ledger.push({ at: now(), actor, ...agentLedgerFields(agent), kind, summary });
339
+ }
340
+
341
+ function appendMonthlyMemory(state, actor, kind, summary, agent = activeAgentFor(state, actor)) {
342
+ if (memoryPolicy(state).enabled === false) return null;
343
+ const entry = { at: now(), actor, ...agentLedgerFields(agent), kind, summary };
344
+ const monthlyPath = monthlyMemoryPath(state);
345
+ mkdirSync(dirname(monthlyPath), { recursive: true });
346
+ writeFileSync(monthlyPath, `${JSON.stringify(entry)}\n`, { encoding: 'utf8', flag: 'a' });
347
+ writeSessionBrief(state, actor);
348
+ return { entry, monthlyPath };
349
+ }
350
+
351
+ function writeSessionBrief(state, actor) {
352
+ const path = sessionBriefPath(state);
353
+ const agent = activeAgentFor(state, actor);
354
+ const entries = latestMemoryEntries(state, memoryPolicy(state).recentLimit || 20);
355
+ const contract = answerContractFor(state, actor, agent);
356
+ const lines = [
357
+ '# MOP Session Brief',
358
+ '',
359
+ `Updated: ${now()}`,
360
+ `Actor: ${actor || state.activeMember || 'unknown'}`,
361
+ `Active agent: ${agent ? `${agent.name} (${agent.role})` : 'none'}`,
362
+ `Current month: ${monthKey()}`,
363
+ '',
364
+ '## Required Session Flow',
365
+ '',
366
+ '1. Read `.MOP/STATE.json` and follow `.MOP/PROTOCOL.md`.',
367
+ '2. Authenticate if required.',
368
+ '3. Run `agent route` for the user task before answering.',
369
+ `4. Start every authenticated answer with: \`${contract.firstLine || 'agent: <name> (<role>) to <user>'}\``,
370
+ '5. Save a one-line memory after meaningful work.',
371
+ '',
372
+ '## Recent Memory',
373
+ '',
374
+ ...entries.map((entry) => {
375
+ const who = entry.agent ? `${entry.agent} (${entry.agentRole || 'agent'})` : entry.actor;
376
+ return `- ${entry.at} - ${who}: ${entry.summary}`;
377
+ })
378
+ ];
379
+ mkdirSync(dirname(path), { recursive: true });
380
+ writeFileSync(path, `${lines.join('\n')}\n`, 'utf8');
381
+ }
382
+
383
+ const routeRules = [
384
+ {
385
+ role: 'memory',
386
+ support: ['researcher'],
387
+ keywords: ['memory', 'memori', 'ingat', 'recall', 'search', 'cari semula', 'journal', 'ledger', 'history', 'sejarah']
388
+ },
389
+ {
390
+ role: 'github',
391
+ support: ['reviewer'],
392
+ keywords: ['github', 'git', 'branch', 'merge', 'megre', 'commit', 'push', 'pull', 'pr', 'repo', 'repository', 'autosycn', 'autosync']
393
+ },
394
+ {
395
+ role: 'deploy',
396
+ support: ['devops', 'github'],
397
+ keywords: ['deploy', 'deployment', 'vercel', 'docker', 'github pages', 'github actions', 'hosting', 'release']
398
+ },
399
+ {
400
+ role: 'security',
401
+ support: ['architect', 'reviewer'],
402
+ keywords: ['security', 'secure', 'auth', 'login', 'password', 'token', 'secret', 'permission', 'role', 'akses', 'encrypt', 'api key']
403
+ },
404
+ {
405
+ role: 'performance',
406
+ support: ['architect', 'coder'],
407
+ keywords: ['performance', 'slow', 'lambat', 'speed', 'optimize', 'latency', 'memory leak', 'bundle', 'cache']
408
+ },
409
+ {
410
+ role: 'database',
411
+ support: ['backend', 'architect'],
412
+ keywords: ['database', 'db', 'schema', 'migration', 'sql', 'postgres', 'mysql', 'sqlite', 'prisma', 'query']
413
+ },
414
+ {
415
+ role: 'backend',
416
+ support: ['database', 'security', 'tester'],
417
+ keywords: ['backend', 'api', 'server', 'endpoint', 'route', 'auth api', 'middleware', 'webhook', 'integration']
418
+ },
419
+ {
420
+ role: 'frontend',
421
+ support: ['design', 'ux', 'tester'],
422
+ keywords: ['frontend', 'ui', 'react', 'next', 'vue', 'css', 'tailwind', 'component', 'page', 'browser', 'dashboard']
423
+ },
424
+ {
425
+ role: 'mobile',
426
+ support: ['ux', 'backend'],
427
+ keywords: ['mobile', 'android', 'ios', 'react native', 'flutter', 'pwa']
428
+ },
429
+ {
430
+ role: 'design',
431
+ support: ['ux', 'frontend'],
432
+ keywords: ['design', 'ui/ux', 'layout', 'figma', 'wireframe', 'visual', 'color', 'theme', 'responsive']
433
+ },
434
+ {
435
+ role: 'ux',
436
+ support: ['planner', 'design'],
437
+ keywords: ['ux', 'user flow', 'persona', 'journey', 'usability', 'pengguna', 'flow']
438
+ },
439
+ {
440
+ role: 'tester',
441
+ support: ['reviewer'],
442
+ keywords: ['test', 'testing', 'bug', 'error', 'fix', 'regression', 'playwright', 'vitest', 'jest', 'qa']
443
+ },
444
+ {
445
+ role: 'reviewer',
446
+ support: ['security', 'tester'],
447
+ keywords: ['review', 'semak', 'audit', 'check', 'validate', 'risk', 'risiko', 'quality']
448
+ },
449
+ {
450
+ role: 'docs',
451
+ support: ['prompt'],
452
+ keywords: ['docs', 'documentation', 'readme', 'guide', 'manual', 'changelog', 'spec', 'tulis']
453
+ },
454
+ {
455
+ role: 'prompt',
456
+ support: ['architect', 'docs'],
457
+ keywords: ['prompt', 'prompts', 'copy to prompts', 'ai prompt', 'system prompt', 'agent prompt', 'chatgpt', 'claude', 'gemini']
458
+ },
459
+ {
460
+ role: 'architect',
461
+ support: ['planner', 'researcher', 'coder', 'reviewer'],
462
+ keywords: ['system', 'architecture', 'architect', 'platform', 'workflow', 'engine', 'core', 'framework', 'template', 'buat sebuah system', 'bina system']
463
+ },
464
+ {
465
+ role: 'planner',
466
+ support: ['architect', 'researcher'],
467
+ keywords: ['plan', 'roadmap', 'scope', 'idea', 'konsep', 'feature', 'requirement', 'mvp', 'project']
468
+ },
469
+ {
470
+ role: 'coder',
471
+ support: ['tester', 'reviewer'],
472
+ keywords: ['code', 'coding', 'implement', 'buat file', 'ubah file', 'fix code', 'script', 'function']
473
+ },
474
+ {
475
+ role: 'browser',
476
+ support: ['researcher', 'tester'],
477
+ keywords: ['agent browser', 'browser agent', 'browser automation', 'browser', 'browse', 'scrape', 'scraping', 'web scraping', 'extract', 'click', 'login flow', 'fill form', 'captcha', 'bot detection', 'website', 'url', 'webpage']
478
+ },
479
+ {
480
+ role: 'researcher',
481
+ support: ['planner'],
482
+ keywords: ['research', 'kaji', 'compare', 'pilih', 'cari info', 'best practice']
483
+ }
484
+ ];
485
+
486
+ function catalogForRole(state, role) {
487
+ return (state.agentCatalog || []).find((item) => item.role === role) || {
488
+ role,
489
+ title: role.split('-').map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(' ')
490
+ };
491
+ }
492
+
493
+ function ownedAgentForRole(state, actor, role) {
494
+ return (state.agentRoster || []).find((agent) => agent.role === role && (agent.owners || []).includes(actor)) || null;
495
+ }
496
+
497
+ function routeScore(task, rule) {
498
+ return rule.keywords.reduce((score, keyword) => task.includes(keyword) ? score + Math.max(1, keyword.split(/\s+/).length) : score, 0);
499
+ }
500
+
501
+ function hasBrowserWorkIntent(task) {
502
+ return /\b(agent browser|browser agent|browser automation|browse|scrape|scraping|web scraping|extract|click|login flow|fill form|captcha|bot detection|webpage|url)\b/.test(task);
503
+ }
504
+
505
+ function uniqueValues(values) {
506
+ return [...new Set(values.filter(Boolean))];
507
+ }
508
+
509
+ function maybeLimit(values, limit) {
510
+ if (limit === null || limit === undefined || limit === '' || limit === 'unlimited') return values;
511
+ const numeric = Number(limit);
512
+ if (!Number.isFinite(numeric) || numeric < 1) return values;
513
+ return values.slice(0, numeric);
514
+ }
515
+
516
+ function shouldActivatePartyMode(state, task, primaryRole, supportRoles, newSystemIntent) {
517
+ if (state.partyMode?.enabled === false || state.partyMode?.autoActivateWhenNeeded === false) return false;
518
+ const explicitPartyIntent = /\b(party mode|party|multi[- ]?agent|swarm|semua agent|banyak agent|agent.*bincang|bincang.*agent|agent.*discuss|discuss.*agent)\b/.test(task);
519
+ const multiDomainIntent = [
520
+ ['ui', 'backend'],
521
+ ['frontend', 'backend'],
522
+ ['design', 'api'],
523
+ ['database', 'api'],
524
+ ['deploy', 'github'],
525
+ ['security', 'auth'],
526
+ ['prompt', 'system']
527
+ ].some(([first, second]) => task.includes(first) && task.includes(second));
528
+ const browserRiskIntent = hasBrowserWorkIntent(task);
529
+ const connectiveIntent = /\b(connect|connected|integrate|integration|bersambung|sambung|hubung|flow|workflow)\b/.test(task);
530
+ const broadBuild = newSystemIntent && supportRoles.length >= 2;
531
+ const specialistStack = supportRoles.length >= 3 && ['architect', 'planner', 'core'].includes(primaryRole);
532
+ return explicitPartyIntent || multiDomainIntent || browserRiskIntent || connectiveIntent || broadBuild || specialistStack;
533
+ }
534
+
535
+ function partyFormat(state) {
536
+ const format = state.partyMode?.format || {};
537
+ return {
538
+ banner: format.banner || state.partyMode?.banner || 'PARTY MODE',
539
+ agentToAgent: format.agentToAgent || 'agent: <from-name> (<from-role>) to agent: <to-name> (<to-role>)',
540
+ agentToUser: format.agentToUser || 'agent: <from-name> (<from-role>) to <user>',
541
+ explanation: format.explanation || 'agent: <from-name> (<from-role>)',
542
+ messageIndent: format.messageIndent || ' ',
543
+ blankLineBeforeMessage: format.blankLineBeforeMessage !== false
544
+ };
545
+ }
546
+
547
+ function partyParticipantsFor(state, primaryRole, supportRoles, scored, partyActive) {
548
+ if (!partyActive) return [];
549
+ const preferredMinimum = Number(state.partyMode?.preferredMinimumParticipants || 4);
550
+ const minimum = Number(state.partyMode?.minimumParticipants || 3);
551
+ const floor = Number.isFinite(preferredMinimum) ? Math.max(minimum, preferredMinimum) : minimum;
552
+ const fallbackRoles = ['planner', 'researcher', 'reviewer', 'coder', 'architect', 'prompt', 'tester'];
553
+ const relevant = uniqueValues([
554
+ primaryRole,
555
+ ...supportRoles,
556
+ ...scored.map((rule) => rule.role)
557
+ ]);
558
+ const participants = relevant.length >= floor
559
+ ? relevant
560
+ : uniqueValues([...relevant, ...fallbackRoles]).slice(0, floor);
561
+ const catalogRoles = new Set((state.agentCatalog || []).map((item) => item.role));
562
+ const filtered = participants.filter((role) => catalogRoles.has(role));
563
+ const enough = filtered.length >= floor ? filtered : participants;
564
+ return maybeLimit(enough, state.partyMode?.participantLimit);
565
+ }
566
+
567
+ function inferAgentRoute(state, taskText) {
568
+ const task = taskText.toLowerCase();
569
+ const words = task.split(/\s+/).filter(Boolean);
570
+ const scored = routeRules
571
+ .map((rule) => ({ ...rule, score: routeScore(task, rule) }))
572
+ .filter((rule) => rule.score > 0)
573
+ .sort((a, b) => b.score - a.score);
574
+
575
+ const newSystemIntent = /\b(system|sistem|app|tool|platform|website|dashboard|engine|core)\b/.test(task)
576
+ || /buat sebuah|bina sebuah|create a|build a/.test(task);
577
+ const implementationIntent = /\b(code|coding|implement|fix|ubah file|buat file)\b/.test(task);
578
+ const browserWorkIntent = hasBrowserWorkIntent(task);
579
+ const top = scored[0];
580
+ let primaryRole = browserWorkIntent ? 'browser' : (top?.role || state.agentPolicy?.defaultRole || 'core');
581
+
582
+ if (newSystemIntent && !implementationIntent && !browserWorkIntent && state.agentRouter?.preferHighReasoningForNewSystems !== false) {
583
+ primaryRole = state.agentRouter?.defaultHighReasoningRole || 'architect';
584
+ }
585
+
586
+ const primary = catalogForRole(state, primaryRole);
587
+ const baseSupport = newSystemIntent && !browserWorkIntent
588
+ ? ['planner', 'researcher', 'prompt', 'coder', 'reviewer']
589
+ : (top?.support || []);
590
+ const supportRoles = maybeLimit(uniqueValues([
591
+ ...baseSupport,
592
+ ...scored.slice(1).map((rule) => rule.role)
593
+ ])
594
+ .filter((role) => role !== primaryRole), state.agentRouter?.supportAgentLimit);
595
+ const partyActive = shouldActivatePartyMode(state, task, primaryRole, supportRoles, newSystemIntent);
596
+ const partyParticipants = partyParticipantsFor(state, primaryRole, supportRoles, scored, partyActive);
597
+
598
+ const ambiguousNewSystem = newSystemIntent && !browserWorkIntent && words.length < 18;
599
+ const noClearMatch = scored.length === 0 && words.length > 3;
600
+ const needsClarification = state.agentRouter?.clarifyBeforeActionWhenAmbiguous !== false
601
+ && (ambiguousNewSystem || noClearMatch || /\b(maybe|mungkin|lebih kurang|macam)\b/.test(task));
602
+
603
+ const questions = needsClarification ? [
604
+ 'Apa tujuan utama system ini dan masalah apa yang dia selesaikan?',
605
+ 'Siapa pengguna utama system ini?',
606
+ 'Output wajib apa yang awak nak lihat dulu: plan, UI, repo/file, atau prompt template?'
607
+ ] : [];
608
+
609
+ return {
610
+ task: taskText,
611
+ primaryRole,
612
+ primaryTitle: primary.title,
613
+ supportRoles,
614
+ partyMode: {
615
+ active: partyActive,
616
+ banner: partyActive && state.partyMode?.bannerRequired !== false ? (state.partyMode?.banner || 'PARTY MODE') : '',
617
+ participants: partyActive ? partyParticipants : [],
618
+ minimumParticipants: state.partyMode?.minimumParticipants || 3,
619
+ preferredMinimumParticipants: state.partyMode?.preferredMinimumParticipants || 4,
620
+ visibleToUser: state.partyMode?.showAgentDialogueToUser !== false,
621
+ format: partyFormat(state),
622
+ reason: partyActive
623
+ ? 'Task needs several specialist agents to reason together before the primary agent answers the user.'
624
+ : 'Single-agent route is enough for this task.'
625
+ },
626
+ confidence: top ? Math.min(0.95, 0.45 + (top.score * 0.08)) : 0.35,
627
+ needsClarification,
628
+ questions,
629
+ reason: newSystemIntent && !browserWorkIntent
630
+ ? `New or broad system task routed to ${primary.title} for high-reasoning planning before implementation.`
631
+ : top
632
+ ? `Matched keywords for ${primary.title}: ${top.keywords.filter((keyword) => task.includes(keyword)).join(', ')}.`
633
+ : `No strong specialist match; using ${primary.title}.`
634
+ };
635
+ }
636
+
637
+ function setup(args) {
638
+ const state = readState();
639
+ if (state.initialized) {
640
+ throw new Error('MOP already initialized.');
641
+ }
642
+
643
+ const folderDefault = rootDir.split(/[\\/]/).filter(Boolean).pop() || 'MOP';
644
+ const projectName = String(args['project-name'] || folderDefault);
645
+ const displayName = requireArg(args, 'name');
646
+ const codename = slug(requireArg(args, 'codename'));
647
+ const password = requireArg(args, 'password');
648
+ const mode = requireArg(args, 'mode').toLowerCase();
649
+ const conversationLanguage = String(args['conversation-language'] || 'Melayu');
650
+ const codingLanguage = String(args['coding-language'] || 'English');
651
+ const githubUrl = String(args['github-url'] || '');
652
+ const gitName = String(args['git-name'] || displayName);
653
+ const gitEmail = String(args['git-email'] || 'github-noreply');
654
+ const githubUsername = String(args['github-username'] || '');
655
+ const joinMode = String(args['join-mode'] || 'owner-approved');
656
+
657
+ if (codename.length < 2) throw new Error('Codename too short.');
658
+ if (password.length < 8) throw new Error('Password must be at least 8 characters.');
659
+ if (!['solo', 'team'].includes(mode)) throw new Error('Mode must be solo or team.');
660
+ if (mode === 'team' && !githubUrl) throw new Error('Team mode requires --github-url.');
661
+ if (!['open', 'owner-approved', 'invite'].includes(joinMode)) {
662
+ throw new Error('Join mode must be open, owner-approved, or invite.');
663
+ }
664
+ const gitIdentity = resolveGitIdentityInput(state, codename, gitName, gitEmail, githubUsername);
665
+
666
+ const { passwordHash, passwordSalt } = hashPassword(password);
667
+ state.initialized = true;
668
+ state.projectName = projectName;
669
+ state.projectNameDefault = folderDefault;
670
+ state.ownerCodename = codename;
671
+ state.activeMember = codename;
672
+ state.activeAgents ||= {};
673
+ state.agentPolicy ||= {
674
+ requiredAfterAuth: true,
675
+ requireForEveryConversation: true,
676
+ defaultRole: 'core',
677
+ defaultTitle: 'Core Agent',
678
+ gateOrder: 'AUTH_GATE_THEN_AGENT_ROUTER_THEN_AGENT_GATE_THEN_ACTION'
679
+ };
680
+ state.mode = mode;
681
+ state.joinMode = mode === 'team' ? joinMode : 'owner-approved';
682
+ state.githubUrl = githubUrl;
683
+ state.members = {
684
+ [codename]: {
685
+ codename,
686
+ displayName,
687
+ role: 'owner',
688
+ passwordHash,
689
+ passwordSalt,
690
+ languagePreferences: {
691
+ conversation: conversationLanguage,
692
+ coding: codingLanguage
693
+ },
694
+ gitIdentity,
695
+ joinedAt: now()
696
+ }
697
+ };
698
+ appendLedger(state, codename, 'setup', `Initialized ${projectName} in ${mode} mode.`);
699
+ writeState(state);
700
+ console.log(`MOP initialized. Owner ${displayName} (${codename}) is active.`);
701
+ }
702
+
703
+ function login(args) {
704
+ const state = readState();
705
+ const codename = slug(requireArg(args, 'codename'));
706
+ const password = requireArg(args, 'password');
707
+ const member = state.members?.[codename];
708
+ if (!member || !verifyPassword(password, member.passwordSalt, member.passwordHash)) {
709
+ console.log('Credentials tidak sah.');
710
+ process.exitCode = 1;
711
+ return;
712
+ }
713
+ state.activeMember = codename;
714
+ appendLedger(state, codename, 'login', 'Member authenticated.');
715
+ writeState(state);
716
+ console.log(`Active member: ${codename}`);
717
+ if (!activeAgentFor(state, codename) && state.agentPolicy?.requiredAfterAuth !== false) {
718
+ console.log(`Agent diperlukan. Jalankan: node .MOP/scripts/mop-core.mjs agent activate --actor ${codename} --role ${state.agentPolicy?.defaultRole || 'core'} --title "${state.agentPolicy?.defaultTitle || 'Core Agent'}" --name "<agent-name>"`);
719
+ } else {
720
+ console.log(JSON.stringify({
721
+ next: 'restore-memory-and-route-task',
722
+ memoryRestore: `node .MOP/scripts/mop-core.mjs memory brief --actor ${codename}`,
723
+ answerContract: answerContractFor(state, codename)
724
+ }, null, 2));
725
+ }
726
+ }
727
+
728
+ function agentActivate(args) {
729
+ const state = readState();
730
+ if (!state.initialized) throw new Error('MOP is not initialized.');
731
+ const actor = slug(requireArg(args, 'actor'));
732
+ if (!state.members?.[actor]) throw new Error('Unknown actor.');
733
+
734
+ const role = slug(requireArg(args, 'role'));
735
+ const title = String(args.title || role);
736
+ const name = requireArg(args, 'name').trim();
737
+ const key = name.toLowerCase();
738
+ state.agentRoster ||= [];
739
+ state.activeAgents ||= {};
740
+
741
+ let agent = state.agentRoster.find((item) => item.name.toLowerCase() === key);
742
+ if (agent) {
743
+ agent.owners ||= [];
744
+ if (!agent.owners.includes(actor)) agent.owners.push(actor);
745
+ appendLedger(state, actor, 'agent-share', `${actor} joined agent ${agent.name}.`);
746
+ } else {
747
+ agent = {
748
+ id: `agent-${slug(name)}`,
749
+ role,
750
+ title,
751
+ name,
752
+ owners: [actor],
753
+ createdBy: actor,
754
+ createdAt: now()
755
+ };
756
+ state.agentRoster.push(agent);
757
+ appendLedger(state, actor, 'agent-activate', `Named ${title} as ${name}.`);
758
+ }
759
+ state.activeAgents[actor] = agent.id;
760
+ appendLedger(state, actor, 'agent-use', `Set active agent to ${agent.name}.`, agent);
761
+ writeState(state);
762
+ console.log(`Agent active: ${agent.name} (${agent.role}) owners=${agent.owners.join(',')}`);
763
+ }
764
+
765
+ function agentUse(args) {
766
+ const state = readState();
767
+ if (!state.initialized) throw new Error('MOP is not initialized.');
768
+ const actor = slug(requireArg(args, 'actor'));
769
+ if (!state.members?.[actor]) throw new Error('Unknown actor.');
770
+ const name = requireArg(args, 'name').trim();
771
+ const agent = (state.agentRoster || []).find((item) => item.name.toLowerCase() === name.toLowerCase());
772
+ if (!agent) throw new Error(`Unknown agent: ${name}`);
773
+ if (!(agent.owners || []).includes(actor)) throw new Error(`${actor} does not own agent ${agent.name}.`);
774
+ state.activeAgents ||= {};
775
+ state.activeAgents[actor] = agent.id;
776
+ appendLedger(state, actor, 'agent-use', `Set active agent to ${agent.name}.`, agent);
777
+ writeState(state);
778
+ console.log(`Active agent for ${actor}: ${agent.name} (${agent.role})`);
779
+ }
780
+
781
+ function agentCurrent(args) {
782
+ const state = readState();
783
+ const actor = slug(requireArg(args, 'actor'));
784
+ const agent = activeAgentFor(state, actor);
785
+ if (!agent) {
786
+ console.log(`No active agent for ${actor}.`);
787
+ process.exitCode = 2;
788
+ return;
789
+ }
790
+ console.log(JSON.stringify({
791
+ actor,
792
+ agent: agent.name,
793
+ role: agent.role,
794
+ title: agent.title,
795
+ id: agent.id
796
+ }, null, 2));
797
+ }
798
+
799
+ function agentRequire(args) {
800
+ const state = readState();
801
+ const actor = slug(requireArg(args, 'actor'));
802
+ const role = slug(String(args.role || state.agentPolicy?.defaultRole || 'core'));
803
+ const title = String(args.title || state.agentPolicy?.defaultTitle || 'Core Agent');
804
+ const agent = requireActiveAgent(state, actor, role, title);
805
+ console.log(JSON.stringify({
806
+ actor,
807
+ agent: agent.name,
808
+ role: agent.role,
809
+ title: agent.title,
810
+ id: agent.id
811
+ }, null, 2));
812
+ }
813
+
814
+ function agentRoute(args) {
815
+ const state = readState();
816
+ if (!state.initialized) throw new Error('MOP is not initialized.');
817
+ if (state.agentRouter?.enabled === false) throw new Error('Agent Router is disabled.');
818
+ const actor = slug(requireArg(args, 'actor'));
819
+ if (!state.members?.[actor]) throw new Error('Unknown actor.');
820
+ const task = String(args.task || args._?.join(' ') || '').trim();
821
+ if (!task) throw new Error('Missing --task');
822
+
823
+ const route = inferAgentRoute(state, task);
824
+ const agent = ownedAgentForRole(state, actor, route.primaryRole);
825
+ const partyAgents = route.partyMode.active ? route.partyMode.participants.map((role) => {
826
+ const catalog = catalogForRole(state, role);
827
+ const owned = ownedAgentForRole(state, actor, role);
828
+ return {
829
+ role,
830
+ title: catalog.title,
831
+ name: owned?.name || null,
832
+ id: owned?.id || null,
833
+ missing: !owned
834
+ };
835
+ }) : [];
836
+ const missingPartyAgents = partyAgents.filter((item) => item.missing);
837
+ const missingAgentCommands = missingPartyAgents.map((item) => (
838
+ `node .MOP/scripts/mop-core.mjs agent activate --actor ${actor} --role ${item.role} --title "${item.title}" --name "<agent-name>"`
839
+ ));
840
+ const missingAgentQuestions = missingPartyAgents.map((item) => (
841
+ `Beri nama untuk ${item.title} (${item.role}) kamu:`
842
+ ));
843
+ const browserPreflight = route.primaryRole === 'browser'
844
+ || route.supportRoles.includes('browser')
845
+ || route.partyMode?.participants?.includes('browser')
846
+ || hasBrowserWorkIntent(route.task || '')
847
+ ? browserPreflightFor(state)
848
+ : null;
849
+ const response = {
850
+ ok: Boolean(agent),
851
+ actor,
852
+ route,
853
+ partyAgents,
854
+ missingAgents: missingPartyAgents,
855
+ activeAgent: null,
856
+ answerContract: null,
857
+ browserPreflight,
858
+ monthlyMemory: {
859
+ restoreCommand: `node .MOP/scripts/mop-core.mjs memory brief --actor ${actor}`,
860
+ saveCommand: `node .MOP/scripts/mop-core.mjs memory add --actor ${actor} --kind conversation --summary "<one-line outcome>"`
861
+ },
862
+ nextAction: null
863
+ };
864
+
865
+ if (agent) {
866
+ state.activeAgents ||= {};
867
+ state.activeAgents[actor] = agent.id;
868
+ appendLedger(state, actor, 'agent-route', `Routed task to ${agent.name}: ${route.reason}`, agent);
869
+ writeState(state);
870
+ response.activeAgent = {
871
+ id: agent.id,
872
+ name: agent.name,
873
+ role: agent.role,
874
+ title: agent.title
875
+ };
876
+ response.answerContract = answerContractFor(state, actor, agent);
877
+ if (route.partyMode.active && missingPartyAgents.length) {
878
+ response.ok = false;
879
+ response.nextAction = 'name-required-party-agents';
880
+ response.message = `Party Mode perlukan ${missingPartyAgents.length} agent yang belum ada nama. Minta nama semua agent ini dahulu sebelum sambung kerja.`;
881
+ response.ask = `Kita ada ${missingPartyAgents.length} agent belum ada nama. ${missingAgentQuestions.join(' ')}`;
882
+ response.missingAgentQuestions = missingAgentQuestions;
883
+ response.missingAgentCommands = missingAgentCommands;
884
+ } else if (browserPreflight?.required && browserPreflight.needsQuestion) {
885
+ response.ok = false;
886
+ response.nextAction = 'ask-browser-before-browser-work';
887
+ response.message = 'Browser preflight belum ready. Tanya browser user dahulu sebelum scraping/browser automation.';
888
+ response.ask = browserPreflight.question;
889
+ } else {
890
+ response.nextAction = route.needsClarification ? 'ask-clarifying-questions' : 'proceed-with-agent';
891
+ }
892
+ } else {
893
+ response.nextAction = route.partyMode.active && missingPartyAgents.length
894
+ ? 'name-required-party-agents'
895
+ : 'name-required-agent';
896
+ response.message = route.partyMode.active && missingPartyAgents.length
897
+ ? `Party Mode perlukan ${missingPartyAgents.length} agent yang belum ada nama. Minta nama semua agent ini dahulu sebelum sambung kerja.`
898
+ : `Task ini perlukan ${route.primaryTitle}. Agent ini belum ada nama lagi atau belum dipilih.`;
899
+ response.ask = route.partyMode.active && missingPartyAgents.length
900
+ ? `Kita ada ${missingPartyAgents.length} agent belum ada nama. ${missingAgentQuestions.join(' ')}`
901
+ : `Beri nama untuk ${route.primaryTitle} kamu:`;
902
+ response.command = `node .MOP/scripts/mop-core.mjs agent activate --actor ${actor} --role ${route.primaryRole} --title "${route.primaryTitle}" --name "<agent-name>"`;
903
+ if (route.partyMode.active && missingPartyAgents.length) {
904
+ response.missingAgentQuestions = missingAgentQuestions;
905
+ response.missingAgentCommands = missingAgentCommands;
906
+ }
907
+ if (route.needsClarification) response.afterNaming = route.questions;
908
+ }
909
+
910
+ console.log(JSON.stringify(response, null, 2));
911
+ }
912
+
913
+ function agentList() {
914
+ const state = readState();
915
+ console.log(JSON.stringify({
916
+ activeAgents: state.activeAgents || {},
917
+ agents: state.agentRoster || []
918
+ }, null, 2));
919
+ }
920
+
921
+ function browserPreflight() {
922
+ const state = readState();
923
+ console.log(JSON.stringify(browserPreflightFor(state), null, 2));
924
+ }
925
+
926
+ function memoryAdd(args) {
927
+ const state = readState();
928
+ if (!state.initialized) throw new Error('MOP is not initialized.');
929
+ const actor = slug(requireArg(args, 'actor'));
930
+ if (!state.members?.[actor]) throw new Error('Unknown actor.');
931
+ const agent = requireActiveAgent(state, actor);
932
+ const summary = String(args.summary || args._?.join(' ') || '').trim();
933
+ const kind = String(args.kind || 'conversation');
934
+ if (!summary) throw new Error('Missing --summary');
935
+
936
+ appendLedger(state, actor, 'memory', summary, agent);
937
+ const saved = appendMonthlyMemory(state, actor, kind, summary, agent);
938
+ writeState(state);
939
+ console.log(JSON.stringify({
940
+ ok: true,
941
+ actor,
942
+ agent: agent.name,
943
+ kind,
944
+ summary,
945
+ monthlyMemory: saved ? relativeFromRoot(saved.monthlyPath) : 'disabled',
946
+ sessionBrief: relativeFromRoot(sessionBriefPath(state)),
947
+ answerContract: answerContractFor(state, actor, agent)
948
+ }, null, 2));
949
+ }
950
+
951
+ function memoryBrief(args) {
952
+ const state = readState();
953
+ if (!state.initialized) {
954
+ console.log('MOP belum di-setup. Jalankan /mop-setup.');
955
+ return;
956
+ }
957
+ const actor = slug(String(args.actor || state.activeMember || ''));
958
+ if (!actor) throw new Error('Missing --actor');
959
+ if (!state.members?.[actor]) throw new Error('Unknown actor.');
960
+ const agent = activeAgentFor(state, actor);
961
+ const month = String(args.month || monthKey());
962
+ const limit = Number(args.limit || memoryPolicy(state).recentLimit || 20);
963
+ const currentEntries = readJsonl(monthlyMemoryPath(state, month)).slice(-limit);
964
+ const recentEntries = latestMemoryEntries(state, limit);
965
+ if (agent) writeSessionBrief(state, actor);
966
+ console.log(JSON.stringify({
967
+ ok: true,
968
+ actor,
969
+ activeAgent: agent ? {
970
+ id: agent.id,
971
+ name: agent.name,
972
+ role: agent.role,
973
+ title: agent.title
974
+ } : null,
975
+ answerContract: answerContractFor(state, actor, agent),
976
+ memory: {
977
+ month,
978
+ monthPath: relativeFromRoot(monthlyMemoryPath(state, month)),
979
+ sessionBrief: relativeFromRoot(sessionBriefPath(state)),
980
+ currentMonthEntries: currentEntries,
981
+ recentEntries
982
+ },
983
+ next: agent
984
+ ? 'Use answerContract.firstLine before answering, then save memory after meaningful work.'
985
+ : `Agent diperlukan. Jalankan: node .MOP/scripts/mop-core.mjs agent activate --actor ${actor} --role ${state.agentPolicy?.defaultRole || 'core'} --title "${state.agentPolicy?.defaultTitle || 'Core Agent'}" --name "<agent-name>"`
986
+ }, null, 2));
987
+ }
988
+
989
+ function memoryRestore(args) {
990
+ return memoryBrief(args);
991
+ }
992
+
993
+ function memberGitIdentity(args) {
994
+ const state = readState();
995
+ if (!state.initialized) throw new Error('MOP is not initialized.');
996
+ const actor = slug(requireArg(args, 'actor'));
997
+ const member = state.members?.[actor];
998
+ if (!member) throw new Error('Unknown actor.');
999
+ const agent = requireActiveAgent(state, actor);
1000
+ const name = String(args.name || member.displayName || actor);
1001
+ const email = String(args.email || 'github-noreply');
1002
+ const githubUsername = String(args['github-username'] || member.gitIdentity?.githubUsername || '');
1003
+ member.gitIdentity = resolveGitIdentityInput(state, actor, name, email, githubUsername);
1004
+ appendLedger(state, actor, 'git-identity', `Updated git identity for ${actor}.`, agent);
1005
+ writeState(state);
1006
+ console.log(`Git identity set for ${actor}: ${member.gitIdentity.name} <${member.gitIdentity.email}>${member.gitIdentity.githubUsername ? ` github=${member.gitIdentity.githubUsername}` : ''}`);
1007
+ }
1008
+
1009
+ function validate() {
1010
+ const state = readState();
1011
+ const errors = [];
1012
+ if (typeof state.initialized !== 'boolean') errors.push('initialized must be boolean');
1013
+ if (!state.projectName) errors.push('projectName is required');
1014
+ if (!Array.isArray(state.agentRoster)) errors.push('agentRoster must be array');
1015
+ if (!Array.isArray(state.agentCatalog)) errors.push('agentCatalog must be array');
1016
+ if (state.activeAgents && typeof state.activeAgents !== 'object') errors.push('activeAgents must be object');
1017
+ if (state.agentPolicy && typeof state.agentPolicy !== 'object') errors.push('agentPolicy must be object');
1018
+ if (state.answerPolicy && typeof state.answerPolicy !== 'object') errors.push('answerPolicy must be object');
1019
+ if (state.memoryPolicy && typeof state.memoryPolicy !== 'object') errors.push('memoryPolicy must be object');
1020
+ if (state.browserPolicy && typeof state.browserPolicy !== 'object') errors.push('browserPolicy must be object');
1021
+ if (state.agentRouter && typeof state.agentRouter !== 'object') errors.push('agentRouter must be object');
1022
+ if (state.partyMode && typeof state.partyMode !== 'object') errors.push('partyMode must be object');
1023
+ if (state.autosync?.githubIdentity && typeof state.autosync.githubIdentity !== 'object') {
1024
+ errors.push('autosync.githubIdentity must be object');
1025
+ }
1026
+ if (state.mopFlow && typeof state.mopFlow !== 'object') errors.push('mopFlow must be object');
1027
+ if (state.mopFlow?.enabled !== false) {
1028
+ if (state.mopFlow?.brand !== 'MOP Flow') errors.push('mopFlow.brand must be MOP Flow');
1029
+ if (state.mopFlow?.canonicalMcpServer !== 'mop-flow') errors.push('mopFlow.canonicalMcpServer must be mop-flow');
1030
+ if (state.mopFlow?.providerParity?.enabled === false) errors.push('mopFlow.providerParity must remain enabled');
1031
+ for (const path of [
1032
+ '.MOP/scripts/mop-flow.mjs',
1033
+ '.agents/skills/mop-flow/SKILL.md',
1034
+ '.claude/skills/mop-flow/SKILL.md'
1035
+ ]) {
1036
+ if (!existsSync(join(rootDir, path))) errors.push(`mopFlow required file missing: ${path}`);
1037
+ }
1038
+ const mcpText = existsSync(join(rootDir, '.mcp.json')) ? readFileSync(join(rootDir, '.mcp.json'), 'utf8') : '';
1039
+ if (mcpText && !mcpText.includes('"mop-flow"')) errors.push('.mcp.json must register mop-flow');
1040
+ }
1041
+ if (state.projectRootPolicy && typeof state.projectRootPolicy !== 'object') errors.push('projectRootPolicy must be object');
1042
+ if (state.projectRootPolicy?.rules && !Array.isArray(state.projectRootPolicy.rules)) {
1043
+ errors.push('projectRootPolicy.rules must be array');
1044
+ }
1045
+ if (!Array.isArray(state.ledger)) errors.push('ledger must be array');
1046
+ const catalogRoles = new Set();
1047
+ for (const item of state.agentCatalog || []) {
1048
+ if (!item.role) errors.push('agentCatalog entry missing role');
1049
+ if (!item.title) errors.push(`agentCatalog ${item.role || '<unknown>'} missing title`);
1050
+ if (item.role && catalogRoles.has(item.role)) errors.push(`duplicate agentCatalog role: ${item.role}`);
1051
+ if (item.role) catalogRoles.add(item.role);
1052
+ }
1053
+ const routerRole = state.agentRouter?.defaultHighReasoningRole;
1054
+ if (routerRole && !catalogRoles.has(routerRole)) {
1055
+ errors.push(`agentRouter.defaultHighReasoningRole missing from agentCatalog: ${routerRole}`);
1056
+ }
1057
+ const defaultRole = state.agentPolicy?.defaultRole;
1058
+ if (defaultRole && !catalogRoles.has(defaultRole)) {
1059
+ errors.push(`agentPolicy.defaultRole missing from agentCatalog: ${defaultRole}`);
1060
+ }
1061
+ for (const phase of state.workflow?.phases || []) {
1062
+ if (!phase.id) errors.push('workflow phase missing id');
1063
+ if (phase.primaryRole && !catalogRoles.has(phase.primaryRole)) {
1064
+ errors.push(`workflow phase ${phase.id} primaryRole missing from agentCatalog: ${phase.primaryRole}`);
1065
+ }
1066
+ for (const role of phase.partyRoles || []) {
1067
+ if (!catalogRoles.has(role)) errors.push(`workflow phase ${phase.id} partyRole missing from agentCatalog: ${role}`);
1068
+ }
1069
+ if (phase.artifact && !(state.artifacts?.types || []).includes(phase.artifact)) {
1070
+ errors.push(`workflow phase ${phase.id} artifact missing from artifact types: ${phase.artifact}`);
1071
+ }
1072
+ }
1073
+ for (const type of state.artifacts?.types || []) {
1074
+ const templatePath = join(rootDir, state.artifacts?.templateDirectory || '.MOP/templates/artifacts', `${type}.md`);
1075
+ if (!existsSync(templatePath)) errors.push(`artifact template missing: ${templatePath}`);
1076
+ const folder = state.artifacts?.folderByType?.[type];
1077
+ if (state.artifacts?.folderByType && (!folder || typeof folder !== 'string')) {
1078
+ errors.push(`artifact folder missing for type: ${type}`);
1079
+ }
1080
+ }
1081
+ if (state.installer?.entrypoint && !existsSync(join(rootDir, state.installer.entrypoint))) {
1082
+ errors.push(`installer entrypoint missing: ${state.installer.entrypoint}`);
1083
+ }
1084
+ if (state.initialized) {
1085
+ if (!state.ownerCodename) errors.push('ownerCodename is required after setup');
1086
+ if (!state.members?.[state.ownerCodename]) errors.push('owner member missing');
1087
+ if (!['solo', 'team'].includes(state.mode)) errors.push('mode must be solo or team');
1088
+ if (state.mode === 'team' && !state.githubUrl) errors.push('team mode requires githubUrl');
1089
+ if (state.autosync?.requireUserGitEmail !== false) {
1090
+ for (const [codename, member] of Object.entries(state.members || {})) {
1091
+ if (!member.gitIdentity?.email && !member.github?.noreplyEmail) {
1092
+ errors.push(`member ${codename} is missing git identity email`);
1093
+ }
1094
+ }
1095
+ }
1096
+ for (const [codename, agentId] of Object.entries(state.activeAgents || {})) {
1097
+ const agent = (state.agentRoster || []).find((item) => item.id === agentId || item.name === agentId);
1098
+ if (!agent) errors.push(`active agent for ${codename} is missing from agentRoster`);
1099
+ if (agent && !(agent.owners || []).includes(codename)) errors.push(`active agent ${agent.name} does not include owner ${codename}`);
1100
+ }
1101
+ }
1102
+ if (errors.length) {
1103
+ console.error(errors.join('\n'));
1104
+ process.exitCode = 1;
1105
+ return;
1106
+ }
1107
+ console.log('MOP state OK.');
1108
+ }
1109
+
1110
+ function status() {
1111
+ const state = readState();
1112
+ console.log(JSON.stringify({
1113
+ initialized: state.initialized,
1114
+ projectName: state.projectName,
1115
+ activeMember: state.activeMember,
1116
+ activeAgents: Object.fromEntries(Object.entries(state.activeAgents || {}).map(([codename, agentId]) => {
1117
+ const agent = (state.agentRoster || []).find((item) => item.id === agentId || item.name === agentId);
1118
+ return [codename, agent ? { name: agent.name, role: agent.role, id: agent.id } : { id: agentId, missing: true }];
1119
+ })),
1120
+ agentPolicy: state.agentPolicy || {},
1121
+ answerPolicy: answerPolicy(state),
1122
+ memoryPolicy: memoryPolicy(state),
1123
+ browserPolicy: browserPolicy(state),
1124
+ agentRouter: state.agentRouter || {},
1125
+ partyMode: state.partyMode || {},
1126
+ workflow: {
1127
+ enabled: state.workflow?.enabled !== false,
1128
+ currentPhase: state.workflow?.currentPhase || null,
1129
+ phases: state.workflow?.phaseOrder || []
1130
+ },
1131
+ artifacts: state.artifacts || {},
1132
+ projectRootPolicy: state.projectRootPolicy || {},
1133
+ readinessGate: state.readinessGate || {},
1134
+ adversarialReview: state.adversarialReview || {},
1135
+ mopFlow: state.mopFlow || {},
1136
+ installer: state.installer || {},
1137
+ mode: state.mode,
1138
+ githubUrl: state.githubUrl,
1139
+ members: Object.keys(state.members || {}),
1140
+ agents: (state.agentRoster || []).map((agent) => ({
1141
+ name: agent.name,
1142
+ role: agent.role,
1143
+ owners: agent.owners
1144
+ })),
1145
+ autosync: {
1146
+ enabled: state.autosync?.enabled !== false,
1147
+ requireUserGitEmail: state.autosync?.requireUserGitEmail !== false
1148
+ },
1149
+ gitIdentities: Object.fromEntries(Object.entries(state.members || {}).map(([codename, member]) => [
1150
+ codename,
1151
+ {
1152
+ name: member.gitIdentity?.name || member.displayName || codename,
1153
+ email: member.gitIdentity?.email || member.github?.noreplyEmail || '',
1154
+ githubUsername: member.gitIdentity?.githubUsername || member.github?.username || ''
1155
+ }
1156
+ ]))
1157
+ }, null, 2));
1158
+ }
1159
+
1160
+ function main() {
1161
+ if (!existsSync(statePath)) {
1162
+ throw new Error(`Missing state file: ${statePath}`);
1163
+ }
1164
+ const [command, subcommand, ...rest] = process.argv.slice(2);
1165
+ const args = parseArgs(rest);
1166
+
1167
+ if (command === 'setup') return setup(parseArgs([subcommand, ...rest].filter(Boolean)));
1168
+ if (command === 'login') return login(parseArgs([subcommand, ...rest].filter(Boolean)));
1169
+ if (command === 'validate') return validate();
1170
+ if (command === 'status') return status();
1171
+ if (command === 'member' && subcommand === 'git-identity') return memberGitIdentity(args);
1172
+ if (command === 'agent' && subcommand === 'activate') return agentActivate(args);
1173
+ if (command === 'agent' && subcommand === 'use') return agentUse(args);
1174
+ if (command === 'agent' && subcommand === 'current') return agentCurrent(args);
1175
+ if (command === 'agent' && subcommand === 'require') return agentRequire(args);
1176
+ if (command === 'agent' && subcommand === 'route') return agentRoute(args);
1177
+ if (command === 'agent' && subcommand === 'list') return agentList();
1178
+ if (command === 'browser' && subcommand === 'preflight') return browserPreflight();
1179
+ if (command === 'memory' && subcommand === 'add') return memoryAdd(args);
1180
+ if (command === 'memory' && subcommand === 'brief') return memoryBrief(args);
1181
+ if (command === 'memory' && subcommand === 'restore') return memoryRestore(args);
1182
+
1183
+ console.log(`Usage:
1184
+ node .MOP/scripts/mop-core.mjs status
1185
+ node .MOP/scripts/mop-core.mjs validate
1186
+ node .MOP/scripts/mop-core.mjs setup --project-name NAME --name DISPLAY --codename CODE --password PASS --mode solo|team --conversation-language LANG --coding-language LANG [--git-email github-noreply|EMAIL] [--git-name NAME] [--github-username USER] [--github-url URL]
1187
+ node .MOP/scripts/mop-core.mjs login --codename CODE --password PASS
1188
+ node .MOP/scripts/mop-core.mjs member git-identity --actor CODE --name NAME [--email github-noreply|EMAIL] [--github-username USER]
1189
+ node .MOP/scripts/mop-core.mjs agent activate --actor CODE --role ROLE --title TITLE --name NAME
1190
+ node .MOP/scripts/mop-core.mjs agent use --actor CODE --name NAME
1191
+ node .MOP/scripts/mop-core.mjs agent current --actor CODE
1192
+ node .MOP/scripts/mop-core.mjs agent require --actor CODE [--role ROLE] [--title TITLE]
1193
+ node .MOP/scripts/mop-core.mjs agent route --actor CODE --task "task text"
1194
+ node .MOP/scripts/mop-core.mjs agent list
1195
+ node .MOP/scripts/mop-core.mjs browser preflight
1196
+ node .MOP/scripts/mop-core.mjs memory brief --actor CODE [--month YYYY-MM]
1197
+ node .MOP/scripts/mop-core.mjs memory add --actor CODE --kind conversation --summary "what happened"
1198
+ node .MOP/scripts/mop-core.mjs memory restore --actor CODE`);
1199
+ }
1200
+
1201
+ try {
1202
+ main();
1203
+ } catch (error) {
1204
+ console.error(error.message);
1205
+ process.exitCode = 1;
1206
+ }