@warpgogol/forge 5.2.3 → 5.3.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/AGENTS.md +34 -2
- package/README.md +1 -1
- package/README.uk.md +8 -8
- package/bin/cli.ts +1 -0
- package/dist/bin/cli.js +1 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/os/adr/adr.module.d.ts.map +1 -1
- package/dist/os/adr/adr.module.js +8 -3
- package/dist/os/adr/adr.module.js.map +1 -1
- package/dist/os/adr/frontmatter-io.js +5 -5
- package/dist/os/adr/frontmatter-io.js.map +1 -1
- package/dist/os/adr/handlers/archive.d.ts.map +1 -1
- package/dist/os/adr/handlers/archive.js +10 -4
- package/dist/os/adr/handlers/archive.js.map +1 -1
- package/dist/os/adr/handlers/implement-stamp.d.ts.map +1 -1
- package/dist/os/adr/handlers/implement-stamp.js +10 -9
- package/dist/os/adr/handlers/implement-stamp.js.map +1 -1
- package/dist/os/adr/handlers/list-create.js +5 -5
- package/dist/os/adr/handlers/list-create.js.map +1 -1
- package/dist/os/adr/handlers/validate.js +1 -1
- package/dist/os/adr/handlers/validate.js.map +1 -1
- package/dist/os/audit/audit.module.js +3 -3
- package/dist/os/audit/audit.module.js.map +1 -1
- package/dist/os/audit/frontmatter-io.js +5 -5
- package/dist/os/audit/frontmatter-io.js.map +1 -1
- package/dist/os/audit/handlers/archive.d.ts.map +1 -1
- package/dist/os/audit/handlers/archive.js +10 -4
- package/dist/os/audit/handlers/archive.js.map +1 -1
- package/dist/os/compass/compass.module.d.ts.map +1 -1
- package/dist/os/compass/compass.module.js +17 -1
- 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 +12 -5
- package/dist/os/compass/handlers/compass-audit-handler.js.map +1 -1
- package/dist/os/compass/handlers/compass-change-summary-handler.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-change-summary-handler.js +3 -2
- package/dist/os/compass/handlers/compass-change-summary-handler.js.map +1 -1
- package/dist/os/compass/handlers/compass-inventory-handler.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-inventory-handler.js +6 -4
- package/dist/os/compass/handlers/compass-inventory-handler.js.map +1 -1
- package/dist/os/compass/handlers/compass-inventory.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-inventory.js +10 -8
- package/dist/os/compass/handlers/compass-inventory.js.map +1 -1
- package/dist/os/compass/handlers/compass-migrate-handler.js +1 -1
- package/dist/os/compass/handlers/compass-migrate-handler.js.map +1 -1
- package/dist/os/compass/handlers/compass-migrate.d.ts.map +1 -1
- package/dist/os/compass/handlers/compass-migrate.js +6 -3
- package/dist/os/compass/handlers/compass-migrate.js.map +1 -1
- package/dist/os/compass/handlers/git-revision.d.ts.map +1 -1
- package/dist/os/compass/handlers/git-revision.js +9 -6
- package/dist/os/compass/handlers/git-revision.js.map +1 -1
- package/dist/os/compass/handlers/resolve-scan-root.js +1 -1
- package/dist/os/compass/handlers/resolve-scan-root.js.map +1 -1
- package/dist/os/compass/handlers/summary-record.d.ts.map +1 -1
- package/dist/os/compass/handlers/summary-record.js +8 -4
- package/dist/os/compass/handlers/summary-record.js.map +1 -1
- package/dist/os/core/core.module.d.ts.map +1 -1
- package/dist/os/core/core.module.js +57 -4
- package/dist/os/core/core.module.js.map +1 -1
- package/dist/os/core/handlers/assets-helpers.d.ts.map +1 -1
- package/dist/os/core/handlers/assets-helpers.js +6 -3
- package/dist/os/core/handlers/assets-helpers.js.map +1 -1
- package/dist/os/core/handlers/build.js +1 -1
- package/dist/os/core/handlers/build.js.map +1 -1
- package/dist/os/core/handlers/determinism-check.d.ts.map +1 -1
- package/dist/os/core/handlers/determinism-check.js +10 -6
- package/dist/os/core/handlers/determinism-check.js.map +1 -1
- package/dist/os/core/handlers/dev.js +1 -1
- package/dist/os/core/handlers/dev.js.map +1 -1
- package/dist/os/core/handlers/file-size-lint.d.ts.map +1 -1
- package/dist/os/core/handlers/file-size-lint.js +11 -7
- package/dist/os/core/handlers/file-size-lint.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 +9 -5
- package/dist/os/core/handlers/forge-autonomy-validate.js.map +1 -1
- package/dist/os/core/handlers/knowledge-compact.js +1 -1
- package/dist/os/core/handlers/knowledge-compact.js.map +1 -1
- package/dist/os/core/handlers/package-health.js +1 -1
- package/dist/os/core/handlers/package-health.js.map +1 -1
- package/dist/os/core/handlers/pinned-check.js +2 -2
- package/dist/os/core/handlers/pinned-check.js.map +1 -1
- package/dist/os/core/handlers/pinned-init.d.ts.map +1 -1
- package/dist/os/core/handlers/pinned-init.js +9 -8
- package/dist/os/core/handlers/pinned-init.js.map +1 -1
- package/dist/os/core/handlers/pinned-validate.js +3 -3
- package/dist/os/core/handlers/pinned-validate.js.map +1 -1
- package/dist/os/core/handlers/profile-resolve.js +1 -1
- package/dist/os/core/handlers/profile-resolve.js.map +1 -1
- package/dist/os/core/handlers/public-surface.js +1 -1
- package/dist/os/core/handlers/public-surface.js.map +1 -1
- package/dist/os/core/handlers/release-prepare.d.ts.map +1 -1
- package/dist/os/core/handlers/release-prepare.js +10 -6
- package/dist/os/core/handlers/release-prepare.js.map +1 -1
- package/dist/os/core/handlers/release-publish.js +6 -6
- package/dist/os/core/handlers/release-publish.js.map +1 -1
- package/dist/os/core/handlers/validate.js +1 -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 +1 -0
- package/dist/os/exploration/exploration.module.js.map +1 -1
- package/dist/os/exploration/frontmatter-io.js +4 -4
- package/dist/os/exploration/frontmatter-io.js.map +1 -1
- package/dist/os/exploration/handlers/archive.js +3 -3
- package/dist/os/exploration/handlers/archive.js.map +1 -1
- package/dist/os/mission/handlers/archive.d.ts.map +1 -1
- package/dist/os/mission/handlers/archive.js +22 -19
- package/dist/os/mission/handlers/archive.js.map +1 -1
- package/dist/os/mission/mission.module.js +3 -3
- package/dist/os/mission/mission.module.js.map +1 -1
- package/dist/os/naming/naming-convention.d.ts.map +1 -1
- package/dist/os/naming/naming-convention.js +7 -3
- package/dist/os/naming/naming-convention.js.map +1 -1
- package/dist/os/naming/naming.module.d.ts.map +1 -1
- package/dist/os/naming/naming.module.js +4 -3
- package/dist/os/naming/naming.module.js.map +1 -1
- package/dist/os/notes/notes.module.d.ts.map +1 -1
- package/dist/os/notes/notes.module.js +6 -3
- package/dist/os/notes/notes.module.js.map +1 -1
- package/dist/os/plan/frontmatter-io.js +5 -5
- package/dist/os/plan/frontmatter-io.js.map +1 -1
- package/dist/os/plan/handlers/archive.d.ts.map +1 -1
- package/dist/os/plan/handlers/archive.js +10 -4
- package/dist/os/plan/handlers/archive.js.map +1 -1
- package/dist/os/plan/plan.module.js +3 -3
- package/dist/os/plan/plan.module.js.map +1 -1
- package/dist/os/plugin/plugin.module.d.ts.map +1 -1
- package/dist/os/plugin/plugin.module.js +6 -3
- package/dist/os/plugin/plugin.module.js.map +1 -1
- package/dist/os/program/discovery.js +2 -2
- package/dist/os/program/discovery.js.map +1 -1
- package/dist/os/program/handlers/complete.js +1 -1
- package/dist/os/program/handlers/complete.js.map +1 -1
- package/dist/os/program/handlers/lease.js +1 -1
- package/dist/os/program/handlers/lease.js.map +1 -1
- package/dist/os/program/handlers/seal.js +1 -1
- package/dist/os/program/handlers/seal.js.map +1 -1
- package/dist/os/program/lease.js +1 -1
- package/dist/os/program/lease.js.map +1 -1
- package/dist/os/program/program.module.d.ts.map +1 -1
- package/dist/os/program/program.module.js +9 -3
- package/dist/os/program/program.module.js.map +1 -1
- package/dist/os/queue/index.js +1 -1
- package/dist/os/queue/manifest.d.ts.map +1 -1
- package/dist/os/queue/manifest.js +4 -8
- package/dist/os/queue/manifest.js.map +1 -1
- package/dist/os/rfc/acceptance.d.ts.map +1 -1
- package/dist/os/rfc/acceptance.js +10 -6
- package/dist/os/rfc/acceptance.js.map +1 -1
- package/dist/os/rfc/decision-log.d.ts.map +1 -1
- package/dist/os/rfc/decision-log.js +4 -3
- package/dist/os/rfc/decision-log.js.map +1 -1
- package/dist/os/rfc/dna-trace.d.ts.map +1 -1
- package/dist/os/rfc/dna-trace.js +7 -2
- package/dist/os/rfc/dna-trace.js.map +1 -1
- package/dist/os/rfc/frontmatter-io.js +5 -5
- 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 +11 -5
- package/dist/os/rfc/handlers/archive.js.map +1 -1
- package/dist/os/rfc/handlers/check.d.ts.map +1 -1
- package/dist/os/rfc/handlers/check.js +6 -3
- package/dist/os/rfc/handlers/check.js.map +1 -1
- package/dist/os/rfc/handlers/implement-stamp.d.ts.map +1 -1
- package/dist/os/rfc/handlers/implement-stamp.js +11 -10
- package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
- package/dist/os/rfc/handlers/index-graph.js +3 -3
- 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 -2
- 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 +7 -6
- package/dist/os/rfc/handlers/list-create.js.map +1 -1
- package/dist/os/rfc/handlers/shared.js +3 -3
- package/dist/os/rfc/handlers/shared.js.map +1 -1
- package/dist/os/rfc/handlers/supersede-propose.d.ts.map +1 -1
- package/dist/os/rfc/handlers/supersede-propose.js +7 -3
- 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 +8 -5
- package/dist/os/rfc/handlers/validate-rules.js.map +1 -1
- package/dist/os/rfc/rfc.module.d.ts.map +1 -1
- package/dist/os/rfc/rfc.module.js +44 -4
- package/dist/os/rfc/rfc.module.js.map +1 -1
- package/dist/os/rfc/verification-evidence.d.ts.map +1 -1
- package/dist/os/rfc/verification-evidence.js +9 -5
- package/dist/os/rfc/verification-evidence.js.map +1 -1
- package/dist/os/rfc/verification-refresh.d.ts.map +1 -1
- package/dist/os/rfc/verification-refresh.js +4 -3
- package/dist/os/rfc/verification-refresh.js.map +1 -1
- package/dist/os/session/frontmatter-io.js +12 -12
- package/dist/os/session/frontmatter-io.js.map +1 -1
- package/dist/os/session/handlers/archive.d.ts.map +1 -1
- package/dist/os/session/handlers/archive.js +10 -4
- package/dist/os/session/handlers/archive.js.map +1 -1
- package/dist/os/session/handlers/metrics-aggregate.d.ts.map +1 -1
- package/dist/os/session/handlers/metrics-aggregate.js +9 -5
- package/dist/os/session/handlers/metrics-aggregate.js.map +1 -1
- package/dist/os/session/handlers/metrics-rfc.d.ts.map +1 -1
- package/dist/os/session/handlers/metrics-rfc.js +11 -8
- package/dist/os/session/handlers/metrics-rfc.js.map +1 -1
- package/dist/os/session/handlers/metrics-session.d.ts.map +1 -1
- package/dist/os/session/handlers/metrics-session.js +6 -3
- package/dist/os/session/handlers/metrics-session.js.map +1 -1
- package/dist/os/session/handlers/save.d.ts.map +1 -1
- package/dist/os/session/handlers/save.js +14 -8
- package/dist/os/session/handlers/save.js.map +1 -1
- package/dist/os/session/session.module.d.ts.map +1 -1
- package/dist/os/session/session.module.js +6 -0
- package/dist/os/session/session.module.js.map +1 -1
- package/dist/os/spec/live-spec-list.js +4 -4
- package/dist/os/spec/live-spec-list.js.map +1 -1
- package/dist/os/spec/live-spec-merge.js +5 -5
- package/dist/os/spec/live-spec-merge.js.map +1 -1
- package/dist/os/spec/live-spec-show.js +3 -3
- package/dist/os/spec/live-spec-show.js.map +1 -1
- package/dist/os/spec/live-spec-validate.js +4 -4
- package/dist/os/spec/live-spec-validate.js.map +1 -1
- package/dist/os/spec/spec-materialize.js +9 -9
- package/dist/os/spec/spec-materialize.js.map +1 -1
- package/dist/os/spec/spec-status.js +9 -9
- package/dist/os/spec/spec-status.js.map +1 -1
- package/dist/os/spec/spec-validate.js +7 -7
- package/dist/os/spec/spec-validate.js.map +1 -1
- package/dist/os/spec/spec.module.d.ts.map +1 -1
- package/dist/os/spec/spec.module.js +8 -0
- package/dist/os/spec/spec.module.js.map +1 -1
- package/dist/os/werkstatt/handlers/lock.js +16 -16
- package/dist/os/werkstatt/handlers/lock.js.map +1 -1
- package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js +3 -3
- package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js.map +1 -1
- package/dist/os/werkstatt/handlers/werkstatt-operation-validate.d.ts.map +1 -1
- package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js +3 -2
- package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js.map +1 -1
- package/dist/os/werkstatt/werkstatt.module.d.ts.map +1 -1
- package/dist/os/werkstatt/werkstatt.module.js +6 -2
- package/dist/os/werkstatt/werkstatt.module.js.map +1 -1
- package/dist/os/workflow/handlers.d.ts.map +1 -1
- package/dist/os/workflow/handlers.js +8 -5
- package/dist/os/workflow/handlers.js.map +1 -1
- package/dist/os/workflow/workflow.module.d.ts.map +1 -1
- package/dist/os/workflow/workflow.module.js +6 -3
- package/dist/os/workflow/workflow.module.js.map +1 -1
- package/dist/src/compass/contract-registry.js +1 -1
- package/dist/src/compass/contract-registry.js.map +1 -1
- package/dist/src/config/forge-config.d.ts +10 -1
- package/dist/src/config/forge-config.d.ts.map +1 -1
- package/dist/src/config/forge-config.js +8 -1
- package/dist/src/config/forge-config.js.map +1 -1
- package/dist/src/knowledge/budgets.js +1 -1
- package/dist/src/knowledge/budgets.js.map +1 -1
- package/dist/src/knowledge/compact.js +1 -1
- package/dist/src/knowledge/compact.js.map +1 -1
- package/dist/src/knowledge/parse.js +1 -1
- package/dist/src/knowledge/parse.js.map +1 -1
- package/dist/src/knowledge/sync.d.ts.map +1 -1
- package/dist/src/knowledge/sync.js +3 -5
- package/dist/src/knowledge/sync.js.map +1 -1
- package/dist/src/migration-adapters/git-utils.js +2 -2
- package/dist/src/migration-adapters/git-utils.js.map +1 -1
- package/dist/src/migration-adapters/ignored-files.js +2 -2
- package/dist/src/migration-adapters/ignored-files.js.map +1 -1
- package/dist/src/migration-adapters/node-typescript-pnpm/index.js +1 -1
- package/dist/src/migration-adapters/node-typescript-pnpm/index.js.map +1 -1
- package/dist/src/migration-adapters/phaser-pnpm/index.js +1 -1
- package/dist/src/migration-adapters/phaser-pnpm/index.js.map +1 -1
- package/dist/src/onboarding/agents-generate.d.ts +2 -0
- package/dist/src/onboarding/agents-generate.d.ts.map +1 -1
- package/dist/src/onboarding/agents-generate.js +73 -48
- 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 +10 -10
- package/dist/src/onboarding/create.js.map +1 -1
- package/dist/src/onboarding/doctor.d.ts +6 -0
- package/dist/src/onboarding/doctor.d.ts.map +1 -1
- package/dist/src/onboarding/doctor.js +179 -61
- 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 +30 -1
- package/dist/src/onboarding/init.js.map +1 -1
- package/dist/src/onboarding/invariant-engine.js +1 -1
- package/dist/src/onboarding/invariant-engine.js.map +1 -1
- package/dist/src/onboarding/memory-compact.d.ts +22 -0
- package/dist/src/onboarding/memory-compact.d.ts.map +1 -0
- package/dist/src/onboarding/memory-compact.js +148 -0
- package/dist/src/onboarding/memory-compact.js.map +1 -0
- package/dist/src/onboarding/memory-scaffold.d.ts +1 -0
- package/dist/src/onboarding/memory-scaffold.d.ts.map +1 -1
- package/dist/src/onboarding/memory-scaffold.js +2 -2
- package/dist/src/onboarding/memory-scaffold.js.map +1 -1
- package/dist/src/onboarding/nested-agents-generate.d.ts +4 -1
- package/dist/src/onboarding/nested-agents-generate.d.ts.map +1 -1
- package/dist/src/onboarding/nested-agents-generate.js +35 -6
- 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 +8 -12
- package/dist/src/onboarding/nested-agents-templates.js.map +1 -1
- package/dist/src/onboarding/npm-token-check.js +2 -2
- package/dist/src/onboarding/npm-token-check.js.map +1 -1
- package/dist/src/onboarding/prettierignore.d.ts +29 -0
- package/dist/src/onboarding/prettierignore.d.ts.map +1 -0
- package/dist/src/onboarding/prettierignore.js +231 -0
- package/dist/src/onboarding/prettierignore.js.map +1 -0
- package/dist/src/onboarding/profile-validate.d.ts.map +1 -1
- package/dist/src/onboarding/profile-validate.js +5 -4
- package/dist/src/onboarding/profile-validate.js.map +1 -1
- package/dist/src/onboarding/scaffold-project.d.ts.map +1 -1
- package/dist/src/onboarding/scaffold-project.js +35 -27
- package/dist/src/onboarding/scaffold-project.js.map +1 -1
- package/dist/src/onboarding/scaffold.js +1 -1
- package/dist/src/onboarding/scaffold.js.map +1 -1
- package/dist/src/onboarding/skill-markers.d.ts +27 -0
- package/dist/src/onboarding/skill-markers.d.ts.map +1 -0
- package/dist/src/onboarding/skill-markers.js +131 -0
- package/dist/src/onboarding/skill-markers.js.map +1 -0
- package/dist/src/onboarding/upgrade.d.ts +10 -0
- package/dist/src/onboarding/upgrade.d.ts.map +1 -1
- package/dist/src/onboarding/upgrade.js +215 -74
- package/dist/src/onboarding/upgrade.js.map +1 -1
- package/dist/src/onboarding/workspace-discovery.d.ts +1 -1
- package/dist/src/onboarding/workspace-discovery.d.ts.map +1 -1
- package/dist/src/onboarding/workspace-discovery.js +15 -3
- package/dist/src/onboarding/workspace-discovery.js.map +1 -1
- package/dist/src/pipeline-status.d.ts +6 -5
- package/dist/src/pipeline-status.d.ts.map +1 -1
- package/dist/src/pipeline-status.js +24 -19
- package/dist/src/pipeline-status.js.map +1 -1
- package/dist/src/profiles/stack-profile.js +1 -1
- package/dist/src/profiles/stack-profile.js.map +1 -1
- package/dist/src/registry.d.ts +1 -1
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +3 -3
- package/dist/src/registry.js.map +1 -1
- package/dist/src/skill-schema.d.ts +1 -1
- package/dist/src/skill-schema.d.ts.map +1 -1
- package/dist/src/skill-schema.js +4 -1
- package/dist/src/skill-schema.js.map +1 -1
- package/dist/src/types.d.ts +116 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/editable-region.d.ts +46 -0
- package/dist/src/utils/editable-region.d.ts.map +1 -0
- package/dist/src/utils/editable-region.js +125 -0
- package/dist/src/utils/editable-region.js.map +1 -0
- package/dist/src/utils/fs-idempotent.d.ts +2 -1
- package/dist/src/utils/fs-idempotent.d.ts.map +1 -1
- package/dist/src/utils/fs-idempotent.js +11 -7
- package/dist/src/utils/fs-idempotent.js.map +1 -1
- package/dist/src/utils/generated-marker.d.ts +17 -0
- package/dist/src/utils/generated-marker.d.ts.map +1 -1
- package/dist/src/utils/generated-marker.js +29 -1
- package/dist/src/utils/generated-marker.js.map +1 -1
- package/dist/src/utils/index.d.ts +3 -1
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +3 -1
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/io.d.ts +9 -0
- package/dist/src/utils/io.d.ts.map +1 -0
- package/dist/src/utils/io.js +130 -0
- package/dist/src/utils/io.js.map +1 -0
- package/dist/src/utils/markdown-table.d.ts +21 -0
- package/dist/src/utils/markdown-table.d.ts.map +1 -0
- package/dist/src/utils/markdown-table.js +116 -0
- package/dist/src/utils/markdown-table.js.map +1 -0
- package/dist/src/utils/sync-fs.d.ts +5 -0
- package/dist/src/utils/sync-fs.d.ts.map +1 -0
- package/dist/src/utils/sync-fs.js +26 -0
- package/dist/src/utils/sync-fs.js.map +1 -0
- package/dist/src/validators/note-frontmatter-validate.js +1 -1
- package/dist/src/validators/note-frontmatter-validate.js.map +1 -1
- package/dist/src/validators/note-link-validate.js +1 -1
- package/dist/src/validators/note-link-validate.js.map +1 -1
- package/dist/src/validators/note-orphan-detect.js +1 -1
- package/dist/src/validators/note-orphan-detect.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 +34 -13
- package/dist/src/validators/skill-validate.js.map +1 -1
- package/docs/reference/forge-yaml.md +12 -0
- package/os/adr/adr.module.ts +136 -132
- package/os/adr/frontmatter-io.ts +5 -5
- package/os/adr/handlers/archive.ts +8 -4
- package/os/adr/handlers/implement-stamp.ts +14 -9
- package/os/adr/handlers/list-create.ts +5 -5
- package/os/adr/handlers/validate.ts +1 -1
- package/os/audit/audit.module.ts +33 -34
- package/os/audit/frontmatter-io.ts +5 -5
- package/os/audit/handlers/archive.ts +8 -4
- package/os/compass/compass.module.ts +17 -1
- package/os/compass/handlers/compass-audit-handler.ts +13 -5
- package/os/compass/handlers/compass-change-summary-handler.ts +4 -2
- package/os/compass/handlers/compass-inventory-handler.ts +7 -4
- package/os/compass/handlers/compass-inventory.ts +11 -8
- package/os/compass/handlers/compass-migrate-handler.ts +1 -1
- package/os/compass/handlers/compass-migrate.ts +7 -3
- package/os/compass/handlers/git-revision.ts +11 -6
- package/os/compass/handlers/resolve-scan-root.ts +1 -1
- package/os/compass/handlers/summary-record.ts +10 -4
- package/os/compass/handlers/tests/compass-audit-plan.test.ts +2 -1
- package/os/core/core.module.ts +58 -4
- package/os/core/handlers/assets-helpers.ts +7 -3
- package/os/core/handlers/build.ts +1 -1
- package/os/core/handlers/determinism-check.ts +12 -6
- package/os/core/handlers/dev.ts +1 -1
- package/os/core/handlers/file-size-lint.ts +16 -9
- package/os/core/handlers/forge-autonomy-validate.ts +10 -5
- package/os/core/handlers/knowledge-compact.ts +1 -1
- package/os/core/handlers/package-health.ts +1 -1
- package/os/core/handlers/pinned-check.ts +2 -2
- package/os/core/handlers/pinned-init.ts +9 -8
- package/os/core/handlers/pinned-validate.ts +3 -3
- package/os/core/handlers/profile-resolve.ts +1 -1
- package/os/core/handlers/public-surface.ts +1 -1
- package/os/core/handlers/release-prepare.ts +11 -6
- package/os/core/handlers/release-publish.ts +6 -6
- package/os/core/handlers/validate.ts +1 -1
- package/os/exploration/exploration.module.ts +1 -0
- package/os/exploration/frontmatter-io.ts +4 -4
- package/os/exploration/handlers/archive.ts +3 -3
- package/os/mission/handlers/archive.ts +27 -19
- package/os/mission/mission.module.ts +38 -39
- package/os/naming/naming-convention.ts +9 -3
- package/os/naming/naming.module.ts +25 -25
- package/os/notes/notes.module.ts +87 -85
- package/os/plan/frontmatter-io.ts +5 -5
- package/os/plan/handlers/archive.ts +8 -4
- package/os/plan/plan.module.ts +33 -34
- package/os/plugin/plugin.module.ts +8 -6
- package/os/program/discovery.ts +2 -2
- package/os/program/handlers/complete.ts +1 -1
- package/os/program/handlers/lease.ts +1 -1
- package/os/program/handlers/seal.ts +1 -1
- package/os/program/lease.ts +1 -1
- package/os/program/program.module.ts +198 -193
- package/os/queue/index.ts +1 -1
- package/os/queue/manifest.ts +10 -9
- package/os/queue/queue-validate.test.ts +6 -15
- package/os/rfc/acceptance.ts +12 -6
- package/os/rfc/decision-log.ts +4 -3
- package/os/rfc/dna-trace.ts +8 -2
- package/os/rfc/frontmatter-io.ts +5 -5
- package/os/rfc/handlers/archive.ts +9 -5
- package/os/rfc/handlers/check.ts +5 -3
- package/os/rfc/handlers/implement-stamp.ts +15 -10
- package/os/rfc/handlers/index-graph.ts +3 -3
- package/os/rfc/handlers/lifecycle.ts +7 -2
- package/os/rfc/handlers/list-create.ts +7 -6
- package/os/rfc/handlers/shared.ts +3 -3
- package/os/rfc/handlers/supersede-propose.ts +8 -3
- package/os/rfc/handlers/validate-rules-rfc1006.test.ts +18 -6
- package/os/rfc/handlers/validate-rules.ts +10 -5
- package/os/rfc/rfc-create-concurrent.test.ts +11 -3
- package/os/rfc/rfc.module.ts +413 -374
- package/os/rfc/verification-evidence.ts +11 -5
- package/os/rfc/verification-refresh.ts +4 -3
- package/os/session/frontmatter-io.ts +14 -14
- package/os/session/handlers/archive.ts +8 -4
- package/os/session/handlers/metrics-aggregate.ts +34 -13
- package/os/session/handlers/metrics-rfc.ts +13 -8
- package/os/session/handlers/metrics-session.ts +7 -3
- package/os/session/handlers/save.ts +12 -8
- package/os/session/session.module.ts +6 -0
- package/os/spec/live-spec-list.ts +4 -4
- package/os/spec/live-spec-merge.ts +5 -5
- package/os/spec/live-spec-show.ts +3 -3
- package/os/spec/live-spec-validate.ts +4 -4
- package/os/spec/spec-materialize.ts +9 -9
- package/os/spec/spec-status.ts +9 -9
- package/os/spec/spec-validate.ts +7 -7
- package/os/spec/spec.module.ts +8 -0
- package/os/werkstatt/handlers/lock.ts +16 -16
- package/os/werkstatt/handlers/werkstatt-lock-recover.ts +3 -3
- package/os/werkstatt/handlers/werkstatt-operation-validate.ts +4 -2
- package/os/werkstatt/werkstatt.module.ts +8 -5
- package/os/workflow/handlers.ts +7 -5
- package/os/workflow/workflow.module.ts +45 -44
- package/package.json +1 -1
- package/profiles/forge-shell.yaml +3 -0
- package/profiles/godot-game.yaml +3 -0
- package/profiles/phaser-game.yaml +3 -0
- package/profiles/site-workshop.yaml +567 -564
- package/skills/fo/fo-add-tests/SKILL.md +2 -2
- package/skills/fo/fo-architecture/SKILL.md +2 -2
- package/skills/fo/fo-compass-annotate/SKILL.md +2 -2
- package/skills/fo/fo-design-summit/SKILL.md +2 -2
- package/skills/fo/fo-doc-audit/SKILL.md +2 -2
- package/skills/fo/fo-explore/SKILL.md +2 -2
- package/skills/fo/fo-extract-dna/SKILL.md +2 -2
- package/skills/fo/fo-fix/SKILL.md +2 -2
- package/skills/fo/fo-handoff/SKILL.md +2 -2
- package/skills/fo/fo-harvest/SKILL.md +2 -2
- package/skills/fo/fo-idea/SKILL.md +2 -2
- package/skills/fo/fo-idea-audit/SKILL.md +2 -2
- package/skills/fo/fo-idea-create-adr/SKILL.md +3 -3
- package/skills/fo/fo-idea-create-rfc/SKILL.md +3 -3
- package/skills/fo/fo-idea-enhance/SKILL.md +2 -2
- package/skills/fo/fo-idea-i-just-want-to-see-the-plan/SKILL.md +2 -2
- package/skills/fo/fo-idea-i-just-want-to-see-the-result/SKILL.md +1 -1
- package/skills/fo/fo-idea-implement/SKILL.md +2 -2
- package/skills/fo/fo-idea-plan/SKILL.md +2 -2
- package/skills/fo/fo-idea-status/SKILL.md +2 -2
- package/skills/fo/fo-knowledge-distill/SKILL.md +2 -2
- package/skills/fo/fo-memory-sync/SKILL.md +2 -2
- package/skills/fo/fo-qa/SKILL.md +2 -2
- package/skills/fo/fo-review/SKILL.md +2 -2
- package/skills/fo/fo-session-retro/SKILL.md +2 -2
- package/skills/fo/fo-session-save/SKILL.md +2 -2
- package/skills/fo/fo-spec-ingest/SKILL.md +2 -2
- package/skills/fo/fo-step-commit/SKILL.md +1 -1
- package/skills/fo/fo-triage/SKILL.md +2 -2
- package/skills/meta/forge-bootstrap/SKILL.md +1 -1
- package/skills/meta/port-to-forge/SKILL.md +1 -1
- package/skills/meta/skill-create/SKILL.md +1 -1
- package/skills/shared/grilling/SKILL.md +1 -1
- package/skills/shared/grilling/learned-principles.archive.md +17 -0
- package/skills/shared/grilling/learned-principles.md +0 -1
- package/skills/shared/knowledge/learned-principles.md +6 -0
- package/skills/shared/my-preferences/SKILL.md +1 -1
- package/skills/shared/windows-ai-tooling/SKILL.md +1 -1
- package/skills/shared/writing-great-skills/SKILL.md +1 -1
- package/src/compass/contract-registry.ts +1 -1
- package/src/config/forge-config.ts +12 -1
- package/src/knowledge/__tests__/sync.test.ts +2 -7
- package/src/knowledge/budgets.ts +1 -1
- package/src/knowledge/compact.ts +1 -1
- package/src/knowledge/parse.ts +1 -1
- package/src/knowledge/sync.ts +3 -5
- package/src/migration-adapters/git-utils.ts +2 -2
- package/src/migration-adapters/ignored-files.ts +2 -2
- package/src/migration-adapters/node-typescript-pnpm/index.ts +1 -1
- package/src/migration-adapters/phaser-pnpm/index.ts +1 -1
- package/src/onboarding/agents-generate.ts +91 -50
- package/src/onboarding/create.ts +10 -10
- package/src/onboarding/doctor.ts +199 -59
- package/src/onboarding/init.ts +38 -1
- package/src/onboarding/invariant-engine.ts +1 -1
- package/src/onboarding/memory-compact.ts +189 -0
- package/src/onboarding/memory-scaffold.ts +2 -2
- package/src/onboarding/nested-agents-generate.ts +50 -5
- package/src/onboarding/nested-agents-templates.ts +19 -13
- package/src/onboarding/npm-token-check.ts +2 -2
- package/src/onboarding/prettierignore.ts +263 -0
- package/src/onboarding/profile-validate.ts +5 -4
- package/src/onboarding/scaffold-project.ts +38 -27
- package/src/onboarding/scaffold.ts +1 -1
- package/src/onboarding/skill-markers.ts +162 -0
- package/src/onboarding/templates/behavioral-layer-core.md +2 -4
- package/src/onboarding/upgrade.ts +285 -89
- package/src/onboarding/workspace-discovery.ts +16 -2
- package/src/pipeline-status.test.ts +1 -4
- package/src/pipeline-status.ts +30 -13
- package/src/profiles/stack-profile.ts +1 -1
- package/src/registry.ts +4 -4
- package/src/skill-schema.ts +4 -1
- package/src/tests/acceptance-probe-kinds.test.ts +5 -15
- package/src/tests/agents-generate.test.ts +32 -7
- package/src/tests/contract-registry.test.ts +12 -6
- package/src/tests/doctor-dist-freshness.test.ts +110 -0
- package/src/tests/doctor-fix.test.ts +142 -0
- package/src/tests/doctor-nested-agents.test.ts +160 -0
- package/src/tests/editable-generated-region.test.ts +231 -0
- package/src/tests/file-size-lint.test.ts +8 -12
- package/src/tests/fixtures/agents-generate-business-before.txt +54 -54
- package/src/tests/markdown-table.test.ts +107 -0
- package/src/tests/memory-compact.test.ts +143 -0
- package/src/tests/prettierignore-manage.test.ts +134 -0
- package/src/tests/skill-agents-sync.test.ts +168 -0
- package/src/tests/skill-sync-marker.test.ts +134 -0
- package/src/tests/skill-validate.test.ts +12 -5
- package/src/tests/upgrade.test.ts +87 -41
- package/src/tests/workspace-discovery.test.ts +28 -0
- package/src/types.ts +123 -0
- package/src/utils/editable-region.ts +156 -0
- package/src/utils/fs-idempotent.ts +12 -6
- package/src/utils/generated-marker.ts +36 -2
- package/src/utils/index.ts +17 -0
- package/src/utils/io.ts +143 -0
- package/src/utils/markdown-table.ts +121 -0
- package/src/utils/sync-fs.ts +43 -0
- package/src/validators/note-frontmatter-validate.ts +1 -1
- package/src/validators/note-link-validate.ts +1 -1
- package/src/validators/note-orphan-detect.ts +1 -1
- package/src/validators/port-validate.ts +1 -1
- package/src/validators/skill-validate.ts +38 -13
package/src/onboarding/doctor.ts
CHANGED
|
@@ -21,8 +21,10 @@ Sweep batch 2: real KEY_DECISIONS on 10 files, expanded purposes (CONTRACT-02/PU
|
|
|
21
21
|
</CHANGE_SUMMARY>
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
24
|
+
import type { WorkspaceIO } from "../types.ts";
|
|
25
|
+
import { resolveIo } from "../utils/io.ts";
|
|
26
|
+
import { hasEditableGeneratedMarker, mergeEditableGenerated } from "../utils/index.ts";
|
|
27
|
+
import { readFileSync, existsSync } from "../utils/sync-fs.ts";
|
|
26
28
|
import { join, relative, dirname, resolve } from "node:path";
|
|
27
29
|
import { parse as parseYaml } from "yaml";
|
|
28
30
|
import { forgePluginManifestSchema } from "../plugin/forge-plugin-manifest.ts";
|
|
@@ -35,7 +37,7 @@ import { resolveForgeRoot, loadForgeConfig, resolveBinding, resolveTerminology,
|
|
|
35
37
|
import { FORGE_SKILLS, discoverPackSkills } from "../registry.ts";
|
|
36
38
|
import { discoverWorkspaces } from "./workspace-discovery.ts";
|
|
37
39
|
import { buildNestedAgentsMd, selectNestedTemplate } from "./nested-agents-templates.ts";
|
|
38
|
-
import { readPackageInfo } from "./nested-agents-generate.ts";
|
|
40
|
+
import { readPackageInfo, generateNestedAgentsMd } from "./nested-agents-generate.ts";
|
|
39
41
|
import { listStackProfiles, type StackProfile } from "../profiles/stack-profile.ts";
|
|
40
42
|
import { resolveAllTerminology } from "../profiles/terminology-utils.ts";
|
|
41
43
|
import { TERMINOLOGY_DEFAULTS } from "../profiles/profile-schema.ts";
|
|
@@ -47,14 +49,21 @@ import type { ParsedKnowledgeFile } from "../knowledge/index.ts";
|
|
|
47
49
|
import { computeLayerBudgets, resolveKnowledgeBudgets, DEFAULT_KNOWLEDGE_BUDGETS } from "../knowledge/budgets.ts";
|
|
48
50
|
import { detectDuplicatePrinciples } from "../knowledge/index.ts";
|
|
49
51
|
import type { DuplicatePair } from "../knowledge/index.ts";
|
|
50
|
-
import { checkMemoryLayerHealth } from "./memory-scaffold.ts";
|
|
52
|
+
import { checkMemoryLayerHealth, resolveMemoryBudget } from "./memory-scaffold.ts";
|
|
53
|
+
import { compactMemoryMd } from "./memory-compact.ts";
|
|
51
54
|
import { checkInvariants } from "./invariant-engine.ts";
|
|
52
55
|
import type { InvariantViolation } from "./invariant-engine.ts";
|
|
53
56
|
import { checkNpmToken, workshopNeedsWarpgogolToken } from "./npm-token-check.ts";
|
|
54
|
-
import { execSync } from "
|
|
55
|
-
import fs from "
|
|
57
|
+
import { execSync } from "../utils/sync-fs.ts";
|
|
58
|
+
import * as fs from "../utils/sync-fs.ts";
|
|
56
59
|
import type { ProfilePrerequisite } from "../profiles/profile-schema.ts";
|
|
57
60
|
|
|
61
|
+
interface DoctorFixResult {
|
|
62
|
+
check: string;
|
|
63
|
+
action: "fixed" | "skipped" | "failed";
|
|
64
|
+
detail: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
58
67
|
interface DoctorCheck {
|
|
59
68
|
name: string;
|
|
60
69
|
status: "pass" | "fail" | "warn";
|
|
@@ -80,13 +89,8 @@ interface BindingNotice {
|
|
|
80
89
|
suggestion: string;
|
|
81
90
|
}
|
|
82
91
|
|
|
83
|
-
async function pathExists(target: string): Promise<boolean> {
|
|
84
|
-
|
|
85
|
-
await stat(target);
|
|
86
|
-
return true;
|
|
87
|
-
} catch {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
92
|
+
async function pathExists(target: string, io: WorkspaceIO): Promise<boolean> {
|
|
93
|
+
return io.exists(target);
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
const FORBIDDEN_IMPORT_PATTERN =
|
|
@@ -95,19 +99,20 @@ const FORBIDDEN_IMPORT_PATTERN =
|
|
|
95
99
|
async function scanForForbiddenImports(
|
|
96
100
|
dir: string,
|
|
97
101
|
workspaceRoot: string,
|
|
102
|
+
io: WorkspaceIO,
|
|
98
103
|
): Promise<ForbiddenImport[]> {
|
|
99
104
|
const violations: ForbiddenImport[] = [];
|
|
100
|
-
const entries = await readdir(dir
|
|
105
|
+
const entries = await io.readdir(dir).catch(() => []);
|
|
101
106
|
|
|
102
107
|
for (const entry of entries) {
|
|
103
108
|
const fullPath = join(dir, entry.name);
|
|
104
109
|
|
|
105
|
-
if (entry.isDirectory
|
|
110
|
+
if (entry.isDirectory) {
|
|
106
111
|
if (entry.name === "node_modules" || entry.name === "tests") continue;
|
|
107
|
-
const sub = await scanForForbiddenImports(fullPath, workspaceRoot);
|
|
112
|
+
const sub = await scanForForbiddenImports(fullPath, workspaceRoot, io);
|
|
108
113
|
violations.push(...sub);
|
|
109
114
|
} else if (entry.name.endsWith(".ts")) {
|
|
110
|
-
const content = await readFile(fullPath
|
|
115
|
+
const content = await io.readFile(fullPath).catch(() => "");
|
|
111
116
|
let match: RegExpExecArray | null;
|
|
112
117
|
const pattern = new RegExp(FORBIDDEN_IMPORT_PATTERN.source, "g");
|
|
113
118
|
while ((match = pattern.exec(content)) !== null) {
|
|
@@ -144,7 +149,7 @@ const BINDING_COMMAND_KEYS = [
|
|
|
144
149
|
"commands.sessionSave",
|
|
145
150
|
];
|
|
146
151
|
|
|
147
|
-
async function validateBindings(workspaceRoot: string): Promise<BindingValidation> {
|
|
152
|
+
async function validateBindings(workspaceRoot: string, io: WorkspaceIO): Promise<BindingValidation> {
|
|
148
153
|
const result: BindingValidation = { resolved: [], absent: [], invalid: [], notices: [] };
|
|
149
154
|
|
|
150
155
|
let config;
|
|
@@ -163,7 +168,7 @@ async function validateBindings(workspaceRoot: string): Promise<BindingValidatio
|
|
|
163
168
|
if (value === null) {
|
|
164
169
|
result.absent.push(key);
|
|
165
170
|
} else if (typeof value === "string") {
|
|
166
|
-
const exists = await pathExists(join(workspaceRoot, value));
|
|
171
|
+
const exists = await pathExists(join(workspaceRoot, value), io);
|
|
167
172
|
if (exists) {
|
|
168
173
|
result.resolved.push(key);
|
|
169
174
|
} else {
|
|
@@ -175,7 +180,7 @@ async function validateBindings(workspaceRoot: string): Promise<BindingValidatio
|
|
|
175
180
|
const compassDocs = resolveBinding(config, "paths.compassDocs");
|
|
176
181
|
if (Array.isArray(compassDocs) && compassDocs.length > 0) {
|
|
177
182
|
for (const docPath of compassDocs) {
|
|
178
|
-
const exists = await pathExists(join(workspaceRoot, docPath));
|
|
183
|
+
const exists = await pathExists(join(workspaceRoot, docPath), io);
|
|
179
184
|
if (exists) {
|
|
180
185
|
result.resolved.push(`paths.compassDocs[${docPath}]`);
|
|
181
186
|
} else {
|
|
@@ -219,6 +224,7 @@ async function validateBindings(workspaceRoot: string): Promise<BindingValidatio
|
|
|
219
224
|
async function checkStaleKnowledgeFiles(
|
|
220
225
|
workspaceRoot: string,
|
|
221
226
|
forgeRoot: string,
|
|
227
|
+
io: WorkspaceIO,
|
|
222
228
|
): Promise<DoctorCheck> {
|
|
223
229
|
const stale: string[] = [];
|
|
224
230
|
|
|
@@ -240,8 +246,8 @@ async function checkStaleKnowledgeFiles(
|
|
|
240
246
|
const srcPath = join(skillSrcDir, kf);
|
|
241
247
|
const destPath = join(agentsSkillsDir, skill.name, kf);
|
|
242
248
|
|
|
243
|
-
const srcExists = await pathExists(srcPath);
|
|
244
|
-
const destExists = await pathExists(destPath);
|
|
249
|
+
const srcExists = await pathExists(srcPath, io);
|
|
250
|
+
const destExists = await pathExists(destPath, io);
|
|
245
251
|
|
|
246
252
|
if (srcExists && destExists) {
|
|
247
253
|
// Append-only contract: local copies legitimately accumulate entries.
|
|
@@ -272,8 +278,8 @@ async function checkStaleKnowledgeFiles(
|
|
|
272
278
|
const srcPath = join(skillSrcDir, kf);
|
|
273
279
|
const destPath = join(agentsSkillsDir, skill.name, kf);
|
|
274
280
|
|
|
275
|
-
const srcExists = await pathExists(srcPath);
|
|
276
|
-
const destExists = await pathExists(destPath);
|
|
281
|
+
const srcExists = await pathExists(srcPath, io);
|
|
282
|
+
const destExists = await pathExists(destPath, io);
|
|
277
283
|
|
|
278
284
|
if (srcExists && destExists) {
|
|
279
285
|
const plan = planKnowledgeSync(srcPath, destPath);
|
|
@@ -635,7 +641,7 @@ function checkSharedKnowledgeFile(
|
|
|
635
641
|
// Independent version packages diagnostics (RFC-0704)
|
|
636
642
|
// ---------------------------------------------------------------------------
|
|
637
643
|
|
|
638
|
-
async function checkIndependentVersionPackages(workspaceRoot: string): Promise<DoctorCheck> {
|
|
644
|
+
async function checkIndependentVersionPackages(workspaceRoot: string, io: WorkspaceIO): Promise<DoctorCheck> {
|
|
639
645
|
let config;
|
|
640
646
|
try {
|
|
641
647
|
config = loadForgeConfig(workspaceRoot);
|
|
@@ -651,8 +657,8 @@ async function checkIndependentVersionPackages(workspaceRoot: string): Promise<D
|
|
|
651
657
|
let validCount = 0;
|
|
652
658
|
|
|
653
659
|
for (const pkgPath of config.independentVersionPackages) {
|
|
654
|
-
const dirExists = await pathExists(join(workspaceRoot, pkgPath));
|
|
655
|
-
const pkgJsonExists = await pathExists(join(workspaceRoot, pkgPath, "package.json"));
|
|
660
|
+
const dirExists = await pathExists(join(workspaceRoot, pkgPath), io);
|
|
661
|
+
const pkgJsonExists = await pathExists(join(workspaceRoot, pkgPath, "package.json"), io);
|
|
656
662
|
if (!dirExists) {
|
|
657
663
|
issues.push(`path '${pkgPath}' does not exist`);
|
|
658
664
|
} else if (!pkgJsonExists) {
|
|
@@ -681,7 +687,7 @@ async function checkIndependentVersionPackages(workspaceRoot: string): Promise<D
|
|
|
681
687
|
// Pack skill diagnostics (RFC-0539)
|
|
682
688
|
// ---------------------------------------------------------------------------
|
|
683
689
|
|
|
684
|
-
async function checkPackSkills(workspaceRoot: string): Promise<DoctorCheck> {
|
|
690
|
+
async function checkPackSkills(workspaceRoot: string, io: WorkspaceIO): Promise<DoctorCheck> {
|
|
685
691
|
let config;
|
|
686
692
|
try {
|
|
687
693
|
config = loadForgeConfig(workspaceRoot);
|
|
@@ -713,7 +719,7 @@ async function checkPackSkills(workspaceRoot: string): Promise<DoctorCheck> {
|
|
|
713
719
|
}
|
|
714
720
|
dirs.add(pack.dir);
|
|
715
721
|
|
|
716
|
-
const packDirExists = await pathExists(join(workspaceRoot, pack.dir));
|
|
722
|
+
const packDirExists = await pathExists(join(workspaceRoot, pack.dir), io);
|
|
717
723
|
if (!packDirExists) {
|
|
718
724
|
issues.push(`pack dir '${pack.dir}' does not exist`);
|
|
719
725
|
}
|
|
@@ -732,12 +738,12 @@ async function checkPackSkills(workspaceRoot: string): Promise<DoctorCheck> {
|
|
|
732
738
|
const srcPath = join(workspaceRoot, skill.dir, skill.path);
|
|
733
739
|
const destPath = join(agentsSkillsDir, skill.name, "SKILL.md");
|
|
734
740
|
|
|
735
|
-
const srcExists = await pathExists(srcPath);
|
|
736
|
-
const destExists = await pathExists(destPath);
|
|
741
|
+
const srcExists = await pathExists(srcPath, io);
|
|
742
|
+
const destExists = await pathExists(destPath, io);
|
|
737
743
|
|
|
738
744
|
if (srcExists && destExists) {
|
|
739
|
-
const srcContent = await readFile(srcPath
|
|
740
|
-
const destContent = await readFile(destPath
|
|
745
|
+
const srcContent = await io.readFile(srcPath).catch(() => "");
|
|
746
|
+
const destContent = await io.readFile(destPath).catch(() => "");
|
|
741
747
|
if (srcContent !== destContent) {
|
|
742
748
|
issues.push(`stale copy of '${skill.name}'`);
|
|
743
749
|
}
|
|
@@ -760,7 +766,7 @@ async function checkPackSkills(workspaceRoot: string): Promise<DoctorCheck> {
|
|
|
760
766
|
// Pack manifest diagnostics (RFC-0941)
|
|
761
767
|
// ---------------------------------------------------------------------------
|
|
762
768
|
|
|
763
|
-
async function checkPackManifests(workspaceRoot: string): Promise<DoctorCheck> {
|
|
769
|
+
async function checkPackManifests(workspaceRoot: string, _io: WorkspaceIO): Promise<DoctorCheck> {
|
|
764
770
|
let config;
|
|
765
771
|
try {
|
|
766
772
|
config = loadForgeConfig(workspaceRoot);
|
|
@@ -813,7 +819,8 @@ async function checkPackManifests(workspaceRoot: string): Promise<DoctorCheck> {
|
|
|
813
819
|
|
|
814
820
|
async function checkNestedAgentsMd(
|
|
815
821
|
workspaceRoot: string,
|
|
816
|
-
workspaceTypes
|
|
822
|
+
workspaceTypes: ProfileWorkspaceType[] | undefined,
|
|
823
|
+
io: WorkspaceIO,
|
|
817
824
|
): Promise<DoctorCheck> {
|
|
818
825
|
let config;
|
|
819
826
|
try {
|
|
@@ -826,7 +833,11 @@ async function checkNestedAgentsMd(
|
|
|
826
833
|
};
|
|
827
834
|
}
|
|
828
835
|
|
|
829
|
-
const workspaces = discoverWorkspaces(
|
|
836
|
+
const workspaces = discoverWorkspaces(
|
|
837
|
+
workspaceRoot,
|
|
838
|
+
workspaceTypes,
|
|
839
|
+
config.bindings?.workspaces?.skipDirs,
|
|
840
|
+
);
|
|
830
841
|
|
|
831
842
|
if (workspaces.length === 0) {
|
|
832
843
|
return {
|
|
@@ -840,6 +851,7 @@ async function checkNestedAgentsMd(
|
|
|
840
851
|
let missing = 0;
|
|
841
852
|
let stale = 0;
|
|
842
853
|
let handwritten = 0;
|
|
854
|
+
let unmapped = 0;
|
|
843
855
|
|
|
844
856
|
for (const ws of workspaces) {
|
|
845
857
|
if (!ws.hasAgentsMd) {
|
|
@@ -852,7 +864,7 @@ async function checkNestedAgentsMd(
|
|
|
852
864
|
handwritten++;
|
|
853
865
|
const suggestions: string[] = [];
|
|
854
866
|
try {
|
|
855
|
-
const content = await readFile(join(workspaceRoot, ws.path, "AGENTS.md")
|
|
867
|
+
const content = await io.readFile(join(workspaceRoot, ws.path, "AGENTS.md"));
|
|
856
868
|
if (!content.includes("AGENTS.md")) {
|
|
857
869
|
suggestions.push("reference root AGENTS.md");
|
|
858
870
|
}
|
|
@@ -874,8 +886,19 @@ async function checkNestedAgentsMd(
|
|
|
874
886
|
const terminology = resolveAllTerminology(config, profile);
|
|
875
887
|
const wsType = workspaceTypes?.find((wt) => wt.id === ws.type);
|
|
876
888
|
const expected = selectNestedTemplate(wsType, profile, terminology, fallback);
|
|
877
|
-
const actual = await readFile(join(workspaceRoot, ws.path, "AGENTS.md")
|
|
878
|
-
|
|
889
|
+
const actual = await io.readFile(join(workspaceRoot, ws.path, "AGENTS.md"));
|
|
890
|
+
// RFC-1153: boundary-aware staleness — merge(expected, actual) compares
|
|
891
|
+
// only the generated head; content below the forge:custom boundary (or
|
|
892
|
+
// the canonical footer fallback) is preserved, not drift. Files bearing
|
|
893
|
+
// the restrictive GENERATED marker are generator-owned (RFC-0081) — any
|
|
894
|
+
// divergence is plain staleness, never unmapped-customization.
|
|
895
|
+
const merged = mergeEditableGenerated(expected, actual, `${ws.path}/AGENTS.md`);
|
|
896
|
+
if (merged === null && hasEditableGeneratedMarker(actual)) {
|
|
897
|
+
unmapped++;
|
|
898
|
+
issues.push(
|
|
899
|
+
`${ws.path}/AGENTS.md has custom content but no resolvable boundary — add <!-- forge:custom --> manually`,
|
|
900
|
+
);
|
|
901
|
+
} else if (merged === null || merged !== actual.replace(/\r\n/g, "\n")) {
|
|
879
902
|
stale++;
|
|
880
903
|
issues.push(`${ws.path}/AGENTS.md stale — run 'forge agents generate'`);
|
|
881
904
|
}
|
|
@@ -895,11 +918,12 @@ async function checkNestedAgentsMd(
|
|
|
895
918
|
const parts: string[] = [];
|
|
896
919
|
if (missing > 0) parts.push(`${missing} missing`);
|
|
897
920
|
if (stale > 0) parts.push(`${stale} stale`);
|
|
921
|
+
if (unmapped > 0) parts.push(`${unmapped} unmapped-customization`);
|
|
898
922
|
if (handwritten > 0) parts.push(`${handwritten} hand-written`);
|
|
899
923
|
|
|
900
924
|
return {
|
|
901
925
|
name: "nested-AGENTS.md",
|
|
902
|
-
status: stale > 0 ? "warn" : "pass",
|
|
926
|
+
status: stale > 0 || unmapped > 0 ? "warn" : "pass",
|
|
903
927
|
message: `${parts.join(", ")} — ${issues.slice(0, 3).join("; ")}${issues.length > 3 ? ` (+${issues.length - 3} more)` : ""}`,
|
|
904
928
|
};
|
|
905
929
|
}
|
|
@@ -1209,13 +1233,15 @@ function checkPrerequisites(prerequisites: ProfilePrerequisite[]): DoctorCheck {
|
|
|
1209
1233
|
export async function runDoctor(
|
|
1210
1234
|
input: ForgeCommandInput,
|
|
1211
1235
|
context: ForgeRuntimeContext,
|
|
1212
|
-
): Promise<ForgeCommandResult<{ command: string; checks: DoctorCheck[]; allPass: boolean; forbiddenImports: ForbiddenImport[]; bindings: BindingValidation; domain?: DomainReport }>> {
|
|
1213
|
-
const { workspaceRoot, logger, outputFormat } = context;
|
|
1236
|
+
): Promise<ForgeCommandResult<{ command: string; checks: DoctorCheck[]; allPass: boolean; forbiddenImports: ForbiddenImport[]; bindings: BindingValidation; domain?: DomainReport; fixes?: DoctorFixResult[] }>> {
|
|
1237
|
+
const { workspaceRoot, logger, outputFormat, dryRun } = context;
|
|
1238
|
+
const fio = resolveIo(context.io);
|
|
1214
1239
|
const strict = input.flags["strict"] === true;
|
|
1240
|
+
const fix = input.flags["fix"] === true;
|
|
1215
1241
|
const checks: DoctorCheck[] = [];
|
|
1216
1242
|
|
|
1217
1243
|
// Check forge.yaml
|
|
1218
|
-
const forgeYamlExists = await pathExists(join(workspaceRoot, "forge.yaml"));
|
|
1244
|
+
const forgeYamlExists = await pathExists(join(workspaceRoot, "forge.yaml"), fio);
|
|
1219
1245
|
checks.push({
|
|
1220
1246
|
name: "forge.yaml",
|
|
1221
1247
|
status: forgeYamlExists ? "pass" : "warn",
|
|
@@ -1225,7 +1251,7 @@ export async function runDoctor(
|
|
|
1225
1251
|
});
|
|
1226
1252
|
|
|
1227
1253
|
// Check AGENTS.md
|
|
1228
|
-
const agentsMdExists = await pathExists(join(workspaceRoot, "AGENTS.md"));
|
|
1254
|
+
const agentsMdExists = await pathExists(join(workspaceRoot, "AGENTS.md"), fio);
|
|
1229
1255
|
checks.push({
|
|
1230
1256
|
name: "AGENTS.md",
|
|
1231
1257
|
status: agentsMdExists ? "pass" : "warn",
|
|
@@ -1235,7 +1261,7 @@ export async function runDoctor(
|
|
|
1235
1261
|
});
|
|
1236
1262
|
|
|
1237
1263
|
// Check PREFERENCES.md
|
|
1238
|
-
const preferencesExists = await pathExists(join(workspaceRoot, "PREFERENCES.md"));
|
|
1264
|
+
const preferencesExists = await pathExists(join(workspaceRoot, "PREFERENCES.md"), fio);
|
|
1239
1265
|
checks.push({
|
|
1240
1266
|
name: "PREFERENCES.md",
|
|
1241
1267
|
status: preferencesExists ? "pass" : "warn",
|
|
@@ -1245,7 +1271,7 @@ export async function runDoctor(
|
|
|
1245
1271
|
});
|
|
1246
1272
|
|
|
1247
1273
|
// Check .agents/skills/
|
|
1248
|
-
const skillsDirExists = await pathExists(join(workspaceRoot, ".agents", "skills"));
|
|
1274
|
+
const skillsDirExists = await pathExists(join(workspaceRoot, ".agents", "skills"), fio);
|
|
1249
1275
|
checks.push({
|
|
1250
1276
|
name: ".agents/skills/",
|
|
1251
1277
|
status: skillsDirExists ? "pass" : "fail",
|
|
@@ -1255,7 +1281,7 @@ export async function runDoctor(
|
|
|
1255
1281
|
});
|
|
1256
1282
|
|
|
1257
1283
|
// Check docs/rfcs/
|
|
1258
|
-
const rfcsDirExists = await pathExists(join(workspaceRoot, "docs", "rfcs"));
|
|
1284
|
+
const rfcsDirExists = await pathExists(join(workspaceRoot, "docs", "rfcs"), fio);
|
|
1259
1285
|
checks.push({
|
|
1260
1286
|
name: "docs/rfcs/",
|
|
1261
1287
|
status: rfcsDirExists ? "pass" : "warn",
|
|
@@ -1265,7 +1291,7 @@ export async function runDoctor(
|
|
|
1265
1291
|
});
|
|
1266
1292
|
|
|
1267
1293
|
// Check docs/adrs/
|
|
1268
|
-
const adrsDirExists = await pathExists(join(workspaceRoot, "docs", "adrs"));
|
|
1294
|
+
const adrsDirExists = await pathExists(join(workspaceRoot, "docs", "adrs"), fio);
|
|
1269
1295
|
checks.push({
|
|
1270
1296
|
name: "docs/adrs/",
|
|
1271
1297
|
status: adrsDirExists ? "pass" : "warn",
|
|
@@ -1374,7 +1400,7 @@ export async function runDoctor(
|
|
|
1374
1400
|
: `${invalidProfiles.length} profile(s) invalid (advisory): ${invalidProfiles.map((p) => p.id).join(", ")}`,
|
|
1375
1401
|
});
|
|
1376
1402
|
|
|
1377
|
-
const forbiddenImports = await scanForForbiddenImports(forgeRoot, workspaceRoot);
|
|
1403
|
+
const forbiddenImports = await scanForForbiddenImports(forgeRoot, workspaceRoot, fio);
|
|
1378
1404
|
checks.push({
|
|
1379
1405
|
name: "autonomy-guard",
|
|
1380
1406
|
status: forbiddenImports.length === 0 ? "pass" : "fail",
|
|
@@ -1385,7 +1411,7 @@ export async function runDoctor(
|
|
|
1385
1411
|
});
|
|
1386
1412
|
|
|
1387
1413
|
// Check bindings contract (RFC-0393)
|
|
1388
|
-
const bindingsResult = await validateBindings(workspaceRoot);
|
|
1414
|
+
const bindingsResult = await validateBindings(workspaceRoot, fio);
|
|
1389
1415
|
checks.push({
|
|
1390
1416
|
name: "bindings",
|
|
1391
1417
|
status: bindingsResult.invalid.length === 0 ? "pass" : "fail",
|
|
@@ -1396,7 +1422,7 @@ export async function runDoctor(
|
|
|
1396
1422
|
});
|
|
1397
1423
|
|
|
1398
1424
|
// Check stale knowledge files (RFC-0524, RFC-0539)
|
|
1399
|
-
const staleCheck = await checkStaleKnowledgeFiles(workspaceRoot, forgeRoot);
|
|
1425
|
+
const staleCheck = await checkStaleKnowledgeFiles(workspaceRoot, forgeRoot, fio);
|
|
1400
1426
|
checks.push(staleCheck);
|
|
1401
1427
|
|
|
1402
1428
|
// RFC-0660: Check legacy sections in knowledge files
|
|
@@ -1418,16 +1444,19 @@ export async function runDoctor(
|
|
|
1418
1444
|
// RFC-0664: Check memory layer health (budget, gitignore coverage, leak risk)
|
|
1419
1445
|
checks.push(checkMemoryLayer(workspaceRoot));
|
|
1420
1446
|
|
|
1447
|
+
// RFC-1151: Check dist freshness — stale dist/ silently shadows src/ in source checkouts
|
|
1448
|
+
checks.push(checkDistFreshness(forgeRoot));
|
|
1449
|
+
|
|
1421
1450
|
// RFC-0539: Check pack skills — stale/missing copies and config validation
|
|
1422
|
-
const packCheck = await checkPackSkills(workspaceRoot);
|
|
1451
|
+
const packCheck = await checkPackSkills(workspaceRoot, fio);
|
|
1423
1452
|
checks.push(packCheck);
|
|
1424
1453
|
|
|
1425
1454
|
// RFC-0941: Check pack manifests — forge.plugin.yaml existence and validity
|
|
1426
|
-
const packManifestCheck = await checkPackManifests(workspaceRoot);
|
|
1455
|
+
const packManifestCheck = await checkPackManifests(workspaceRoot, fio);
|
|
1427
1456
|
checks.push(packManifestCheck);
|
|
1428
1457
|
|
|
1429
1458
|
// RFC-0704: Check independent version packages — paths must exist and contain package.json
|
|
1430
|
-
const independentCheck = await checkIndependentVersionPackages(workspaceRoot);
|
|
1459
|
+
const independentCheck = await checkIndependentVersionPackages(workspaceRoot, fio);
|
|
1431
1460
|
checks.push(independentCheck);
|
|
1432
1461
|
|
|
1433
1462
|
// RFC-0611: Check nested AGENTS.md — missing, stale, hand-written
|
|
@@ -1435,8 +1464,8 @@ export async function runDoctor(
|
|
|
1435
1464
|
// RFC-0640 fix: previously gated by isSoftwareDomain, which skipped the check
|
|
1436
1465
|
// entirely for non-software domains. Now runs for all domains — profile-driven
|
|
1437
1466
|
// wsTypes replace hardcoded detection when present.
|
|
1467
|
+
let wsTypes: ProfileWorkspaceType[] | undefined;
|
|
1438
1468
|
{
|
|
1439
|
-
let wsTypes: ProfileWorkspaceType[] | undefined;
|
|
1440
1469
|
try {
|
|
1441
1470
|
const config = loadForgeConfig(workspaceRoot);
|
|
1442
1471
|
// RFC-0643: prefer config.profile (loaded by loadForgeConfig)
|
|
@@ -1455,7 +1484,7 @@ export async function runDoctor(
|
|
|
1455
1484
|
} catch {
|
|
1456
1485
|
// profiles not loadable
|
|
1457
1486
|
}
|
|
1458
|
-
const nestedCheck = await checkNestedAgentsMd(workspaceRoot, wsTypes);
|
|
1487
|
+
const nestedCheck = await checkNestedAgentsMd(workspaceRoot, wsTypes, fio);
|
|
1459
1488
|
checks.push(nestedCheck);
|
|
1460
1489
|
}
|
|
1461
1490
|
|
|
@@ -1472,6 +1501,15 @@ export async function runDoctor(
|
|
|
1472
1501
|
const allPass = finalChecks.every((c) => c.status === "pass");
|
|
1473
1502
|
const hasFails = finalChecks.some((c) => c.status === "fail");
|
|
1474
1503
|
|
|
1504
|
+
// RFC-1151: --fix applies registered safe remediations for warn/fail checks
|
|
1505
|
+
const fixes: DoctorFixResult[] = [];
|
|
1506
|
+
if (fix) {
|
|
1507
|
+
for (const check of finalChecks) {
|
|
1508
|
+
if (check.status === "pass") continue;
|
|
1509
|
+
fixes.push(await applyDoctorRemediation(check, workspaceRoot, wsTypes, dryRun === true, fio));
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1475
1513
|
if (outputFormat === "pretty") {
|
|
1476
1514
|
logger.section(`Forge Doctor — ${workspaceRoot}`);
|
|
1477
1515
|
for (const check of finalChecks) {
|
|
@@ -1479,6 +1517,10 @@ export async function runDoctor(
|
|
|
1479
1517
|
const fn = check.status === "pass" ? logger.success : check.status === "warn" ? logger.warn : logger.error;
|
|
1480
1518
|
fn(`${icon} ${check.name}: ${check.message}`);
|
|
1481
1519
|
}
|
|
1520
|
+
for (const f of fixes) {
|
|
1521
|
+
const fn = f.action === "fixed" ? logger.success : f.action === "failed" ? logger.error : logger.info;
|
|
1522
|
+
fn(` fix ${f.check}: ${f.action} — ${f.detail}`);
|
|
1523
|
+
}
|
|
1482
1524
|
if (allPass) {
|
|
1483
1525
|
logger.success("All checks passed — forge is properly configured.");
|
|
1484
1526
|
} else if (hasFails) {
|
|
@@ -1488,11 +1530,109 @@ export async function runDoctor(
|
|
|
1488
1530
|
}
|
|
1489
1531
|
}
|
|
1490
1532
|
|
|
1533
|
+
const fixFailed = fixes.some((f) => f.action === "failed");
|
|
1534
|
+
|
|
1491
1535
|
return {
|
|
1492
|
-
data: { command: "forge.doctor", checks: finalChecks, allPass, forbiddenImports, bindings: bindingsResult, domain: domainReport },
|
|
1493
|
-
exitCode: hasFails ? 1 : 0,
|
|
1536
|
+
data: { command: "forge.doctor", checks: finalChecks, allPass, forbiddenImports, bindings: bindingsResult, domain: domainReport, ...(fix ? { fixes } : {}) },
|
|
1537
|
+
exitCode: hasFails || fixFailed ? 1 : 0,
|
|
1494
1538
|
summary: allPass
|
|
1495
1539
|
? "forge.doctor: all checks passed"
|
|
1496
|
-
: `forge.doctor: ${finalChecks.filter((c) => c.status === "fail").length} fail(s), ${finalChecks.filter((c) => c.status === "warn").length} warn(s)`,
|
|
1540
|
+
: `forge.doctor: ${finalChecks.filter((c) => c.status === "fail").length} fail(s), ${finalChecks.filter((c) => c.status === "warn").length} warn(s)${fix ? `, ${fixes.filter((f) => f.action === "fixed").length} fixed` : ""}`,
|
|
1497
1541
|
};
|
|
1498
1542
|
}
|
|
1543
|
+
|
|
1544
|
+
// RFC-1151: dist-freshness — a stale dist/ silently shadows src/ because
|
|
1545
|
+
// bin/cli.js prefers dist when present. Warn-only; rebuild is a pnpm script,
|
|
1546
|
+
// not forge's call. Pass (skip) when src/ or dist/ is absent — npm consumers
|
|
1547
|
+
// ship dist-only, so this activates only in source checkouts.
|
|
1548
|
+
function checkDistFreshness(forgeRoot: string): DoctorCheck {
|
|
1549
|
+
const srcDir = join(forgeRoot, "src");
|
|
1550
|
+
const distDir = join(forgeRoot, "dist");
|
|
1551
|
+
if (!fs.existsSync(srcDir) || !fs.existsSync(distDir)) {
|
|
1552
|
+
return {
|
|
1553
|
+
name: "dist-freshness",
|
|
1554
|
+
status: "pass",
|
|
1555
|
+
message: "no src+dist pair — not a source checkout",
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
const newestSrc = newestMtime(srcDir);
|
|
1559
|
+
const distMtime = fs.statSync(distDir).mtimeMs;
|
|
1560
|
+
if (newestSrc > distMtime) {
|
|
1561
|
+
return {
|
|
1562
|
+
name: "dist-freshness",
|
|
1563
|
+
status: "warn",
|
|
1564
|
+
message: `dist/ older than newest src/ file — run 'pnpm run build' in ${forgeRoot}`,
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
return { name: "dist-freshness", status: "pass", message: "dist/ is fresh" };
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
function newestMtime(dir: string): number {
|
|
1571
|
+
let newest = 0;
|
|
1572
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true, recursive: true })) {
|
|
1573
|
+
if (!entry.isFile()) continue;
|
|
1574
|
+
const m = fs.statSync(join(entry.parentPath, entry.name)).mtimeMs;
|
|
1575
|
+
if (m > newest) newest = m;
|
|
1576
|
+
}
|
|
1577
|
+
return newest;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
// RFC-1151: remediation dispatch — check name → safe fix action.
|
|
1581
|
+
// Remediations reuse existing generators; hand-written files are never touched
|
|
1582
|
+
// (generated-marker edit guard inside generateNestedAgentsMd).
|
|
1583
|
+
async function applyDoctorRemediation(
|
|
1584
|
+
check: DoctorCheck,
|
|
1585
|
+
workspaceRoot: string,
|
|
1586
|
+
workspaceTypes: ProfileWorkspaceType[] | undefined,
|
|
1587
|
+
dryRun: boolean,
|
|
1588
|
+
io: WorkspaceIO,
|
|
1589
|
+
): Promise<DoctorFixResult> {
|
|
1590
|
+
switch (check.name) {
|
|
1591
|
+
case "nested-AGENTS.md": {
|
|
1592
|
+
try {
|
|
1593
|
+
const config = loadForgeConfig(workspaceRoot);
|
|
1594
|
+
const res = await generateNestedAgentsMd(workspaceRoot, config, dryRun, workspaceTypes, io);
|
|
1595
|
+
return {
|
|
1596
|
+
check: check.name,
|
|
1597
|
+
action: res.generated.length > 0 ? "fixed" : "skipped",
|
|
1598
|
+
detail: `${res.generated.length} file(s) ${dryRun ? "would be " : ""}regenerated, ${res.skipped.length} skipped`,
|
|
1599
|
+
};
|
|
1600
|
+
} catch (err) {
|
|
1601
|
+
return { check: check.name, action: "failed", detail: (err as Error).message };
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
case "memory-layer": {
|
|
1605
|
+
try {
|
|
1606
|
+
const memoryPath = join(workspaceRoot, ".agents", "memory", "MEMORY.md");
|
|
1607
|
+
if (!(await io.exists(memoryPath))) {
|
|
1608
|
+
return { check: check.name, action: "skipped", detail: "MEMORY.md absent" };
|
|
1609
|
+
}
|
|
1610
|
+
const content = await io.readFile(memoryPath);
|
|
1611
|
+
const budget = resolveMemoryBudget(workspaceRoot);
|
|
1612
|
+
const { lines, removedLines, fitsBudget } = compactMemoryMd(content, budget);
|
|
1613
|
+
if (!fitsBudget) {
|
|
1614
|
+
return {
|
|
1615
|
+
check: check.name,
|
|
1616
|
+
action: "failed",
|
|
1617
|
+
detail: "still over budget after Environment notes truncation — manual editorial compaction required",
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1620
|
+
if (removedLines.length === 0) {
|
|
1621
|
+
return { check: check.name, action: "skipped", detail: "within budget" };
|
|
1622
|
+
}
|
|
1623
|
+
if (!dryRun) {
|
|
1624
|
+
await io.writeFile(memoryPath, lines.join("\n"));
|
|
1625
|
+
}
|
|
1626
|
+
return {
|
|
1627
|
+
check: check.name,
|
|
1628
|
+
action: "fixed",
|
|
1629
|
+
detail: `${dryRun ? "would remove" : "removed"} ${removedLines.length} bullet(s)`,
|
|
1630
|
+
};
|
|
1631
|
+
} catch (err) {
|
|
1632
|
+
return { check: check.name, action: "failed", detail: (err as Error).message };
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
default:
|
|
1636
|
+
return { check: check.name, action: "skipped", detail: "no-remediation" };
|
|
1637
|
+
}
|
|
1638
|
+
}
|
package/src/onboarding/init.ts
CHANGED
|
@@ -20,11 +20,13 @@ Sweep batch 2: real KEY_DECISIONS on 10 files, expanded purposes (CONTRACT-02/PU
|
|
|
20
20
|
</CHANGE_SUMMARY>
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import fs from "
|
|
23
|
+
import * as fs from "../utils/sync-fs.ts";
|
|
24
24
|
import path from "node:path";
|
|
25
25
|
import { stringify as stringifyYaml, parse as parseYaml } from "yaml";
|
|
26
26
|
import { FORGE_SKILLS, discoverPackSkills } from "../registry.ts";
|
|
27
27
|
import { syncKnowledgeFile } from "../knowledge/index.ts";
|
|
28
|
+
import { writeSkillMarkerSync } from "./skill-markers.ts";
|
|
29
|
+
import { planPrettierignoreSync, applyPrettierignoreSync } from "./prettierignore.ts";
|
|
28
30
|
import { defaultForgeConfig, loadForgeConfig, resolveForgeRoot, type ForgeConfig } from "../config/forge-config.ts";
|
|
29
31
|
import { listStackProfiles, detectStack } from "../profiles/stack-profile.ts";
|
|
30
32
|
|
|
@@ -280,6 +282,11 @@ export function runInit(
|
|
|
280
282
|
fs.writeFileSync(destPath, content, "utf8");
|
|
281
283
|
created.push(`${config.paths.skillsDir}/${skillName}/SKILL.md`);
|
|
282
284
|
|
|
285
|
+
// RFC-1154: marker manifest lists SKILL.md + knowledge files whose content
|
|
286
|
+
// is purely forge's (copied/unchanged); merged/skipped files carry consumer
|
|
287
|
+
// entries and stay out of the manifest so prune never deletes them.
|
|
288
|
+
const markerFiles = ["SKILL.md"];
|
|
289
|
+
|
|
283
290
|
// RFC-0524: sync declared knowledge files
|
|
284
291
|
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
285
292
|
if (fmMatch) {
|
|
@@ -298,6 +305,9 @@ export function runInit(
|
|
|
298
305
|
if (syncResult.action === "copied" || syncResult.action === "merged") {
|
|
299
306
|
created.push(`${config.paths.skillsDir}/${skillName}/${kf}`);
|
|
300
307
|
}
|
|
308
|
+
if (syncResult.action === "copied" || syncResult.action === "unchanged") {
|
|
309
|
+
markerFiles.push(kf);
|
|
310
|
+
}
|
|
301
311
|
} else {
|
|
302
312
|
errors.push(`Knowledge file '${kf}' declared in ${skillName} but not found in source`);
|
|
303
313
|
}
|
|
@@ -307,6 +317,7 @@ export function runInit(
|
|
|
307
317
|
// Frontmatter parse error — SKILL-01 will catch this in validation
|
|
308
318
|
}
|
|
309
319
|
}
|
|
320
|
+
writeSkillMarkerSync(destDir, markerFiles);
|
|
310
321
|
}
|
|
311
322
|
|
|
312
323
|
// RFC-0539: Copy declared pack skills to .agents/skills/<name>/ for IDE discovery
|
|
@@ -352,6 +363,9 @@ export function runInit(
|
|
|
352
363
|
fs.writeFileSync(destPath, content, "utf8");
|
|
353
364
|
created.push(`${config.paths.skillsDir}/${skillName}/SKILL.md`);
|
|
354
365
|
|
|
366
|
+
// RFC-1154: same marker rule as forge skills.
|
|
367
|
+
const markerFiles = ["SKILL.md"];
|
|
368
|
+
|
|
355
369
|
// RFC-0524: sync declared knowledge files for pack skills
|
|
356
370
|
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
357
371
|
if (fmMatch) {
|
|
@@ -370,6 +384,9 @@ export function runInit(
|
|
|
370
384
|
if (syncResult.action === "copied" || syncResult.action === "merged") {
|
|
371
385
|
created.push(`${config.paths.skillsDir}/${skillName}/${kf}`);
|
|
372
386
|
}
|
|
387
|
+
if (syncResult.action === "copied" || syncResult.action === "unchanged") {
|
|
388
|
+
markerFiles.push(kf);
|
|
389
|
+
}
|
|
373
390
|
} else {
|
|
374
391
|
errors.push(`Knowledge file '${kf}' declared in ${skillName} but not found in source`);
|
|
375
392
|
}
|
|
@@ -379,6 +396,7 @@ export function runInit(
|
|
|
379
396
|
// Frontmatter parse error — SKILL-01 will catch this in validation
|
|
380
397
|
}
|
|
381
398
|
}
|
|
399
|
+
writeSkillMarkerSync(destDir, markerFiles);
|
|
382
400
|
}
|
|
383
401
|
|
|
384
402
|
// RFC-0663: Sync shared knowledge layer to .agents/skills/shared-knowledge/
|
|
@@ -391,6 +409,25 @@ export function runInit(
|
|
|
391
409
|
if (syncResult.action === "copied" || syncResult.action === "merged") {
|
|
392
410
|
created.push(`${config.paths.skillsDir}/shared-knowledge/learned-principles.md`);
|
|
393
411
|
}
|
|
412
|
+
// RFC-1154: marker lists the file only when its content is purely forge's.
|
|
413
|
+
writeSkillMarkerSync(
|
|
414
|
+
sharedKnowledgeDestDir,
|
|
415
|
+
syncResult.action === "copied" || syncResult.action === "unchanged"
|
|
416
|
+
? ["learned-principles.md"]
|
|
417
|
+
: [],
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// RFC-1154: reconcile the forge-managed .prettierignore block (prettier
|
|
422
|
+
// consumers only; additive + idempotent, no-op otherwise). Non-fatal —
|
|
423
|
+
// a prettierignore write failure must not fail init.
|
|
424
|
+
try {
|
|
425
|
+
applyPrettierignoreSync(
|
|
426
|
+
workspaceRoot,
|
|
427
|
+
planPrettierignoreSync(workspaceRoot, config.paths.skillsDir),
|
|
428
|
+
);
|
|
429
|
+
} catch (err) {
|
|
430
|
+
errors.push(`.prettierignore reconcile failed: ${(err as Error).message}`);
|
|
394
431
|
}
|
|
395
432
|
|
|
396
433
|
// 4. Create docs directories from config paths
|
|
@@ -20,7 +20,7 @@ Sweep batch 4: 73 Compass headers on headerless engine files (certification, com
|
|
|
20
20
|
</CHANGE_SUMMARY>
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import fs from "
|
|
23
|
+
import * as fs from "../utils/sync-fs.ts";
|
|
24
24
|
import path from "node:path";
|
|
25
25
|
import { parse as parseYaml } from "yaml";
|
|
26
26
|
import type { StackProfile } from "../profiles/stack-profile.ts";
|