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.
- package/.MOP/PROTOCOL.md +579 -0
- package/.MOP/STATE.json +668 -0
- package/.MOP/config/defaults.json +55 -0
- package/.MOP/config/team.json +8 -0
- package/.MOP/flow/ROADMAP.md +51 -0
- package/.MOP/flow/skill-manifest.json +645 -0
- package/.MOP/scripts/burhan-mop.mjs +291 -0
- package/.MOP/scripts/mop-auto-deploy.mjs +152 -0
- package/.MOP/scripts/mop-autosycn.mjs +790 -0
- package/.MOP/scripts/mop-core.mjs +1206 -0
- package/.MOP/scripts/mop-flow.mjs +396 -0
- package/.MOP/scripts/mop-smoke-test.mjs +76 -0
- package/.MOP/scripts/mop-workflow.mjs +348 -0
- package/.MOP/templates/artifacts/adversarial-review.md +33 -0
- package/.MOP/templates/artifacts/architecture.md +28 -0
- package/.MOP/templates/artifacts/decision-log.md +21 -0
- package/.MOP/templates/artifacts/handoff.md +21 -0
- package/.MOP/templates/artifacts/implementation-notes.md +21 -0
- package/.MOP/templates/artifacts/prd.md +29 -0
- package/.MOP/templates/artifacts/product-brief.md +30 -0
- package/.MOP/templates/artifacts/readiness-report.md +25 -0
- package/.MOP/templates/artifacts/release-notes.md +21 -0
- package/.MOP/templates/artifacts/review.md +21 -0
- package/.MOP/templates/artifacts/story.md +25 -0
- package/.MOP/templates/artifacts/ux-spec.md +32 -0
- package/.agents/AGENTS.md +85 -0
- package/.agents/skills/auto-deploy/SKILL.md +48 -0
- package/.agents/skills/autosycn/SKILL.md +75 -0
- package/.agents/skills/mop-flow/SKILL.md +53 -0
- package/.agents/skills/mop-help/SKILL.md +35 -0
- package/.agents/skills/ruflo-core/SKILL.md +36 -0
- package/.claude/agents/analysis/analyze-code-quality.md +179 -0
- package/.claude/agents/analysis/code-analyzer.md +210 -0
- package/.claude/agents/analysis/code-review/analyze-code-quality.md +179 -0
- package/.claude/agents/architecture/arch-system-design.md +157 -0
- package/.claude/agents/architecture/system-design/arch-system-design.md +155 -0
- package/.claude/agents/browser/browser-agent.yaml +182 -0
- package/.claude/agents/consensus/byzantine-coordinator.md +63 -0
- package/.claude/agents/consensus/crdt-synchronizer.md +997 -0
- package/.claude/agents/consensus/gossip-coordinator.md +63 -0
- package/.claude/agents/consensus/performance-benchmarker.md +851 -0
- package/.claude/agents/consensus/quorum-manager.md +823 -0
- package/.claude/agents/consensus/raft-manager.md +63 -0
- package/.claude/agents/consensus/security-manager.md +622 -0
- package/.claude/agents/core/planner.md +375 -0
- package/.claude/agents/custom/test-long-runner.md +44 -0
- package/.claude/agents/data/data-ml-model.md +445 -0
- package/.claude/agents/data/ml/data-ml-model.md +193 -0
- package/.claude/agents/development/backend/dev-backend-api.md +142 -0
- package/.claude/agents/development/dev-backend-api.md +345 -0
- package/.claude/agents/devops/ci-cd/ops-cicd-github.md +164 -0
- package/.claude/agents/devops/ops-cicd-github.md +165 -0
- package/.claude/agents/documentation/api-docs/docs-api-openapi.md +174 -0
- package/.claude/agents/documentation/docs-api-openapi.md +355 -0
- package/.claude/agents/flow-nexus/app-store.md +88 -0
- package/.claude/agents/flow-nexus/authentication.md +69 -0
- package/.claude/agents/flow-nexus/challenges.md +81 -0
- package/.claude/agents/flow-nexus/neural-network.md +88 -0
- package/.claude/agents/flow-nexus/payments.md +83 -0
- package/.claude/agents/flow-nexus/sandbox.md +76 -0
- package/.claude/agents/flow-nexus/swarm.md +76 -0
- package/.claude/agents/flow-nexus/user-tools.md +96 -0
- package/.claude/agents/flow-nexus/workflow.md +84 -0
- package/.claude/agents/github/code-review-swarm.md +377 -0
- package/.claude/agents/github/github-modes.md +173 -0
- package/.claude/agents/github/issue-tracker.md +576 -0
- package/.claude/agents/github/multi-repo-swarm.md +553 -0
- package/.claude/agents/github/pr-manager.md +438 -0
- package/.claude/agents/github/project-board-sync.md +509 -0
- package/.claude/agents/github/release-manager.md +605 -0
- package/.claude/agents/github/release-swarm.md +583 -0
- package/.claude/agents/github/repo-architect.md +398 -0
- package/.claude/agents/github/swarm-issue.md +573 -0
- package/.claude/agents/github/swarm-pr.md +428 -0
- package/.claude/agents/github/sync-coordinator.md +452 -0
- package/.claude/agents/github/workflow-automation.md +903 -0
- package/.claude/agents/goal/agent.md +816 -0
- package/.claude/agents/optimization/benchmark-suite.md +665 -0
- package/.claude/agents/optimization/load-balancer.md +431 -0
- package/.claude/agents/optimization/performance-monitor.md +672 -0
- package/.claude/agents/optimization/resource-allocator.md +674 -0
- package/.claude/agents/optimization/topology-optimizer.md +808 -0
- package/.claude/agents/payments/agentic-payments.md +126 -0
- package/.claude/agents/sona/sona-learning-optimizer.md +74 -0
- package/.claude/agents/sparc/architecture.md +699 -0
- package/.claude/agents/sparc/pseudocode.md +520 -0
- package/.claude/agents/sparc/refinement.md +802 -0
- package/.claude/agents/sparc/specification.md +478 -0
- package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +225 -0
- package/.claude/agents/specialized/spec-mobile-react-native.md +227 -0
- package/.claude/agents/sublinear/consensus-coordinator.md +338 -0
- package/.claude/agents/sublinear/matrix-optimizer.md +185 -0
- package/.claude/agents/sublinear/pagerank-analyzer.md +299 -0
- package/.claude/agents/sublinear/performance-optimizer.md +368 -0
- package/.claude/agents/sublinear/trading-predictor.md +246 -0
- package/.claude/agents/swarm/adaptive-coordinator.md +1127 -0
- package/.claude/agents/swarm/hierarchical-coordinator.md +710 -0
- package/.claude/agents/swarm/mesh-coordinator.md +963 -0
- package/.claude/agents/templates/automation-smart-agent.md +205 -0
- package/.claude/agents/templates/base-template-generator.md +289 -0
- package/.claude/agents/templates/coordinator-swarm-init.md +90 -0
- package/.claude/agents/templates/github-pr-manager.md +177 -0
- package/.claude/agents/templates/implementer-sparc-coder.md +259 -0
- package/.claude/agents/templates/memory-coordinator.md +187 -0
- package/.claude/agents/templates/orchestrator-task.md +139 -0
- package/.claude/agents/templates/performance-analyzer.md +199 -0
- package/.claude/agents/templates/sparc-coordinator.md +514 -0
- package/.claude/agents/testing/production-validator.md +395 -0
- package/.claude/agents/testing/tdd-london-swarm.md +244 -0
- package/.claude/agents/v3/aidefence-guardian.md +282 -0
- package/.claude/agents/v3/claims-authorizer.md +208 -0
- package/.claude/agents/v3/collective-intelligence-coordinator.md +993 -0
- package/.claude/agents/v3/ddd-domain-expert.md +220 -0
- package/.claude/agents/v3/injection-analyst.md +236 -0
- package/.claude/agents/v3/performance-engineer.md +1233 -0
- package/.claude/agents/v3/pii-detector.md +151 -0
- package/.claude/agents/v3/reasoningbank-learner.md +213 -0
- package/.claude/agents/v3/security-architect-aidefence.md +410 -0
- package/.claude/agents/v3/security-architect.md +867 -0
- package/.claude/agents/v3/swarm-memory-manager.md +157 -0
- package/.claude/agents/v3/v3-integration-architect.md +205 -0
- package/.claude/commands/agents/README.md +50 -0
- package/.claude/commands/agents/agent-capabilities.md +140 -0
- package/.claude/commands/agents/agent-coordination.md +28 -0
- package/.claude/commands/agents/agent-spawning.md +28 -0
- package/.claude/commands/agents/agent-types.md +216 -0
- package/.claude/commands/agents/health.md +139 -0
- package/.claude/commands/agents/list.md +100 -0
- package/.claude/commands/agents/logs.md +130 -0
- package/.claude/commands/agents/metrics.md +122 -0
- package/.claude/commands/agents/pool.md +127 -0
- package/.claude/commands/agents/spawn.md +140 -0
- package/.claude/commands/agents/status.md +115 -0
- package/.claude/commands/agents/stop.md +102 -0
- package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +54 -0
- package/.claude/commands/analysis/README.md +9 -0
- package/.claude/commands/analysis/bottleneck-detect.md +162 -0
- package/.claude/commands/analysis/performance-bottlenecks.md +59 -0
- package/.claude/commands/analysis/performance-report.md +25 -0
- package/.claude/commands/analysis/token-efficiency.md +45 -0
- package/.claude/commands/analysis/token-usage.md +25 -0
- package/.claude/commands/automation/README.md +9 -0
- package/.claude/commands/automation/auto-agent.md +122 -0
- package/.claude/commands/automation/self-healing.md +106 -0
- package/.claude/commands/automation/session-memory.md +90 -0
- package/.claude/commands/automation/smart-agents.md +73 -0
- package/.claude/commands/automation/smart-spawn.md +25 -0
- package/.claude/commands/automation/workflow-select.md +25 -0
- package/.claude/commands/claude-flow-help.md +103 -0
- package/.claude/commands/claude-flow-memory.md +107 -0
- package/.claude/commands/claude-flow-swarm.md +205 -0
- package/.claude/commands/coordination/README.md +9 -0
- package/.claude/commands/coordination/agent-spawn.md +25 -0
- package/.claude/commands/coordination/init.md +44 -0
- package/.claude/commands/coordination/orchestrate.md +43 -0
- package/.claude/commands/coordination/spawn.md +45 -0
- package/.claude/commands/coordination/swarm-init.md +85 -0
- package/.claude/commands/coordination/task-orchestrate.md +25 -0
- package/.claude/commands/github/README.md +11 -0
- package/.claude/commands/github/code-review-swarm.md +514 -0
- package/.claude/commands/github/code-review.md +25 -0
- package/.claude/commands/github/github-modes.md +147 -0
- package/.claude/commands/github/github-swarm.md +121 -0
- package/.claude/commands/github/issue-tracker.md +292 -0
- package/.claude/commands/github/issue-triage.md +25 -0
- package/.claude/commands/github/multi-repo-swarm.md +519 -0
- package/.claude/commands/github/pr-enhance.md +26 -0
- package/.claude/commands/github/pr-manager.md +170 -0
- package/.claude/commands/github/project-board-sync.md +471 -0
- package/.claude/commands/github/release-manager.md +340 -0
- package/.claude/commands/github/release-swarm.md +544 -0
- package/.claude/commands/github/repo-analyze.md +25 -0
- package/.claude/commands/github/repo-architect.md +367 -0
- package/.claude/commands/github/swarm-issue.md +485 -0
- package/.claude/commands/github/swarm-pr.md +288 -0
- package/.claude/commands/github/sync-coordinator.md +303 -0
- package/.claude/commands/github/workflow-automation.md +442 -0
- package/.claude/commands/hive-mind/README.md +17 -0
- package/.claude/commands/hive-mind/hive-mind-consensus.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-init.md +18 -0
- package/.claude/commands/hive-mind/hive-mind-memory.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-metrics.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-resume.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-sessions.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-spawn.md +21 -0
- package/.claude/commands/hive-mind/hive-mind-status.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-stop.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-wizard.md +8 -0
- package/.claude/commands/hive-mind/hive-mind.md +27 -0
- package/.claude/commands/hooks/README.md +11 -0
- package/.claude/commands/hooks/overview.md +58 -0
- package/.claude/commands/hooks/post-edit.md +117 -0
- package/.claude/commands/hooks/post-task.md +112 -0
- package/.claude/commands/hooks/pre-edit.md +113 -0
- package/.claude/commands/hooks/pre-task.md +111 -0
- package/.claude/commands/hooks/session-end.md +118 -0
- package/.claude/commands/hooks/setup.md +103 -0
- package/.claude/commands/memory/README.md +9 -0
- package/.claude/commands/memory/memory-persist.md +25 -0
- package/.claude/commands/memory/memory-search.md +25 -0
- package/.claude/commands/memory/memory-usage.md +25 -0
- package/.claude/commands/memory/neural.md +47 -0
- package/.claude/commands/monitoring/README.md +9 -0
- package/.claude/commands/monitoring/agent-metrics.md +25 -0
- package/.claude/commands/monitoring/agents.md +44 -0
- package/.claude/commands/monitoring/real-time-view.md +25 -0
- package/.claude/commands/monitoring/status.md +46 -0
- package/.claude/commands/monitoring/swarm-monitor.md +25 -0
- package/.claude/commands/optimization/README.md +9 -0
- package/.claude/commands/optimization/auto-topology.md +62 -0
- package/.claude/commands/optimization/cache-manage.md +25 -0
- package/.claude/commands/optimization/parallel-execute.md +25 -0
- package/.claude/commands/optimization/parallel-execution.md +50 -0
- package/.claude/commands/optimization/topology-optimize.md +25 -0
- package/.claude/commands/pair/README.md +261 -0
- package/.claude/commands/pair/commands.md +546 -0
- package/.claude/commands/pair/config.md +510 -0
- package/.claude/commands/pair/examples.md +512 -0
- package/.claude/commands/pair/modes.md +348 -0
- package/.claude/commands/pair/session.md +407 -0
- package/.claude/commands/pair/start.md +209 -0
- package/.claude/commands/sparc/analyzer.md +52 -0
- package/.claude/commands/sparc/architect.md +53 -0
- package/.claude/commands/sparc/ask.md +97 -0
- package/.claude/commands/sparc/batch-executor.md +54 -0
- package/.claude/commands/sparc/code.md +89 -0
- package/.claude/commands/sparc/coder.md +54 -0
- package/.claude/commands/sparc/debug.md +83 -0
- package/.claude/commands/sparc/debugger.md +54 -0
- package/.claude/commands/sparc/designer.md +53 -0
- package/.claude/commands/sparc/devops.md +109 -0
- package/.claude/commands/sparc/docs-writer.md +80 -0
- package/.claude/commands/sparc/documenter.md +54 -0
- package/.claude/commands/sparc/innovator.md +54 -0
- package/.claude/commands/sparc/integration.md +83 -0
- package/.claude/commands/sparc/mcp.md +117 -0
- package/.claude/commands/sparc/memory-manager.md +54 -0
- package/.claude/commands/sparc/optimizer.md +54 -0
- package/.claude/commands/sparc/orchestrator.md +132 -0
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -0
- package/.claude/commands/sparc/refinement-optimization-mode.md +83 -0
- package/.claude/commands/sparc/researcher.md +54 -0
- package/.claude/commands/sparc/reviewer.md +54 -0
- package/.claude/commands/sparc/security-review.md +80 -0
- package/.claude/commands/sparc/sparc-modes.md +174 -0
- package/.claude/commands/sparc/sparc.md +111 -0
- package/.claude/commands/sparc/spec-pseudocode.md +80 -0
- package/.claude/commands/sparc/supabase-admin.md +348 -0
- package/.claude/commands/sparc/swarm-coordinator.md +54 -0
- package/.claude/commands/sparc/tdd.md +54 -0
- package/.claude/commands/sparc/tester.md +54 -0
- package/.claude/commands/sparc/tutorial.md +79 -0
- package/.claude/commands/sparc/workflow-manager.md +54 -0
- package/.claude/commands/stream-chain/pipeline.md +121 -0
- package/.claude/commands/stream-chain/run.md +70 -0
- package/.claude/commands/swarm/README.md +15 -0
- package/.claude/commands/swarm/analysis.md +95 -0
- package/.claude/commands/swarm/development.md +96 -0
- package/.claude/commands/swarm/examples.md +168 -0
- package/.claude/commands/swarm/maintenance.md +102 -0
- package/.claude/commands/swarm/optimization.md +117 -0
- package/.claude/commands/swarm/research.md +136 -0
- package/.claude/commands/swarm/swarm-analysis.md +8 -0
- package/.claude/commands/swarm/swarm-background.md +8 -0
- package/.claude/commands/swarm/swarm-init.md +19 -0
- package/.claude/commands/swarm/swarm-modes.md +8 -0
- package/.claude/commands/swarm/swarm-monitor.md +8 -0
- package/.claude/commands/swarm/swarm-spawn.md +19 -0
- package/.claude/commands/swarm/swarm-status.md +8 -0
- package/.claude/commands/swarm/swarm-strategies.md +8 -0
- package/.claude/commands/swarm/swarm.md +87 -0
- package/.claude/commands/swarm/testing.md +131 -0
- package/.claude/commands/training/README.md +9 -0
- package/.claude/commands/training/model-update.md +25 -0
- package/.claude/commands/training/neural-patterns.md +108 -0
- package/.claude/commands/training/neural-train.md +75 -0
- package/.claude/commands/training/pattern-learn.md +25 -0
- package/.claude/commands/training/specialization.md +63 -0
- package/.claude/commands/truth/start.md +143 -0
- package/.claude/commands/verify/check.md +50 -0
- package/.claude/commands/verify/start.md +128 -0
- package/.claude/commands/workflows/README.md +9 -0
- package/.claude/commands/workflows/development.md +78 -0
- package/.claude/commands/workflows/research.md +63 -0
- package/.claude/commands/workflows/workflow-create.md +25 -0
- package/.claude/commands/workflows/workflow-execute.md +25 -0
- package/.claude/commands/workflows/workflow-export.md +25 -0
- package/.claude/helpers/README.md +97 -0
- package/.claude/helpers/adr-compliance.sh +186 -0
- package/.claude/helpers/auto-commit.sh +178 -0
- package/.claude/helpers/auto-memory-hook.mjs +368 -0
- package/.claude/helpers/checkpoint-manager.sh +251 -0
- package/.claude/helpers/daemon-manager.sh +252 -0
- package/.claude/helpers/ddd-tracker.sh +144 -0
- package/.claude/helpers/github-safe.js +156 -0
- package/.claude/helpers/github-setup.sh +45 -0
- package/.claude/helpers/guidance-hook.sh +13 -0
- package/.claude/helpers/guidance-hooks.sh +102 -0
- package/.claude/helpers/health-monitor.sh +108 -0
- package/.claude/helpers/hook-handler.cjs +286 -0
- package/.claude/helpers/intelligence.cjs +1031 -0
- package/.claude/helpers/learning-hooks.sh +329 -0
- package/.claude/helpers/learning-optimizer.sh +127 -0
- package/.claude/helpers/learning-service.mjs +1144 -0
- package/.claude/helpers/memory.js +83 -0
- package/.claude/helpers/metrics-db.mjs +488 -0
- package/.claude/helpers/pattern-consolidator.sh +86 -0
- package/.claude/helpers/perf-worker.sh +160 -0
- package/.claude/helpers/post-commit +16 -0
- package/.claude/helpers/pre-commit +26 -0
- package/.claude/helpers/quick-start.sh +19 -0
- package/.claude/helpers/router.js +105 -0
- package/.claude/helpers/ruflo-hook.cjs +59 -0
- package/.claude/helpers/security-scanner.sh +127 -0
- package/.claude/helpers/session.js +157 -0
- package/.claude/helpers/setup-mcp.sh +18 -0
- package/.claude/helpers/standard-checkpoint-hooks.sh +189 -0
- package/.claude/helpers/statusline-hook.sh +21 -0
- package/.claude/helpers/statusline.cjs +693 -0
- package/.claude/helpers/statusline.js +352 -0
- package/.claude/helpers/swarm-comms.sh +353 -0
- package/.claude/helpers/swarm-hooks.sh +761 -0
- package/.claude/helpers/swarm-monitor.sh +211 -0
- package/.claude/helpers/sync-v3-metrics.sh +245 -0
- package/.claude/helpers/update-v3-progress.sh +166 -0
- package/.claude/helpers/v3-quick-status.sh +58 -0
- package/.claude/helpers/v3.sh +111 -0
- package/.claude/helpers/validate-v3-config.sh +216 -0
- package/.claude/helpers/worker-manager.sh +170 -0
- package/.claude/settings.json +305 -0
- package/.claude/skills/agentdb-advanced/SKILL.md +550 -0
- package/.claude/skills/agentdb-learning/SKILL.md +545 -0
- package/.claude/skills/agentdb-memory-patterns/SKILL.md +339 -0
- package/.claude/skills/agentdb-optimization/SKILL.md +509 -0
- package/.claude/skills/agentdb-vector-search/SKILL.md +339 -0
- package/.claude/skills/auto-deploy/SKILL.md +31 -0
- package/.claude/skills/autosycn/SKILL.md +30 -0
- package/.claude/skills/browser/SKILL.md +204 -0
- package/.claude/skills/dual-mode/README.md +71 -0
- package/.claude/skills/dual-mode/dual-collect.md +103 -0
- package/.claude/skills/dual-mode/dual-coordinate.md +85 -0
- package/.claude/skills/dual-mode/dual-spawn.md +81 -0
- package/.claude/skills/flow-nexus-neural/SKILL.md +727 -0
- package/.claude/skills/flow-nexus-platform/SKILL.md +1154 -0
- package/.claude/skills/flow-nexus-swarm/SKILL.md +604 -0
- package/.claude/skills/github-code-review/SKILL.md +1125 -0
- package/.claude/skills/github-multi-repo/SKILL.md +862 -0
- package/.claude/skills/github-project-management/SKILL.md +1262 -0
- package/.claude/skills/github-release-management/SKILL.md +1064 -0
- package/.claude/skills/github-workflow-automation/SKILL.md +1047 -0
- package/.claude/skills/hooks-automation/SKILL.md +1201 -0
- package/.claude/skills/mop-flow/SKILL.md +53 -0
- package/.claude/skills/mop-help/SKILL.md +35 -0
- package/.claude/skills/pair-programming/SKILL.md +1202 -0
- package/.claude/skills/reasoningbank-agentdb/SKILL.md +446 -0
- package/.claude/skills/reasoningbank-intelligence/SKILL.md +201 -0
- package/.claude/skills/skill-builder/SKILL.md +910 -0
- package/.claude/skills/sparc-methodology/SKILL.md +1106 -0
- package/.claude/skills/stream-chain/SKILL.md +560 -0
- package/.claude/skills/swarm-advanced/SKILL.md +970 -0
- package/.claude/skills/swarm-orchestration/SKILL.md +179 -0
- package/.claude/skills/v3-cli-modernization/SKILL.md +872 -0
- package/.claude/skills/v3-core-implementation/SKILL.md +797 -0
- package/.claude/skills/v3-ddd-architecture/SKILL.md +442 -0
- package/.claude/skills/v3-integration-deep/SKILL.md +241 -0
- package/.claude/skills/v3-mcp-optimization/SKILL.md +777 -0
- package/.claude/skills/v3-memory-unification/SKILL.md +174 -0
- package/.claude/skills/v3-performance-optimization/SKILL.md +390 -0
- package/.claude/skills/v3-security-overhaul/SKILL.md +82 -0
- package/.claude/skills/v3-swarm-coordination/SKILL.md +340 -0
- package/.claude/skills/verification-quality/SKILL.md +691 -0
- package/.claude-flow/CAPABILITIES.md +406 -0
- package/.claude-flow/config.yaml +45 -0
- package/.claude-flow/metrics/learning.json +17 -0
- package/.claude-flow/metrics/swarm-activity.json +18 -0
- package/.claude-flow/metrics/v3-progress.json +26 -0
- package/.claude-flow/security/audit-status.json +8 -0
- package/.codex/config.toml +42 -0
- package/.gemini/settings.json +51 -0
- package/.mcp.json +58 -0
- package/AGENTS.md +180 -0
- package/CLAUDE.md +277 -0
- package/GEMINI.md +48 -0
- package/README.bm.md +171 -0
- package/README.md +170 -0
- package/bin/burhan-mop.mjs +2 -0
- package/bin/mop-core.mjs +2 -0
- package/bin/mop-flow.mjs +2 -0
- package/bin/mop-workflow.mjs +2 -0
- package/package.json +72 -0
|
@@ -0,0 +1,790 @@
|
|
|
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 { spawnSync } from 'node:child_process';
|
|
6
|
+
|
|
7
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const coreDir = resolve(here, '..');
|
|
9
|
+
const rootDir = resolve(coreDir, '..');
|
|
10
|
+
const statePath = join(coreDir, 'STATE.json');
|
|
11
|
+
|
|
12
|
+
function now() {
|
|
13
|
+
return new Date().toISOString();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function readState() {
|
|
17
|
+
return JSON.parse(readFileSync(statePath, 'utf8'));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function writeState(state) {
|
|
21
|
+
const tmp = `${statePath}.tmp`;
|
|
22
|
+
writeFileSync(tmp, `${JSON.stringify(state, null, 2)}\n`, 'utf8');
|
|
23
|
+
renameSync(tmp, statePath);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function parseArgs(argv) {
|
|
27
|
+
const out = { _: [] };
|
|
28
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
29
|
+
const item = argv[i];
|
|
30
|
+
if (!item.startsWith('--')) {
|
|
31
|
+
out._.push(item);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const key = item.slice(2);
|
|
35
|
+
const next = argv[i + 1];
|
|
36
|
+
if (!next || next.startsWith('--')) {
|
|
37
|
+
out[key] = true;
|
|
38
|
+
} else {
|
|
39
|
+
out[key] = next;
|
|
40
|
+
i += 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function requireArg(args, key) {
|
|
47
|
+
const value = args[key];
|
|
48
|
+
if (!value || value === true) throw new Error(`Missing --${key}`);
|
|
49
|
+
return String(value);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function runGit(args, options = {}) {
|
|
53
|
+
const result = spawnSync('git', args, {
|
|
54
|
+
cwd: rootDir,
|
|
55
|
+
env: { ...process.env, ...(options.env || {}) },
|
|
56
|
+
encoding: 'utf8'
|
|
57
|
+
});
|
|
58
|
+
if (result.status !== 0) {
|
|
59
|
+
const detail = `${result.stderr || result.stdout}`.trim();
|
|
60
|
+
throw new Error(`git ${args.join(' ')} failed${detail ? `: ${detail}` : ''}`);
|
|
61
|
+
}
|
|
62
|
+
return (result.stdout || '').trim();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function runGitAllowFailure(args, options = {}) {
|
|
66
|
+
return spawnSync('git', args, {
|
|
67
|
+
cwd: rootDir,
|
|
68
|
+
env: { ...process.env, ...(options.env || {}) },
|
|
69
|
+
encoding: 'utf8'
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function runOptional(command, args, options = {}) {
|
|
74
|
+
const result = spawnSync(command, args, {
|
|
75
|
+
cwd: rootDir,
|
|
76
|
+
env: { ...process.env, ...(options.env || {}) },
|
|
77
|
+
encoding: 'utf8'
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
ok: result.status === 0,
|
|
81
|
+
stdout: (result.stdout || '').trim(),
|
|
82
|
+
stderr: (result.stderr || '').trim()
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function activeAgentFor(state, actor) {
|
|
87
|
+
const activeId = state.activeAgents?.[actor];
|
|
88
|
+
if (!activeId) return null;
|
|
89
|
+
const agent = (state.agentRoster || []).find((item) => item.id === activeId || item.name === activeId);
|
|
90
|
+
if (!agent || !(agent.owners || []).includes(actor)) return null;
|
|
91
|
+
return agent;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function requireActiveAgent(state, actor, role = 'core', title = 'Core Agent') {
|
|
95
|
+
const agent = activeAgentFor(state, actor);
|
|
96
|
+
if (agent) return agent;
|
|
97
|
+
throw new Error([
|
|
98
|
+
`Agent diperlukan sebelum autosycn untuk ${actor}.`,
|
|
99
|
+
`Task ini perlukan ${title}. Agent ini belum ada nama lagi atau belum dipilih.`,
|
|
100
|
+
`Jalankan: node .MOP/scripts/mop-core.mjs agent activate --actor ${actor} --role ${role} --title "${title}" --name "<agent-name>"`
|
|
101
|
+
].join(' '));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function agentLedgerFields(agent) {
|
|
105
|
+
return agent ? {
|
|
106
|
+
agent: agent.name,
|
|
107
|
+
agentRole: agent.role,
|
|
108
|
+
agentId: agent.id
|
|
109
|
+
} : {};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function memoryPolicy(state) {
|
|
113
|
+
return state.memoryPolicy || {
|
|
114
|
+
enabled: true,
|
|
115
|
+
directory: '.MOP/memory',
|
|
116
|
+
sessionBrief: '.MOP/memory/SESSION_BRIEF.md',
|
|
117
|
+
monthlyPattern: 'YYYY-MM.jsonl',
|
|
118
|
+
recentLimit: 20
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function answerPolicy(state) {
|
|
123
|
+
return state.answerPolicy || {
|
|
124
|
+
requireVisibleAgent: true,
|
|
125
|
+
visibleAgentFormat: 'agent: <agent-name> (<agent-role>) to <user>'
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function monthKey(date = new Date()) {
|
|
130
|
+
return date.toISOString().slice(0, 7);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function memoryDirFor(state) {
|
|
134
|
+
return join(rootDir, memoryPolicy(state).directory || '.MOP/memory');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function monthlyMemoryPath(state, month = monthKey()) {
|
|
138
|
+
const policy = memoryPolicy(state);
|
|
139
|
+
const filename = (policy.monthlyPattern || 'YYYY-MM.jsonl').replace('YYYY-MM', month);
|
|
140
|
+
return join(memoryDirFor(state), filename);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function sessionBriefPath(state) {
|
|
144
|
+
return join(rootDir, memoryPolicy(state).sessionBrief || '.MOP/memory/SESSION_BRIEF.md');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function readJsonl(path) {
|
|
148
|
+
if (!existsSync(path)) return [];
|
|
149
|
+
return readFileSync(path, 'utf8')
|
|
150
|
+
.split(/\r?\n/)
|
|
151
|
+
.filter(Boolean)
|
|
152
|
+
.map((line) => {
|
|
153
|
+
try {
|
|
154
|
+
return JSON.parse(line);
|
|
155
|
+
} catch {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
.filter(Boolean);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function memoryMonths(state) {
|
|
163
|
+
const dir = memoryDirFor(state);
|
|
164
|
+
if (!existsSync(dir)) return [];
|
|
165
|
+
return readdirSync(dir)
|
|
166
|
+
.filter((name) => /^\d{4}-\d{2}\.jsonl$/.test(name))
|
|
167
|
+
.map((name) => name.replace(/\.jsonl$/, ''))
|
|
168
|
+
.sort();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function latestMemoryEntries(state, limit = memoryPolicy(state).recentLimit || 20) {
|
|
172
|
+
const months = memoryMonths(state);
|
|
173
|
+
const selected = months.length ? months.slice(-3) : [monthKey()];
|
|
174
|
+
return selected
|
|
175
|
+
.flatMap((month) => readJsonl(monthlyMemoryPath(state, month)))
|
|
176
|
+
.sort((a, b) => String(a.at || '').localeCompare(String(b.at || '')))
|
|
177
|
+
.slice(-limit);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function answerLineFor(state, actor, agent = activeAgentFor(state, actor)) {
|
|
181
|
+
if (!agent) return 'agent: <name> (<role>) to <user>';
|
|
182
|
+
return (answerPolicy(state).visibleAgentFormat || 'agent: <agent-name> (<agent-role>) to <user>')
|
|
183
|
+
.replace('<agent-name>', agent.name)
|
|
184
|
+
.replace('<agent-role>', agent.role)
|
|
185
|
+
.replace('<agent-title>', agent.title || agent.role)
|
|
186
|
+
.replace('<user>', actor || 'user');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function appendMonthlyMemory(state, actor, kind, summary, agent = activeAgentFor(state, actor)) {
|
|
190
|
+
if (memoryPolicy(state).enabled === false) return;
|
|
191
|
+
const entry = { at: now(), actor, ...agentLedgerFields(agent), kind, summary };
|
|
192
|
+
const monthlyPath = monthlyMemoryPath(state);
|
|
193
|
+
mkdirSync(dirname(monthlyPath), { recursive: true });
|
|
194
|
+
writeFileSync(monthlyPath, `${JSON.stringify(entry)}\n`, { encoding: 'utf8', flag: 'a' });
|
|
195
|
+
writeSessionBrief(state, actor);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function writeSessionBrief(state, actor) {
|
|
199
|
+
const path = sessionBriefPath(state);
|
|
200
|
+
const agent = activeAgentFor(state, actor);
|
|
201
|
+
const entries = latestMemoryEntries(state, memoryPolicy(state).recentLimit || 20);
|
|
202
|
+
const lines = [
|
|
203
|
+
'# MOP Session Brief',
|
|
204
|
+
'',
|
|
205
|
+
`Updated: ${now()}`,
|
|
206
|
+
`Actor: ${actor || state.activeMember || 'unknown'}`,
|
|
207
|
+
`Active agent: ${agent ? `${agent.name} (${agent.role})` : 'none'}`,
|
|
208
|
+
`Current month: ${monthKey()}`,
|
|
209
|
+
'',
|
|
210
|
+
'## Required Session Flow',
|
|
211
|
+
'',
|
|
212
|
+
'1. Read `.MOP/STATE.json` and follow `.MOP/PROTOCOL.md`.',
|
|
213
|
+
'2. Restore memory with `node .MOP/scripts/mop-core.mjs memory brief --actor <codename>`.',
|
|
214
|
+
'3. Run `agent route` for the user task before answering.',
|
|
215
|
+
`4. Start every authenticated answer with: \`${answerLineFor(state, actor, agent)}\``,
|
|
216
|
+
'5. Save a one-line memory after meaningful work.',
|
|
217
|
+
'',
|
|
218
|
+
'## Recent Memory',
|
|
219
|
+
'',
|
|
220
|
+
...entries.map((entry) => {
|
|
221
|
+
const who = entry.agent ? `${entry.agent} (${entry.agentRole || 'agent'})` : entry.actor;
|
|
222
|
+
return `- ${entry.at} - ${who}: ${entry.summary}`;
|
|
223
|
+
})
|
|
224
|
+
];
|
|
225
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
226
|
+
writeFileSync(path, `${lines.join('\n')}\n`, 'utf8');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function appendLedger(state, actor, kind, summary, agent = activeAgentFor(state, actor)) {
|
|
230
|
+
state.ledger ||= [];
|
|
231
|
+
state.ledger.push({ at: now(), actor, ...agentLedgerFields(agent), kind, summary });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function guardianConfig(state) {
|
|
235
|
+
return state.autosync?.mergeGuardian || {
|
|
236
|
+
enabled: true,
|
|
237
|
+
name: 'BURHAN-MOP',
|
|
238
|
+
autoReviewAfterPush: true,
|
|
239
|
+
decision: 'required',
|
|
240
|
+
checks: {}
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function getMember(state, actor) {
|
|
245
|
+
const member = state.members?.[actor];
|
|
246
|
+
if (!member) throw new Error(`Unknown actor: ${actor}`);
|
|
247
|
+
return member;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function githubIdentityPolicy(state) {
|
|
251
|
+
return state.autosync?.githubIdentity || {
|
|
252
|
+
requireMatchedGhUser: true,
|
|
253
|
+
useNoreplyForMemberCommits: true,
|
|
254
|
+
noreplyFormat: 'id-plus-login'
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function currentGhUser() {
|
|
259
|
+
const result = runOptional('gh', ['api', 'user', '--jq', '{login:.login,id:.id,email:.email}']);
|
|
260
|
+
if (!result.ok) return null;
|
|
261
|
+
try {
|
|
262
|
+
return JSON.parse(result.stdout || '{}');
|
|
263
|
+
} catch {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function githubNoreplyEmail(user) {
|
|
269
|
+
if (!user?.login || !user?.id) return '';
|
|
270
|
+
return `${user.id}+${user.login}@users.noreply.github.com`;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function identityFor(state, actor) {
|
|
274
|
+
const member = getMember(state, actor);
|
|
275
|
+
const identity = member.gitIdentity || {};
|
|
276
|
+
const policy = githubIdentityPolicy(state);
|
|
277
|
+
const gh = currentGhUser();
|
|
278
|
+
const name = identity.name || member.displayName || actor;
|
|
279
|
+
const githubUsername = identity.githubUsername || member.github?.username || gh?.login || '';
|
|
280
|
+
if (gh?.login && githubUsername && policy.requireMatchedGhUser !== false && gh.login.toLowerCase() !== githubUsername.toLowerCase()) {
|
|
281
|
+
throw new Error(`GitHub CLI authenticated as ${gh.login}, expected ${githubUsername}. Refusing to commit or push as the wrong user.`);
|
|
282
|
+
}
|
|
283
|
+
let email = identity.email || member.github?.noreplyEmail || '';
|
|
284
|
+
if (policy.useNoreplyForMemberCommits !== false) {
|
|
285
|
+
email = githubNoreplyEmail(gh);
|
|
286
|
+
if (!email) {
|
|
287
|
+
throw new Error('GitHub noreply identity is required for member commits. Run gh auth login as the real user, or set autosync.githubIdentity.useNoreplyForMemberCommits=false.');
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (!email && state.autosync?.requireUserGitEmail !== false) {
|
|
291
|
+
throw new Error([
|
|
292
|
+
`Missing git email for ${actor}.`,
|
|
293
|
+
'Set a GitHub-verified email or let MOP derive GitHub noreply from gh:',
|
|
294
|
+
`node .MOP/scripts/mop-core.mjs member git-identity --actor ${actor} --name "${name}" --email github-noreply [--github-username "<username>"]`
|
|
295
|
+
].join(' '));
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
name,
|
|
299
|
+
email,
|
|
300
|
+
githubUsername,
|
|
301
|
+
githubUserId: gh?.login?.toLowerCase() === githubUsername.toLowerCase() ? gh.id : identity.githubUserId,
|
|
302
|
+
emailSource: policy.useNoreplyForMemberCommits !== false ? 'github-noreply' : (identity.emailSource || 'manual')
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function identityEnv(identity) {
|
|
307
|
+
return {
|
|
308
|
+
GIT_AUTHOR_NAME: identity.name,
|
|
309
|
+
GIT_AUTHOR_EMAIL: identity.email,
|
|
310
|
+
GIT_COMMITTER_NAME: identity.name,
|
|
311
|
+
GIT_COMMITTER_EMAIL: identity.email
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function mergeIdentityFor(state, actorIdentity) {
|
|
316
|
+
const guardian = guardianConfig(state);
|
|
317
|
+
const guardianIdentity = guardian.gitIdentity || {};
|
|
318
|
+
return {
|
|
319
|
+
name: guardianIdentity.name || guardian.name || 'BURHAN-MOP',
|
|
320
|
+
email: guardianIdentity.email || 'burhan-mop@users.noreply.github.com',
|
|
321
|
+
githubUsername: guardianIdentity.githubUsername || 'BURHAN-MOP'
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function ensureGitRepo() {
|
|
326
|
+
if (!existsSync(join(rootDir, '.git'))) {
|
|
327
|
+
throw new Error(`Not a git repository: ${rootDir}`);
|
|
328
|
+
}
|
|
329
|
+
runGit(['rev-parse', '--show-toplevel']);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function ensureGitRepoForInit() {
|
|
333
|
+
if (!existsSync(join(rootDir, '.git'))) {
|
|
334
|
+
const init = runGitAllowFailure(['init', '-b', 'main']);
|
|
335
|
+
if (init.status !== 0) {
|
|
336
|
+
runGit(['init']);
|
|
337
|
+
runGit(['branch', '-M', 'main']);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
runGit(['rev-parse', '--show-toplevel']);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function remoteBranchExists(branch) {
|
|
344
|
+
const result = runOptional('git', ['ls-remote', '--exit-code', '--heads', 'origin', branch]);
|
|
345
|
+
return result.ok;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function localBranchExists(branch) {
|
|
349
|
+
return runOptional('git', ['rev-parse', '--verify', branch]).ok;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function configureLocalIdentity(identity) {
|
|
353
|
+
runGit(['config', '--local', 'user.name', identity.name]);
|
|
354
|
+
runGit(['config', '--local', 'user.email', identity.email]);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function configureRemote(url, replaceRemote = false) {
|
|
358
|
+
const existing = runOptional('git', ['remote', 'get-url', 'origin']);
|
|
359
|
+
if (existing.ok) {
|
|
360
|
+
if (url && existing.stdout !== url) {
|
|
361
|
+
if (!replaceRemote) {
|
|
362
|
+
throw new Error(`origin already points to ${existing.stdout}. Re-run with --replace-remote to set ${url}.`);
|
|
363
|
+
}
|
|
364
|
+
runGit(['remote', 'set-url', 'origin', url]);
|
|
365
|
+
return url;
|
|
366
|
+
}
|
|
367
|
+
return existing.stdout;
|
|
368
|
+
}
|
|
369
|
+
if (!url) throw new Error('Missing --url and no origin remote is configured.');
|
|
370
|
+
runGit(['remote', 'add', 'origin', url]);
|
|
371
|
+
return url;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function verifyGhUser(identity, state) {
|
|
375
|
+
const policy = githubIdentityPolicy(state);
|
|
376
|
+
if (state.autosync?.verifyGhUserWhenConfigured === false && policy.requireMatchedGhUser === false) return 'skipped';
|
|
377
|
+
const gh = currentGhUser();
|
|
378
|
+
if (!gh?.login) {
|
|
379
|
+
throw new Error('GitHub username is configured, but gh could not verify the active account. Run gh auth login as the real user or set autosync.verifyGhUserWhenConfigured=false for SSH-only workflows.');
|
|
380
|
+
}
|
|
381
|
+
if (identity.githubUsername && gh.login.toLowerCase() !== identity.githubUsername.toLowerCase()) {
|
|
382
|
+
throw new Error(`GitHub CLI authenticated as ${gh.login}, expected ${identity.githubUsername}. Refusing to push as the wrong account.`);
|
|
383
|
+
}
|
|
384
|
+
return `verified:${gh.login}:${githubNoreplyEmail(gh) || 'email-unavailable'}`;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function runProjectCommand(command, env) {
|
|
388
|
+
if (!command) return 'skipped';
|
|
389
|
+
const result = spawnSync(command, {
|
|
390
|
+
cwd: rootDir,
|
|
391
|
+
env: { ...process.env, ...env },
|
|
392
|
+
encoding: 'utf8',
|
|
393
|
+
shell: true
|
|
394
|
+
});
|
|
395
|
+
if (result.status !== 0) {
|
|
396
|
+
const detail = `${result.stderr || result.stdout}`.trim();
|
|
397
|
+
throw new Error(`Command failed: ${command}${detail ? `: ${detail}` : ''}`);
|
|
398
|
+
}
|
|
399
|
+
return 'passed';
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function highConfidenceSecretPattern() {
|
|
403
|
+
return /(AIza[0-9A-Za-z_-]{20,}|ghp_[0-9A-Za-z_]{20,}|github_pat_[0-9A-Za-z_]{20,}|sk-[A-Za-z0-9_-]{20,}|xox[baprs]-[0-9A-Za-z-]{20,})/;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function scanDiffForHighConfidenceSecrets(diffArgs, label) {
|
|
407
|
+
const diff = runOptional('git', ['diff', '--no-ext-diff', ...diffArgs, '--', '.']);
|
|
408
|
+
if (!diff.ok || !diff.stdout) return 'passed';
|
|
409
|
+
if (!highConfidenceSecretPattern().test(diff.stdout)) return 'passed';
|
|
410
|
+
const names = runOptional('git', ['diff', '--name-only', ...diffArgs, '--', '.']);
|
|
411
|
+
const changedFiles = names.stdout || 'changed files unavailable';
|
|
412
|
+
throw new Error(`Possible high-confidence secret found in ${label}:\n${changedFiles}`);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function validateStateIfPresent() {
|
|
416
|
+
if (!existsSync(join(rootDir, '.MOP', 'STATE.json'))) return 'skipped';
|
|
417
|
+
const result = spawnSync('node', ['.MOP/scripts/mop-core.mjs', 'validate'], {
|
|
418
|
+
cwd: rootDir,
|
|
419
|
+
encoding: 'utf8'
|
|
420
|
+
});
|
|
421
|
+
if (result.status !== 0) {
|
|
422
|
+
const detail = `${result.stderr || result.stdout}`.trim();
|
|
423
|
+
throw new Error(`State validation failed${detail ? `: ${detail}` : ''}`);
|
|
424
|
+
}
|
|
425
|
+
return 'passed';
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function guardianReject(message) {
|
|
429
|
+
throw new Error(`BURHAN-MOP rejected merge: ${message}`);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function guardianReview(state, sourceRef, env) {
|
|
433
|
+
const guardian = guardianConfig(state);
|
|
434
|
+
const checks = guardian.checks || {};
|
|
435
|
+
const mainBranch = state.autosync?.targetMainBranch || 'main';
|
|
436
|
+
const report = {
|
|
437
|
+
guardian: guardian.name || 'BURHAN-MOP',
|
|
438
|
+
source: sourceRef,
|
|
439
|
+
main: mainBranch,
|
|
440
|
+
checks: {}
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
if (checks.workingTreeCleanAfterCommit !== false) {
|
|
444
|
+
const dirty = runGit(['status', '--porcelain']);
|
|
445
|
+
if (dirty) guardianReject('working tree is not clean before merge review');
|
|
446
|
+
report.checks.workingTreeCleanAfterCommit = 'passed';
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
runGit(['fetch', 'origin']);
|
|
450
|
+
if (checks.branchUpToDateWithMain !== false) {
|
|
451
|
+
const ancestor = runOptional('git', ['merge-base', '--is-ancestor', `origin/${mainBranch}`, sourceRef]);
|
|
452
|
+
if (!ancestor.ok) {
|
|
453
|
+
guardianReject(`${sourceRef} is not up to date with origin/${mainBranch}. Run preflight first.`);
|
|
454
|
+
}
|
|
455
|
+
report.checks.branchUpToDateWithMain = 'passed';
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (checks.secretScan !== false) {
|
|
459
|
+
const pattern = '(AIza|ghp_|github_pat_|sk-[A-Za-z0-9]|xox[baprs]-|password\\s*[:=]|secret\\s*[:=]|api[_-]?key\\s*[:=]|token\\s*[:=])';
|
|
460
|
+
const scan = runOptional('git', ['diff', '--name-only', '-G', pattern, `origin/${mainBranch}..${sourceRef}`, '--', '.']);
|
|
461
|
+
if (scan.ok && scan.stdout) {
|
|
462
|
+
guardianReject(`possible secret pattern found in changed files:\n${scan.stdout}`);
|
|
463
|
+
}
|
|
464
|
+
report.checks.secretScan = 'passed';
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
report.checks.stateValid = checks.stateValid === false ? 'skipped-before-merge' : 'pending-after-merge';
|
|
468
|
+
report.checks.testCommand = checks.testCommand ? 'pending-after-merge' : 'skipped';
|
|
469
|
+
report.checks.buildCommand = checks.buildCommand ? 'pending-after-merge' : 'skipped';
|
|
470
|
+
return report;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function commitIfNeeded(reason, env, state) {
|
|
474
|
+
runGit(['add', '-A']);
|
|
475
|
+
const status = runGit(['status', '--porcelain']);
|
|
476
|
+
if (!status) return 'nothing-to-commit';
|
|
477
|
+
if (state?.autosync?.secretScanBeforeCommit !== false) {
|
|
478
|
+
scanDiffForHighConfidenceSecrets(['--cached'], 'staged changes');
|
|
479
|
+
}
|
|
480
|
+
runGit(['commit', '-m', reason], { env });
|
|
481
|
+
return runGit(['rev-parse', '--short', 'HEAD']);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function currentBranch() {
|
|
485
|
+
return runGit(['branch', '--show-current']);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function workBranchFor(state, actor) {
|
|
489
|
+
const mainBranch = state.autosync?.targetMainBranch || 'main';
|
|
490
|
+
const prefix = state.autosync?.workBranchPrefix || 'dev';
|
|
491
|
+
return state.mode === 'team' ? `${prefix}/${actor}` : mainBranch;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function ensureBranch(branch) {
|
|
495
|
+
runGit(['fetch', 'origin']);
|
|
496
|
+
if (localBranchExists(branch)) {
|
|
497
|
+
runGit(['checkout', branch]);
|
|
498
|
+
} else if (remoteBranchExists(branch)) {
|
|
499
|
+
runGit(['checkout', '-B', branch, `origin/${branch}`]);
|
|
500
|
+
} else {
|
|
501
|
+
runGit(['checkout', '-B', branch]);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
function syncMainFromOrigin(state, env) {
|
|
506
|
+
const mainBranch = state.autosync?.targetMainBranch || 'main';
|
|
507
|
+
runGit(['fetch', 'origin']);
|
|
508
|
+
if (localBranchExists(mainBranch)) {
|
|
509
|
+
runGit(['checkout', mainBranch]);
|
|
510
|
+
} else if (remoteBranchExists(mainBranch)) {
|
|
511
|
+
runGit(['checkout', '-B', mainBranch, `origin/${mainBranch}`]);
|
|
512
|
+
} else {
|
|
513
|
+
runGit(['checkout', '-B', mainBranch]);
|
|
514
|
+
}
|
|
515
|
+
if (remoteBranchExists(mainBranch)) {
|
|
516
|
+
runGit(['pull', '--ff-only', 'origin', mainBranch], { env });
|
|
517
|
+
}
|
|
518
|
+
return mainBranch;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function preflight(args) {
|
|
522
|
+
ensureGitRepo();
|
|
523
|
+
const state = readState();
|
|
524
|
+
if (!state.initialized) throw new Error('MOP is not initialized.');
|
|
525
|
+
const actor = requireArg(args, 'actor');
|
|
526
|
+
const agent = requireActiveAgent(state, actor);
|
|
527
|
+
const identity = identityFor(state, actor);
|
|
528
|
+
const env = identityEnv(identity);
|
|
529
|
+
const ghStatus = verifyGhUser(identity, state);
|
|
530
|
+
configureLocalIdentity(identity);
|
|
531
|
+
|
|
532
|
+
const dirty = runGit(['status', '--porcelain']);
|
|
533
|
+
if (dirty) {
|
|
534
|
+
throw new Error('Working tree has uncommitted changes. Run autosycn or commit/stash before preflight.');
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
const mainBranch = syncMainFromOrigin(state, env);
|
|
538
|
+
const workBranch = workBranchFor(state, actor);
|
|
539
|
+
if (workBranch !== mainBranch) {
|
|
540
|
+
if (localBranchExists(workBranch)) {
|
|
541
|
+
runGit(['checkout', workBranch]);
|
|
542
|
+
} else if (remoteBranchExists(workBranch)) {
|
|
543
|
+
runGit(['checkout', '-B', workBranch, `origin/${workBranch}`]);
|
|
544
|
+
} else {
|
|
545
|
+
runGit(['checkout', '-B', workBranch, mainBranch]);
|
|
546
|
+
}
|
|
547
|
+
const merge = runGitAllowFailure(['merge', '--no-edit', mainBranch], { env });
|
|
548
|
+
if (merge.status !== 0) {
|
|
549
|
+
runOptional('git', ['merge', '--abort']);
|
|
550
|
+
const detail = `${merge.stderr || merge.stdout}`.trim();
|
|
551
|
+
throw new Error(`Could not sync ${workBranch} with ${mainBranch}. Merge aborted.${detail ? ` ${detail}` : ''}`);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
console.log(JSON.stringify({
|
|
556
|
+
ok: true,
|
|
557
|
+
actor,
|
|
558
|
+
agent: agent.name,
|
|
559
|
+
ghStatus,
|
|
560
|
+
mainBranch,
|
|
561
|
+
workBranch,
|
|
562
|
+
head: runGit(['rev-parse', '--short', 'HEAD'])
|
|
563
|
+
}, null, 2));
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function saveMemory(actor, summary, kind = 'conversation') {
|
|
567
|
+
const state = readState();
|
|
568
|
+
const agent = requireActiveAgent(state, actor);
|
|
569
|
+
appendLedger(state, actor, 'memory', summary, agent);
|
|
570
|
+
appendMonthlyMemory(state, actor, kind, summary, agent);
|
|
571
|
+
writeState(state);
|
|
572
|
+
return state;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function push(args) {
|
|
576
|
+
ensureGitRepo();
|
|
577
|
+
const state = readState();
|
|
578
|
+
if (!state.initialized) throw new Error('MOP is not initialized.');
|
|
579
|
+
const actor = requireArg(args, 'actor');
|
|
580
|
+
const agent = requireActiveAgent(state, actor);
|
|
581
|
+
const reason = String(args.reason || 'MOP autosycn');
|
|
582
|
+
const identity = identityFor(state, actor);
|
|
583
|
+
const env = identityEnv(identity);
|
|
584
|
+
const ghStatus = verifyGhUser(identity, state);
|
|
585
|
+
configureLocalIdentity(identity);
|
|
586
|
+
|
|
587
|
+
const target = workBranchFor(state, actor);
|
|
588
|
+
const before = currentBranch();
|
|
589
|
+
const dirty = runGit(['status', '--porcelain']);
|
|
590
|
+
if (state.mode === 'team' && before !== target && dirty) {
|
|
591
|
+
throw new Error(`Team autosycn must commit from ${target}. Run preflight before starting work: node .MOP/scripts/mop-autosycn.mjs preflight --actor ${actor}`);
|
|
592
|
+
}
|
|
593
|
+
ensureBranch(target);
|
|
594
|
+
const commit = commitIfNeeded(reason, env, state);
|
|
595
|
+
runGit(['push', '-u', 'origin', target], { env });
|
|
596
|
+
|
|
597
|
+
console.log(JSON.stringify({
|
|
598
|
+
ok: true,
|
|
599
|
+
actor,
|
|
600
|
+
agent: agent.name,
|
|
601
|
+
author: `${identity.name} <${identity.email}>`,
|
|
602
|
+
ghStatus,
|
|
603
|
+
branch: target,
|
|
604
|
+
previousBranch: before,
|
|
605
|
+
commit
|
|
606
|
+
}, null, 2));
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
function init(args) {
|
|
610
|
+
const state = readState();
|
|
611
|
+
if (!state.initialized) throw new Error('MOP is not initialized.');
|
|
612
|
+
const actor = requireArg(args, 'actor');
|
|
613
|
+
const agent = requireActiveAgent(state, actor);
|
|
614
|
+
if (actor !== state.ownerCodename) throw new Error('Only the owner can initialize autosycn.');
|
|
615
|
+
const identity = identityFor(state, actor);
|
|
616
|
+
const env = identityEnv(identity);
|
|
617
|
+
const url = String(args.url || state.githubUrl || '');
|
|
618
|
+
const ghStatus = verifyGhUser(identity, state);
|
|
619
|
+
|
|
620
|
+
ensureGitRepoForInit();
|
|
621
|
+
configureLocalIdentity(identity);
|
|
622
|
+
const remote = configureRemote(url, args['replace-remote'] === true);
|
|
623
|
+
runGit(['checkout', '-B', state.autosync?.targetMainBranch || 'main']);
|
|
624
|
+
|
|
625
|
+
appendLedger(state, actor, 'autosycn-init', `Initialized autosycn remote ${remote}.`, agent);
|
|
626
|
+
if (url) state.githubUrl = url;
|
|
627
|
+
writeState(state);
|
|
628
|
+
const commit = commitIfNeeded('Initialize MOP autosycn baseline', env, state);
|
|
629
|
+
runGit(['push', '-u', 'origin', state.autosync?.targetMainBranch || 'main'], { env });
|
|
630
|
+
|
|
631
|
+
console.log(JSON.stringify({
|
|
632
|
+
ok: true,
|
|
633
|
+
actor,
|
|
634
|
+
agent: agent.name,
|
|
635
|
+
author: `${identity.name} <${identity.email}>`,
|
|
636
|
+
ghStatus,
|
|
637
|
+
remote,
|
|
638
|
+
branch: state.autosync?.targetMainBranch || 'main',
|
|
639
|
+
commit
|
|
640
|
+
}, null, 2));
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function mergeMain(args) {
|
|
644
|
+
ensureGitRepo();
|
|
645
|
+
const state = readState();
|
|
646
|
+
if (!state.initialized) throw new Error('MOP is not initialized.');
|
|
647
|
+
const actor = requireArg(args, 'actor');
|
|
648
|
+
const agent = requireActiveAgent(state, actor);
|
|
649
|
+
if (state.autosync?.requireOwnerForMerge === true && actor !== state.ownerCodename) {
|
|
650
|
+
throw new Error('Only the owner can request BURHAN-MOP merge to main.');
|
|
651
|
+
}
|
|
652
|
+
const from = String(args.from || actor);
|
|
653
|
+
const prefix = state.autosync?.workBranchPrefix || 'dev';
|
|
654
|
+
const reason = String(args.reason || `Merge ${prefix}/${from}`);
|
|
655
|
+
const identity = identityFor(state, actor);
|
|
656
|
+
const mergeIdentity = mergeIdentityFor(state, identity);
|
|
657
|
+
const env = identityEnv(mergeIdentity);
|
|
658
|
+
const ghStatus = verifyGhUser(identity, state);
|
|
659
|
+
configureLocalIdentity(mergeIdentity);
|
|
660
|
+
|
|
661
|
+
const mainBranch = state.autosync?.targetMainBranch || 'main';
|
|
662
|
+
const source = `origin/${prefix}/${from}`;
|
|
663
|
+
const guardian = guardianConfig(state);
|
|
664
|
+
const review = guardian.enabled === false ? { guardian: 'disabled', checks: {} } : guardianReview(state, source, env);
|
|
665
|
+
runGit(['checkout', mainBranch]);
|
|
666
|
+
runGit(['pull', 'origin', mainBranch], { env });
|
|
667
|
+
runGit(['fetch', 'origin']);
|
|
668
|
+
const merge = runGitAllowFailure(['merge', '--no-ff', '--no-commit', source], { env });
|
|
669
|
+
if (merge.status !== 0) {
|
|
670
|
+
const conflicted = runOptional('git', ['diff', '--name-only', '--diff-filter=U']);
|
|
671
|
+
const files = conflicted.stdout.split(/\r?\n/).filter(Boolean);
|
|
672
|
+
if (files.length === 1 && files[0].replaceAll('\\', '/') === '.MOP/STATE.json') {
|
|
673
|
+
runGit(['checkout', '--ours', '--', '.MOP/STATE.json']);
|
|
674
|
+
runGit(['add', '.MOP/STATE.json']);
|
|
675
|
+
} else {
|
|
676
|
+
runOptional('git', ['merge', '--abort']);
|
|
677
|
+
const detail = `${merge.stderr || merge.stdout}`.trim();
|
|
678
|
+
guardianReject(`merge conflict outside STATE.json. Merge aborted.${detail ? ` ${detail}` : ''}`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
try {
|
|
682
|
+
if (guardian.checks?.stateValid !== false) review.checks.stateValid = validateStateIfPresent();
|
|
683
|
+
review.checks.testCommand = runProjectCommand(guardian.checks?.testCommand || '', env);
|
|
684
|
+
review.checks.buildCommand = runProjectCommand(guardian.checks?.buildCommand || '', env);
|
|
685
|
+
|
|
686
|
+
if (existsSync(statePath)) {
|
|
687
|
+
const mergedState = readState();
|
|
688
|
+
appendLedger(mergedState, guardian.name || 'BURHAN-MOP', 'merge-approved', `${source} approved and merged to ${mainBranch}.`);
|
|
689
|
+
writeState(mergedState);
|
|
690
|
+
runGit(['add', '.MOP/STATE.json']);
|
|
691
|
+
}
|
|
692
|
+
runGit(['commit', '-m', reason], { env });
|
|
693
|
+
} catch (error) {
|
|
694
|
+
runOptional('git', ['merge', '--abort']);
|
|
695
|
+
guardianReject(error.message);
|
|
696
|
+
}
|
|
697
|
+
runGit(['push', 'origin', mainBranch], { env });
|
|
698
|
+
|
|
699
|
+
console.log(JSON.stringify({
|
|
700
|
+
ok: true,
|
|
701
|
+
actor,
|
|
702
|
+
agent: agent.name,
|
|
703
|
+
guardian: review.guardian,
|
|
704
|
+
author: `${mergeIdentity.name} <${mergeIdentity.email}>`,
|
|
705
|
+
ghStatus,
|
|
706
|
+
merged: source,
|
|
707
|
+
branch: mainBranch,
|
|
708
|
+
review: review.checks,
|
|
709
|
+
head: runGit(['rev-parse', '--short', 'HEAD'])
|
|
710
|
+
}, null, 2));
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function runAll(args) {
|
|
714
|
+
const actor = requireArg(args, 'actor');
|
|
715
|
+
const reason = String(args.reason || 'MOP autosycn');
|
|
716
|
+
saveMemory(actor, reason);
|
|
717
|
+
push({ ...args, actor, reason });
|
|
718
|
+
const state = readState();
|
|
719
|
+
const guardian = guardianConfig(state);
|
|
720
|
+
if (state.mode === 'team' && state.autosync?.autoMergeToMain !== false && guardian.autoReviewAfterPush !== false) {
|
|
721
|
+
const prefix = state.autosync?.workBranchPrefix || 'dev';
|
|
722
|
+
mergeMain({ actor, from: actor, reason: `${guardian.name || 'BURHAN-MOP'} approved merge ${prefix}/${actor}: ${reason}` });
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
function status() {
|
|
727
|
+
const state = readState();
|
|
728
|
+
console.log(JSON.stringify({
|
|
729
|
+
enabled: state.autosync?.enabled !== false,
|
|
730
|
+
main: state.autosync?.targetMainBranch || 'main',
|
|
731
|
+
workBranchPrefix: state.autosync?.workBranchPrefix || 'dev',
|
|
732
|
+
autoMergeToMain: state.autosync?.autoMergeToMain !== false,
|
|
733
|
+
secretScanBeforeCommit: state.autosync?.secretScanBeforeCommit !== false,
|
|
734
|
+
mergeGuardian: guardianConfig(state),
|
|
735
|
+
githubIdentity: githubIdentityPolicy(state),
|
|
736
|
+
preflightBeforeWork: state.autosync?.preflightBeforeWork !== false,
|
|
737
|
+
requireUserGitEmail: state.autosync?.requireUserGitEmail !== false,
|
|
738
|
+
initialized: state.initialized,
|
|
739
|
+
activeMember: state.activeMember,
|
|
740
|
+
activeAgents: Object.fromEntries(Object.entries(state.activeAgents || {}).map(([codename, agentId]) => {
|
|
741
|
+
const agent = (state.agentRoster || []).find((item) => item.id === agentId || item.name === agentId);
|
|
742
|
+
return [codename, agent ? { name: agent.name, role: agent.role, id: agent.id } : { id: agentId, missing: true }];
|
|
743
|
+
})),
|
|
744
|
+
members: Object.fromEntries(Object.entries(state.members || {}).map(([key, member]) => [
|
|
745
|
+
key,
|
|
746
|
+
{
|
|
747
|
+
displayName: member.displayName,
|
|
748
|
+
gitIdentityConfigured: Boolean(member.gitIdentity?.email || member.github?.noreplyEmail),
|
|
749
|
+
gitName: member.gitIdentity?.name || member.displayName || key,
|
|
750
|
+
gitEmail: member.gitIdentity?.email || member.github?.noreplyEmail || '',
|
|
751
|
+
githubUsername: member.gitIdentity?.githubUsername || member.github?.username || ''
|
|
752
|
+
}
|
|
753
|
+
]))
|
|
754
|
+
}, null, 2));
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
function main() {
|
|
758
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
759
|
+
const args = parseArgs(rest);
|
|
760
|
+
if (command === 'status') return status();
|
|
761
|
+
if (command === 'preflight' || command === 'start') return preflight(args);
|
|
762
|
+
if (command === 'init') return init(args);
|
|
763
|
+
if (command === 'memory') {
|
|
764
|
+
const actor = requireArg(args, 'actor');
|
|
765
|
+
const summary = String(args.summary || args.reason || 'MOP conversation');
|
|
766
|
+
const kind = String(args.kind || 'conversation');
|
|
767
|
+
saveMemory(actor, summary, kind);
|
|
768
|
+
console.log(`Memory saved for ${actor}.`);
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
if (command === 'push') return push(args);
|
|
772
|
+
if (command === 'merge') return mergeMain(args);
|
|
773
|
+
if (command === 'run') return runAll(args);
|
|
774
|
+
|
|
775
|
+
console.log(`Usage:
|
|
776
|
+
node .MOP/scripts/mop-autosycn.mjs status
|
|
777
|
+
node .MOP/scripts/mop-autosycn.mjs preflight --actor <codename>
|
|
778
|
+
node .MOP/scripts/mop-autosycn.mjs init --actor <owner-codename> --url <github-url>
|
|
779
|
+
node .MOP/scripts/mop-autosycn.mjs memory --actor <codename> --summary "what happened"
|
|
780
|
+
node .MOP/scripts/mop-autosycn.mjs push --actor <codename> --reason "what changed"
|
|
781
|
+
node .MOP/scripts/mop-autosycn.mjs merge --actor <owner> --from <codename> --reason "merge reason"
|
|
782
|
+
node .MOP/scripts/mop-autosycn.mjs run --actor <codename> --reason "what changed"`);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
try {
|
|
786
|
+
main();
|
|
787
|
+
} catch (error) {
|
|
788
|
+
console.error(error.message);
|
|
789
|
+
process.exitCode = 1;
|
|
790
|
+
}
|