mindforge-cc 9.0.0 → 10.0.0
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/.mindforge/config.json +1 -1
- package/CHANGELOG.md +15 -0
- package/LICENSE +1 -1
- package/MINDFORGE.md +13 -0
- package/README.md +7 -1
- package/bin/autonomous/audit-writer.js +90 -0
- package/bin/autonomous/auto-runner.js +209 -431
- package/bin/autonomous/state-manager.js +116 -0
- package/bin/autonomous/task-dispatcher.js +114 -0
- package/bin/autonomous/wave-executor.js +169 -0
- package/bin/browser/browser-daemon.js +31 -1
- package/bin/change-classifier.js +3 -3
- package/bin/dashboard/api-router.js +21 -22
- package/bin/dashboard/metrics-aggregator.js +44 -3
- package/bin/dashboard/server.js +54 -10
- package/bin/dashboard/sse-bridge.js +51 -5
- package/bin/engine/learning-manager.js +1 -1
- package/bin/engine/mesh-syncer.js +26 -22
- package/bin/engine/nexus-tracer.js +6 -5
- package/bin/engine/orbital-guardian.js +13 -10
- package/bin/engine/skill-evolver.js +12 -14
- package/bin/engine/temporal-hub.js +25 -1
- package/bin/governance/policy-engine.js +5 -5
- package/bin/governance/policy-gate-hardened.js +2 -2
- package/bin/governance/quantum-crypto.js +10 -2
- package/bin/memory/identity-synthesizer.js +9 -11
- package/bin/memory/knowledge-store.js +62 -6
- package/bin/memory/semantic-hub.js +26 -30
- package/bin/memory/vector-hub.js +377 -193
- package/bin/migrations/v8-sqlite-migration.js +22 -21
- package/bin/migrations/v9-unified-memory.js +1 -1
- package/bin/mindforge-cli.js +47 -11
- package/bin/models/model-broker.js +2 -0
- package/bin/revops/remediation-queue.js +16 -55
- package/bin/utils/errors.js +40 -0
- package/bin/utils/file-io.js +102 -0
- package/bin/utils/index.js +6 -0
- package/bin/utils/paths.js +33 -0
- package/docs/sdk-reference.md +374 -24
- package/docs/troubleshooting.md +4 -4
- package/examples/sdk-integration/README.md +24 -0
- package/examples/sdk-integration/index.js +24 -0
- package/examples/starter-project/MINDFORGE.md +8 -8
- package/package.json +25 -14
- package/.agent/bin/lib/commands.cjs +0 -959
- package/.agent/bin/lib/config.cjs +0 -421
- package/.agent/bin/lib/core.cjs +0 -1166
- package/.agent/bin/lib/frontmatter.cjs +0 -307
- package/.agent/bin/lib/init.cjs +0 -1336
- package/.agent/bin/lib/milestone.cjs +0 -252
- package/.agent/bin/lib/model-profiles.cjs +0 -68
- package/.agent/bin/lib/phase.cjs +0 -888
- package/.agent/bin/lib/profile-output.cjs +0 -952
- package/.agent/bin/lib/profile-pipeline.cjs +0 -539
- package/.agent/bin/lib/roadmap.cjs +0 -329
- package/.agent/bin/lib/security.cjs +0 -356
- package/.agent/bin/lib/state.cjs +0 -969
- package/.agent/bin/lib/template.cjs +0 -222
- package/.agent/bin/lib/uat.cjs +0 -189
- package/.agent/bin/lib/verify.cjs +0 -851
- package/.agent/bin/lib/workstream.cjs +0 -491
- package/.agent/bin/mindforge-tools.cjs +0 -897
- package/.agent/file-manifest.json +0 -219
- package/.agent/forge/help.md +0 -11
- package/.agent/forge/init-project.md +0 -36
- package/.agent/forge/plan-phase.md +0 -34
- package/.agent/mindforge/add-backlog.md +0 -32
- package/.agent/mindforge/agent.md +0 -31
- package/.agent/mindforge/approve.md +0 -22
- package/.agent/mindforge/audit.md +0 -34
- package/.agent/mindforge/auto.md +0 -26
- package/.agent/mindforge/benchmark.md +0 -37
- package/.agent/mindforge/browse.md +0 -30
- package/.agent/mindforge/complete-milestone.md +0 -22
- package/.agent/mindforge/costs.md +0 -15
- package/.agent/mindforge/cross-review.md +0 -21
- package/.agent/mindforge/dashboard.md +0 -102
- package/.agent/mindforge/debug.md +0 -133
- package/.agent/mindforge/discuss-phase.md +0 -142
- package/.agent/mindforge/do.md +0 -31
- package/.agent/mindforge/execute-phase.md +0 -200
- package/.agent/mindforge/health.md +0 -31
- package/.agent/mindforge/help.md +0 -33
- package/.agent/mindforge/init-org.md +0 -135
- package/.agent/mindforge/init-project.md +0 -170
- package/.agent/mindforge/install-skill.md +0 -28
- package/.agent/mindforge/learn.md +0 -147
- package/.agent/mindforge/learning.md +0 -20
- package/.agent/mindforge/map-codebase.md +0 -302
- package/.agent/mindforge/marketplace.md +0 -124
- package/.agent/mindforge/metrics.md +0 -26
- package/.agent/mindforge/migrate.md +0 -44
- package/.agent/mindforge/milestone.md +0 -16
- package/.agent/mindforge/new-runtime.md +0 -23
- package/.agent/mindforge/next.md +0 -109
- package/.agent/mindforge/note.md +0 -35
- package/.agent/mindforge/plan-phase.md +0 -131
- package/.agent/mindforge/plant-seed.md +0 -31
- package/.agent/mindforge/plugins.md +0 -44
- package/.agent/mindforge/pr-review.md +0 -45
- package/.agent/mindforge/profile-team.md +0 -27
- package/.agent/mindforge/publish-skill.md +0 -23
- package/.agent/mindforge/qa.md +0 -20
- package/.agent/mindforge/quick.md +0 -139
- package/.agent/mindforge/record-learning.md +0 -22
- package/.agent/mindforge/release.md +0 -14
- package/.agent/mindforge/remember.md +0 -30
- package/.agent/mindforge/research.md +0 -16
- package/.agent/mindforge/retrospective.md +0 -31
- package/.agent/mindforge/review-backlog.md +0 -34
- package/.agent/mindforge/review.md +0 -161
- package/.agent/mindforge/security-scan.md +0 -242
- package/.agent/mindforge/session-report.md +0 -39
- package/.agent/mindforge/ship.md +0 -111
- package/.agent/mindforge/skills.md +0 -145
- package/.agent/mindforge/status.md +0 -113
- package/.agent/mindforge/steer.md +0 -17
- package/.agent/mindforge/sync-confluence.md +0 -15
- package/.agent/mindforge/sync-jira.md +0 -16
- package/.agent/mindforge/tokens.md +0 -12
- package/.agent/mindforge/ui-phase.md +0 -34
- package/.agent/mindforge/ui-review.md +0 -36
- package/.agent/mindforge/update.md +0 -46
- package/.agent/mindforge/validate-phase.md +0 -31
- package/.agent/mindforge/verify-phase.md +0 -66
- package/.agent/mindforge/workspace.md +0 -33
- package/.agent/mindforge/workstreams.md +0 -35
- package/.agent/settings.json +0 -42
- package/.agent/skills/mindforge-add-backlog/SKILL.md +0 -72
- package/.agent/skills/mindforge-add-phase/SKILL.md +0 -39
- package/.agent/skills/mindforge-add-tests/SKILL.md +0 -28
- package/.agent/skills/mindforge-add-todo/SKILL.md +0 -42
- package/.agent/skills/mindforge-audit-milestone/SKILL.md +0 -29
- package/.agent/skills/mindforge-audit-uat/SKILL.md +0 -20
- package/.agent/skills/mindforge-autonomous/SKILL.md +0 -33
- package/.agent/skills/mindforge-brainstorming/SKILL.md +0 -164
- package/.agent/skills/mindforge-brainstorming/scripts/frame-template.html +0 -214
- package/.agent/skills/mindforge-brainstorming/scripts/helper.js +0 -88
- package/.agent/skills/mindforge-brainstorming/scripts/server.cjs +0 -354
- package/.agent/skills/mindforge-brainstorming/scripts/start-server.sh +0 -148
- package/.agent/skills/mindforge-brainstorming/scripts/stop-server.sh +0 -56
- package/.agent/skills/mindforge-brainstorming/spec-document-reviewer-prompt.md +0 -49
- package/.agent/skills/mindforge-brainstorming/visual-companion.md +0 -287
- package/.agent/skills/mindforge-check-todos/SKILL.md +0 -40
- package/.agent/skills/mindforge-cleanup/SKILL.md +0 -19
- package/.agent/skills/mindforge-complete-milestone/SKILL.md +0 -131
- package/.agent/skills/mindforge-debug/SKILL.md +0 -163
- package/.agent/skills/mindforge-debug_extended/CREATION-LOG.md +0 -119
- package/.agent/skills/mindforge-debug_extended/SKILL.md +0 -296
- package/.agent/skills/mindforge-debug_extended/condition-based-waiting-example.ts +0 -158
- package/.agent/skills/mindforge-debug_extended/condition-based-waiting.md +0 -115
- package/.agent/skills/mindforge-debug_extended/defense-in-depth.md +0 -122
- package/.agent/skills/mindforge-debug_extended/find-polluter.sh +0 -63
- package/.agent/skills/mindforge-debug_extended/root-cause-tracing.md +0 -169
- package/.agent/skills/mindforge-debug_extended/test-academic.md +0 -14
- package/.agent/skills/mindforge-debug_extended/test-pressure-1.md +0 -58
- package/.agent/skills/mindforge-debug_extended/test-pressure-2.md +0 -68
- package/.agent/skills/mindforge-debug_extended/test-pressure-3.md +0 -69
- package/.agent/skills/mindforge-discuss-phase/SKILL.md +0 -54
- package/.agent/skills/mindforge-do/SKILL.md +0 -26
- package/.agent/skills/mindforge-execute-phase/SKILL.md +0 -49
- package/.agent/skills/mindforge-execute-phase_extended/SKILL.md +0 -70
- package/.agent/skills/mindforge-fast/SKILL.md +0 -23
- package/.agent/skills/mindforge-forensics/SKILL.md +0 -49
- package/.agent/skills/mindforge-health/SKILL.md +0 -17
- package/.agent/skills/mindforge-help/SKILL.md +0 -23
- package/.agent/skills/mindforge-insert-phase/SKILL.md +0 -28
- package/.agent/skills/mindforge-join-discord/SKILL.md +0 -19
- package/.agent/skills/mindforge-list-phase-assumptions/SKILL.md +0 -41
- package/.agent/skills/mindforge-list-workspaces/SKILL.md +0 -17
- package/.agent/skills/mindforge-manager/SKILL.md +0 -32
- package/.agent/skills/mindforge-map-codebase/SKILL.md +0 -64
- package/.agent/skills/mindforge-milestone-summary/SKILL.md +0 -44
- package/.agent/skills/mindforge-neural-orchestrator/SKILL.md +0 -115
- package/.agent/skills/mindforge-neural-orchestrator/references/codex-tools.md +0 -100
- package/.agent/skills/mindforge-neural-orchestrator/references/gemini-tools.md +0 -33
- package/.agent/skills/mindforge-new-milestone/SKILL.md +0 -38
- package/.agent/skills/mindforge-new-project/SKILL.md +0 -36
- package/.agent/skills/mindforge-new-workspace/SKILL.md +0 -39
- package/.agent/skills/mindforge-next/SKILL.md +0 -19
- package/.agent/skills/mindforge-note/SKILL.md +0 -29
- package/.agent/skills/mindforge-parallel-mesh_extended/SKILL.md +0 -182
- package/.agent/skills/mindforge-pause-work/SKILL.md +0 -35
- package/.agent/skills/mindforge-plan-milestone-gaps/SKILL.md +0 -28
- package/.agent/skills/mindforge-plan-phase/SKILL.md +0 -38
- package/.agent/skills/mindforge-plan-phase_extended/SKILL.md +0 -152
- package/.agent/skills/mindforge-plan-phase_extended/plan-document-reviewer-prompt.md +0 -49
- package/.agent/skills/mindforge-plant-seed/SKILL.md +0 -22
- package/.agent/skills/mindforge-pr-branch/SKILL.md +0 -21
- package/.agent/skills/mindforge-profile-user/SKILL.md +0 -38
- package/.agent/skills/mindforge-progress/SKILL.md +0 -19
- package/.agent/skills/mindforge-quick/SKILL.md +0 -38
- package/.agent/skills/mindforge-reapply-patches/SKILL.md +0 -124
- package/.agent/skills/mindforge-remove-phase/SKILL.md +0 -26
- package/.agent/skills/mindforge-remove-workspace/SKILL.md +0 -22
- package/.agent/skills/mindforge-research-phase/SKILL.md +0 -186
- package/.agent/skills/mindforge-resume-work/SKILL.md +0 -35
- package/.agent/skills/mindforge-review/SKILL.md +0 -31
- package/.agent/skills/mindforge-review-backlog/SKILL.md +0 -58
- package/.agent/skills/mindforge-review-inbound/SKILL.md +0 -213
- package/.agent/skills/mindforge-review-request/SKILL.md +0 -105
- package/.agent/skills/mindforge-review-request/code-reviewer.md +0 -146
- package/.agent/skills/mindforge-session-report/SKILL.md +0 -16
- package/.agent/skills/mindforge-set-profile/SKILL.md +0 -9
- package/.agent/skills/mindforge-settings/SKILL.md +0 -32
- package/.agent/skills/mindforge-ship/SKILL.md +0 -16
- package/.agent/skills/mindforge-ship_extended/SKILL.md +0 -200
- package/.agent/skills/mindforge-skill-creation/SKILL.md +0 -655
- package/.agent/skills/mindforge-skill-creation/anthropic-best-practices.md +0 -1150
- package/.agent/skills/mindforge-skill-creation/examples/CLAUDE_MD_TESTING.md +0 -189
- package/.agent/skills/mindforge-skill-creation/graphviz-conventions.dot +0 -172
- package/.agent/skills/mindforge-skill-creation/persuasion-principles.md +0 -187
- package/.agent/skills/mindforge-skill-creation/render-graphs.js +0 -168
- package/.agent/skills/mindforge-skill-creation/testing-skills-with-subagents.md +0 -384
- package/.agent/skills/mindforge-stats/SKILL.md +0 -16
- package/.agent/skills/mindforge-swarm-execution/SKILL.md +0 -277
- package/.agent/skills/mindforge-swarm-execution/code-quality-reviewer-prompt.md +0 -26
- package/.agent/skills/mindforge-swarm-execution/implementer-prompt.md +0 -113
- package/.agent/skills/mindforge-swarm-execution/spec-reviewer-prompt.md +0 -61
- package/.agent/skills/mindforge-system-architecture/SKILL.md +0 -136
- package/.agent/skills/mindforge-system-architecture/examples.md +0 -120
- package/.agent/skills/mindforge-system-architecture/scaling-checklist.md +0 -76
- package/.agent/skills/mindforge-tdd/SKILL.md +0 -112
- package/.agent/skills/mindforge-tdd/deep-modules.md +0 -21
- package/.agent/skills/mindforge-tdd/interface-design.md +0 -22
- package/.agent/skills/mindforge-tdd/mocking.md +0 -24
- package/.agent/skills/mindforge-tdd/refactoring.md +0 -21
- package/.agent/skills/mindforge-tdd/tests.md +0 -28
- package/.agent/skills/mindforge-tdd_extended/SKILL.md +0 -371
- package/.agent/skills/mindforge-tdd_extended/testing-anti-patterns.md +0 -299
- package/.agent/skills/mindforge-thread/SKILL.md +0 -123
- package/.agent/skills/mindforge-ui-phase/SKILL.md +0 -24
- package/.agent/skills/mindforge-ui-review/SKILL.md +0 -24
- package/.agent/skills/mindforge-update/SKILL.md +0 -35
- package/.agent/skills/mindforge-validate-phase/SKILL.md +0 -26
- package/.agent/skills/mindforge-verify-work/SKILL.md +0 -30
- package/.agent/skills/mindforge-verify-work_extended/SKILL.md +0 -139
- package/.agent/skills/mindforge-workspace-isolated/SKILL.md +0 -218
- package/.agent/skills/mindforge-workstreams/SKILL.md +0 -65
- package/.agent/workflows/forge:help.md +0 -10
- package/.agent/workflows/forge:init-project.md +0 -35
- package/.agent/workflows/forge:plan-phase.md +0 -33
- package/.agent/workflows/mindforge-add-phase.md +0 -112
- package/.agent/workflows/mindforge-add-tests.md +0 -351
- package/.agent/workflows/mindforge-add-todo.md +0 -158
- package/.agent/workflows/mindforge-audit-milestone.md +0 -332
- package/.agent/workflows/mindforge-audit-uat.md +0 -109
- package/.agent/workflows/mindforge-autonomous.md +0 -815
- package/.agent/workflows/mindforge-check-todos.md +0 -177
- package/.agent/workflows/mindforge-cleanup.md +0 -152
- package/.agent/workflows/mindforge-complete-milestone.md +0 -766
- package/.agent/workflows/mindforge-diagnose-issues.md +0 -220
- package/.agent/workflows/mindforge-discovery-phase.md +0 -289
- package/.agent/workflows/mindforge-discuss-phase-assumptions.md +0 -645
- package/.agent/workflows/mindforge-discuss-phase.md +0 -1047
- package/.agent/workflows/mindforge-do.md +0 -104
- package/.agent/workflows/mindforge-execute-phase.md +0 -838
- package/.agent/workflows/mindforge-execute-plan.md +0 -509
- package/.agent/workflows/mindforge-fast.md +0 -105
- package/.agent/workflows/mindforge-forensics.md +0 -265
- package/.agent/workflows/mindforge-health.md +0 -181
- package/.agent/workflows/mindforge-help.md +0 -606
- package/.agent/workflows/mindforge-insert-phase.md +0 -130
- package/.agent/workflows/mindforge-list-phase-assumptions.md +0 -178
- package/.agent/workflows/mindforge-list-workspaces.md +0 -56
- package/.agent/workflows/mindforge-manager.md +0 -360
- package/.agent/workflows/mindforge-map-codebase.md +0 -370
- package/.agent/workflows/mindforge-milestone-summary.md +0 -223
- package/.agent/workflows/mindforge-new-milestone.md +0 -469
- package/.agent/workflows/mindforge-new-project.md +0 -1226
- package/.agent/workflows/mindforge-new-workspace.md +0 -237
- package/.agent/workflows/mindforge-next.md +0 -97
- package/.agent/workflows/mindforge-node-repair.md +0 -92
- package/.agent/workflows/mindforge-note.md +0 -156
- package/.agent/workflows/mindforge-pause-work.md +0 -176
- package/.agent/workflows/mindforge-plan-milestone-gaps.md +0 -273
- package/.agent/workflows/mindforge-plan-phase.md +0 -877
- package/.agent/workflows/mindforge-plant-seed.md +0 -169
- package/.agent/workflows/mindforge-pr-branch.md +0 -129
- package/.agent/workflows/mindforge-profile-user.md +0 -450
- package/.agent/workflows/mindforge-progress.md +0 -507
- package/.agent/workflows/mindforge-quick.md +0 -732
- package/.agent/workflows/mindforge-remove-phase.md +0 -155
- package/.agent/workflows/mindforge-remove-workspace.md +0 -90
- package/.agent/workflows/mindforge-research-phase.md +0 -74
- package/.agent/workflows/mindforge-resume-project.md +0 -325
- package/.agent/workflows/mindforge-review.md +0 -228
- package/.agent/workflows/mindforge-session-report.md +0 -146
- package/.agent/workflows/mindforge-settings.md +0 -283
- package/.agent/workflows/mindforge-ship.md +0 -228
- package/.agent/workflows/mindforge-stats.md +0 -60
- package/.agent/workflows/mindforge-transition.md +0 -671
- package/.agent/workflows/mindforge-ui-phase.md +0 -290
- package/.agent/workflows/mindforge-ui-review.md +0 -157
- package/.agent/workflows/mindforge-update.md +0 -323
- package/.agent/workflows/mindforge-validate-phase.md +0 -167
- package/.agent/workflows/mindforge-verify-phase.md +0 -254
- package/.agent/workflows/mindforge-verify-work.md +0 -628
- package/.agent/workflows/mindforge:add-backlog.md +0 -24
- package/.agent/workflows/mindforge:agent.md +0 -25
- package/.agent/workflows/mindforge:approve.md +0 -21
- package/.agent/workflows/mindforge:architecture.md +0 -40
- package/.agent/workflows/mindforge:audit.md +0 -33
- package/.agent/workflows/mindforge:auto.md +0 -25
- package/.agent/workflows/mindforge:benchmark.md +0 -36
- package/.agent/workflows/mindforge:brainstorming.md +0 -16
- package/.agent/workflows/mindforge:browse.md +0 -29
- package/.agent/workflows/mindforge:complete-milestone.md +0 -21
- package/.agent/workflows/mindforge:costs.md +0 -14
- package/.agent/workflows/mindforge:cross-review.md +0 -20
- package/.agent/workflows/mindforge:dashboard.md +0 -101
- package/.agent/workflows/mindforge:debug.md +0 -131
- package/.agent/workflows/mindforge:discuss-phase.md +0 -141
- package/.agent/workflows/mindforge:do.md +0 -25
- package/.agent/workflows/mindforge:execute-phase.md +0 -205
- package/.agent/workflows/mindforge:executor.md +0 -18
- package/.agent/workflows/mindforge:health.md +0 -24
- package/.agent/workflows/mindforge:help.md +0 -26
- package/.agent/workflows/mindforge:identity.md +0 -18
- package/.agent/workflows/mindforge:init-org.md +0 -134
- package/.agent/workflows/mindforge:init-project.md +0 -185
- package/.agent/workflows/mindforge:install-skill.md +0 -27
- package/.agent/workflows/mindforge:learn.md +0 -146
- package/.agent/workflows/mindforge:map-codebase.md +0 -301
- package/.agent/workflows/mindforge:marketplace.md +0 -123
- package/.agent/workflows/mindforge:memory.md +0 -18
- package/.agent/workflows/mindforge:metrics.md +0 -25
- package/.agent/workflows/mindforge:migrate.md +0 -43
- package/.agent/workflows/mindforge:milestone.md +0 -15
- package/.agent/workflows/mindforge:new-runtime.md +0 -22
- package/.agent/workflows/mindforge:next.md +0 -108
- package/.agent/workflows/mindforge:note.md +0 -27
- package/.agent/workflows/mindforge:plan-phase.md +0 -139
- package/.agent/workflows/mindforge:planner.md +0 -18
- package/.agent/workflows/mindforge:plant-seed.md +0 -24
- package/.agent/workflows/mindforge:plugins.md +0 -43
- package/.agent/workflows/mindforge:pr-review.md +0 -44
- package/.agent/workflows/mindforge:profile-team.md +0 -26
- package/.agent/workflows/mindforge:publish-skill.md +0 -22
- package/.agent/workflows/mindforge:qa.md +0 -19
- package/.agent/workflows/mindforge:quick.md +0 -138
- package/.agent/workflows/mindforge:release.md +0 -13
- package/.agent/workflows/mindforge:remember.md +0 -29
- package/.agent/workflows/mindforge:research.md +0 -15
- package/.agent/workflows/mindforge:researcher.md +0 -18
- package/.agent/workflows/mindforge:retrospective.md +0 -29
- package/.agent/workflows/mindforge:review-backlog.md +0 -26
- package/.agent/workflows/mindforge:review.md +0 -160
- package/.agent/workflows/mindforge:reviewer.md +0 -18
- package/.agent/workflows/mindforge:security-scan.md +0 -236
- package/.agent/workflows/mindforge:session-report.md +0 -31
- package/.agent/workflows/mindforge:ship.md +0 -108
- package/.agent/workflows/mindforge:skills.md +0 -144
- package/.agent/workflows/mindforge:soul.md +0 -54
- package/.agent/workflows/mindforge:status.md +0 -107
- package/.agent/workflows/mindforge:steer.md +0 -16
- package/.agent/workflows/mindforge:sync-confluence.md +0 -14
- package/.agent/workflows/mindforge:sync-jira.md +0 -15
- package/.agent/workflows/mindforge:tdd.md +0 -46
- package/.agent/workflows/mindforge:tokens.md +0 -11
- package/.agent/workflows/mindforge:tool.md +0 -18
- package/.agent/workflows/mindforge:ui-phase.md +0 -27
- package/.agent/workflows/mindforge:ui-review.md +0 -28
- package/.agent/workflows/mindforge:update.md +0 -45
- package/.agent/workflows/mindforge:validate-phase.md +0 -25
- package/.agent/workflows/mindforge:verify-phase.md +0 -65
- package/.agent/workflows/mindforge:workspace.md +0 -32
- package/.agent/workflows/mindforge:workstreams.md +0 -27
- package/.agent/workflows/publish-release.md +0 -36
- package/.claude/CLAUDE.md +0 -102
- package/.claude/commands/forge/help.md +0 -7
- package/.claude/commands/forge/init-project.md +0 -32
- package/.claude/commands/forge/plan-phase.md +0 -30
- package/.claude/commands/mindforge/add-backlog.md +0 -32
- package/.claude/commands/mindforge/agent.md +0 -31
- package/.claude/commands/mindforge/approve.md +0 -22
- package/.claude/commands/mindforge/audit.md +0 -34
- package/.claude/commands/mindforge/auto.md +0 -26
- package/.claude/commands/mindforge/benchmark.md +0 -37
- package/.claude/commands/mindforge/browse.md +0 -30
- package/.claude/commands/mindforge/complete-milestone.md +0 -22
- package/.claude/commands/mindforge/costs.md +0 -15
- package/.claude/commands/mindforge/cross-review.md +0 -21
- package/.claude/commands/mindforge/dashboard.md +0 -102
- package/.claude/commands/mindforge/debug.md +0 -133
- package/.claude/commands/mindforge/discuss-phase.md +0 -142
- package/.claude/commands/mindforge/do.md +0 -31
- package/.claude/commands/mindforge/execute-phase.md +0 -200
- package/.claude/commands/mindforge/health.md +0 -31
- package/.claude/commands/mindforge/help.md +0 -33
- package/.claude/commands/mindforge/init-org.md +0 -135
- package/.claude/commands/mindforge/init-project.md +0 -170
- package/.claude/commands/mindforge/install-skill.md +0 -28
- package/.claude/commands/mindforge/learn.md +0 -147
- package/.claude/commands/mindforge/learning.md +0 -20
- package/.claude/commands/mindforge/map-codebase.md +0 -302
- package/.claude/commands/mindforge/marketplace.md +0 -124
- package/.claude/commands/mindforge/metrics.md +0 -26
- package/.claude/commands/mindforge/migrate.md +0 -44
- package/.claude/commands/mindforge/milestone.md +0 -16
- package/.claude/commands/mindforge/new-runtime.md +0 -23
- package/.claude/commands/mindforge/next.md +0 -109
- package/.claude/commands/mindforge/note.md +0 -35
- package/.claude/commands/mindforge/plan-phase.md +0 -131
- package/.claude/commands/mindforge/plant-seed.md +0 -31
- package/.claude/commands/mindforge/plugins.md +0 -44
- package/.claude/commands/mindforge/pr-review.md +0 -45
- package/.claude/commands/mindforge/profile-team.md +0 -27
- package/.claude/commands/mindforge/publish-skill.md +0 -23
- package/.claude/commands/mindforge/qa.md +0 -20
- package/.claude/commands/mindforge/quick.md +0 -139
- package/.claude/commands/mindforge/record-learning.md +0 -22
- package/.claude/commands/mindforge/release.md +0 -14
- package/.claude/commands/mindforge/remember.md +0 -30
- package/.claude/commands/mindforge/research.md +0 -16
- package/.claude/commands/mindforge/retrospective.md +0 -31
- package/.claude/commands/mindforge/review-backlog.md +0 -34
- package/.claude/commands/mindforge/review.md +0 -161
- package/.claude/commands/mindforge/security-scan.md +0 -242
- package/.claude/commands/mindforge/session-report.md +0 -39
- package/.claude/commands/mindforge/ship.md +0 -111
- package/.claude/commands/mindforge/skills.md +0 -145
- package/.claude/commands/mindforge/status.md +0 -113
- package/.claude/commands/mindforge/steer.md +0 -17
- package/.claude/commands/mindforge/sync-confluence.md +0 -15
- package/.claude/commands/mindforge/sync-jira.md +0 -16
- package/.claude/commands/mindforge/tokens.md +0 -12
- package/.claude/commands/mindforge/ui-phase.md +0 -34
- package/.claude/commands/mindforge/ui-review.md +0 -36
- package/.claude/commands/mindforge/update.md +0 -46
- package/.claude/commands/mindforge/validate-phase.md +0 -31
- package/.claude/commands/mindforge/verify-phase.md +0 -66
- package/.claude/commands/mindforge/workspace.md +0 -33
- package/.claude/commands/mindforge/workstreams.md +0 -35
- package/.claude/settings.local.json +0 -16
- package/.mindforge/audit/AUDIT-SCHEMA.md +0 -470
- package/.mindforge/browser/daemon-protocol.md +0 -24
- package/.mindforge/browser/qa-engine.md +0 -16
- package/.mindforge/browser/session-manager.md +0 -18
- package/.mindforge/browser/visual-verify-spec.md +0 -31
- package/.mindforge/celestial.db +0 -0
- package/.mindforge/ci/ci-config-schema.md +0 -21
- package/.mindforge/ci/ci-mode.md +0 -179
- package/.mindforge/ci/github-actions-adapter.md +0 -224
- package/.mindforge/ci/gitlab-ci-adapter.md +0 -31
- package/.mindforge/ci/jenkins-adapter.md +0 -44
- package/.mindforge/dashboard/api-reference.md +0 -122
- package/.mindforge/dashboard/dashboard-spec.md +0 -96
- package/.mindforge/distribution/marketplace.md +0 -53
- package/.mindforge/distribution/registry-client.md +0 -166
- package/.mindforge/distribution/registry-schema.md +0 -96
- package/.mindforge/distribution/skill-publisher.md +0 -44
- package/.mindforge/distribution/skill-validator.md +0 -74
- package/.mindforge/governance/GOVERNANCE-CONFIG.md +0 -17
- package/.mindforge/governance/approval-workflow.md +0 -37
- package/.mindforge/governance/change-classifier.md +0 -63
- package/.mindforge/governance/compliance-gates.md +0 -31
- package/.mindforge/governance/policies/sovereign-default.json +0 -16
- package/.mindforge/integrations/confluence.md +0 -27
- package/.mindforge/integrations/connection-manager.md +0 -163
- package/.mindforge/integrations/github.md +0 -25
- package/.mindforge/integrations/gitlab.md +0 -13
- package/.mindforge/integrations/jira.md +0 -102
- package/.mindforge/integrations/slack.md +0 -41
- package/.mindforge/intelligence/antipattern-detector.md +0 -75
- package/.mindforge/intelligence/difficulty-scorer.md +0 -55
- package/.mindforge/intelligence/health-engine.md +0 -208
- package/.mindforge/intelligence/skill-gap-analyser.md +0 -40
- package/.mindforge/intelligence/smart-compaction.md +0 -71
- package/.mindforge/memory/MEMORY-SCHEMA.md +0 -155
- package/.mindforge/memory/engine/capture-protocol.md +0 -36
- package/.mindforge/memory/engine/global-sync-spec.md +0 -42
- package/.mindforge/memory/engine/retrieval-spec.md +0 -44
- package/.mindforge/memory/sync-manifest.json +0 -6
- package/.mindforge/metrics/METRICS-SCHEMA.md +0 -42
- package/.mindforge/metrics/quality-tracker.md +0 -32
- package/.mindforge/models/model-registry.md +0 -48
- package/.mindforge/models/model-router.md +0 -30
- package/.mindforge/monorepo/cross-package-planner.md +0 -114
- package/.mindforge/monorepo/dependency-graph-builder.md +0 -32
- package/.mindforge/monorepo/workspace-detector.md +0 -129
- package/.mindforge/org/CONVENTIONS.md +0 -62
- package/.mindforge/org/ORG.md +0 -51
- package/.mindforge/org/SECURITY.md +0 -50
- package/.mindforge/org/TOOLS.md +0 -53
- package/.mindforge/org/integrations/INTEGRATIONS-CONFIG.md +0 -58
- package/.mindforge/org/skills/MANIFEST.md +0 -15
- package/.mindforge/plugins/PLUGINS-MANIFEST.md +0 -23
- package/.mindforge/plugins/plugin-loader.md +0 -93
- package/.mindforge/plugins/plugin-registry.md +0 -44
- package/.mindforge/plugins/plugin-schema.md +0 -68
- package/.mindforge/pr-review/ai-reviewer.md +0 -266
- package/.mindforge/pr-review/finding-formatter.md +0 -46
- package/.mindforge/pr-review/review-prompt-templates.md +0 -44
- package/.mindforge/production/compatibility-layer.md +0 -39
- package/.mindforge/production/migration-engine.md +0 -52
- package/.mindforge/production/production-checklist.md +0 -76
- package/.mindforge/production/token-optimiser.md +0 -68
- package/.mindforge/skills-builder/auto-capture-protocol.md +0 -88
- package/.mindforge/skills-builder/learn-protocol.md +0 -161
- package/.mindforge/skills-builder/quality-scoring.md +0 -120
- package/.mindforge/team/TEAM-PROFILE.md +0 -42
- package/.mindforge/team/multi-handoff.md +0 -23
- package/.mindforge/team/profiles/README.md +0 -13
- package/.mindforge/team/session-merger.md +0 -18
- package/.planning/ARCHITECTURE.md +0 -0
- package/.planning/HANDOFF.json +0 -8
- package/.planning/PROJECT.md +0 -33
- package/.planning/RELEASE-CHECKLIST.md +0 -68
- package/.planning/REQUIREMENTS.md +0 -35
- package/.planning/ROADMAP.md +0 -12
- package/.planning/STATE.md +0 -36
- package/.planning/approvals/.gitkeep +0 -1
- package/.planning/archive/.gitkeep +0 -1
- package/.planning/audit-archive/.gitkeep +0 -1
- package/.planning/decisions/.gitkeep +0 -0
- package/.planning/jira-sync.json +0 -1
- package/.planning/milestones/.gitkeep +0 -1
- package/.planning/phases/.gitkeep +0 -0
- package/.planning/research/.gitkeep +0 -0
- package/.planning/screenshots/.gitkeep +0 -0
- package/.planning/slack-threads.json +0 -1
- package/docs/CAPABILITIES-MANIFEST.md +0 -64
- package/docs/Context/Master-Context.md +0 -731
- package/docs/INTELLIGENCE-MESH.md +0 -37
- package/docs/MIND-FORGE-REFERENCE-V6.md +0 -96
- package/docs/PERSONAS.md +0 -960
- package/docs/References/audit-events.md +0 -59
- package/docs/References/checkpoints.md +0 -778
- package/docs/References/commands.md +0 -107
- package/docs/References/config-reference.md +0 -81
- package/docs/References/continuation-format.md +0 -249
- package/docs/References/decimal-phase-calculation.md +0 -64
- package/docs/References/git-integration.md +0 -295
- package/docs/References/git-planning-commit.md +0 -38
- package/docs/References/model-profile-resolution.md +0 -36
- package/docs/References/model-profiles.md +0 -139
- package/docs/References/phase-argument-parsing.md +0 -61
- package/docs/References/planning-config.md +0 -202
- package/docs/References/questioning.md +0 -162
- package/docs/References/sdk-api.md +0 -53
- package/docs/References/skills-api.md +0 -57
- package/docs/References/tdd.md +0 -263
- package/docs/References/ui-brand.md +0 -160
- package/docs/References/user-profiling.md +0 -681
- package/docs/References/verification-patterns.md +0 -612
- package/docs/References/workstream-flag.md +0 -58
- package/docs/Templates/Agents/CLAUDE-MD.md +0 -122
- package/docs/Templates/Agents/COPILOT-INSTRUCTIONS.md +0 -7
- package/docs/Templates/Agents/DEBUGGER-PROMPT.md +0 -91
- package/docs/Templates/Agents/PLANNER-PROMPT.md +0 -117
- package/docs/Templates/Codebase/architecture.md +0 -255
- package/docs/Templates/Codebase/concerns.md +0 -310
- package/docs/Templates/Codebase/conventions.md +0 -307
- package/docs/Templates/Codebase/integrations.md +0 -280
- package/docs/Templates/Codebase/stack.md +0 -186
- package/docs/Templates/Codebase/structure.md +0 -285
- package/docs/Templates/Codebase/testing.md +0 -480
- package/docs/Templates/Execution/CONTINUE-HERE.md +0 -78
- package/docs/Templates/Execution/DISCUSSION-LOG.md +0 -63
- package/docs/Templates/Execution/PHASE-PROMPT.md +0 -610
- package/docs/Templates/Execution/STATE.md +0 -176
- package/docs/Templates/Execution/SUMMARY-COMPLEX.md +0 -59
- package/docs/Templates/Execution/SUMMARY-MINIMAL.md +0 -41
- package/docs/Templates/Execution/SUMMARY-STANDARD.md +0 -48
- package/docs/Templates/Execution/SUMMARY.md +0 -248
- package/docs/Templates/Profile/DEV-PREFERENCES.md +0 -21
- package/docs/Templates/Profile/USER-PROFILE.md +0 -146
- package/docs/Templates/Profile/USER-SETUP.md +0 -311
- package/docs/Templates/Project/AGENTS_LEARNING.md +0 -88
- package/docs/Templates/Project/DISCOVERY.md +0 -146
- package/docs/Templates/Project/MILESTONE-ARCHIVE.md +0 -123
- package/docs/Templates/Project/MILESTONE.md +0 -115
- package/docs/Templates/Project/PROJECT.md +0 -206
- package/docs/Templates/Project/REQUIREMENTS.md +0 -231
- package/docs/Templates/Project/RETROSPECTIVE.md +0 -54
- package/docs/Templates/Project/ROADMAP.md +0 -202
- package/docs/Templates/Quality/DEBUG.md +0 -164
- package/docs/Templates/Quality/UAT.md +0 -280
- package/docs/Templates/Quality/UI-SPEC.md +0 -100
- package/docs/Templates/Quality/VALIDATION.md +0 -76
- package/docs/Templates/Quality/VERIFICATION-REPORT.md +0 -322
- package/docs/Templates/Research/ARCHITECTURE.md +0 -204
- package/docs/Templates/Research/FEATURES.md +0 -147
- package/docs/Templates/Research/PITFALLS.md +0 -200
- package/docs/Templates/Research/STACK.md +0 -120
- package/docs/Templates/Research/SUMMARY.md +0 -170
- package/docs/Templates/System/CONFIG.json +0 -43
- package/docs/Templates/System/CONTEXT.md +0 -352
- package/docs/adr/ADR-024-browser-localhost-only.md +0 -17
- package/docs/adr/ADR-025-visual-verify-failure-treatment.md +0 -19
- package/docs/adr/ADR-026-session-persistence-security.md +0 -20
- package/docs/adr/ADR-042-ads-protocol.md +0 -30
- package/docs/architecture/NEXUS-DASHBOARD.md +0 -35
- package/docs/architecture/PAR-ZTS-SURVEY.md +0 -43
- package/docs/architecture/README.md +0 -78
- package/docs/architecture/V3-CORE.md +0 -52
- package/docs/architecture/V4-SWARM-MESH.md +0 -77
- package/docs/architecture/V5-ENTERPRISE.md +0 -131
- package/docs/architecture/V6-SOVEREIGN.md +0 -43
- package/docs/architecture/V8-SRE.md +0 -88
- package/docs/architecture/V9-BEDROCK.md +0 -162
- package/docs/architecture/adr-039-multi-runtime-support.md +0 -20
- package/docs/architecture/adr-040-additive-schema-migration.md +0 -21
- package/docs/architecture/adr-041-stable-runtime-interface-contract.md +0 -20
- package/docs/architecture/decision-records-index.md +0 -29
- package/docs/ci-cd-integration.md +0 -30
- package/docs/ci-cd.md +0 -92
- package/docs/ci-quickstart.md +0 -78
- package/docs/commands-skills/DISCOVERED_SKILLS.md +0 -21
- package/docs/contributing/CONTRIBUTING.md +0 -38
- package/docs/contributing/plugin-authoring.md +0 -50
- package/docs/contributing/skill-authoring.md +0 -41
- package/docs/enterprise-setup.md +0 -25
- package/docs/feature-dashboard.md +0 -63
- package/docs/governance-guide.md +0 -134
- package/docs/monorepo-guide.md +0 -26
- package/docs/persona-customisation.md +0 -56
- package/docs/publishing-guide.md +0 -43
- package/docs/quick-verify.md +0 -33
- package/docs/registry/AGENTS.md +0 -37
- package/docs/registry/COMMANDS.md +0 -87
- package/docs/registry/HOOKS.md +0 -38
- package/docs/registry/PERSONAS.md +0 -64
- package/docs/registry/README.md +0 -27
- package/docs/registry/SKILLS.md +0 -142
- package/docs/registry/WORKFLOWS.md +0 -72
- package/docs/release-checklist-guide.md +0 -37
- package/docs/requirements.md +0 -29
- package/docs/security/SECURITY.md +0 -55
- package/docs/security/ZTAI-OVERVIEW.md +0 -37
- package/docs/security/penetration-test-results.md +0 -31
- package/docs/security/threat-model.md +0 -142
- package/docs/skills-authoring-guide.md +0 -176
- package/docs/skills-publishing-guide.md +0 -22
- package/docs/team-setup-guide.md +0 -21
- package/docs/testing-current-version.md +0 -130
- package/docs/tutorial.md +0 -162
- package/docs/upgrade.md +0 -58
- package/docs/usp-features.md +0 -102
- package/docs/workflow-atlas.md +0 -57
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — State Manager
|
|
3
|
+
* Extracted from auto-runner.js — handles state transitions, HANDOFF.json and
|
|
4
|
+
* auto-state.json read/write, and phase management.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const VALID_PHASES = ['idle', 'planning', 'executing', 'verifying', 'complete', 'running', 'paused', 'completed'];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates a state manager for the given planning directory.
|
|
15
|
+
* @param {string} planningDir — Absolute path to the .planning directory
|
|
16
|
+
* @returns {{ getState, updateState, transition, readHandoff, writeHandoff }}
|
|
17
|
+
*/
|
|
18
|
+
function createStateManager(planningDir) {
|
|
19
|
+
const statePath = path.join(planningDir, 'auto-state.json');
|
|
20
|
+
const handoffPath = path.join(planningDir, 'HANDOFF.json');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Reads the current state from auto-state.json.
|
|
24
|
+
* Returns a fresh object (never a shared reference).
|
|
25
|
+
*/
|
|
26
|
+
function getState() {
|
|
27
|
+
if (!fs.existsSync(statePath)) {
|
|
28
|
+
return Object.create(null);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const raw = fs.readFileSync(statePath, 'utf8');
|
|
33
|
+
const parsed = JSON.parse(raw);
|
|
34
|
+
return sanitizeState(parsed);
|
|
35
|
+
} catch (e) {
|
|
36
|
+
// Corrupt state file — return empty
|
|
37
|
+
return Object.create(null);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Merges a patch into the current state (immutable — writes new object to disk).
|
|
43
|
+
* @param {object} patch — Key/value pairs to merge
|
|
44
|
+
*/
|
|
45
|
+
function updateState(patch) {
|
|
46
|
+
const current = getState();
|
|
47
|
+
const merged = Object.assign(Object.create(null), current, patch);
|
|
48
|
+
fs.writeFileSync(statePath, JSON.stringify(merged, null, 2));
|
|
49
|
+
return merged;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Transitions the state to a new status phase.
|
|
54
|
+
* @param {string} newPhase — One of: idle, planning, executing, verifying, complete, running, paused, completed
|
|
55
|
+
*/
|
|
56
|
+
function transition(newPhase) {
|
|
57
|
+
if (!VALID_PHASES.includes(newPhase)) {
|
|
58
|
+
throw new Error(`Invalid state transition target: "${newPhase}". Valid: ${VALID_PHASES.join(', ')}`);
|
|
59
|
+
}
|
|
60
|
+
return updateState({
|
|
61
|
+
status: newPhase,
|
|
62
|
+
lastTransition: new Date().toISOString(),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Reads and parses HANDOFF.json. Throws if missing or malformed.
|
|
68
|
+
* @returns {object} Parsed handoff data (fresh object)
|
|
69
|
+
*/
|
|
70
|
+
function readHandoff() {
|
|
71
|
+
if (!fs.existsSync(handoffPath)) {
|
|
72
|
+
throw new Error('HANDOFF.json not found — run /mindforge:plan-phase first');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let handoff;
|
|
76
|
+
try {
|
|
77
|
+
handoff = JSON.parse(fs.readFileSync(handoffPath, 'utf8'));
|
|
78
|
+
} catch (e) {
|
|
79
|
+
throw new Error(`HANDOFF.json is malformed: ${e.message}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!handoff.handoffs || !Array.isArray(handoff.handoffs)) {
|
|
83
|
+
throw new Error('HANDOFF.json has no handoffs array');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return handoff;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Writes data to HANDOFF.json (immutable — creates new file contents).
|
|
91
|
+
* @param {object} data — The handoff object to persist
|
|
92
|
+
*/
|
|
93
|
+
function writeHandoff(data) {
|
|
94
|
+
const timestamped = Object.assign(Object.create(null), data, {
|
|
95
|
+
last_updated: new Date().toISOString(),
|
|
96
|
+
});
|
|
97
|
+
fs.writeFileSync(handoffPath, JSON.stringify(timestamped, null, 2) + '\n');
|
|
98
|
+
return timestamped;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return Object.freeze({ getState, updateState, transition, readHandoff, writeHandoff });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Sanitizes parsed JSON to prevent prototype pollution.
|
|
106
|
+
*/
|
|
107
|
+
function sanitizeState(parsed) {
|
|
108
|
+
const clean = Object.create(null);
|
|
109
|
+
for (const key of Object.keys(parsed)) {
|
|
110
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;
|
|
111
|
+
clean[key] = parsed[key];
|
|
112
|
+
}
|
|
113
|
+
return clean;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = { createStateManager };
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — Task Dispatcher
|
|
3
|
+
* Extracted from auto-runner.js — handles task parsing from HANDOFF.json,
|
|
4
|
+
* task queue management, task prioritization, and dispatch logic.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const crypto = require('crypto');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parses a HANDOFF.json file content into a normalized task list.
|
|
12
|
+
* @param {object} handoffData — Parsed HANDOFF.json object (must have .handoffs array)
|
|
13
|
+
* @returns {Array<{ id: string, name: string, plan: string|null, depends_on: string[], wave: number }>}
|
|
14
|
+
*/
|
|
15
|
+
function parseHandoff(handoffData) {
|
|
16
|
+
if (!handoffData || !Array.isArray(handoffData.handoffs)) {
|
|
17
|
+
throw new Error('Invalid handoff data — missing handoffs array');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return handoffData.handoffs.map(h => Object.freeze({
|
|
21
|
+
id: h.id || h.task_id || `task_${crypto.randomBytes(4).toString('hex')}`,
|
|
22
|
+
name: h.name || h.task || h.description || h.id || 'unnamed-task',
|
|
23
|
+
plan: h.plan || null,
|
|
24
|
+
depends_on: Array.isArray(h.depends_on) ? [...h.depends_on] : [],
|
|
25
|
+
wave: typeof h.wave === 'number' ? h.wave : null,
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Prioritizes tasks based on dependency depth and wave ordering.
|
|
31
|
+
* Tasks with fewer dependencies come first; within same depth, preserves original order.
|
|
32
|
+
* @param {Array} tasks — Normalized task list from parseHandoff
|
|
33
|
+
* @returns {Array} — New sorted array (input is not mutated)
|
|
34
|
+
*/
|
|
35
|
+
function prioritizeTasks(tasks) {
|
|
36
|
+
// Build a dependency depth map
|
|
37
|
+
const depthMap = new Map();
|
|
38
|
+
|
|
39
|
+
function getDepth(task, visited = new Set()) {
|
|
40
|
+
if (depthMap.has(task.id)) return depthMap.get(task.id);
|
|
41
|
+
if (visited.has(task.id)) return 0; // circular — break cycle
|
|
42
|
+
visited.add(task.id);
|
|
43
|
+
|
|
44
|
+
if (task.depends_on.length === 0) {
|
|
45
|
+
depthMap.set(task.id, 0);
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const maxParentDepth = task.depends_on.reduce((max, depId) => {
|
|
50
|
+
const parent = tasks.find(t => t.id === depId);
|
|
51
|
+
if (!parent) return max;
|
|
52
|
+
return Math.max(max, getDepth(parent, new Set(visited)));
|
|
53
|
+
}, 0);
|
|
54
|
+
|
|
55
|
+
const depth = maxParentDepth + 1;
|
|
56
|
+
depthMap.set(task.id, depth);
|
|
57
|
+
return depth;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Compute depth for all tasks
|
|
61
|
+
for (const task of tasks) {
|
|
62
|
+
getDepth(task);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Sort by wave first (if present), then by depth, then by original order
|
|
66
|
+
const indexed = tasks.map((task, i) => ({ task, originalIndex: i }));
|
|
67
|
+
|
|
68
|
+
const sorted = [...indexed].sort((a, b) => {
|
|
69
|
+
// Wave ordering first
|
|
70
|
+
const waveA = a.task.wave ?? Infinity;
|
|
71
|
+
const waveB = b.task.wave ?? Infinity;
|
|
72
|
+
if (waveA !== waveB) return waveA - waveB;
|
|
73
|
+
|
|
74
|
+
// Then by dependency depth
|
|
75
|
+
const depthA = depthMap.get(a.task.id) || 0;
|
|
76
|
+
const depthB = depthMap.get(b.task.id) || 0;
|
|
77
|
+
if (depthA !== depthB) return depthA - depthB;
|
|
78
|
+
|
|
79
|
+
// Preserve original order as tiebreaker
|
|
80
|
+
return a.originalIndex - b.originalIndex;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return sorted.map(item => item.task);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Dispatches a single task to an executor function.
|
|
88
|
+
* Returns the result wrapped in a status envelope.
|
|
89
|
+
* @param {object} task — A normalized task object
|
|
90
|
+
* @param {function} executor — async function(task) => result
|
|
91
|
+
* @returns {Promise<{ task_id: string, status: string, result?: any, error?: string, duration_ms: number }>}
|
|
92
|
+
*/
|
|
93
|
+
async function dispatchTask(task, executor) {
|
|
94
|
+
const start = Date.now();
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const result = await executor(task);
|
|
98
|
+
return Object.freeze({
|
|
99
|
+
task_id: task.id,
|
|
100
|
+
status: 'completed',
|
|
101
|
+
result,
|
|
102
|
+
duration_ms: Date.now() - start,
|
|
103
|
+
});
|
|
104
|
+
} catch (err) {
|
|
105
|
+
return Object.freeze({
|
|
106
|
+
task_id: task.id,
|
|
107
|
+
status: 'failed',
|
|
108
|
+
error: err.message,
|
|
109
|
+
duration_ms: Date.now() - start,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
module.exports = { parseHandoff, prioritizeTasks, dispatchTask };
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — Wave Executor
|
|
3
|
+
* Extracted from auto-runner.js — handles wave orchestration: grouping tasks
|
|
4
|
+
* into waves, executing waves in sequence, and managing wave dependencies.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const crypto = require('crypto');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates a wave executor with the given configuration.
|
|
12
|
+
* @param {object} config
|
|
13
|
+
* @param {function} [config.onTaskStart] — Called when a task begins
|
|
14
|
+
* @param {function} [config.onTaskComplete] — Called when a task finishes
|
|
15
|
+
* @param {function} [config.onTaskFail] — Called when a task fails
|
|
16
|
+
* @param {function} [config.onWaveStart] — Called when a wave begins
|
|
17
|
+
* @param {function} [config.onWaveComplete] — Called when a wave finishes
|
|
18
|
+
* @returns {{ planWaves, executeWave, getWaveStatus }}
|
|
19
|
+
*/
|
|
20
|
+
function createWaveExecutor(config = {}) {
|
|
21
|
+
const {
|
|
22
|
+
onTaskStart = () => {},
|
|
23
|
+
onTaskComplete = () => {},
|
|
24
|
+
onTaskFail = () => {},
|
|
25
|
+
onWaveStart = () => {},
|
|
26
|
+
onWaveComplete = () => {},
|
|
27
|
+
} = config;
|
|
28
|
+
|
|
29
|
+
// Internal state — immutable snapshots exposed via getWaveStatus
|
|
30
|
+
let waves = [];
|
|
31
|
+
let currentWaveIndex = 0;
|
|
32
|
+
let completedTasks = new Set();
|
|
33
|
+
let status = 'idle'; // idle | running | paused | completed
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Groups handoff tasks into sequential waves based on wave field or dependency topology.
|
|
37
|
+
* Returns a new array of wave objects — does not mutate input.
|
|
38
|
+
* @param {Array} handoffs — Raw handoffs array from HANDOFF.json
|
|
39
|
+
* @returns {Array<{ wave: number, tasks: Array }>}
|
|
40
|
+
*/
|
|
41
|
+
function planWaves(handoffs) {
|
|
42
|
+
if (!Array.isArray(handoffs) || handoffs.length === 0) {
|
|
43
|
+
waves = [];
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const hasWaveField = handoffs.some(h => typeof h.wave === 'number');
|
|
48
|
+
|
|
49
|
+
if (hasWaveField) {
|
|
50
|
+
const byWave = new Map();
|
|
51
|
+
for (const h of handoffs) {
|
|
52
|
+
const w = h.wave ?? 0;
|
|
53
|
+
if (!byWave.has(w)) byWave.set(w, []);
|
|
54
|
+
byWave.get(w).push(normalizeTask(h));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
waves = Array.from(byWave.entries())
|
|
58
|
+
.sort((a, b) => a[0] - b[0])
|
|
59
|
+
.map(([waveNum, tasks]) => Object.freeze({ wave: waveNum, tasks: Object.freeze(tasks) }));
|
|
60
|
+
} else {
|
|
61
|
+
// Single wave with all tasks
|
|
62
|
+
waves = [Object.freeze({
|
|
63
|
+
wave: 0,
|
|
64
|
+
tasks: Object.freeze(handoffs.map(normalizeTask)),
|
|
65
|
+
})];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
currentWaveIndex = 0;
|
|
69
|
+
completedTasks = new Set();
|
|
70
|
+
status = 'idle';
|
|
71
|
+
|
|
72
|
+
return waves;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Executes a single wave — runs tasks sequentially, skipping already-completed ones.
|
|
77
|
+
* @param {object} wave — A wave object from planWaves
|
|
78
|
+
* @param {object} context — Execution context passed to callbacks
|
|
79
|
+
* @param {object} context.executor — async function(task) => result (performs actual work)
|
|
80
|
+
* @returns {Promise<{ completed: string[], failed: string[], skipped: string[] }>}
|
|
81
|
+
*/
|
|
82
|
+
async function executeWave(wave, context = {}) {
|
|
83
|
+
const { executor = async () => {} } = context;
|
|
84
|
+
status = 'running';
|
|
85
|
+
|
|
86
|
+
const pending = wave.tasks.filter(t => !completedTasks.has(t.id));
|
|
87
|
+
const result = { completed: [], failed: [], skipped: [] };
|
|
88
|
+
|
|
89
|
+
onWaveStart({ wave: wave.wave, taskCount: pending.length });
|
|
90
|
+
|
|
91
|
+
for (const task of pending) {
|
|
92
|
+
const taskStart = Date.now();
|
|
93
|
+
onTaskStart({ task, wave: wave.wave });
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
await executor(task);
|
|
97
|
+
|
|
98
|
+
const duration = Date.now() - taskStart;
|
|
99
|
+
completedTasks = new Set([...completedTasks, task.id]);
|
|
100
|
+
result.completed.push(task.id);
|
|
101
|
+
|
|
102
|
+
onTaskComplete({ task, wave: wave.wave, duration_ms: duration });
|
|
103
|
+
} catch (err) {
|
|
104
|
+
const duration = Date.now() - taskStart;
|
|
105
|
+
result.failed.push(task.id);
|
|
106
|
+
|
|
107
|
+
onTaskFail({ task, wave: wave.wave, error: err, duration_ms: duration });
|
|
108
|
+
|
|
109
|
+
// Re-throw to let caller decide on retry/escalation strategy
|
|
110
|
+
throw err;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
currentWaveIndex++;
|
|
115
|
+
onWaveComplete({ wave: wave.wave, result });
|
|
116
|
+
|
|
117
|
+
if (currentWaveIndex >= waves.length) {
|
|
118
|
+
status = 'completed';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return Object.freeze(result);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Returns a snapshot of the current wave execution status.
|
|
126
|
+
*/
|
|
127
|
+
function getWaveStatus() {
|
|
128
|
+
return Object.freeze({
|
|
129
|
+
status,
|
|
130
|
+
currentWaveIndex,
|
|
131
|
+
totalWaves: waves.length,
|
|
132
|
+
completedTasks: Array.from(completedTasks),
|
|
133
|
+
waves: waves.map(w => Object.freeze({
|
|
134
|
+
wave: w.wave,
|
|
135
|
+
taskCount: w.tasks.length,
|
|
136
|
+
completedCount: w.tasks.filter(t => completedTasks.has(t.id)).length,
|
|
137
|
+
})),
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Restores progress from a previously saved state.
|
|
143
|
+
* @param {{ currentWaveIndex: number, completedTasks: string[] }} savedState
|
|
144
|
+
*/
|
|
145
|
+
function restore(savedState) {
|
|
146
|
+
if (savedState && typeof savedState.currentWaveIndex === 'number') {
|
|
147
|
+
currentWaveIndex = savedState.currentWaveIndex;
|
|
148
|
+
}
|
|
149
|
+
if (savedState && Array.isArray(savedState.completedTasks)) {
|
|
150
|
+
completedTasks = new Set(savedState.completedTasks);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return Object.freeze({ planWaves, executeWave, getWaveStatus, restore });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Normalizes a raw handoff entry into a clean task object.
|
|
159
|
+
*/
|
|
160
|
+
function normalizeTask(h) {
|
|
161
|
+
return Object.freeze({
|
|
162
|
+
id: h.id || h.task_id || `task_${crypto.randomBytes(4).toString('hex')}`,
|
|
163
|
+
name: h.name || h.task || h.description || h.id || 'unnamed-task',
|
|
164
|
+
plan: h.plan || null,
|
|
165
|
+
depends_on: Array.isArray(h.depends_on) ? [...h.depends_on] : [],
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
module.exports = { createWaveExecutor };
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
const http = require('http');
|
|
9
|
+
const crypto = require('crypto');
|
|
9
10
|
const playwright = require('playwright-core');
|
|
10
11
|
const fs = require('fs');
|
|
11
12
|
const path = require('path');
|
|
@@ -14,6 +15,26 @@ const PORT = process.env.BROWSER_PORT || 7338;
|
|
|
14
15
|
const HEADLESS = process.env.BROWSER_HEADLESS !== 'false';
|
|
15
16
|
const TIMEOUT = (parseInt(process.env.BROWSER_IDLE_TIMEOUT_MINUTES) || 30) * 60 * 1000;
|
|
16
17
|
|
|
18
|
+
// ── Bearer token authentication ──────────────────────────────────────────────
|
|
19
|
+
const DAEMON_TOKEN = crypto.randomBytes(32).toString('hex');
|
|
20
|
+
const DAEMON_TOKEN_FILE = path.join(process.cwd(), '.mindforge', '.browser-daemon-token');
|
|
21
|
+
|
|
22
|
+
// Write token to file with restrictive permissions (owner-only read/write)
|
|
23
|
+
fs.mkdirSync(path.dirname(DAEMON_TOKEN_FILE), { recursive: true });
|
|
24
|
+
fs.writeFileSync(DAEMON_TOKEN_FILE, DAEMON_TOKEN, { mode: 0o600 });
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Validate bearer token from Authorization header.
|
|
28
|
+
* Returns true if valid, false otherwise.
|
|
29
|
+
*/
|
|
30
|
+
function isAuthValid(req) {
|
|
31
|
+
const authHeader = req.headers.authorization;
|
|
32
|
+
if (!authHeader || !authHeader.startsWith('Bearer ')) return false;
|
|
33
|
+
const provided = authHeader.slice(7);
|
|
34
|
+
if (provided.length !== DAEMON_TOKEN.length) return false;
|
|
35
|
+
return crypto.timingSafeEqual(Buffer.from(provided), Buffer.from(DAEMON_TOKEN));
|
|
36
|
+
}
|
|
37
|
+
|
|
17
38
|
let browser, lastActionAt = Date.now(), isLaunching = false;
|
|
18
39
|
const sessions = new Map(); // name -> { context, page }
|
|
19
40
|
|
|
@@ -98,6 +119,9 @@ const server = http.createServer(async (req, res) => {
|
|
|
98
119
|
}
|
|
99
120
|
|
|
100
121
|
if (req.url === '/evaluate' && req.method === 'POST') {
|
|
122
|
+
if (!isAuthValid(req)) {
|
|
123
|
+
return send({ error: 'Authentication required. Use the token printed at daemon startup.' }, 401);
|
|
124
|
+
}
|
|
101
125
|
const result = await page.evaluate(script);
|
|
102
126
|
return send({ success: true, result });
|
|
103
127
|
}
|
|
@@ -123,7 +147,11 @@ const server = http.createServer(async (req, res) => {
|
|
|
123
147
|
});
|
|
124
148
|
|
|
125
149
|
init().then(() => {
|
|
126
|
-
server.listen(PORT, '127.0.0.1', () =>
|
|
150
|
+
server.listen(PORT, '127.0.0.1', () => {
|
|
151
|
+
console.log(`[BrowserDaemon] Listening on port ${PORT}`);
|
|
152
|
+
console.log(`[BrowserDaemon] Auth token: ${DAEMON_TOKEN}`);
|
|
153
|
+
console.log(`[BrowserDaemon] Token file: ${DAEMON_TOKEN_FILE}`);
|
|
154
|
+
});
|
|
127
155
|
}).catch(err => {
|
|
128
156
|
console.error('[daemon] Initialization failed:', err);
|
|
129
157
|
process.exit(1);
|
|
@@ -131,6 +159,8 @@ init().then(() => {
|
|
|
131
159
|
|
|
132
160
|
async function shutdown() {
|
|
133
161
|
console.log('[daemon] Shutting down gracefully...');
|
|
162
|
+
// Remove sensitive token file on shutdown
|
|
163
|
+
if (fs.existsSync(DAEMON_TOKEN_FILE)) fs.unlinkSync(DAEMON_TOKEN_FILE);
|
|
134
164
|
if (browser) await browser.close();
|
|
135
165
|
process.exit(0);
|
|
136
166
|
}
|
package/bin/change-classifier.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
const { execSync } = require('child_process');
|
|
9
|
+
const { execSync, execFileSync } = require('child_process');
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
|
|
12
12
|
const SENSITIVE_PATHS = [
|
|
@@ -33,7 +33,7 @@ function classify() {
|
|
|
33
33
|
try {
|
|
34
34
|
// Get list of changed files compared to origin/main or HEAD~1
|
|
35
35
|
const base = process.env.GITHUB_BASE_REF ? `origin/${process.env.GITHUB_BASE_REF}` : 'HEAD~1';
|
|
36
|
-
const diffFiles =
|
|
36
|
+
const diffFiles = execFileSync('git', ['diff', '--name-only', `${base}..HEAD`], { encoding: 'utf8' }).split('\n').filter(Boolean);
|
|
37
37
|
|
|
38
38
|
let tier = 1;
|
|
39
39
|
let reasons = [];
|
|
@@ -47,7 +47,7 @@ function classify() {
|
|
|
47
47
|
|
|
48
48
|
// 2. Pattern-based detection in diff (Tier 3)
|
|
49
49
|
if (tier < 3) {
|
|
50
|
-
const diffContent =
|
|
50
|
+
const diffContent = execFileSync('git', ['diff', `${base}..HEAD`], { encoding: 'utf8' });
|
|
51
51
|
for (const pattern of SENSITIVE_PATTERNS) {
|
|
52
52
|
if (pattern.test(diffContent)) {
|
|
53
53
|
tier = 3;
|
|
@@ -130,18 +130,29 @@ function register(app) {
|
|
|
130
130
|
});
|
|
131
131
|
|
|
132
132
|
// ── Steering (requires auto mode running) ───────────────────────────────────
|
|
133
|
+
const VALID_STEER_ACTIONS = ['pause', 'resume', 'switch_phase', 'priority_bump', 'skip_task', 'abort'];
|
|
134
|
+
|
|
133
135
|
app.post('/api/steer', (req, res) => {
|
|
134
136
|
try {
|
|
135
|
-
const {
|
|
137
|
+
const { action, params = {} } = req.body || {};
|
|
136
138
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
// Validate action is present and in allowlist
|
|
140
|
+
if (!action || typeof action !== 'string') {
|
|
141
|
+
return res.status(400).json({
|
|
142
|
+
error: `Invalid action. Valid actions: ${VALID_STEER_ACTIONS.join(', ')}`
|
|
143
|
+
});
|
|
139
144
|
}
|
|
140
|
-
if (
|
|
141
|
-
return res.status(400).json({
|
|
145
|
+
if (!VALID_STEER_ACTIONS.includes(action)) {
|
|
146
|
+
return res.status(400).json({
|
|
147
|
+
error: `Invalid action. Valid actions: ${VALID_STEER_ACTIONS.join(', ')}`
|
|
148
|
+
});
|
|
142
149
|
}
|
|
143
|
-
|
|
144
|
-
|
|
150
|
+
|
|
151
|
+
// If params contains freeText, cap at 200 characters
|
|
152
|
+
if (params.freeText && typeof params.freeText === 'string') {
|
|
153
|
+
if (params.freeText.length > 200) {
|
|
154
|
+
return res.status(400).json({ error: 'params.freeText exceeds 200 character limit' });
|
|
155
|
+
}
|
|
145
156
|
}
|
|
146
157
|
|
|
147
158
|
// Check auto mode is running
|
|
@@ -153,24 +164,12 @@ function register(app) {
|
|
|
153
164
|
return res.status(409).json({ error: 'Auto mode is not running. Steering has no effect.' });
|
|
154
165
|
}
|
|
155
166
|
|
|
156
|
-
// Run injection guard
|
|
157
|
-
const INJECTION_PATTERNS = [
|
|
158
|
-
/IGNORE ALL PREVIOUS INSTRUCTIONS/i,
|
|
159
|
-
/DISREGARD YOUR INSTRUCTIONS/i,
|
|
160
|
-
/FORGET YOUR TRAINING/i,
|
|
161
|
-
/YOUR NEW INSTRUCTIONS ARE/i,
|
|
162
|
-
/OVERRIDE:/i,
|
|
163
|
-
];
|
|
164
|
-
if (INJECTION_PATTERNS.some(p => p.test(instruction))) {
|
|
165
|
-
return res.status(400).json({ error: 'Instruction rejected: contains prohibited patterns' });
|
|
166
|
-
}
|
|
167
|
-
|
|
168
167
|
// Write to steering queue
|
|
169
168
|
const entry = {
|
|
170
169
|
id: require('crypto').randomBytes(8).toString('hex'),
|
|
171
170
|
timestamp: new Date().toISOString(),
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
action,
|
|
172
|
+
params,
|
|
174
173
|
authored_by: 'dashboard',
|
|
175
174
|
applies_to: 'all',
|
|
176
175
|
status: 'queued',
|
|
@@ -183,7 +182,7 @@ function register(app) {
|
|
|
183
182
|
}
|
|
184
183
|
fs.appendFileSync(STEERING_QUEUE, JSON.stringify(entry) + '\n');
|
|
185
184
|
|
|
186
|
-
res.json({ success: true, queued: true, id: entry.id,
|
|
185
|
+
res.json({ success: true, queued: true, id: entry.id, action });
|
|
187
186
|
} catch (err) {
|
|
188
187
|
res.status(500).json({ error: err.message });
|
|
189
188
|
}
|
|
@@ -8,6 +8,24 @@
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
10
|
|
|
11
|
+
// ── TTL Cache (5-second window) ──────────────────────────────────────────────
|
|
12
|
+
const _cache = new Map();
|
|
13
|
+
const CACHE_TTL_MS = 5000;
|
|
14
|
+
|
|
15
|
+
function cacheGet(key) {
|
|
16
|
+
const entry = _cache.get(key);
|
|
17
|
+
if (!entry) return undefined;
|
|
18
|
+
if (Date.now() - entry.timestamp >= CACHE_TTL_MS) {
|
|
19
|
+
_cache.delete(key);
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
return entry.data;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function cacheSet(key, data) {
|
|
26
|
+
_cache.set(key, { data, timestamp: Date.now() });
|
|
27
|
+
}
|
|
28
|
+
|
|
11
29
|
// Paths are resolved lazily to support testing in temp directories
|
|
12
30
|
const getPaths = () => ({
|
|
13
31
|
quality: path.join(process.cwd(), '.mindforge', 'metrics', 'session-quality.jsonl'),
|
|
@@ -70,6 +88,10 @@ function getStatus() {
|
|
|
70
88
|
|
|
71
89
|
// ── Audit ─────────────────────────────────────────────────────────────────────
|
|
72
90
|
function getAuditEntries(limit = 50, offset = 0, eventFilter = null) {
|
|
91
|
+
const cacheKey = `audit:${limit}:${offset}:${eventFilter || ''}`;
|
|
92
|
+
const cached = cacheGet(cacheKey);
|
|
93
|
+
if (cached !== undefined) return cached;
|
|
94
|
+
|
|
73
95
|
const paths = getPaths();
|
|
74
96
|
const all = readJSONL(paths.audit, 1000);
|
|
75
97
|
const reversed = all.reverse(); // Newest first
|
|
@@ -78,16 +100,22 @@ function getAuditEntries(limit = 50, offset = 0, eventFilter = null) {
|
|
|
78
100
|
? reversed.filter(e => e.event === eventFilter)
|
|
79
101
|
: reversed;
|
|
80
102
|
|
|
81
|
-
|
|
103
|
+
const result = {
|
|
82
104
|
entries: filtered.slice(offset, offset + limit),
|
|
83
105
|
total: filtered.length,
|
|
84
106
|
limit,
|
|
85
107
|
offset,
|
|
86
108
|
};
|
|
109
|
+
|
|
110
|
+
cacheSet(cacheKey, result);
|
|
111
|
+
return result;
|
|
87
112
|
}
|
|
88
113
|
|
|
89
114
|
// ── Metrics ───────────────────────────────────────────────────────────────────
|
|
90
115
|
function getMetrics() {
|
|
116
|
+
const cached = cacheGet('metrics');
|
|
117
|
+
if (cached !== undefined) return cached;
|
|
118
|
+
|
|
91
119
|
const paths = getPaths();
|
|
92
120
|
const qualityEntries = readJSONL(paths.quality, 20);
|
|
93
121
|
const usageEntries = readJSONL(paths.usage, 200);
|
|
@@ -123,7 +151,7 @@ function getMetrics() {
|
|
|
123
151
|
const node_repair_rate = taskEvents.length
|
|
124
152
|
? repairEvents.length / taskEvents.length : 0;
|
|
125
153
|
|
|
126
|
-
|
|
154
|
+
const result = {
|
|
127
155
|
sessions,
|
|
128
156
|
avg_quality: Math.round(avg_quality * 100) / 100,
|
|
129
157
|
avg_cost_usd: Math.round(avg_cost_usd * 10000) / 10000,
|
|
@@ -131,6 +159,9 @@ function getMetrics() {
|
|
|
131
159
|
node_repair_rate: Math.round(node_repair_rate * 100) / 100,
|
|
132
160
|
total_tasks: taskEvents.filter(e => e.event === 'task_completed').length,
|
|
133
161
|
};
|
|
162
|
+
|
|
163
|
+
cacheSet('metrics', result);
|
|
164
|
+
return result;
|
|
134
165
|
}
|
|
135
166
|
|
|
136
167
|
// ── Approvals ─────────────────────────────────────────────────────────────────
|
|
@@ -168,6 +199,9 @@ function getApprovals() {
|
|
|
168
199
|
|
|
169
200
|
// ── Team activity ─────────────────────────────────────────────────────────────
|
|
170
201
|
function getTeamActivity() {
|
|
202
|
+
const cached = cacheGet('teamActivity');
|
|
203
|
+
if (cached !== undefined) return cached;
|
|
204
|
+
|
|
171
205
|
const paths = getPaths();
|
|
172
206
|
const auditEntries = readJSONL(paths.audit, 200);
|
|
173
207
|
|
|
@@ -197,7 +231,9 @@ function getTeamActivity() {
|
|
|
197
231
|
// Conflict detection — two authors recently touching same file
|
|
198
232
|
const conflicts = detectFileConflicts(auditEntries);
|
|
199
233
|
|
|
200
|
-
|
|
234
|
+
const result = { active, conflicts };
|
|
235
|
+
cacheSet('teamActivity', result);
|
|
236
|
+
return result;
|
|
201
237
|
}
|
|
202
238
|
|
|
203
239
|
function detectFileConflicts(auditEntries) {
|
|
@@ -249,6 +285,10 @@ function getMemory(query = '', limit = 20) {
|
|
|
249
285
|
|
|
250
286
|
// ── Costs ─────────────────────────────────────────────────────────────────────
|
|
251
287
|
function getCosts(windowDays = 7) {
|
|
288
|
+
const cacheKey = `costs:${windowDays}`;
|
|
289
|
+
const cached = cacheGet(cacheKey);
|
|
290
|
+
if (cached !== undefined) return cached;
|
|
291
|
+
|
|
252
292
|
const paths = getPaths();
|
|
253
293
|
const entries = readJSONL(paths.usage, 1000);
|
|
254
294
|
const cutoff = new Date(Date.now() - windowDays * 86_400_000).toISOString().slice(0, 10);
|
|
@@ -282,6 +322,7 @@ function getCosts(windowDays = 7) {
|
|
|
282
322
|
stats.by_model[m] = Math.round(stats.by_model[m] * 100) / 100;
|
|
283
323
|
}
|
|
284
324
|
|
|
325
|
+
cacheSet(cacheKey, stats);
|
|
285
326
|
return stats;
|
|
286
327
|
}
|
|
287
328
|
|