mindforge-cc 1.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/.agent/CLAUDE.md +462 -0
- package/.agent/forge/help.md +7 -0
- package/.agent/forge/init-project.md +32 -0
- package/.agent/forge/plan-phase.md +30 -0
- package/.agent/mindforge/approve.md +18 -0
- package/.agent/mindforge/audit.md +30 -0
- package/.agent/mindforge/benchmark.md +33 -0
- package/.agent/mindforge/complete-milestone.md +18 -0
- package/.agent/mindforge/debug.md +126 -0
- package/.agent/mindforge/discuss-phase.md +138 -0
- package/.agent/mindforge/execute-phase.md +165 -0
- package/.agent/mindforge/health.md +21 -0
- package/.agent/mindforge/help.md +23 -0
- package/.agent/mindforge/init-org.md +131 -0
- package/.agent/mindforge/init-project.md +155 -0
- package/.agent/mindforge/install-skill.md +15 -0
- package/.agent/mindforge/map-codebase.md +298 -0
- package/.agent/mindforge/metrics.md +22 -0
- package/.agent/mindforge/migrate.md +40 -0
- package/.agent/mindforge/milestone.md +12 -0
- package/.agent/mindforge/next.md +105 -0
- package/.agent/mindforge/plan-phase.md +125 -0
- package/.agent/mindforge/plugins.md +40 -0
- package/.agent/mindforge/pr-review.md +41 -0
- package/.agent/mindforge/profile-team.md +23 -0
- package/.agent/mindforge/publish-skill.md +19 -0
- package/.agent/mindforge/quick.md +135 -0
- package/.agent/mindforge/release.md +10 -0
- package/.agent/mindforge/retrospective.md +26 -0
- package/.agent/mindforge/review.md +157 -0
- package/.agent/mindforge/security-scan.md +233 -0
- package/.agent/mindforge/ship.md +100 -0
- package/.agent/mindforge/skills.md +141 -0
- package/.agent/mindforge/status.md +104 -0
- package/.agent/mindforge/sync-confluence.md +11 -0
- package/.agent/mindforge/sync-jira.md +12 -0
- package/.agent/mindforge/tokens.md +8 -0
- package/.agent/mindforge/update.md +42 -0
- package/.agent/mindforge/verify-phase.md +62 -0
- package/.agent/mindforge/workspace.md +29 -0
- package/.claude/CLAUDE.md +462 -0
- package/.claude/commands/forge/help.md +7 -0
- package/.claude/commands/forge/init-project.md +32 -0
- package/.claude/commands/forge/plan-phase.md +30 -0
- package/.claude/commands/mindforge/approve.md +18 -0
- package/.claude/commands/mindforge/audit.md +30 -0
- package/.claude/commands/mindforge/benchmark.md +33 -0
- package/.claude/commands/mindforge/complete-milestone.md +18 -0
- package/.claude/commands/mindforge/debug.md +126 -0
- package/.claude/commands/mindforge/discuss-phase.md +138 -0
- package/.claude/commands/mindforge/execute-phase.md +165 -0
- package/.claude/commands/mindforge/health.md +21 -0
- package/.claude/commands/mindforge/help.md +23 -0
- package/.claude/commands/mindforge/init-org.md +131 -0
- package/.claude/commands/mindforge/init-project.md +155 -0
- package/.claude/commands/mindforge/install-skill.md +15 -0
- package/.claude/commands/mindforge/map-codebase.md +298 -0
- package/.claude/commands/mindforge/metrics.md +22 -0
- package/.claude/commands/mindforge/migrate.md +40 -0
- package/.claude/commands/mindforge/milestone.md +12 -0
- package/.claude/commands/mindforge/next.md +105 -0
- package/.claude/commands/mindforge/plan-phase.md +125 -0
- package/.claude/commands/mindforge/plugins.md +40 -0
- package/.claude/commands/mindforge/pr-review.md +41 -0
- package/.claude/commands/mindforge/profile-team.md +23 -0
- package/.claude/commands/mindforge/publish-skill.md +19 -0
- package/.claude/commands/mindforge/quick.md +135 -0
- package/.claude/commands/mindforge/release.md +10 -0
- package/.claude/commands/mindforge/retrospective.md +26 -0
- package/.claude/commands/mindforge/review.md +157 -0
- package/.claude/commands/mindforge/security-scan.md +233 -0
- package/.claude/commands/mindforge/ship.md +100 -0
- package/.claude/commands/mindforge/skills.md +141 -0
- package/.claude/commands/mindforge/status.md +104 -0
- package/.claude/commands/mindforge/sync-confluence.md +11 -0
- package/.claude/commands/mindforge/sync-jira.md +12 -0
- package/.claude/commands/mindforge/tokens.md +8 -0
- package/.claude/commands/mindforge/update.md +42 -0
- package/.claude/commands/mindforge/verify-phase.md +62 -0
- package/.claude/commands/mindforge/workspace.md +29 -0
- package/.forge/org/CONVENTIONS.md +0 -0
- package/.forge/org/ORG.md +0 -0
- package/.forge/org/SECURITY.md +0 -0
- package/.forge/org/TOOLS.md +0 -0
- package/.forge/personas/analyst.md +0 -0
- package/.forge/personas/architect.md +0 -0
- package/.forge/personas/debug-specialist.md +0 -0
- package/.forge/personas/developer.md +26 -0
- package/.forge/personas/qa-engineer.md +0 -0
- package/.forge/personas/release-manager.md +0 -0
- package/.forge/personas/security-reviewer.md +33 -0
- package/.forge/personas/tech-writer.md +0 -0
- package/.forge/skills/api-design/SKILL.md +0 -0
- package/.forge/skills/code-quality/SKILL.md +0 -0
- package/.forge/skills/documentation/SKILL.md +0 -0
- package/.forge/skills/security-review/SKILL.md +23 -0
- package/.forge/skills/testing-standards/SKILL.md +27 -0
- package/.github/workflows/mindforge-ci.yml +224 -0
- package/.gitlab-ci-mindforge.yml +18 -0
- package/.mindforge/MINDFORGE-SCHEMA.json +165 -0
- package/.mindforge/audit/AUDIT-SCHEMA.md +451 -0
- package/.mindforge/ci/ci-config-schema.md +21 -0
- package/.mindforge/ci/ci-mode.md +179 -0
- package/.mindforge/ci/github-actions-adapter.md +224 -0
- package/.mindforge/ci/gitlab-ci-adapter.md +31 -0
- package/.mindforge/ci/jenkins-adapter.md +44 -0
- package/.mindforge/distribution/registry-client.md +166 -0
- package/.mindforge/distribution/registry-schema.md +96 -0
- package/.mindforge/distribution/skill-publisher.md +44 -0
- package/.mindforge/distribution/skill-validator.md +74 -0
- package/.mindforge/engine/compaction-protocol.md +182 -0
- package/.mindforge/engine/context-injector.md +128 -0
- package/.mindforge/engine/dependency-parser.md +113 -0
- package/.mindforge/engine/skills/conflict-resolver.md +69 -0
- package/.mindforge/engine/skills/loader.md +184 -0
- package/.mindforge/engine/skills/registry.md +98 -0
- package/.mindforge/engine/skills/versioning.md +75 -0
- package/.mindforge/engine/verification-pipeline.md +111 -0
- package/.mindforge/engine/wave-executor.md +235 -0
- package/.mindforge/governance/GOVERNANCE-CONFIG.md +17 -0
- package/.mindforge/governance/approval-workflow.md +37 -0
- package/.mindforge/governance/change-classifier.md +63 -0
- package/.mindforge/governance/compliance-gates.md +31 -0
- package/.mindforge/integrations/confluence.md +27 -0
- package/.mindforge/integrations/connection-manager.md +163 -0
- package/.mindforge/integrations/github.md +25 -0
- package/.mindforge/integrations/gitlab.md +13 -0
- package/.mindforge/integrations/jira.md +102 -0
- package/.mindforge/integrations/slack.md +41 -0
- package/.mindforge/intelligence/antipattern-detector.md +75 -0
- package/.mindforge/intelligence/difficulty-scorer.md +55 -0
- package/.mindforge/intelligence/health-engine.md +208 -0
- package/.mindforge/intelligence/skill-gap-analyser.md +40 -0
- package/.mindforge/intelligence/smart-compaction.md +71 -0
- package/.mindforge/metrics/METRICS-SCHEMA.md +42 -0
- package/.mindforge/metrics/quality-tracker.md +32 -0
- package/.mindforge/monorepo/cross-package-planner.md +114 -0
- package/.mindforge/monorepo/dependency-graph-builder.md +32 -0
- package/.mindforge/monorepo/workspace-detector.md +129 -0
- package/.mindforge/org/CONVENTIONS.md +62 -0
- package/.mindforge/org/ORG.md +51 -0
- package/.mindforge/org/SECURITY.md +50 -0
- package/.mindforge/org/TOOLS.md +53 -0
- package/.mindforge/org/integrations/INTEGRATIONS-CONFIG.md +58 -0
- package/.mindforge/org/skills/MANIFEST.md +38 -0
- package/.mindforge/personas/analyst.md +52 -0
- package/.mindforge/personas/architect.md +75 -0
- package/.mindforge/personas/debug-specialist.md +52 -0
- package/.mindforge/personas/developer.md +85 -0
- package/.mindforge/personas/overrides/README.md +85 -0
- package/.mindforge/personas/qa-engineer.md +61 -0
- package/.mindforge/personas/release-manager.md +76 -0
- package/.mindforge/personas/security-reviewer.md +91 -0
- package/.mindforge/personas/tech-writer.md +51 -0
- package/.mindforge/plugins/PLUGINS-MANIFEST.md +23 -0
- package/.mindforge/plugins/plugin-loader.md +93 -0
- package/.mindforge/plugins/plugin-registry.md +44 -0
- package/.mindforge/plugins/plugin-schema.md +68 -0
- package/.mindforge/pr-review/ai-reviewer.md +266 -0
- package/.mindforge/pr-review/finding-formatter.md +46 -0
- package/.mindforge/pr-review/review-prompt-templates.md +44 -0
- package/.mindforge/production/compatibility-layer.md +39 -0
- package/.mindforge/production/migration-engine.md +52 -0
- package/.mindforge/production/production-checklist.md +165 -0
- package/.mindforge/production/token-optimiser.md +68 -0
- package/.mindforge/skills/accessibility/SKILL.md +106 -0
- package/.mindforge/skills/api-design/SKILL.md +98 -0
- package/.mindforge/skills/code-quality/SKILL.md +88 -0
- package/.mindforge/skills/data-privacy/SKILL.md +126 -0
- package/.mindforge/skills/database-patterns/SKILL.md +192 -0
- package/.mindforge/skills/documentation/SKILL.md +91 -0
- package/.mindforge/skills/incident-response/SKILL.md +180 -0
- package/.mindforge/skills/performance/SKILL.md +120 -0
- package/.mindforge/skills/security-review/SKILL.md +83 -0
- package/.mindforge/skills/testing-standards/SKILL.md +97 -0
- package/.mindforge/team/TEAM-PROFILE.md +42 -0
- package/.mindforge/team/multi-handoff.md +23 -0
- package/.mindforge/team/profiles/README.md +13 -0
- package/.mindforge/team/session-merger.md +18 -0
- package/.planning/ARCHITECTURE.md +0 -0
- package/.planning/AUDIT.jsonl +0 -0
- package/.planning/HANDOFF.json +28 -0
- package/.planning/PROJECT.md +33 -0
- package/.planning/RELEASE-CHECKLIST.md +68 -0
- package/.planning/REQUIREMENTS.md +0 -0
- package/.planning/ROADMAP.md +0 -0
- package/.planning/STATE.md +31 -0
- package/.planning/approvals/.gitkeep +1 -0
- package/.planning/archive/.gitkeep +1 -0
- package/.planning/audit-archive/.gitkeep +1 -0
- package/.planning/decisions/.gitkeep +0 -0
- package/.planning/decisions/ADR-001-handoff-tracking.md +41 -0
- package/.planning/decisions/ADR-002-markdown-commands.md +46 -0
- package/.planning/decisions/ADR-003-skills-trigger-model.md +37 -0
- package/.planning/decisions/ADR-004-wave-parallelism-model.md +45 -0
- package/.planning/decisions/ADR-005-append-only-audit-log.md +51 -0
- package/.planning/decisions/ADR-006-tiered-skills-system.md +22 -0
- package/.planning/decisions/ADR-007-trigger-keyword-model.md +22 -0
- package/.planning/decisions/ADR-008-just-in-time-skill-loading.md +29 -0
- package/.planning/decisions/ADR-009-enterprise-integration-retry-policy.md +8 -0
- package/.planning/decisions/ADR-010-governance-tier-escalation.md +8 -0
- package/.planning/decisions/ADR-011-multi-developer-handoff-contract.md +8 -0
- package/.planning/decisions/ADR-012-intelligence-feedback-loops.md +19 -0
- package/.planning/decisions/ADR-013-mindforge-md-constitution.md +16 -0
- package/.planning/decisions/ADR-014-metrics-as-signals-not-evaluation.md +15 -0
- package/.planning/decisions/ADR-015-npm-based-skill-registry.md +26 -0
- package/.planning/decisions/ADR-016-ci-exit-code-0-on-timeout.md +27 -0
- package/.planning/decisions/ADR-017-sdk-localhost-only.md +28 -0
- package/.planning/decisions/ADR-018-installer-self-install-detection.md +15 -0
- package/.planning/decisions/ADR-019-self-update-scope-preservation.md +14 -0
- package/.planning/decisions/ADR-020-v1.0.0-stable-interface-contract.md +23 -0
- package/.planning/jira-sync.json +9 -0
- package/.planning/milestones/.gitkeep +1 -0
- package/.planning/phases/day1/REVIEW-DAY1.md +50 -0
- package/.planning/phases/day1/SECURITY-REVIEW-DAY1.md +15 -0
- package/.planning/phases/day2/REVIEW-DAY2.md +521 -0
- package/.planning/phases/day3/REVIEW-DAY3.md +234 -0
- package/.planning/slack-threads.json +6 -0
- package/CHANGELOG.md +175 -0
- package/LICENSE +21 -0
- package/MINDFORGE.md +76 -0
- package/README.md +182 -0
- package/RELEASENOTES.md +41 -0
- package/SECURITY.md +4 -0
- package/bin/install.js +120 -0
- package/bin/installer-core.js +292 -0
- package/bin/migrations/0.1.0-to-0.5.0.js +37 -0
- package/bin/migrations/0.5.0-to-0.6.0.js +17 -0
- package/bin/migrations/0.6.0-to-1.0.0.js +100 -0
- package/bin/migrations/migrate.js +151 -0
- package/bin/migrations/schema-versions.js +64 -0
- package/bin/updater/changelog-fetcher.js +62 -0
- package/bin/updater/self-update.js +169 -0
- package/bin/updater/version-comparator.js +68 -0
- package/bin/validate-config.js +92 -0
- package/bin/wizard/config-generator.js +112 -0
- package/bin/wizard/environment-detector.js +76 -0
- package/bin/wizard/setup-wizard.js +237 -0
- package/docs/Context/Master-Context.md +701 -0
- package/docs/architecture/README.md +35 -0
- package/docs/architecture/decision-records-index.md +26 -0
- package/docs/ci-cd-integration.md +30 -0
- package/docs/ci-quickstart.md +78 -0
- package/docs/commands-reference.md +11 -0
- package/docs/contributing/CONTRIBUTING.md +38 -0
- package/docs/contributing/plugin-authoring.md +50 -0
- package/docs/contributing/skill-authoring.md +41 -0
- package/docs/enterprise-setup.md +25 -0
- package/docs/faq.md +38 -0
- package/docs/getting-started.md +36 -0
- package/docs/governance-guide.md +23 -0
- package/docs/mindforge-md-reference.md +53 -0
- package/docs/monorepo-guide.md +26 -0
- package/docs/persona-customisation.md +56 -0
- package/docs/quick-verify.md +33 -0
- package/docs/reference/audit-events.md +53 -0
- package/docs/reference/commands.md +82 -0
- package/docs/reference/config-reference.md +64 -0
- package/docs/reference/sdk-api.md +48 -0
- package/docs/reference/skills-api.md +57 -0
- package/docs/release-checklist-guide.md +37 -0
- package/docs/requirements.md +29 -0
- package/docs/sdk-reference.md +27 -0
- package/docs/security/SECURITY.md +42 -0
- package/docs/security/penetration-test-results.md +31 -0
- package/docs/security/threat-model.md +142 -0
- package/docs/skills-authoring-guide.md +119 -0
- package/docs/skills-publishing-guide.md +21 -0
- package/docs/team-setup-guide.md +21 -0
- package/docs/troubleshooting.md +119 -0
- package/docs/tutorial.md +195 -0
- package/docs/upgrade.md +44 -0
- package/docs/user-guide.md +131 -0
- package/docs/usp-features.md +214 -0
- package/eslint.config.mjs +31 -0
- package/examples/starter-project/.planning/AUDIT.jsonl +1 -0
- package/examples/starter-project/.planning/HANDOFF.json +23 -0
- package/examples/starter-project/.planning/PROJECT.md +27 -0
- package/examples/starter-project/.planning/STATE.md +10 -0
- package/examples/starter-project/MINDFORGE.md +40 -0
- package/examples/starter-project/README.md +14 -0
- package/implementation-roadmap/day-1-imp/DAY1-HARDEN.md +823 -0
- package/implementation-roadmap/day-1-imp/DAY1-IMPLEMENT.md +2459 -0
- package/implementation-roadmap/day-1-imp/DAY1-REVIEW.md +288 -0
- package/implementation-roadmap/day-2-imp/DAY2-HARDEN.md +954 -0
- package/implementation-roadmap/day-2-imp/DAY2-IMPLEMENT.md +2347 -0
- package/implementation-roadmap/day-2-imp/DAY2-REVIEW.md +422 -0
- package/implementation-roadmap/day-3-imp/DAY3-HARDEN.md +870 -0
- package/implementation-roadmap/day-3-imp/DAY3-IMPLEMENT.md +2798 -0
- package/implementation-roadmap/day-3-imp/DAY3-REVIEW.md +484 -0
- package/implementation-roadmap/day-4-imp/DAY4-HARDEN.md +1087 -0
- package/implementation-roadmap/day-4-imp/DAY4-IMPLEMENT.md +2874 -0
- package/implementation-roadmap/day-4-imp/DAY4-REVIEW.md +386 -0
- package/implementation-roadmap/day-5-imp/DAY5-HARDEN.md +1078 -0
- package/implementation-roadmap/day-5-imp/DAY5-IMPLEMENT.md +3151 -0
- package/implementation-roadmap/day-5-imp/DAY5-REVIEW.md +345 -0
- package/implementation-roadmap/day-6-imp/DAY6-COMPLETE.md +3919 -0
- package/implementation-roadmap/day-7-imp-prod/DAY7-PRODUCTION-FINAL.md +4513 -0
- package/package.json +31 -0
- package/sdk/README.md +69 -0
- package/sdk/eslint.config.mjs +34 -0
- package/sdk/package-lock.json +1507 -0
- package/sdk/package.json +30 -0
- package/sdk/src/client.ts +133 -0
- package/sdk/src/commands.ts +63 -0
- package/sdk/src/events.ts +166 -0
- package/sdk/src/index.ts +22 -0
- package/sdk/src/types.ts +87 -0
- package/sdk/tsconfig.json +13 -0
- package/tests/audit.test.js +206 -0
- package/tests/ci-mode.test.js +162 -0
- package/tests/compaction.test.js +161 -0
- package/tests/distribution.test.js +205 -0
- package/tests/e2e.test.js +618 -0
- package/tests/governance.test.js +130 -0
- package/tests/install.test.js +209 -0
- package/tests/integrations.test.js +128 -0
- package/tests/intelligence.test.js +117 -0
- package/tests/metrics.test.js +96 -0
- package/tests/migration.test.js +309 -0
- package/tests/production.test.js +416 -0
- package/tests/sdk.test.js +200 -0
- package/tests/skills-platform.test.js +403 -0
- package/tests/wave-engine.test.js +338 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge Day 7 — Migration Engine Tests
|
|
3
|
+
* Tests the migration logic without touching real .planning/ files.
|
|
4
|
+
*
|
|
5
|
+
* Run: node tests/migration.test.js
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const os = require('os');
|
|
12
|
+
const assert = require('assert');
|
|
13
|
+
let passed = 0, failed = 0;
|
|
14
|
+
|
|
15
|
+
function test(name, fn) {
|
|
16
|
+
try { fn(); console.log(` ✅ ${name}`); passed++; }
|
|
17
|
+
catch(e) { console.error(` ❌ ${name}\n ${e.message}`); failed++; }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ── Simulation helpers ─────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
function simulateHandoffMigration(handoff, toVersion) {
|
|
23
|
+
const result = JSON.parse(JSON.stringify(handoff));
|
|
24
|
+
if (toVersion === '0.5.0' || toVersion === '1.0.0') {
|
|
25
|
+
if (!Array.isArray(result.decisions_made)) result.decisions_made = [];
|
|
26
|
+
if (!Array.isArray(result.discoveries)) result.discoveries = [];
|
|
27
|
+
if (!Array.isArray(result.implicit_knowledge)) result.implicit_knowledge = [];
|
|
28
|
+
if (!Array.isArray(result.quality_signals)) result.quality_signals = [];
|
|
29
|
+
}
|
|
30
|
+
if (toVersion === '0.6.0' || toVersion === '1.0.0') {
|
|
31
|
+
if (!result.developer_id) result.developer_id = null;
|
|
32
|
+
if (!result.session_id) result.session_id = null;
|
|
33
|
+
if (!Array.isArray(result.recent_commits)) result.recent_commits = [];
|
|
34
|
+
if (!Array.isArray(result.recent_files)) result.recent_files = [];
|
|
35
|
+
}
|
|
36
|
+
if (toVersion === '1.0.0') {
|
|
37
|
+
if (!result.plugin_api_version) result.plugin_api_version = '1.0.0';
|
|
38
|
+
result.schema_version = '1.0.0';
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function simulateAuditMigration(lines) {
|
|
44
|
+
return lines.map(line => {
|
|
45
|
+
try {
|
|
46
|
+
const entry = JSON.parse(line);
|
|
47
|
+
if (!entry.session_id) {
|
|
48
|
+
return JSON.stringify({ ...entry, session_id: 'migrated-from-pre-1.0' });
|
|
49
|
+
}
|
|
50
|
+
return line;
|
|
51
|
+
} catch {
|
|
52
|
+
return line; // preserve invalid lines
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function simulateMindforgeMdMigration(content) {
|
|
58
|
+
return content.replace(
|
|
59
|
+
/^(VERIFY_PASS_RATE_WARNING_THRESHOLD=)(\d+(?:\.\d+)?)(\s*)$/m,
|
|
60
|
+
(match, prefix, val, suffix) => {
|
|
61
|
+
const num = parseFloat(val);
|
|
62
|
+
return num > 1
|
|
63
|
+
? `${prefix}${(num / 100).toFixed(2)}${suffix}`
|
|
64
|
+
: match;
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ── Tests ──────────────────────────────────────────────────────────────────────
|
|
70
|
+
console.log('\nMindForge Day 7 — Migration Tests\n');
|
|
71
|
+
|
|
72
|
+
console.log('Version comparator:');
|
|
73
|
+
|
|
74
|
+
test('compareSemver works for all comparison cases', () => {
|
|
75
|
+
const { compareSemver } = require('../bin/updater/version-comparator');
|
|
76
|
+
assert.ok(compareSemver('1.0.0', '0.9.9') > 0, '1.0.0 > 0.9.9');
|
|
77
|
+
assert.ok(compareSemver('0.1.0', '1.0.0') < 0, '0.1.0 < 1.0.0');
|
|
78
|
+
assert.strictEqual(compareSemver('0.5.0', '0.5.0'), 0, '0.5.0 == 0.5.0');
|
|
79
|
+
assert.ok(compareSemver('2.0.0', '1.99.99') > 0, 'Major beats all minors');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('migration chain for v0.3.0 → v1.0.0 includes ALL 3 migrations', () => {
|
|
83
|
+
// Simulate the filter logic
|
|
84
|
+
const { compareSemver } = require('../bin/updater/version-comparator');
|
|
85
|
+
const fromVersion = '0.3.0';
|
|
86
|
+
const toVersion = '1.0.0';
|
|
87
|
+
|
|
88
|
+
const migrations = [
|
|
89
|
+
{ fromVersion: '0.1.0', toVersion: '0.5.0' },
|
|
90
|
+
{ fromVersion: '0.5.0', toVersion: '0.6.0' },
|
|
91
|
+
{ fromVersion: '0.6.0', toVersion: '1.0.0' },
|
|
92
|
+
].filter(m =>
|
|
93
|
+
compareSemver(m.toVersion, fromVersion) > 0 &&
|
|
94
|
+
compareSemver(m.toVersion, toVersion) <= 0
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
assert.strictEqual(migrations.length, 3,
|
|
98
|
+
`Expected 3 migrations for 0.3.0→1.0.0, got ${migrations.length}`);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('migration chain for v0.6.0 → v1.0.0 includes only 1 migration', () => {
|
|
102
|
+
const { compareSemver } = require('../bin/updater/version-comparator');
|
|
103
|
+
const fromVersion = '0.6.0';
|
|
104
|
+
const toVersion = '1.0.0';
|
|
105
|
+
|
|
106
|
+
const migrations = [
|
|
107
|
+
{ fromVersion: '0.1.0', toVersion: '0.5.0' },
|
|
108
|
+
{ fromVersion: '0.5.0', toVersion: '0.6.0' },
|
|
109
|
+
{ fromVersion: '0.6.0', toVersion: '1.0.0' },
|
|
110
|
+
].filter(m =>
|
|
111
|
+
compareSemver(m.toVersion, fromVersion) > 0 &&
|
|
112
|
+
compareSemver(m.toVersion, toVersion) <= 0
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
assert.strictEqual(migrations.length, 1,
|
|
116
|
+
`Expected 1 migration for 0.6.0→1.0.0, got ${migrations.length}: ${migrations.map(m=>m.toVersion)}`);
|
|
117
|
+
assert.strictEqual(migrations[0].toVersion, '1.0.0');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('migration chain for same version returns 0 migrations', () => {
|
|
121
|
+
const { compareSemver } = require('../bin/updater/version-comparator');
|
|
122
|
+
const fromVersion = '1.0.0';
|
|
123
|
+
const toVersion = '1.0.0';
|
|
124
|
+
|
|
125
|
+
const migrations = [
|
|
126
|
+
{ fromVersion: '0.1.0', toVersion: '0.5.0' },
|
|
127
|
+
{ fromVersion: '0.5.0', toVersion: '0.6.0' },
|
|
128
|
+
{ fromVersion: '0.6.0', toVersion: '1.0.0' },
|
|
129
|
+
].filter(m =>
|
|
130
|
+
compareSemver(m.toVersion, fromVersion) > 0 &&
|
|
131
|
+
compareSemver(m.toVersion, toVersion) <= 0
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
assert.strictEqual(migrations.length, 0, 'No migrations needed for same version');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
console.log('\nHANDOFF.json migrations:');
|
|
138
|
+
|
|
139
|
+
test('v0.1.0 → v0.5.0: adds intelligence layer fields', () => {
|
|
140
|
+
const h = { schema_version: '0.1.0', next_task: 'test', _warning: 'warn' };
|
|
141
|
+
const m = simulateHandoffMigration(h, '0.5.0');
|
|
142
|
+
assert.ok(Array.isArray(m.decisions_made), 'decisions_made should be array');
|
|
143
|
+
assert.ok(Array.isArray(m.discoveries), 'discoveries should be array');
|
|
144
|
+
assert.ok(Array.isArray(m.implicit_knowledge), 'implicit_knowledge should be array');
|
|
145
|
+
assert.ok(Array.isArray(m.quality_signals), 'quality_signals should be array');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test('v0.5.0 → v0.6.0: adds distribution platform fields', () => {
|
|
149
|
+
const h = { schema_version: '0.5.0', next_task: 'test', _warning: 'warn' };
|
|
150
|
+
const m = simulateHandoffMigration(h, '0.6.0');
|
|
151
|
+
assert.ok(Array.isArray(m.recent_commits), 'recent_commits should be array');
|
|
152
|
+
assert.ok(Array.isArray(m.recent_files), 'recent_files should be array');
|
|
153
|
+
assert.ok('developer_id' in m, 'developer_id should exist');
|
|
154
|
+
assert.ok('session_id' in m, 'session_id should exist');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('v0.6.0 → v1.0.0: adds plugin_api_version', () => {
|
|
158
|
+
const h = { schema_version: '0.6.0', next_task: 'test', _warning: 'warn' };
|
|
159
|
+
const m = simulateHandoffMigration(h, '1.0.0');
|
|
160
|
+
assert.strictEqual(m.plugin_api_version, '1.0.0');
|
|
161
|
+
assert.strictEqual(m.schema_version, '1.0.0');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test('v0.1.0 → v1.0.0 full chain: all fields present', () => {
|
|
165
|
+
const h = { schema_version: '0.1.0', next_task: 'first task', _warning: 'warn', phase: 1 };
|
|
166
|
+
const m = simulateHandoffMigration(h, '1.0.0');
|
|
167
|
+
|
|
168
|
+
// All fields from all migrations should be present
|
|
169
|
+
assert.ok(Array.isArray(m.decisions_made), 'decisions_made from 0.5.0 migration');
|
|
170
|
+
assert.ok(Array.isArray(m.recent_commits), 'recent_commits from 0.6.0 migration');
|
|
171
|
+
assert.strictEqual(m.plugin_api_version, '1.0.0', 'plugin_api_version from 1.0.0 migration');
|
|
172
|
+
assert.strictEqual(m.phase, 1, 'Original field preserved');
|
|
173
|
+
assert.strictEqual(m.next_task, 'first task', 'Original next_task preserved');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test('migration does not overwrite existing values', () => {
|
|
177
|
+
const h = {
|
|
178
|
+
schema_version: '0.1.0',
|
|
179
|
+
next_task: 'existing task',
|
|
180
|
+
_warning: 'original warning',
|
|
181
|
+
phase: 3,
|
|
182
|
+
plan: '04',
|
|
183
|
+
custom_org_field: 'preserved',
|
|
184
|
+
};
|
|
185
|
+
const m = simulateHandoffMigration(h, '1.0.0');
|
|
186
|
+
assert.strictEqual(m.next_task, 'existing task');
|
|
187
|
+
assert.strictEqual(m.phase, 3);
|
|
188
|
+
assert.strictEqual(m.plan, '04');
|
|
189
|
+
assert.strictEqual(m.custom_org_field, 'preserved');
|
|
190
|
+
assert.strictEqual(m._warning, 'original warning');
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
console.log('\nAUDIT.jsonl migration:');
|
|
194
|
+
|
|
195
|
+
test('backfills missing session_id in audit entries', () => {
|
|
196
|
+
const lines = [
|
|
197
|
+
JSON.stringify({ id: 'uuid-1', timestamp: '2026-01-01T00:00:00Z', event: 'task_started', agent: 'test' }),
|
|
198
|
+
JSON.stringify({ id: 'uuid-2', timestamp: '2026-01-01T00:01:00Z', event: 'task_completed', agent: 'test', session_id: 'existing' }),
|
|
199
|
+
];
|
|
200
|
+
const migrated = simulateAuditMigration(lines);
|
|
201
|
+
const first = JSON.parse(migrated[0]);
|
|
202
|
+
const second = JSON.parse(migrated[1]);
|
|
203
|
+
assert.ok(first.session_id, 'Missing session_id should be backfilled');
|
|
204
|
+
assert.strictEqual(first.session_id, 'migrated-from-pre-1.0');
|
|
205
|
+
assert.strictEqual(second.session_id, 'existing', 'Existing session_id must not be changed');
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test('preserves invalid JSON lines without crashing', () => {
|
|
209
|
+
const lines = [
|
|
210
|
+
JSON.stringify({ id: 'uuid-1', event: 'test', timestamp: 't', agent: 'a' }),
|
|
211
|
+
'{this is not valid JSON}',
|
|
212
|
+
JSON.stringify({ id: 'uuid-2', event: 'test', timestamp: 't', agent: 'a' }),
|
|
213
|
+
];
|
|
214
|
+
const migrated = simulateAuditMigration(lines);
|
|
215
|
+
assert.strictEqual(migrated.length, 3, 'All lines preserved');
|
|
216
|
+
assert.strictEqual(migrated[1], '{this is not valid JSON}', 'Invalid line unchanged');
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
test('does not double-backfill entries that already have session_id', () => {
|
|
220
|
+
const original = JSON.stringify({ id: 'uuid', event: 'test', timestamp: 't', agent: 'a', session_id: 'my-session' });
|
|
221
|
+
const [migrated] = simulateAuditMigration([original]);
|
|
222
|
+
const entry = JSON.parse(migrated);
|
|
223
|
+
assert.strictEqual(entry.session_id, 'my-session', 'Should not overwrite existing session_id');
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
console.log('\nMINDFORGE.md migration:');
|
|
227
|
+
|
|
228
|
+
test('converts VERIFY_PASS_RATE_WARNING_THRESHOLD from 75 to 0.75', () => {
|
|
229
|
+
const content = 'VERIFY_PASS_RATE_WARNING_THRESHOLD=75\n';
|
|
230
|
+
const migrated = simulateMindforgeMdMigration(content);
|
|
231
|
+
assert.ok(migrated.includes('0.75'), `Expected 0.75, got: ${migrated.trim()}`);
|
|
232
|
+
assert.ok(!migrated.match(/=75(\s|$)/), 'Should not still contain =75');
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test('converts VERIFY_PASS_RATE_WARNING_THRESHOLD from 80 to 0.80', () => {
|
|
236
|
+
const content = 'VERIFY_PASS_RATE_WARNING_THRESHOLD=80\nOTHER=value\n';
|
|
237
|
+
const migrated = simulateMindforgeMdMigration(content);
|
|
238
|
+
assert.ok(migrated.includes('0.80') || migrated.includes('0.8'), `Expected 0.80`);
|
|
239
|
+
assert.ok(migrated.includes('OTHER=value'), 'Should preserve other settings');
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test('does NOT modify values already in decimal format (0.75)', () => {
|
|
243
|
+
const content = 'VERIFY_PASS_RATE_WARNING_THRESHOLD=0.75\n';
|
|
244
|
+
const migrated = simulateMindforgeMdMigration(content);
|
|
245
|
+
assert.ok(migrated.includes('0.75'), 'Should preserve existing decimal format');
|
|
246
|
+
assert.ok(!migrated.includes('0.0075'), 'Should not double-convert a decimal');
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test('does NOT modify value of exactly 1 (ambiguous — preserve)', () => {
|
|
250
|
+
const content = 'VERIFY_PASS_RATE_WARNING_THRESHOLD=1\n';
|
|
251
|
+
const migrated = simulateMindforgeMdMigration(content);
|
|
252
|
+
// Value of 1 should be preserved as-is (it's ≤ 1, within decimal range)
|
|
253
|
+
assert.ok(migrated.includes('=1'), 'Value of 1 should not be converted');
|
|
254
|
+
assert.ok(!migrated.includes('=0.01'), 'Value of 1 should not become 0.01');
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test('MINDFORGE.md value 1.0 (explicit decimal) is not converted', () => {
|
|
258
|
+
const content = 'VERIFY_PASS_RATE_WARNING_THRESHOLD=1.0\n';
|
|
259
|
+
const migrated = simulateMindforgeMdMigration(content);
|
|
260
|
+
assert.ok(migrated.includes('=1.0'), 'Should preserve 1.0 format without conversion');
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
console.log('\nMigration infrastructure:');
|
|
264
|
+
|
|
265
|
+
test('all migration files have correct fromVersion/toVersion', () => {
|
|
266
|
+
const files = [
|
|
267
|
+
{ file: 'bin/migrations/0.1.0-to-0.5.0.js', from: '0.1.0', to: '0.5.0' },
|
|
268
|
+
{ file: 'bin/migrations/0.5.0-to-0.6.0.js', from: '0.5.0', to: '0.6.0' },
|
|
269
|
+
{ file: 'bin/migrations/0.6.0-to-1.0.0.js', from: '0.6.0', to: '1.0.0' },
|
|
270
|
+
];
|
|
271
|
+
files.forEach(({ file, from, to }) => {
|
|
272
|
+
const c = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : '';
|
|
273
|
+
assert.ok(c.includes(from), `${file}: should contain fromVersion ${from}`);
|
|
274
|
+
assert.ok(c.includes(to), `${file}: should contain toVersion ${to}`);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test('migration chain covers v0.1.0 → v1.0.0 completely', () => {
|
|
279
|
+
const { compareSemver } = require('../bin/updater/version-comparator');
|
|
280
|
+
|
|
281
|
+
// Chain: 0.1.0 → 0.5.0 → 0.6.0 → 1.0.0
|
|
282
|
+
const chain = ['0.1.0', '0.5.0', '0.6.0', '1.0.0'];
|
|
283
|
+
for (let i = 0; i < chain.length - 1; i++) {
|
|
284
|
+
const file = `bin/migrations/${chain[i]}-to-${chain[i+1]}.js`;
|
|
285
|
+
assert.ok(fs.existsSync(file), `Missing migration: ${file}`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Verify no gaps: each migration's toVersion = next migration's fromVersion
|
|
289
|
+
for (let i = 0; i < chain.length - 2; i++) {
|
|
290
|
+
assert.ok(
|
|
291
|
+
compareSemver(chain[i + 1], chain[i]) > 0,
|
|
292
|
+
`Chain gap between ${chain[i]} and ${chain[i+1]}`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test('migrate.js exports runMigrations function', () => {
|
|
298
|
+
const { runMigrations } = require('../bin/migrations/migrate');
|
|
299
|
+
assert.strictEqual(typeof runMigrations, 'function', 'runMigrations should be a function');
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
console.log(`\n${'─'.repeat(55)}`);
|
|
303
|
+
console.log(`Results: ${passed} passed, ${failed} failed`);
|
|
304
|
+
if (failed > 0) {
|
|
305
|
+
console.error(`\n❌ ${failed} test(s) failed.\n`);
|
|
306
|
+
process.exit(1);
|
|
307
|
+
} else {
|
|
308
|
+
console.log(`\n✅ All migration tests passed.\n`);
|
|
309
|
+
}
|