@warpgogol/forge 4.2.4 → 5.1.1
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/AGENTS.md +14 -6
- package/CHANGELOG.md +72 -0
- package/README.md +8 -8
- package/README.uk.md +5 -5
- package/dist/os/adr/handlers/list-create.d.ts.map +1 -1
- package/dist/os/adr/handlers/list-create.js +4 -1
- package/dist/os/adr/handlers/list-create.js.map +1 -1
- package/dist/os/adr/handlers/validate.d.ts.map +1 -1
- package/dist/os/adr/handlers/validate.js +6 -1
- package/dist/os/adr/handlers/validate.js.map +1 -1
- package/dist/os/adr/types.d.ts.map +1 -1
- package/dist/os/adr/types.js +7 -3
- package/dist/os/adr/types.js.map +1 -1
- package/dist/os/compass/compass.module.d.ts.map +1 -1
- package/dist/os/compass/compass.module.js +76 -10
- package/dist/os/compass/compass.module.js.map +1 -1
- package/dist/os/compass/handlers/compass-audit-handler.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-audit-handler.js +7 -3
- package/dist/os/compass/handlers/compass-audit-handler.js.map +1 -1
- package/dist/os/compass/handlers/compass-change-summary-handler.d.ts +1 -9
- package/dist/os/compass/handlers/compass-change-summary-handler.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-change-summary-handler.js +44 -186
- package/dist/os/compass/handlers/compass-change-summary-handler.js.map +1 -1
- package/dist/os/compass/handlers/compass-inventory-handler.d.ts +2 -0
- package/dist/os/compass/handlers/compass-inventory-handler.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-inventory-handler.js +24 -12
- package/dist/os/compass/handlers/compass-inventory-handler.js.map +1 -1
- package/dist/os/compass/handlers/compass-inventory.d.ts +7 -5
- package/dist/os/compass/handlers/compass-inventory.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-inventory.js +84 -241
- package/dist/os/compass/handlers/compass-inventory.js.map +1 -1
- package/dist/os/compass/handlers/compass-migrate-handler.d.ts +4 -0
- package/dist/os/compass/handlers/compass-migrate-handler.d.ts.map +1 -0
- package/dist/os/compass/handlers/compass-migrate-handler.js +100 -0
- package/dist/os/compass/handlers/compass-migrate-handler.js.map +1 -0
- package/dist/os/compass/handlers/compass-migrate.d.ts +34 -0
- package/dist/os/compass/handlers/compass-migrate.d.ts.map +1 -0
- package/dist/os/compass/handlers/compass-migrate.js +273 -0
- package/dist/os/compass/handlers/compass-migrate.js.map +1 -0
- package/dist/os/compass/handlers/resolve-scan-root.d.ts.map +1 -1
- package/dist/os/compass/handlers/resolve-scan-root.js +15 -8
- package/dist/os/compass/handlers/resolve-scan-root.js.map +1 -1
- package/dist/os/compass/handlers/summary-record.d.ts +46 -0
- package/dist/os/compass/handlers/summary-record.d.ts.map +1 -0
- package/dist/os/compass/handlers/summary-record.js +233 -0
- package/dist/os/compass/handlers/summary-record.js.map +1 -0
- package/dist/os/compass/index.d.ts +4 -1
- package/dist/os/compass/index.d.ts.map +1 -1
- package/dist/os/compass/index.js +9 -1
- package/dist/os/compass/index.js.map +1 -1
- package/dist/os/compass/policy.d.ts +65 -0
- package/dist/os/compass/policy.d.ts.map +1 -0
- package/dist/os/compass/policy.js +241 -0
- package/dist/os/compass/policy.js.map +1 -0
- package/dist/os/core/core.module.d.ts.map +1 -1
- package/dist/os/core/core.module.js +11 -23
- package/dist/os/core/core.module.js.map +1 -1
- package/dist/os/core/handlers/forge-autonomy-validate.d.ts.map +1 -1
- package/dist/os/core/handlers/forge-autonomy-validate.js +7 -1
- package/dist/os/core/handlers/forge-autonomy-validate.js.map +1 -1
- package/dist/os/core/handlers/package-health.d.ts.map +1 -1
- package/dist/os/core/handlers/package-health.js +6 -1
- package/dist/os/core/handlers/package-health.js.map +1 -1
- package/dist/os/core/handlers/pinned-check.d.ts.map +1 -1
- package/dist/os/core/handlers/pinned-check.js +6 -1
- package/dist/os/core/handlers/pinned-check.js.map +1 -1
- package/dist/os/core/handlers/pinned-validate.d.ts.map +1 -1
- package/dist/os/core/handlers/pinned-validate.js +6 -1
- package/dist/os/core/handlers/pinned-validate.js.map +1 -1
- package/dist/os/core/handlers/validate.d.ts.map +1 -1
- package/dist/os/core/handlers/validate.js +6 -1
- package/dist/os/core/handlers/validate.js.map +1 -1
- package/dist/os/exploration/exploration.module.d.ts.map +1 -1
- package/dist/os/exploration/exploration.module.js +6 -4
- package/dist/os/exploration/exploration.module.js.map +1 -1
- package/dist/os/exploration/handlers/list.d.ts.map +1 -1
- package/dist/os/exploration/handlers/list.js +4 -1
- package/dist/os/exploration/handlers/list.js.map +1 -1
- package/dist/os/mission/handlers/archive.d.ts.map +1 -1
- package/dist/os/mission/handlers/archive.js +7 -3
- package/dist/os/mission/handlers/archive.js.map +1 -1
- package/dist/os/mission/index.d.ts.map +1 -1
- package/dist/os/mission/index.js +13 -0
- package/dist/os/mission/index.js.map +1 -1
- package/dist/os/notes/index.d.ts.map +1 -1
- package/dist/os/notes/index.js +7 -1
- package/dist/os/notes/index.js.map +1 -1
- package/dist/os/rfc/frontmatter-io.d.ts.map +1 -1
- package/dist/os/rfc/frontmatter-io.js +6 -1
- package/dist/os/rfc/frontmatter-io.js.map +1 -1
- package/dist/os/rfc/handlers/archive.d.ts.map +1 -1
- package/dist/os/rfc/handlers/archive.js +6 -1
- package/dist/os/rfc/handlers/archive.js.map +1 -1
- package/dist/os/rfc/handlers/implement-stamp.d.ts.map +1 -1
- package/dist/os/rfc/handlers/implement-stamp.js +7 -3
- package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
- package/dist/os/rfc/handlers/index-graph.d.ts.map +1 -1
- package/dist/os/rfc/handlers/index-graph.js +6 -1
- package/dist/os/rfc/handlers/index-graph.js.map +1 -1
- package/dist/os/rfc/handlers/lifecycle.d.ts.map +1 -1
- package/dist/os/rfc/handlers/lifecycle.js +6 -1
- package/dist/os/rfc/handlers/lifecycle.js.map +1 -1
- package/dist/os/rfc/handlers/list-create.d.ts.map +1 -1
- package/dist/os/rfc/handlers/list-create.js +6 -1
- package/dist/os/rfc/handlers/list-create.js.map +1 -1
- package/dist/os/rfc/handlers/pipeline-status.d.ts.map +1 -1
- package/dist/os/rfc/handlers/pipeline-status.js +6 -1
- package/dist/os/rfc/handlers/pipeline-status.js.map +1 -1
- package/dist/os/rfc/handlers/supersede-propose.d.ts.map +1 -1
- package/dist/os/rfc/handlers/supersede-propose.js +6 -1
- package/dist/os/rfc/handlers/supersede-propose.js.map +1 -1
- package/dist/os/rfc/handlers/validate-rules.d.ts.map +1 -1
- package/dist/os/rfc/handlers/validate-rules.js +7 -3
- package/dist/os/rfc/handlers/validate-rules.js.map +1 -1
- package/dist/os/rfc/handlers/validate.d.ts.map +1 -1
- package/dist/os/rfc/handlers/validate.js +6 -1
- package/dist/os/rfc/handlers/validate.js.map +1 -1
- package/dist/os/rfc/index.d.ts.map +1 -1
- package/dist/os/rfc/index.js +6 -1
- package/dist/os/rfc/index.js.map +1 -1
- package/dist/os/rfc/rfc.module.d.ts.map +1 -1
- package/dist/os/rfc/rfc.module.js +6 -1
- package/dist/os/rfc/rfc.module.js.map +1 -1
- package/dist/os/rfc/types.d.ts +7 -4
- package/dist/os/rfc/types.d.ts.map +1 -1
- package/dist/os/rfc/types.js +7 -4
- package/dist/os/rfc/types.js.map +1 -1
- package/dist/os/session/handlers/save.d.ts.map +1 -1
- package/dist/os/session/handlers/save.js +6 -1
- package/dist/os/session/handlers/save.js.map +1 -1
- package/dist/os/werkstatt/handlers/werkstatt-lock-recover.d.ts.map +1 -1
- package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js +6 -1
- package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js.map +1 -1
- package/dist/os/werkstatt/handlers/workspace-deps.js +3 -3
- package/dist/os/werkstatt/handlers/workspace-deps.js.map +1 -1
- package/dist/os/workflow/index.d.ts.map +1 -1
- package/dist/os/workflow/index.js +6 -1
- package/dist/os/workflow/index.js.map +1 -1
- package/dist/src/config/forge-config.d.ts +62 -4
- package/dist/src/config/forge-config.d.ts.map +1 -1
- package/dist/src/config/forge-config.js +35 -19
- package/dist/src/config/forge-config.js.map +1 -1
- package/dist/src/forge-module.d.ts.map +1 -1
- package/dist/src/forge-module.js +6 -1
- package/dist/src/forge-module.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +10 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/migration-adapters/git-utils.d.ts.map +1 -1
- package/dist/src/migration-adapters/git-utils.js +6 -2
- package/dist/src/migration-adapters/git-utils.js.map +1 -1
- package/dist/src/migration-adapters/ignored-files.d.ts.map +1 -1
- package/dist/src/migration-adapters/ignored-files.js +6 -1
- package/dist/src/migration-adapters/ignored-files.js.map +1 -1
- package/dist/src/migration-adapters/index.d.ts.map +1 -1
- package/dist/src/migration-adapters/index.js +4 -1
- package/dist/src/migration-adapters/index.js.map +1 -1
- package/dist/src/migration-adapters/types.d.ts.map +1 -1
- package/dist/src/migration-adapters/types.js +6 -2
- package/dist/src/migration-adapters/types.js.map +1 -1
- package/dist/src/onboarding/agents-generate.d.ts.map +1 -1
- package/dist/src/onboarding/agents-generate.js +18 -14
- package/dist/src/onboarding/agents-generate.js.map +1 -1
- package/dist/src/onboarding/create.d.ts.map +1 -1
- package/dist/src/onboarding/create.js +7 -6
- package/dist/src/onboarding/create.js.map +1 -1
- package/dist/src/onboarding/doctor.d.ts.map +1 -1
- package/dist/src/onboarding/doctor.js +7 -13
- package/dist/src/onboarding/doctor.js.map +1 -1
- package/dist/src/onboarding/init.d.ts.map +1 -1
- package/dist/src/onboarding/init.js +7 -12
- package/dist/src/onboarding/init.js.map +1 -1
- package/dist/src/onboarding/invariant-engine.d.ts.map +1 -1
- package/dist/src/onboarding/invariant-engine.js +7 -2
- package/dist/src/onboarding/invariant-engine.js.map +1 -1
- package/dist/src/onboarding/nested-agents-generate.d.ts.map +1 -1
- package/dist/src/onboarding/nested-agents-generate.js +7 -2
- package/dist/src/onboarding/nested-agents-generate.js.map +1 -1
- package/dist/src/onboarding/nested-agents-templates.d.ts.map +1 -1
- package/dist/src/onboarding/nested-agents-templates.js +11 -3
- package/dist/src/onboarding/nested-agents-templates.js.map +1 -1
- package/dist/src/onboarding/scaffold-project.d.ts.map +1 -1
- package/dist/src/onboarding/scaffold-project.js +6 -1
- package/dist/src/onboarding/scaffold-project.js.map +1 -1
- package/dist/src/onboarding/upgrade.d.ts.map +1 -1
- package/dist/src/onboarding/upgrade.js +7 -3
- package/dist/src/onboarding/upgrade.js.map +1 -1
- package/dist/src/profiles/profile-schema.d.ts +54 -4
- package/dist/src/profiles/profile-schema.d.ts.map +1 -1
- package/dist/src/profiles/profile-schema.js +34 -14
- package/dist/src/profiles/profile-schema.js.map +1 -1
- package/dist/src/profiles/stack-profile.d.ts +24 -0
- package/dist/src/profiles/stack-profile.d.ts.map +1 -1
- package/dist/src/profiles/stack-profile.js +7 -3
- package/dist/src/profiles/stack-profile.js.map +1 -1
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +7 -9
- package/dist/src/registry.js.map +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +6 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/fs-atomic.d.ts.map +1 -1
- package/dist/src/utils/fs-atomic.js +13 -1
- package/dist/src/utils/fs-atomic.js.map +1 -1
- package/dist/src/utils/fs-idempotent.d.ts.map +1 -1
- package/dist/src/utils/fs-idempotent.js +13 -0
- package/dist/src/utils/fs-idempotent.js.map +1 -1
- package/dist/src/utils/fs-trash-sync.d.ts.map +1 -1
- package/dist/src/utils/fs-trash-sync.js +13 -1
- package/dist/src/utils/fs-trash-sync.js.map +1 -1
- package/dist/src/utils/fs-trash.d.ts.map +1 -1
- package/dist/src/utils/fs-trash.js +13 -1
- package/dist/src/utils/fs-trash.js.map +1 -1
- package/dist/src/utils/fs.d.ts.map +1 -1
- package/dist/src/utils/fs.js +14 -3
- package/dist/src/utils/fs.js.map +1 -1
- package/dist/src/utils/hash.d.ts.map +1 -1
- package/dist/src/utils/hash.js +12 -1
- package/dist/src/utils/hash.js.map +1 -1
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +13 -2
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/string-utils.d.ts.map +1 -1
- package/dist/src/utils/string-utils.js +12 -1
- package/dist/src/utils/string-utils.js.map +1 -1
- package/dist/src/validators/port-validate.js +1 -1
- package/dist/src/validators/port-validate.js.map +1 -1
- package/dist/src/validators/skill-validate.d.ts.map +1 -1
- package/dist/src/validators/skill-validate.js +7 -8
- package/dist/src/validators/skill-validate.js.map +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/reference/forge-yaml.md +38 -9
- package/docs/reference/profiles.md +8 -8
- package/os/adr/handlers/list-create.ts +4 -1
- package/os/adr/handlers/validate.ts +6 -1
- package/os/adr/types.ts +7 -3
- package/os/compass/compass.module.ts +79 -13
- package/os/compass/handlers/compass-audit-handler.ts +22 -3
- package/os/compass/handlers/compass-change-summary-handler.ts +55 -227
- package/os/compass/handlers/compass-inventory-handler.ts +30 -12
- package/os/compass/handlers/compass-inventory.ts +103 -240
- package/os/compass/handlers/compass-migrate-handler.ts +122 -0
- package/os/compass/handlers/compass-migrate.ts +361 -0
- package/os/compass/handlers/resolve-scan-root-package.test.ts +70 -0
- package/os/compass/handlers/resolve-scan-root.ts +15 -8
- package/os/compass/handlers/summary-record.ts +313 -0
- package/os/compass/handlers/tests/compass-migrate.test.ts +291 -0
- package/os/compass/handlers/tests/compass-policy.test.ts +249 -0
- package/os/compass/handlers/tests/compass-v2-contract.test.ts +9 -9
- package/os/compass/handlers/tests/summary-record.test.ts +224 -0
- package/os/compass/index.ts +23 -5
- package/os/compass/policy.ts +350 -0
- package/os/core/core.module.ts +11 -23
- package/os/core/handlers/forge-autonomy-validate.ts +7 -1
- package/os/core/handlers/package-health.ts +6 -1
- package/os/core/handlers/pinned-check.ts +6 -1
- package/os/core/handlers/pinned-validate.ts +6 -1
- package/os/core/handlers/validate.ts +6 -1
- package/os/exploration/exploration.module.ts +72 -71
- package/os/exploration/handlers/list.ts +4 -1
- package/os/mission/handlers/archive.ts +7 -3
- package/os/mission/index.ts +14 -0
- package/os/notes/index.ts +7 -1
- package/os/rfc/frontmatter-io.ts +6 -1
- package/os/rfc/handlers/archive.ts +6 -1
- package/os/rfc/handlers/implement-stamp.ts +7 -3
- package/os/rfc/handlers/index-graph.ts +6 -1
- package/os/rfc/handlers/lifecycle.ts +6 -1
- package/os/rfc/handlers/list-create.ts +6 -1
- package/os/rfc/handlers/pipeline-status.ts +6 -1
- package/os/rfc/handlers/supersede-propose.ts +6 -1
- package/os/rfc/handlers/validate-rules.ts +7 -3
- package/os/rfc/handlers/validate.ts +6 -1
- package/os/rfc/index.ts +6 -1
- package/os/rfc/rfc.module.ts +6 -1
- package/os/rfc/types.ts +7 -4
- package/os/session/handlers/save.ts +6 -1
- package/os/werkstatt/handlers/werkstatt-lock-recover.ts +6 -1
- package/os/werkstatt/handlers/workspace-deps.ts +3 -3
- package/os/workflow/index.ts +6 -1
- package/package.json +1 -1
- package/profiles/{godot-csharp.yaml → godot-game.yaml} +2 -2
- package/profiles/{knowledge-typescript-turborepo.yaml → knowledge.yaml} +1 -1
- package/profiles/{phaser-turborepo.yaml → phaser-game.yaml} +2 -2
- package/profiles/{typescript-turborepo.yaml → typescript.yaml} +2 -2
- package/skills/fo/fo-add-tests/SKILL.md +14 -0
- package/skills/fo/fo-architecture/SKILL.md +14 -0
- package/skills/fo/fo-compass-annotate/SKILL.md +14 -0
- package/skills/fo/fo-design-summit/SKILL.md +14 -0
- package/skills/fo/fo-doc-audit/SKILL.md +14 -0
- package/skills/fo/fo-explore/SKILL.md +14 -0
- package/skills/fo/fo-extract-dna/SKILL.md +14 -0
- package/skills/fo/fo-fix/SKILL.md +14 -0
- package/skills/fo/fo-handoff/SKILL.md +14 -0
- package/skills/fo/fo-harvest/SKILL.md +14 -0
- package/skills/fo/fo-idea/SKILL.md +14 -0
- package/skills/fo/fo-idea-audit/SKILL.md +14 -0
- package/skills/fo/fo-idea-create-adr/SKILL.md +14 -0
- package/skills/fo/fo-idea-create-rfc/SKILL.md +14 -0
- package/skills/fo/fo-idea-enhance/SKILL.md +14 -0
- package/skills/fo/fo-idea-i-just-want-to-see-the-plan/SKILL.md +14 -0
- package/skills/fo/fo-idea-i-just-want-to-see-the-result/SKILL.md +14 -0
- package/skills/fo/fo-idea-implement/SKILL.md +14 -0
- package/skills/fo/fo-idea-plan/SKILL.md +14 -0
- package/skills/fo/fo-idea-status/SKILL.md +14 -0
- package/skills/fo/fo-knowledge-distill/SKILL.md +14 -0
- package/skills/fo/fo-memory-sync/SKILL.md +14 -0
- package/skills/fo/fo-qa/SKILL.md +14 -0
- package/skills/fo/fo-review/SKILL.md +14 -0
- package/skills/fo/fo-session-retro/SKILL.md +14 -0
- package/skills/fo/fo-session-save/SKILL.md +14 -0
- package/skills/fo/fo-spec-ingest/SKILL.md +14 -0
- package/skills/fo/fo-step-commit/SKILL.md +14 -0
- package/skills/fo/fo-triage/SKILL.md +14 -0
- package/skills/meta/forge-bootstrap/SKILL.md +14 -0
- package/skills/meta/port-to-forge/SKILL.md +14 -0
- package/skills/meta/skill-create/SKILL.md +14 -0
- package/skills/shared/grilling/SKILL.md +14 -0
- package/skills/shared/my-preferences/SKILL.md +14 -0
- package/skills/shared/windows-ai-tooling/SKILL.md +14 -0
- package/skills/shared/writing-great-skills/SKILL.md +14 -0
- package/src/config/forge-config.ts +40 -23
- package/src/forge-module.ts +6 -1
- package/src/index.ts +10 -2
- package/src/migration-adapters/git-utils.ts +6 -2
- package/src/migration-adapters/ignored-files.ts +6 -1
- package/src/migration-adapters/index.ts +4 -1
- package/src/migration-adapters/types.ts +6 -2
- package/src/onboarding/agents-generate.ts +23 -14
- package/src/onboarding/create.ts +7 -6
- package/src/onboarding/doctor.ts +7 -13
- package/src/onboarding/init.ts +7 -12
- package/src/onboarding/invariant-engine.ts +7 -2
- package/src/onboarding/nested-agents-generate.ts +7 -2
- package/src/onboarding/nested-agents-templates.ts +11 -3
- package/src/onboarding/scaffold-project.ts +6 -1
- package/src/onboarding/upgrade.ts +7 -3
- package/src/profiles/profile-schema.ts +42 -18
- package/src/profiles/stack-profile.ts +7 -3
- package/src/registry.ts +7 -9
- package/src/tests/agents-generate-domain.test.ts +3 -3
- package/src/tests/agents-generate.test.ts +2 -2
- package/src/tests/create.test.ts +4 -4
- package/src/tests/forge-autonomy-validate.test.ts +1 -1
- package/src/tests/package-files.test.ts +53 -1
- package/src/tests/profile-schema.test.ts +4 -4
- package/src/tests/scaffold-project.test.ts +3 -3
- package/src/tests/stack-profile.test.ts +12 -12
- package/src/types.ts +6 -1
- package/src/utils/fs-atomic.ts +13 -1
- package/src/utils/fs-idempotent.ts +13 -0
- package/src/utils/fs-trash-sync.ts +13 -1
- package/src/utils/fs-trash.ts +13 -1
- package/src/utils/fs.ts +14 -3
- package/src/utils/hash.ts +12 -1
- package/src/utils/index.ts +13 -2
- package/src/utils/string-utils.ts +12 -1
- package/src/validators/port-validate.ts +1 -1
- package/src/validators/skill-validate.ts +7 -8
- package/skills/shared/extension-e2e-mitm/SKILL.md +0 -53
- package/skills/shared/extension-e2e-mitm/fixture-proxy.ts +0 -113
- package/src/types/werkstatt-engine-shims.d.ts +0 -1416
- package/src/types/werkstatt-shared-shims.d.ts +0 -5686
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>compass.migrate domain logic — the v1 to v2 Compass header codemod
|
|
4
|
+
(RFC-1097). Rewrites authored file headers in place: collapses CHANGE_SUMMARY
|
|
5
|
+
windows into history, strips forbidden v1 blocks, seeds KEY_DECISIONS from
|
|
6
|
+
ai-invariant comments, reorders blocks to canonical order, and reports a
|
|
7
|
+
closed action union per file. Pure per-file transform plus a workspace
|
|
8
|
+
walker; the kernel handler lives in compass-migrate-handler.ts.</purpose>
|
|
9
|
+
<non-goals>
|
|
10
|
+
<item>Do not author headers from scratch — files with no Compass header are reported no-header and skipped; the agent sweep writes them.</item>
|
|
11
|
+
<item>Do not rewrite purpose text — boilerplate purposes are flagged for the sweep, not auto-fixed.</item>
|
|
12
|
+
<item>Do not import @warpgogol/* packages — this module is autonomous (FORGE-AUTONOMY-01).</item>
|
|
13
|
+
</non-goals>
|
|
14
|
+
</MODULE_CONTRACT>
|
|
15
|
+
<KEY_DECISIONS>
|
|
16
|
+
<item>migrateFile is a pure source-to-source function so every action is unit-testable without I/O.</item>
|
|
17
|
+
<item>Collapse reuses the summary.trim repair semantics — ID-less items dropped, overflow IDs merged into history.</item>
|
|
18
|
+
<item>Seeded KEY_DECISIONS strip the leading governance-ID prefix so items satisfy COMPASS-KD-05 immediately.</item>
|
|
19
|
+
<item>Reorder only fires when the inter-block region is whitespace — interleaved content is left for the sweep.</item>
|
|
20
|
+
</KEY_DECISIONS>
|
|
21
|
+
<CHANGE_SUMMARY>
|
|
22
|
+
<item>RFC-1097: initial codemod — migrateFile pure transform, migrateWorkspace walker, closed action union.</item>
|
|
23
|
+
<item>RFC-1097: steps 1-4 — compass.migrate codemod
|
|
24
|
+
|
|
25
|
+
Add the v1 to v2 Compass header codemod: migrateFile pure transform (collapse, strip, seed, reorder, purpose-flag actions), migrateWorkspace walker, runCompassMigrate handler with dirty-tree refusal and --force/--files/--dry-run flags, module registration, and 15 unit tests.</item>
|
|
26
|
+
</CHANGE_SUMMARY>
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { readFile } from "node:fs/promises";
|
|
30
|
+
import { relative, resolve } from "node:path";
|
|
31
|
+
import {
|
|
32
|
+
createCompassInventoryEntries,
|
|
33
|
+
detectRiskClass,
|
|
34
|
+
getEntrySource,
|
|
35
|
+
getRelativeSegments,
|
|
36
|
+
getWorkspaceRelativeSegments,
|
|
37
|
+
} from "./compass-inventory.ts";
|
|
38
|
+
import {
|
|
39
|
+
buildChangeSummaryBlock,
|
|
40
|
+
CHANGE_SUMMARY_WINDOW,
|
|
41
|
+
getLineCommentPrefix,
|
|
42
|
+
mergeHistoryIds,
|
|
43
|
+
parseChangeSummary,
|
|
44
|
+
} from "./summary-record.ts";
|
|
45
|
+
import { writeFileIfChanged } from "../../../src/utils/fs-idempotent.ts";
|
|
46
|
+
import type { CompassPolicy } from "../policy.ts";
|
|
47
|
+
import type { ForgeCommandInput } from "../../../src/types.ts";
|
|
48
|
+
|
|
49
|
+
export type MigrateAction =
|
|
50
|
+
| "collapsed"
|
|
51
|
+
| "stripped"
|
|
52
|
+
| "seeded"
|
|
53
|
+
| "todo"
|
|
54
|
+
| "purpose-flagged"
|
|
55
|
+
| "reordered"
|
|
56
|
+
| "unparseable"
|
|
57
|
+
| "no-header"
|
|
58
|
+
| "unchanged";
|
|
59
|
+
|
|
60
|
+
export interface MigrateFileResult {
|
|
61
|
+
source: string;
|
|
62
|
+
actions: MigrateAction[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface MigrateResult {
|
|
66
|
+
scanned: number;
|
|
67
|
+
files: Array<{ path: string; actions: MigrateAction[] }>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface MigrateOptions {
|
|
71
|
+
/** Explicit root-relative file list — bypasses scan-root filtering entirely. */
|
|
72
|
+
files?: string[];
|
|
73
|
+
/** Compute actions without writing. */
|
|
74
|
+
dryRun?: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const HEADER_SCAN_LINES = 120;
|
|
78
|
+
const KEY_DECISIONS_MAX_ITEMS = 7;
|
|
79
|
+
const TODO_ITEM = "TODO: record current design decisions";
|
|
80
|
+
|
|
81
|
+
const COMPASS_TAGS = ["MODULE_CONTRACT", "KEY_DECISIONS", "CHANGE_SUMMARY"] as const;
|
|
82
|
+
type CompassTag = (typeof COMPASS_TAGS)[number];
|
|
83
|
+
|
|
84
|
+
const FORBIDDEN_BLOCK_TAGS = ["MODULE_MAP", "keywords", "responsibilities"] as const;
|
|
85
|
+
const COMPASS_BLOCK_ANCHOR_RE = /[ \t]*<\/?COMPASS_BLOCK\b[^>]*>[ \t]*/g;
|
|
86
|
+
|
|
87
|
+
function blockSpan(source: string, tag: string): { start: number; end: number } | null {
|
|
88
|
+
const open = source.indexOf(`<${tag}>`);
|
|
89
|
+
if (open < 0) return null;
|
|
90
|
+
const closeTag = `</${tag}>`;
|
|
91
|
+
const close = source.indexOf(closeTag, open);
|
|
92
|
+
if (close < 0) return null;
|
|
93
|
+
return { start: open, end: close + closeTag.length };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function hasUnclosedTag(source: string, tag: string): boolean {
|
|
97
|
+
return source.includes(`<${tag}>`) && !source.includes(`</${tag}>`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function inHeaderRegion(source: string, index: number): boolean {
|
|
101
|
+
return source.slice(0, index).split("\n").length <= HEADER_SCAN_LINES;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Collect ai-invariant comment texts, deduped, capped, ID-prefix stripped. */
|
|
105
|
+
export function collectAiInvariants(source: string, policy: CompassPolicy): string[] {
|
|
106
|
+
const items: string[] = [];
|
|
107
|
+
const seen = new Set<string>();
|
|
108
|
+
const re = /@ai-invariant:?\s+([^\n*]+)/g;
|
|
109
|
+
let m: RegExpExecArray | null;
|
|
110
|
+
while ((m = re.exec(source)) !== null) {
|
|
111
|
+
let text = m[1]!.replace(/(-->|\*\/)\s*$/, "").trim();
|
|
112
|
+
// KD-05: seeded items must not lead with a governance-ID prefix.
|
|
113
|
+
const idMatch = text.match(policy.idPatternPrefix);
|
|
114
|
+
if (idMatch) {
|
|
115
|
+
text = text
|
|
116
|
+
.slice(idMatch[0].length)
|
|
117
|
+
.replace(/^\s*[:—-]\s*/, "")
|
|
118
|
+
.trim();
|
|
119
|
+
}
|
|
120
|
+
if (text.length === 0 || seen.has(text)) continue;
|
|
121
|
+
seen.add(text);
|
|
122
|
+
items.push(text);
|
|
123
|
+
if (items.length >= KEY_DECISIONS_MAX_ITEMS) break;
|
|
124
|
+
}
|
|
125
|
+
return items;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function buildKeyDecisionsBlock(items: string[], filePath: string): string {
|
|
129
|
+
const lines = ["<KEY_DECISIONS>"];
|
|
130
|
+
for (const item of items) {
|
|
131
|
+
lines.push(` <item>${item}</item>`);
|
|
132
|
+
}
|
|
133
|
+
lines.push("</KEY_DECISIONS>");
|
|
134
|
+
const prefix = getLineCommentPrefix(filePath);
|
|
135
|
+
if (prefix) {
|
|
136
|
+
// New block: every line needs the line-comment prefix (unlike block
|
|
137
|
+
// replacement where the first line already carries one).
|
|
138
|
+
return lines.map((line) => prefix + line).join("\n");
|
|
139
|
+
}
|
|
140
|
+
return lines.join("\n");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function extractPurposeText(source: string): string {
|
|
144
|
+
const contract = blockSpan(source, "MODULE_CONTRACT");
|
|
145
|
+
if (!contract) return "";
|
|
146
|
+
const contractText = source.slice(contract.start, contract.end);
|
|
147
|
+
const purposeMatch = contractText.match(/<purpose>([\s\S]*?)<\/purpose>/);
|
|
148
|
+
return purposeMatch ? purposeMatch[1]!.replace(/<[^>]+>/g, " ").trim() : "";
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Pure v1 to v2 transform of one file's source. Returns the rewritten source
|
|
153
|
+
* and the closed action union. `unchanged` is exclusive; every other action
|
|
154
|
+
* may combine. Never throws on malformed input — reports `unparseable`.
|
|
155
|
+
*/
|
|
156
|
+
export function migrateFile(
|
|
157
|
+
source: string,
|
|
158
|
+
policy: CompassPolicy,
|
|
159
|
+
pathFromRoot: string,
|
|
160
|
+
workspaceRelativePath: string,
|
|
161
|
+
): MigrateFileResult {
|
|
162
|
+
const actions: MigrateAction[] = [];
|
|
163
|
+
|
|
164
|
+
// 1. Header detection — a Compass header lives in the header region only.
|
|
165
|
+
const mcIndex = source.indexOf("<MODULE_CONTRACT>");
|
|
166
|
+
const csIndex = source.indexOf("<CHANGE_SUMMARY>");
|
|
167
|
+
const hasHeader =
|
|
168
|
+
(mcIndex >= 0 && inHeaderRegion(source, mcIndex)) ||
|
|
169
|
+
(csIndex >= 0 && inHeaderRegion(source, csIndex));
|
|
170
|
+
if (!hasHeader) {
|
|
171
|
+
return { source, actions: ["no-header"] };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 2. Parseability — an open tag without its close is a broken header.
|
|
175
|
+
for (const tag of COMPASS_TAGS) {
|
|
176
|
+
if (hasUnclosedTag(source, tag)) {
|
|
177
|
+
return { source, actions: ["unparseable"] };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let next = source;
|
|
182
|
+
|
|
183
|
+
// 3. Collapse CHANGE_SUMMARY — same repair semantics as compass.summary.trim.
|
|
184
|
+
const csSpan = blockSpan(next, "CHANGE_SUMMARY");
|
|
185
|
+
if (csSpan) {
|
|
186
|
+
const block = next.slice(csSpan.start, csSpan.end);
|
|
187
|
+
const { items, historyIds } = parseChangeSummary(block);
|
|
188
|
+
const idItems = items.filter((item) => policy.idPatternPrefix.test(item));
|
|
189
|
+
const collapsedIds: string[] = [];
|
|
190
|
+
while (idItems.length > CHANGE_SUMMARY_WINDOW) {
|
|
191
|
+
const oldest = idItems.shift()!;
|
|
192
|
+
const idMatch = oldest.match(policy.idPatternPrefix);
|
|
193
|
+
if (idMatch) collapsedIds.push(idMatch[0]);
|
|
194
|
+
}
|
|
195
|
+
const nextHistory = mergeHistoryIds(historyIds, collapsedIds, policy);
|
|
196
|
+
const changed =
|
|
197
|
+
idItems.length !== items.length ||
|
|
198
|
+
collapsedIds.length > 0 ||
|
|
199
|
+
nextHistory.length !== historyIds.length ||
|
|
200
|
+
nextHistory.some((id, i) => id !== historyIds[i]);
|
|
201
|
+
if (changed) {
|
|
202
|
+
const newBlock = buildChangeSummaryBlock(idItems, nextHistory, pathFromRoot);
|
|
203
|
+
next = next.slice(0, csSpan.start) + newBlock + next.slice(csSpan.end);
|
|
204
|
+
actions.push("collapsed");
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 4. Strip forbidden v1 blocks and COMPASS_BLOCK anchors.
|
|
209
|
+
let stripped = next;
|
|
210
|
+
for (const tag of FORBIDDEN_BLOCK_TAGS) {
|
|
211
|
+
const tagRe = new RegExp(`[ \\t]*<${tag}>[\\s\\S]*?</${tag}>[ \\t]*`, "g");
|
|
212
|
+
stripped = stripped.replace(tagRe, "");
|
|
213
|
+
}
|
|
214
|
+
stripped = stripped.replace(COMPASS_BLOCK_ANCHOR_RE, "");
|
|
215
|
+
if (stripped !== next) {
|
|
216
|
+
next = stripped;
|
|
217
|
+
actions.push("stripped");
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// 5. Seed KEY_DECISIONS on medium/high-risk files that lack the block.
|
|
221
|
+
const riskClass = detectRiskClass(pathFromRoot, workspaceRelativePath, policy);
|
|
222
|
+
const kdRequired = riskClass === "medium" || riskClass === "high";
|
|
223
|
+
if (kdRequired && !next.includes("<KEY_DECISIONS>")) {
|
|
224
|
+
const invariants = collectAiInvariants(next, policy);
|
|
225
|
+
const items = invariants.length > 0 ? invariants : [TODO_ITEM];
|
|
226
|
+
const kdBlock = buildKeyDecisionsBlock(items, pathFromRoot);
|
|
227
|
+
const mcSpan = blockSpan(next, "MODULE_CONTRACT");
|
|
228
|
+
if (mcSpan) {
|
|
229
|
+
next = next.slice(0, mcSpan.end) + "\n" + kdBlock + next.slice(mcSpan.end);
|
|
230
|
+
} else {
|
|
231
|
+
const csSpan2 = blockSpan(next, "CHANGE_SUMMARY");
|
|
232
|
+
if (csSpan2) {
|
|
233
|
+
next = next.slice(0, csSpan2.start) + kdBlock + "\n" + next.slice(csSpan2.start);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
actions.push(invariants.length > 0 ? "seeded" : "todo");
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// 6. Reorder blocks to canonical order — only when the region between the
|
|
240
|
+
// outermost blocks is whitespace and the blocks themselves.
|
|
241
|
+
const spans = COMPASS_TAGS.map((tag) => ({ tag, span: blockSpan(next, tag) }))
|
|
242
|
+
.filter(
|
|
243
|
+
(entry): entry is { tag: CompassTag; span: { start: number; end: number } } =>
|
|
244
|
+
entry.span !== null,
|
|
245
|
+
)
|
|
246
|
+
.sort((a, b) => a.span.start - b.span.start);
|
|
247
|
+
if (spans.length >= 2) {
|
|
248
|
+
const canonicalOrder = spans
|
|
249
|
+
.slice()
|
|
250
|
+
.sort((a, b) => COMPASS_TAGS.indexOf(a.tag) - COMPASS_TAGS.indexOf(b.tag))
|
|
251
|
+
.map((entry) => entry.tag);
|
|
252
|
+
const currentOrder = spans.map((entry) => entry.tag);
|
|
253
|
+
const outOfOrder = currentOrder.some((tag, i) => tag !== canonicalOrder[i]);
|
|
254
|
+
if (outOfOrder) {
|
|
255
|
+
const minStart = Math.min(...spans.map((entry) => entry.span.start));
|
|
256
|
+
const maxEnd = Math.max(...spans.map((entry) => entry.span.end));
|
|
257
|
+
const region = next.slice(minStart, maxEnd);
|
|
258
|
+
const residue = region
|
|
259
|
+
.replace(/<MODULE_CONTRACT>[\s\S]*?<\/MODULE_CONTRACT>/, "")
|
|
260
|
+
.replace(/<KEY_DECISIONS>[\s\S]*?<\/KEY_DECISIONS>/, "")
|
|
261
|
+
.replace(/<CHANGE_SUMMARY>[\s\S]*?<\/CHANGE_SUMMARY>/, "");
|
|
262
|
+
if (residue.trim().length === 0) {
|
|
263
|
+
const ordered = canonicalOrder.map((tag) => {
|
|
264
|
+
const span = spans.find((entry) => entry.tag === tag)!.span;
|
|
265
|
+
return next.slice(span.start, span.end);
|
|
266
|
+
});
|
|
267
|
+
next = next.slice(0, minStart) + ordered.join("\n") + next.slice(maxEnd);
|
|
268
|
+
actions.push("reordered");
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// 7. Flag boilerplate purpose — report only, the sweep rewrites the text.
|
|
274
|
+
const purposeText = extractPurposeText(next);
|
|
275
|
+
if (
|
|
276
|
+
purposeText.length > 0 &&
|
|
277
|
+
policy.purposeBoilerplatePatterns.some((pattern) => pattern.test(purposeText))
|
|
278
|
+
) {
|
|
279
|
+
actions.push("purpose-flagged");
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (actions.length === 0 || next === source) {
|
|
283
|
+
const reportOnly = actions.filter((a) => a === "purpose-flagged");
|
|
284
|
+
return {
|
|
285
|
+
source,
|
|
286
|
+
actions: reportOnly.length > 0 ? reportOnly : ["unchanged"],
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return { source: next, actions };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
interface MigrateTarget {
|
|
294
|
+
absPath: string;
|
|
295
|
+
pathFromRoot: string;
|
|
296
|
+
workspaceRelativePath: string;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function toTarget(workspaceRoot: string, absPath: string, policy: CompassPolicy): MigrateTarget {
|
|
300
|
+
const pathFromRoot = relative(workspaceRoot, absPath).replace(/\\/g, "/");
|
|
301
|
+
const segments = getRelativeSegments(absPath, workspaceRoot);
|
|
302
|
+
const workspaceRelativePath = getWorkspaceRelativeSegments(segments, policy).join("/");
|
|
303
|
+
return { absPath, pathFromRoot, workspaceRelativePath };
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Walk the workspace (or an explicit file list) and apply migrateFile to every
|
|
308
|
+
* authored file. Writes via writeFileIfChanged unless dryRun.
|
|
309
|
+
*/
|
|
310
|
+
export async function migrateWorkspace(
|
|
311
|
+
workspaceRoot: string,
|
|
312
|
+
input: ForgeCommandInput,
|
|
313
|
+
scanRoot: string | undefined,
|
|
314
|
+
policy: CompassPolicy,
|
|
315
|
+
options: MigrateOptions,
|
|
316
|
+
): Promise<MigrateResult> {
|
|
317
|
+
const result: MigrateResult = { scanned: 0, files: [] };
|
|
318
|
+
|
|
319
|
+
if (options.files && options.files.length > 0) {
|
|
320
|
+
for (const file of options.files) {
|
|
321
|
+
const absPath = resolve(scanRoot ?? workspaceRoot, file);
|
|
322
|
+
const target = toTarget(workspaceRoot, absPath, policy);
|
|
323
|
+
let source: string;
|
|
324
|
+
try {
|
|
325
|
+
source = await readFile(absPath, "utf8");
|
|
326
|
+
} catch {
|
|
327
|
+
result.files.push({ path: file, actions: ["unparseable"] });
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
result.scanned += 1;
|
|
331
|
+
const migrated = migrateFile(
|
|
332
|
+
source,
|
|
333
|
+
policy,
|
|
334
|
+
target.pathFromRoot,
|
|
335
|
+
target.workspaceRelativePath,
|
|
336
|
+
);
|
|
337
|
+
result.files.push({ path: target.pathFromRoot, actions: migrated.actions });
|
|
338
|
+
if (!options.dryRun && migrated.source !== source) {
|
|
339
|
+
await writeFileIfChanged(absPath, migrated.source);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return result;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const entries = await createCompassInventoryEntries(workspaceRoot, input, scanRoot, policy);
|
|
346
|
+
for (const entry of entries) {
|
|
347
|
+
if (entry.authoringStatus !== "authored") continue;
|
|
348
|
+
result.scanned += 1;
|
|
349
|
+
const absPath = resolve(workspaceRoot, entry.path);
|
|
350
|
+
const source = getEntrySource(entry) ?? (await readFile(absPath, "utf8"));
|
|
351
|
+
const segments = getRelativeSegments(absPath, workspaceRoot);
|
|
352
|
+
const workspaceRelativePath = getWorkspaceRelativeSegments(segments, policy).join("/");
|
|
353
|
+
const migrated = migrateFile(source, policy, entry.path, workspaceRelativePath);
|
|
354
|
+
result.files.push({ path: entry.path, actions: migrated.actions });
|
|
355
|
+
if (!options.dryRun && migrated.source !== source) {
|
|
356
|
+
await writeFileIfChanged(absPath, migrated.source);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return result;
|
|
361
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, mkdirSync, rmSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { resolveCompassScanRoot } from "./resolve-scan-root.ts";
|
|
6
|
+
import type { ForgeCommandInput, ForgeRuntimeContext } from "../../../src/types.ts";
|
|
7
|
+
|
|
8
|
+
function makeContext(workspaceRoot: string, siteExplicit = false): ForgeRuntimeContext {
|
|
9
|
+
return {
|
|
10
|
+
workspaceRoot,
|
|
11
|
+
site: undefined,
|
|
12
|
+
siteExplicit,
|
|
13
|
+
dryRun: false,
|
|
14
|
+
logger: { info: () => {}, warn: () => {}, error: () => {} },
|
|
15
|
+
} as unknown as ForgeRuntimeContext;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function makeInput(flags: Record<string, unknown> = {}): ForgeCommandInput {
|
|
19
|
+
return { flags } as ForgeCommandInput;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe("resolveCompassScanRoot --package", () => {
|
|
23
|
+
let tempDir: string;
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
tempDir = mkdtempSync(join(tmpdir(), "compass-package-test-"));
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("implies --packages scope: resolves to packages/<name>/src when src exists", () => {
|
|
34
|
+
mkdirSync(join(tempDir, "packages", "my-pkg", "src"), { recursive: true });
|
|
35
|
+
const result = resolveCompassScanRoot(makeInput({ package: "my-pkg" }), makeContext(tempDir));
|
|
36
|
+
expect(result).toBe(join(tempDir, "packages", "my-pkg", "src"));
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("implies --packages scope: resolves to packages/<name> when no src dir", () => {
|
|
40
|
+
mkdirSync(join(tempDir, "packages", "my-pkg"), { recursive: true });
|
|
41
|
+
const result = resolveCompassScanRoot(makeInput({ package: "my-pkg" }), makeContext(tempDir));
|
|
42
|
+
expect(result).toBe(join(tempDir, "packages", "my-pkg"));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("throws when --package and --workpiece are both set", () => {
|
|
46
|
+
expect(() =>
|
|
47
|
+
resolveCompassScanRoot(
|
|
48
|
+
makeInput({ package: "my-pkg", workpiece: "some/path" }),
|
|
49
|
+
makeContext(tempDir),
|
|
50
|
+
),
|
|
51
|
+
).toThrow("--workpiece and --packages are mutually exclusive");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("throws when --package and --site are both set", () => {
|
|
55
|
+
expect(() =>
|
|
56
|
+
resolveCompassScanRoot(makeInput({ package: "my-pkg" }), makeContext(tempDir, true)),
|
|
57
|
+
).toThrow("--site and --packages are mutually exclusive");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("throws when the package does not exist", () => {
|
|
61
|
+
expect(() =>
|
|
62
|
+
resolveCompassScanRoot(makeInput({ package: "nonexistent" }), makeContext(tempDir)),
|
|
63
|
+
).toThrow('Package "nonexistent" not found');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("--packages without --package still scans the packages/ root", () => {
|
|
67
|
+
const result = resolveCompassScanRoot(makeInput({ packages: true }), makeContext(tempDir));
|
|
68
|
+
expect(result).toBe(join(tempDir, "packages"));
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -8,9 +8,18 @@ Moved from @warpgogol/site-kernel to @warpgogol/forge for full autonomous mode (
|
|
|
8
8
|
</non-goals>
|
|
9
9
|
</MODULE_CONTRACT>
|
|
10
10
|
<CHANGE_SUMMARY>
|
|
11
|
-
<item>Introduced as part of RFC-0015 to extend Compass commands to packages/.</item>
|
|
12
11
|
<item>RFC-0556: moved canonical implementation from @warpgogol/site-kernel to @warpgogol/forge for autonomous mode.</item>
|
|
13
12
|
<item>RFC-0617: added --workpiece flag for mission workpiece directory scanning.</item>
|
|
13
|
+
<item>RFC-1097: step 6 — compass.migrate codemod run
|
|
14
|
+
|
|
15
|
+
Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
|
|
16
|
+
<item>RFC-1097: sweep — engine package clean
|
|
17
|
+
|
|
18
|
+
Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. engine package now 0 diagnostics.</item>
|
|
19
|
+
<item>RFC-1097: AC-4 banned literal in os/compass handlers
|
|
20
|
+
|
|
21
|
+
compass-migrate-handler hint used a consumer-specific run command — switched to generic 'pnpm exec forge run' convention. Reworded recorded CHANGE_SUMMARY items in 3 handlers to drop the consumer-specific literal. compass-policy AC-4 test green (65/65).</item>
|
|
22
|
+
<item>RFC-0617: fix — --package alone now implies --packages scope (was a silent no-op falling through to full-repo scan).</item>
|
|
14
23
|
</CHANGE_SUMMARY>
|
|
15
24
|
*/
|
|
16
25
|
|
|
@@ -22,7 +31,9 @@ export function resolveCompassScanRoot(
|
|
|
22
31
|
input: ForgeCommandInput,
|
|
23
32
|
context: ForgeRuntimeContext,
|
|
24
33
|
): string | undefined {
|
|
25
|
-
const
|
|
34
|
+
const packageName = input.flags["package"];
|
|
35
|
+
const hasPackage = typeof packageName === "string" && packageName.length > 0;
|
|
36
|
+
const hasPackages = input.flags["packages"] === true || hasPackage;
|
|
26
37
|
const workpiecePath = input.flags["workpiece"];
|
|
27
38
|
const hasWorkpiece = typeof workpiecePath === "string" && workpiecePath.length > 0;
|
|
28
39
|
|
|
@@ -56,15 +67,11 @@ export function resolveCompassScanRoot(
|
|
|
56
67
|
return context.site ? context.site.directory : undefined;
|
|
57
68
|
}
|
|
58
69
|
|
|
59
|
-
|
|
60
|
-
if (!packageName || typeof packageName !== "string") {
|
|
70
|
+
if (!hasPackage) {
|
|
61
71
|
return resolve(context.workspaceRoot, "packages");
|
|
62
72
|
}
|
|
63
73
|
|
|
64
|
-
const candidates = [
|
|
65
|
-
resolve(context.workspaceRoot, "packages", "os", packageName),
|
|
66
|
-
resolve(context.workspaceRoot, "packages", packageName),
|
|
67
|
-
];
|
|
74
|
+
const candidates = [resolve(context.workspaceRoot, "packages", packageName)];
|
|
68
75
|
|
|
69
76
|
for (const candidate of candidates) {
|
|
70
77
|
if (existsSync(candidate)) {
|