forgecraft-mcp 1.4.0 → 1.7.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/LICENSE +67 -0
- package/README.md +527 -525
- package/dist/analyzers/anchors/anchor-loader.d.ts +47 -0
- package/dist/analyzers/anchors/anchor-loader.d.ts.map +1 -0
- package/dist/analyzers/anchors/anchor-loader.js +113 -0
- package/dist/analyzers/anchors/anchor-loader.js.map +1 -0
- package/dist/analyzers/anti-pattern.d.ts.map +1 -1
- package/dist/analyzers/anti-pattern.js +38 -26
- package/dist/analyzers/anti-pattern.js.map +1 -1
- package/dist/analyzers/completeness-helpers.d.ts +5 -0
- package/dist/analyzers/completeness-helpers.d.ts.map +1 -1
- package/dist/analyzers/completeness-helpers.js +17 -0
- package/dist/analyzers/completeness-helpers.js.map +1 -1
- package/dist/analyzers/completeness.d.ts.map +1 -1
- package/dist/analyzers/completeness.js +4 -4
- package/dist/analyzers/completeness.js.map +1 -1
- package/dist/analyzers/gs-scorer.d.ts +3 -1
- package/dist/analyzers/gs-scorer.d.ts.map +1 -1
- package/dist/analyzers/gs-scorer.js +5 -2
- package/dist/analyzers/gs-scorer.js.map +1 -1
- package/dist/analyzers/package-json.d.ts.map +1 -1
- package/dist/analyzers/package-json.js +194 -34
- package/dist/analyzers/package-json.js.map +1 -1
- package/dist/analyzers/scorers/composable-scorer.d.ts +4 -2
- package/dist/analyzers/scorers/composable-scorer.d.ts.map +1 -1
- package/dist/analyzers/scorers/composable-scorer.js +50 -2
- package/dist/analyzers/scorers/composable-scorer.js.map +1 -1
- package/dist/analyzers/scorers/executable-scorer.d.ts +3 -2
- package/dist/analyzers/scorers/executable-scorer.d.ts.map +1 -1
- package/dist/analyzers/scorers/executable-scorer.js +64 -4
- package/dist/analyzers/scorers/executable-scorer.js.map +1 -1
- package/dist/analyzers/scorers/scorer-utils.d.ts +5 -3
- package/dist/analyzers/scorers/scorer-utils.d.ts.map +1 -1
- package/dist/analyzers/scorers/scorer-utils.js +34 -9
- package/dist/analyzers/scorers/scorer-utils.js.map +1 -1
- package/dist/analyzers/scorers/self-describing-scorer.d.ts +7 -4
- package/dist/analyzers/scorers/self-describing-scorer.d.ts.map +1 -1
- package/dist/analyzers/scorers/self-describing-scorer.js +17 -18
- package/dist/analyzers/scorers/self-describing-scorer.js.map +1 -1
- package/dist/cli/help.js +51 -51
- package/dist/disciplines/catalog.d.ts +16 -0
- package/dist/disciplines/catalog.d.ts.map +1 -0
- package/dist/disciplines/catalog.js +196 -0
- package/dist/disciplines/catalog.js.map +1 -0
- package/dist/disciplines/runner.d.ts +13 -0
- package/dist/disciplines/runner.d.ts.map +1 -0
- package/dist/disciplines/runner.js +35 -0
- package/dist/disciplines/runner.js.map +1 -0
- package/dist/registry/composer.d.ts.map +1 -1
- package/dist/registry/composer.js +9 -4
- package/dist/registry/composer.js.map +1 -1
- package/dist/registry/loader-tag.d.ts.map +1 -1
- package/dist/registry/loader-tag.js +1 -0
- package/dist/registry/loader-tag.js.map +1 -1
- package/dist/registry/remote-gates.js +1 -1
- package/dist/registry/remote-gates.js.map +1 -1
- package/dist/registry/renderer-skeletons.js +92 -92
- package/dist/registry/sentinel-renderer.js +299 -20
- package/dist/registry/sentinel-renderer.js.map +1 -1
- package/dist/sentinel/detect.d.ts +41 -0
- package/dist/sentinel/detect.d.ts.map +1 -0
- package/dist/sentinel/detect.js +122 -0
- package/dist/sentinel/detect.js.map +1 -0
- package/dist/sentinel/write.d.ts +54 -0
- package/dist/sentinel/write.d.ts.map +1 -0
- package/dist/sentinel/write.js +75 -0
- package/dist/sentinel/write.js.map +1 -0
- package/dist/shared/cnt-health.d.ts +16 -0
- package/dist/shared/cnt-health.d.ts.map +1 -1
- package/dist/shared/cnt-health.js +55 -8
- package/dist/shared/cnt-health.js.map +1 -1
- package/dist/shared/config.d.ts +14 -0
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/config.js +45 -0
- package/dist/shared/config.js.map +1 -1
- package/dist/shared/gs-score-logger.js +6 -6
- package/dist/shared/hook-installer.d.ts +58 -0
- package/dist/shared/hook-installer.d.ts.map +1 -0
- package/dist/shared/hook-installer.js +316 -0
- package/dist/shared/hook-installer.js.map +1 -0
- package/dist/shared/project-gates-helpers.d.ts +9 -0
- package/dist/shared/project-gates-helpers.d.ts.map +1 -1
- package/dist/shared/project-gates-helpers.js +35 -0
- package/dist/shared/project-gates-helpers.js.map +1 -1
- package/dist/shared/types/config.d.ts +7 -1
- package/dist/shared/types/config.d.ts.map +1 -1
- package/dist/shared/types/gates.d.ts +34 -0
- package/dist/shared/types/gates.d.ts.map +1 -1
- package/dist/shared/types/project.d.ts +68 -2
- package/dist/shared/types/project.d.ts.map +1 -1
- package/dist/shared/types/project.js +1 -0
- package/dist/shared/types/project.js.map +1 -1
- package/dist/shared/types/templates.d.ts +8 -1
- package/dist/shared/types/templates.d.ts.map +1 -1
- package/dist/shared/types/verify.d.ts +51 -1
- package/dist/shared/types/verify.d.ts.map +1 -1
- package/dist/shared/types/verify.js +37 -1
- package/dist/shared/types/verify.js.map +1 -1
- package/dist/tools/add-hook.d.ts.map +1 -1
- package/dist/tools/add-hook.js +8 -1
- package/dist/tools/add-hook.js.map +1 -1
- package/dist/tools/add-module.js +123 -123
- package/dist/tools/advice-registry.d.ts.map +1 -1
- package/dist/tools/advice-registry.js +108 -18
- package/dist/tools/advice-registry.js.map +1 -1
- package/dist/tools/advise-session-advisor.d.ts +16 -0
- package/dist/tools/advise-session-advisor.d.ts.map +1 -0
- package/dist/tools/advise-session-advisor.js +89 -0
- package/dist/tools/advise-session-advisor.js.map +1 -0
- package/dist/tools/advise-session-signals.d.ts +21 -0
- package/dist/tools/advise-session-signals.d.ts.map +1 -0
- package/dist/tools/advise-session-signals.js +113 -0
- package/dist/tools/advise-session-signals.js.map +1 -0
- package/dist/tools/advise-session.d.ts +22 -0
- package/dist/tools/advise-session.d.ts.map +1 -0
- package/dist/tools/advise-session.js +31 -0
- package/dist/tools/advise-session.js.map +1 -0
- package/dist/tools/analyze-harness.d.ts +18 -0
- package/dist/tools/analyze-harness.d.ts.map +1 -0
- package/dist/tools/analyze-harness.js +298 -0
- package/dist/tools/analyze-harness.js.map +1 -0
- package/dist/tools/audit.d.ts.map +1 -1
- package/dist/tools/audit.js +19 -0
- package/dist/tools/audit.js.map +1 -1
- package/dist/tools/change-request.d.ts +53 -0
- package/dist/tools/change-request.d.ts.map +1 -0
- package/dist/tools/change-request.js +395 -0
- package/dist/tools/change-request.js.map +1 -0
- package/dist/tools/check-cascade-contracts.d.ts +13 -0
- package/dist/tools/check-cascade-contracts.d.ts.map +1 -1
- package/dist/tools/check-cascade-contracts.js +73 -2
- package/dist/tools/check-cascade-contracts.js.map +1 -1
- package/dist/tools/check-cascade-report.js +64 -64
- package/dist/tools/check-cascade-steps.d.ts +3 -0
- package/dist/tools/check-cascade-steps.d.ts.map +1 -1
- package/dist/tools/check-cascade-steps.js +104 -15
- package/dist/tools/check-cascade-steps.js.map +1 -1
- package/dist/tools/check-cascade.d.ts +4 -3
- package/dist/tools/check-cascade.d.ts.map +1 -1
- package/dist/tools/check-cascade.js +30 -12
- package/dist/tools/check-cascade.js.map +1 -1
- package/dist/tools/check-derivation-chain.d.ts +37 -0
- package/dist/tools/check-derivation-chain.d.ts.map +1 -0
- package/dist/tools/check-derivation-chain.js +418 -0
- package/dist/tools/check-derivation-chain.js.map +1 -0
- package/dist/tools/check-spec-consistency.d.ts +25 -0
- package/dist/tools/check-spec-consistency.d.ts.map +1 -0
- package/dist/tools/check-spec-consistency.js +339 -0
- package/dist/tools/check-spec-consistency.js.map +1 -0
- package/dist/tools/check-t4.d.ts +54 -0
- package/dist/tools/check-t4.d.ts.map +1 -0
- package/dist/tools/check-t4.js +305 -0
- package/dist/tools/check-t4.js.map +1 -0
- package/dist/tools/close-cycle.d.ts +11 -0
- package/dist/tools/close-cycle.d.ts.map +1 -1
- package/dist/tools/close-cycle.js +364 -4
- package/dist/tools/close-cycle.js.map +1 -1
- package/dist/tools/cnt-add-routing.d.ts +31 -0
- package/dist/tools/cnt-add-routing.d.ts.map +1 -0
- package/dist/tools/cnt-add-routing.js +99 -0
- package/dist/tools/cnt-add-routing.js.map +1 -0
- package/dist/tools/configure-mcp.d.ts.map +1 -1
- package/dist/tools/configure-mcp.js +52 -2
- package/dist/tools/configure-mcp.js.map +1 -1
- package/dist/tools/consolidate-status.d.ts +31 -0
- package/dist/tools/consolidate-status.d.ts.map +1 -1
- package/dist/tools/consolidate-status.js +105 -0
- package/dist/tools/consolidate-status.js.map +1 -1
- package/dist/tools/executable-gates.d.ts +52 -0
- package/dist/tools/executable-gates.d.ts.map +1 -0
- package/dist/tools/executable-gates.js +333 -0
- package/dist/tools/executable-gates.js.map +1 -0
- package/dist/tools/extract-adrs-from-spec.d.ts +33 -0
- package/dist/tools/extract-adrs-from-spec.d.ts.map +1 -0
- package/dist/tools/extract-adrs-from-spec.js +410 -0
- package/dist/tools/extract-adrs-from-spec.js.map +1 -0
- package/dist/tools/extract-adrs-history.d.ts +47 -0
- package/dist/tools/extract-adrs-history.d.ts.map +1 -0
- package/dist/tools/extract-adrs-history.js +265 -0
- package/dist/tools/extract-adrs-history.js.map +1 -0
- package/dist/tools/forgecraft-dispatch-extended.d.ts.map +1 -1
- package/dist/tools/forgecraft-dispatch-extended.js +137 -0
- package/dist/tools/forgecraft-dispatch-extended.js.map +1 -1
- package/dist/tools/forgecraft-dispatch.d.ts.map +1 -1
- package/dist/tools/forgecraft-dispatch.js +16 -0
- package/dist/tools/forgecraft-dispatch.js.map +1 -1
- package/dist/tools/forgecraft-schema-params.d.ts +174 -2
- package/dist/tools/forgecraft-schema-params.d.ts.map +1 -1
- package/dist/tools/forgecraft-schema-params.js +197 -0
- package/dist/tools/forgecraft-schema-params.js.map +1 -1
- package/dist/tools/forgecraft-schema.d.ts +179 -7
- package/dist/tools/forgecraft-schema.d.ts.map +1 -1
- package/dist/tools/forgecraft-schema.js +37 -0
- package/dist/tools/forgecraft-schema.js.map +1 -1
- package/dist/tools/generate-adr.js +6 -6
- package/dist/tools/generate-adr.js.map +1 -1
- package/dist/tools/generate-decision.d.ts +77 -0
- package/dist/tools/generate-decision.d.ts.map +1 -0
- package/dist/tools/generate-decision.js +162 -0
- package/dist/tools/generate-decision.js.map +1 -0
- package/dist/tools/generate-env-probe.d.ts +49 -0
- package/dist/tools/generate-env-probe.d.ts.map +1 -0
- package/dist/tools/generate-env-probe.js +365 -0
- package/dist/tools/generate-env-probe.js.map +1 -0
- package/dist/tools/generate-harness.d.ts +53 -0
- package/dist/tools/generate-harness.d.ts.map +1 -0
- package/dist/tools/generate-harness.js +395 -0
- package/dist/tools/generate-harness.js.map +1 -0
- package/dist/tools/generate-roadmap.d.ts +1 -1
- package/dist/tools/generate-roadmap.d.ts.map +1 -1
- package/dist/tools/generate-roadmap.js +38 -4
- package/dist/tools/generate-roadmap.js.map +1 -1
- package/dist/tools/generate-session-prompt.d.ts +3 -3
- package/dist/tools/generate-session-prompt.d.ts.map +1 -1
- package/dist/tools/generate-session-prompt.js +9 -1
- package/dist/tools/generate-session-prompt.js.map +1 -1
- package/dist/tools/generate-slo-probe.d.ts +53 -0
- package/dist/tools/generate-slo-probe.d.ts.map +1 -0
- package/dist/tools/generate-slo-probe.js +366 -0
- package/dist/tools/generate-slo-probe.js.map +1 -0
- package/dist/tools/layer-status-gates.d.ts +24 -0
- package/dist/tools/layer-status-gates.d.ts.map +1 -0
- package/dist/tools/layer-status-gates.js +151 -0
- package/dist/tools/layer-status-gates.js.map +1 -0
- package/dist/tools/layer-status.d.ts +126 -0
- package/dist/tools/layer-status.d.ts.map +1 -0
- package/dist/tools/layer-status.js +647 -0
- package/dist/tools/layer-status.js.map +1 -0
- package/dist/tools/list.d.ts.map +1 -1
- package/dist/tools/list.js +9 -5
- package/dist/tools/list.js.map +1 -1
- package/dist/tools/postcondition-coverage.d.ts +57 -0
- package/dist/tools/postcondition-coverage.d.ts.map +1 -0
- package/dist/tools/postcondition-coverage.js +256 -0
- package/dist/tools/postcondition-coverage.js.map +1 -0
- package/dist/tools/probe-runners.d.ts +21 -0
- package/dist/tools/probe-runners.d.ts.map +1 -0
- package/dist/tools/probe-runners.js +246 -0
- package/dist/tools/probe-runners.js.map +1 -0
- package/dist/tools/probe-templates.d.ts +27 -0
- package/dist/tools/probe-templates.d.ts.map +1 -0
- package/dist/tools/probe-templates.js +279 -0
- package/dist/tools/probe-templates.js.map +1 -0
- package/dist/tools/propose-session.d.ts +28 -0
- package/dist/tools/propose-session.d.ts.map +1 -0
- package/dist/tools/propose-session.js +333 -0
- package/dist/tools/propose-session.js.map +1 -0
- package/dist/tools/refresh-output.js +14 -14
- package/dist/tools/review-stubs.d.ts +29 -0
- package/dist/tools/review-stubs.d.ts.map +1 -0
- package/dist/tools/review-stubs.js +173 -0
- package/dist/tools/review-stubs.js.map +1 -0
- package/dist/tools/roadmap-builder.d.ts +49 -1
- package/dist/tools/roadmap-builder.d.ts.map +1 -1
- package/dist/tools/roadmap-builder.js +210 -5
- package/dist/tools/roadmap-builder.js.map +1 -1
- package/dist/tools/run-env-probe.d.ts +57 -0
- package/dist/tools/run-env-probe.d.ts.map +1 -0
- package/dist/tools/run-env-probe.js +270 -0
- package/dist/tools/run-env-probe.js.map +1 -0
- package/dist/tools/run-harness.d.ts +52 -0
- package/dist/tools/run-harness.d.ts.map +1 -0
- package/dist/tools/run-harness.js +279 -0
- package/dist/tools/run-harness.js.map +1 -0
- package/dist/tools/run-slo-probe.d.ts +50 -0
- package/dist/tools/run-slo-probe.d.ts.map +1 -0
- package/dist/tools/run-slo-probe.js +281 -0
- package/dist/tools/run-slo-probe.js.map +1 -0
- package/dist/tools/scaffold-spec-stubs.js +115 -115
- package/dist/tools/scaffold-templates.js +62 -62
- package/dist/tools/scaffold-writer.d.ts.map +1 -1
- package/dist/tools/scaffold-writer.js +9 -0
- package/dist/tools/scaffold-writer.js.map +1 -1
- package/dist/tools/score-rubric.d.ts +19 -0
- package/dist/tools/score-rubric.d.ts.map +1 -0
- package/dist/tools/score-rubric.js +411 -0
- package/dist/tools/score-rubric.js.map +1 -0
- package/dist/tools/session-prompt-builders.d.ts +20 -0
- package/dist/tools/session-prompt-builders.d.ts.map +1 -1
- package/dist/tools/session-prompt-builders.js +78 -5
- package/dist/tools/session-prompt-builders.js.map +1 -1
- package/dist/tools/session-prompt-sections.d.ts +4 -2
- package/dist/tools/session-prompt-sections.d.ts.map +1 -1
- package/dist/tools/session-prompt-sections.js +22 -10
- package/dist/tools/session-prompt-sections.js.map +1 -1
- package/dist/tools/setup-artifact-writers.d.ts +69 -4
- package/dist/tools/setup-artifact-writers.d.ts.map +1 -1
- package/dist/tools/setup-artifact-writers.js +681 -5
- package/dist/tools/setup-artifact-writers.js.map +1 -1
- package/dist/tools/setup-cnt-builders.d.ts.map +1 -1
- package/dist/tools/setup-cnt-builders.js +162 -34
- package/dist/tools/setup-cnt-builders.js.map +1 -1
- package/dist/tools/setup-monitoring.d.ts +41 -0
- package/dist/tools/setup-monitoring.d.ts.map +1 -0
- package/dist/tools/setup-monitoring.js +364 -0
- package/dist/tools/setup-monitoring.js.map +1 -0
- package/dist/tools/setup-phase1.d.ts.map +1 -1
- package/dist/tools/setup-phase1.js +14 -1
- package/dist/tools/setup-phase1.js.map +1 -1
- package/dist/tools/setup-phase2.d.ts +14 -0
- package/dist/tools/setup-phase2.d.ts.map +1 -1
- package/dist/tools/setup-phase2.js +130 -3
- package/dist/tools/setup-phase2.js.map +1 -1
- package/dist/tools/setup-project.d.ts +8 -0
- package/dist/tools/setup-project.d.ts.map +1 -1
- package/dist/tools/setup-project.js +52 -2
- package/dist/tools/setup-project.js.map +1 -1
- package/dist/tools/spec-parser-tags.d.ts.map +1 -1
- package/dist/tools/spec-parser-tags.js +1 -0
- package/dist/tools/spec-parser-tags.js.map +1 -1
- package/dist/tools/verify-formatter.d.ts.map +1 -1
- package/dist/tools/verify-formatter.js +15 -1
- package/dist/tools/verify-formatter.js.map +1 -1
- package/dist/tools/verify.d.ts.map +1 -1
- package/dist/tools/verify.js +3 -0
- package/dist/tools/verify.js.map +1 -1
- package/package.json +98 -89
- package/templates/analytics/instructions.yaml +37 -37
- package/templates/analytics/mcp-servers.yaml +11 -11
- package/templates/analytics/structure.yaml +25 -25
- package/templates/api/harness/uc-template.hurl +20 -0
- package/templates/api/instructions.yaml +231 -231
- package/templates/api/mcp-servers.yaml +22 -22
- package/templates/api/nfr.yaml +23 -23
- package/templates/api/review.yaml +103 -103
- package/templates/api/structure.yaml +34 -34
- package/templates/api/verification.yaml +132 -132
- package/templates/cli/instructions.yaml +31 -31
- package/templates/cli/mcp-servers.yaml +11 -11
- package/templates/cli/review.yaml +53 -53
- package/templates/cli/structure.yaml +16 -16
- package/templates/data-lineage/instructions.yaml +28 -28
- package/templates/data-lineage/mcp-servers.yaml +22 -22
- package/templates/data-pipeline/instructions.yaml +84 -84
- package/templates/data-pipeline/mcp-servers.yaml +13 -13
- package/templates/data-pipeline/nfr.yaml +39 -39
- package/templates/data-pipeline/structure.yaml +23 -23
- package/templates/docs-manifest.yaml +227 -0
- package/templates/fintech/hooks.yaml +55 -55
- package/templates/fintech/instructions.yaml +112 -112
- package/templates/fintech/mcp-servers.yaml +13 -13
- package/templates/fintech/nfr.yaml +46 -46
- package/templates/fintech/playbook.yaml +210 -210
- package/templates/fintech/verification.yaml +239 -239
- package/templates/game/harness/uc-template.sim.ts +29 -0
- package/templates/game/instructions.yaml +289 -289
- package/templates/game/mcp-servers.yaml +38 -38
- package/templates/game/nfr.yaml +64 -64
- package/templates/game/playbook.yaml +214 -214
- package/templates/game/review.yaml +97 -97
- package/templates/game/structure.yaml +67 -67
- package/templates/game/verification.yaml +174 -174
- package/templates/healthcare/instructions.yaml +42 -42
- package/templates/healthcare/mcp-servers.yaml +13 -13
- package/templates/healthcare/nfr.yaml +47 -47
- package/templates/hipaa/instructions.yaml +41 -41
- package/templates/hipaa/mcp-servers.yaml +13 -13
- package/templates/infra/instructions.yaml +104 -104
- package/templates/infra/mcp-servers.yaml +20 -20
- package/templates/infra/nfr.yaml +46 -46
- package/templates/infra/review.yaml +65 -65
- package/templates/infra/structure.yaml +25 -25
- package/templates/library/instructions.yaml +36 -36
- package/templates/library/mcp-servers.yaml +20 -20
- package/templates/library/review.yaml +56 -56
- package/templates/library/structure.yaml +19 -19
- package/templates/medallion-architecture/instructions.yaml +41 -41
- package/templates/medallion-architecture/mcp-servers.yaml +22 -22
- package/templates/ml/instructions.yaml +85 -85
- package/templates/ml/mcp-servers.yaml +11 -11
- package/templates/ml/nfr.yaml +39 -39
- package/templates/ml/structure.yaml +25 -25
- package/templates/ml/verification.yaml +156 -156
- package/templates/mobile/instructions.yaml +44 -44
- package/templates/mobile/mcp-servers.yaml +11 -11
- package/templates/mobile/nfr.yaml +49 -49
- package/templates/mobile/structure.yaml +27 -27
- package/templates/mobile/verification.yaml +121 -121
- package/templates/observability-xray/instructions.yaml +40 -40
- package/templates/observability-xray/mcp-servers.yaml +15 -15
- package/templates/realtime/instructions.yaml +42 -42
- package/templates/realtime/mcp-servers.yaml +13 -13
- package/templates/soc2/instructions.yaml +41 -41
- package/templates/soc2/mcp-servers.yaml +24 -24
- package/templates/social/instructions.yaml +43 -43
- package/templates/social/mcp-servers.yaml +24 -24
- package/templates/state-machine/instructions.yaml +42 -42
- package/templates/state-machine/mcp-servers.yaml +11 -11
- package/templates/tools-registry.yaml +164 -164
- package/templates/universal/claude-md-blocks/layer-navigation.md +20 -0
- package/templates/universal/claude-md-blocks/nfr-contracts.md +22 -0
- package/templates/universal/hooks.yaml +879 -723
- package/templates/universal/instructions.yaml +1692 -1692
- package/templates/universal/mcp-servers.yaml +50 -50
- package/templates/universal/nfr.yaml +197 -197
- package/templates/universal/reference.yaml +326 -326
- package/templates/universal/review.yaml +204 -204
- package/templates/universal/skills.yaml +262 -262
- package/templates/universal/structure.yaml +67 -67
- package/templates/universal/verification.yaml +416 -416
- package/templates/web-next/hooks.yaml +114 -0
- package/templates/web-next/instructions.yaml +106 -0
- package/templates/web-react/harness/uc-template.spec.ts +35 -0
- package/templates/web-react/hooks.yaml +156 -44
- package/templates/web-react/instructions.yaml +296 -207
- package/templates/web-react/mcp-servers.yaml +20 -20
- package/templates/web-react/nfr.yaml +27 -27
- package/templates/web-react/review.yaml +94 -94
- package/templates/web-react/structure.yaml +46 -46
- package/templates/web-react/verification.yaml +126 -126
- package/templates/web-static/hooks.yaml +85 -0
- package/templates/web-static/instructions.yaml +204 -115
- package/templates/web-static/mcp-servers.yaml +20 -20
- package/templates/web3/instructions.yaml +44 -44
- package/templates/web3/mcp-servers.yaml +11 -11
- package/templates/web3/verification.yaml +159 -159
- package/templates/zero-trust/instructions.yaml +41 -41
- package/templates/zero-trust/mcp-servers.yaml +15 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sentinel-renderer.js","sourceRoot":"","sources":["../../src/registry/sentinel-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAYlC,yEAAyE;AAEzE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAA0B,EAC1B,OAAsB;IAEtB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAmB,EAAE,CAAC;IAEjC,kCAAkC;IAClC,MAAM,kBAAkB,GAAmD,EAAE,CAAC;IAE9E,KAAK,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC9C,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAExC,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QAChE,KAAK,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,qBAAqB,MAAM,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAExE,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC;QAC1D,kBAAkB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,qDAAqD;IACrD,kBAAkB,CAAC,IAAI,CACrB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACtC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CACzC,CAAC;IAEF,kEAAkE;IAClE,KAAK,CAAC,OAAO,CAAC;QACZ,YAAY,EAAE,WAAW;QACzB,OAAO,EAAE,sBAAsB,CAAC,kBAAkB,EAAE,OAAO,CAAC;KAC7D,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,yEAAyE;AAEzE;;;GAGG;AACH,SAAS,mBAAmB,CAC1B,MAA0B;IAE1B,MAAM,GAAG,GAAG,IAAI,GAAG,EAA8B,CAAC;IAElD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC;QACzD,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACvC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,gBAAgB,CACvB,MAAc,EACd,MAA0B,EAC1B,OAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,KAAK,GAAa;QACtB,6BAA6B,MAAM,MAAM,IAAI,uDAAuD;QACpG,EAAE;KACH,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/D,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"sentinel-renderer.js","sourceRoot":"","sources":["../../src/registry/sentinel-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentinel detection — find existing AI behavioral instruction files in a repo.
|
|
3
|
+
*
|
|
4
|
+
* Before forgecraft writes any instruction file (CLAUDE.md, AGENTS.md,
|
|
5
|
+
* cursor rules, copilot instructions, ...), it must first see what is
|
|
6
|
+
* already on disk. Multiple sentinels in a single repo is a coordination
|
|
7
|
+
* hazard: silently overwriting one breaks whichever tool was depending on
|
|
8
|
+
* it. Detection is the read-only first half of that contract; the write
|
|
9
|
+
* half lives in `./write.ts`.
|
|
10
|
+
*
|
|
11
|
+
* The priority list below is canonical. Order matters — the first existing
|
|
12
|
+
* entry becomes `primaryFile`. Keep it stable; downstream tools rely on
|
|
13
|
+
* this ordering when deciding which file to map to.
|
|
14
|
+
*/
|
|
15
|
+
import type { SentinelDetectionResult } from "../shared/types.js";
|
|
16
|
+
/**
|
|
17
|
+
* Canonical priority list of sentinel paths, highest priority first.
|
|
18
|
+
* Paths are relative to the repo root and use POSIX separators.
|
|
19
|
+
*
|
|
20
|
+
* Includes both files and directories — `.cursor/rules` is a directory of
|
|
21
|
+
* `.mdc` rule files; everything else is a single markdown/yaml file.
|
|
22
|
+
*/
|
|
23
|
+
export declare const SENTINEL_PRIORITY_PATHS: readonly string[];
|
|
24
|
+
/**
|
|
25
|
+
* Scan `repoPath` for AI instruction files in canonical priority order.
|
|
26
|
+
*
|
|
27
|
+
* @param repoPath Absolute path to the repository root to scan.
|
|
28
|
+
* @returns Detection result enumerating found files and a recommendation.
|
|
29
|
+
*
|
|
30
|
+
* Filesystem semantics:
|
|
31
|
+
* - Files are matched by exact path; their `sizeBytes` is `stat().size`.
|
|
32
|
+
* - Directories (e.g. `.cursor/rules`) are considered present only when
|
|
33
|
+
* they contain at least one immediate file; `sizeBytes` is the sum of
|
|
34
|
+
* those immediate files' sizes. This avoids reporting an empty cursor
|
|
35
|
+
* rules folder as a live sentinel.
|
|
36
|
+
* - Symlinks are followed via `statSync`'s default behaviour.
|
|
37
|
+
* - Errors reading individual entries are swallowed — a permission error
|
|
38
|
+
* on one path must not mask sentinels at other paths.
|
|
39
|
+
*/
|
|
40
|
+
export declare function detectSentinel(repoPath: string): SentinelDetectionResult;
|
|
41
|
+
//# sourceMappingURL=detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/sentinel/detect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EACV,uBAAuB,EAExB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAO3C,CAAC;AAEX;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,uBAAuB,CAyBxE"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentinel detection — find existing AI behavioral instruction files in a repo.
|
|
3
|
+
*
|
|
4
|
+
* Before forgecraft writes any instruction file (CLAUDE.md, AGENTS.md,
|
|
5
|
+
* cursor rules, copilot instructions, ...), it must first see what is
|
|
6
|
+
* already on disk. Multiple sentinels in a single repo is a coordination
|
|
7
|
+
* hazard: silently overwriting one breaks whichever tool was depending on
|
|
8
|
+
* it. Detection is the read-only first half of that contract; the write
|
|
9
|
+
* half lives in `./write.ts`.
|
|
10
|
+
*
|
|
11
|
+
* The priority list below is canonical. Order matters — the first existing
|
|
12
|
+
* entry becomes `primaryFile`. Keep it stable; downstream tools rely on
|
|
13
|
+
* this ordering when deciding which file to map to.
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
/**
|
|
18
|
+
* Canonical priority list of sentinel paths, highest priority first.
|
|
19
|
+
* Paths are relative to the repo root and use POSIX separators.
|
|
20
|
+
*
|
|
21
|
+
* Includes both files and directories — `.cursor/rules` is a directory of
|
|
22
|
+
* `.mdc` rule files; everything else is a single markdown/yaml file.
|
|
23
|
+
*/
|
|
24
|
+
export const SENTINEL_PRIORITY_PATHS = [
|
|
25
|
+
"CLAUDE.md",
|
|
26
|
+
"agents.md",
|
|
27
|
+
"AGENTS.md",
|
|
28
|
+
".cursor/rules",
|
|
29
|
+
".aider.conf.yml",
|
|
30
|
+
".github/copilot-instructions.md",
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* Scan `repoPath` for AI instruction files in canonical priority order.
|
|
34
|
+
*
|
|
35
|
+
* @param repoPath Absolute path to the repository root to scan.
|
|
36
|
+
* @returns Detection result enumerating found files and a recommendation.
|
|
37
|
+
*
|
|
38
|
+
* Filesystem semantics:
|
|
39
|
+
* - Files are matched by exact path; their `sizeBytes` is `stat().size`.
|
|
40
|
+
* - Directories (e.g. `.cursor/rules`) are considered present only when
|
|
41
|
+
* they contain at least one immediate file; `sizeBytes` is the sum of
|
|
42
|
+
* those immediate files' sizes. This avoids reporting an empty cursor
|
|
43
|
+
* rules folder as a live sentinel.
|
|
44
|
+
* - Symlinks are followed via `statSync`'s default behaviour.
|
|
45
|
+
* - Errors reading individual entries are swallowed — a permission error
|
|
46
|
+
* on one path must not mask sentinels at other paths.
|
|
47
|
+
*/
|
|
48
|
+
export function detectSentinel(repoPath) {
|
|
49
|
+
const foundFiles = [];
|
|
50
|
+
for (const relPath of SENTINEL_PRIORITY_PATHS) {
|
|
51
|
+
const absPath = join(repoPath, relPath);
|
|
52
|
+
if (!existsSync(absPath))
|
|
53
|
+
continue;
|
|
54
|
+
const sizeBytes = sizeOfEntry(absPath);
|
|
55
|
+
if (sizeBytes === null)
|
|
56
|
+
continue;
|
|
57
|
+
foundFiles.push({ path: relPath, sizeBytes });
|
|
58
|
+
}
|
|
59
|
+
const primaryFile = foundFiles.length > 0 ? foundFiles[0].path : null;
|
|
60
|
+
let recommendation;
|
|
61
|
+
if (foundFiles.length === 0) {
|
|
62
|
+
recommendation = "none-found";
|
|
63
|
+
}
|
|
64
|
+
else if (foundFiles.length === 1) {
|
|
65
|
+
recommendation = "map";
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
recommendation = "override-required";
|
|
69
|
+
}
|
|
70
|
+
return { foundFiles, primaryFile, recommendation };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Return the size in bytes of a sentinel entry — file size for files,
|
|
74
|
+
* sum of immediate file sizes for directories. Returns `null` when the
|
|
75
|
+
* entry should not count as a sentinel (empty directory, unreadable).
|
|
76
|
+
*/
|
|
77
|
+
function sizeOfEntry(absPath) {
|
|
78
|
+
let stats;
|
|
79
|
+
try {
|
|
80
|
+
stats = statSync(absPath);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
if (stats.isFile()) {
|
|
86
|
+
return stats.size;
|
|
87
|
+
}
|
|
88
|
+
if (stats.isDirectory()) {
|
|
89
|
+
return sumImmediateFileSizes(absPath);
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Sum sizes of the immediate (non-recursive) files inside a directory.
|
|
95
|
+
* An empty directory returns `null` so callers can treat it as absent.
|
|
96
|
+
*/
|
|
97
|
+
function sumImmediateFileSizes(dirPath) {
|
|
98
|
+
let total = 0;
|
|
99
|
+
let foundAny = false;
|
|
100
|
+
let entries;
|
|
101
|
+
try {
|
|
102
|
+
entries = readdirSync(dirPath, {
|
|
103
|
+
withFileTypes: true,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
if (!entry.isFile())
|
|
111
|
+
continue;
|
|
112
|
+
try {
|
|
113
|
+
total += statSync(join(dirPath, entry.name)).size;
|
|
114
|
+
foundAny = true;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Skip unreadable entries; keep scanning.
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return foundAny ? total : null;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/sentinel/detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentinel-respecting writer for AI behavioral instruction files.
|
|
3
|
+
*
|
|
4
|
+
* Pairs with `./detect.ts`: detection is the read-only check, this is the
|
|
5
|
+
* gated write. Default behaviour is the safe one — if any sentinel exists
|
|
6
|
+
* (at the target path or anywhere on the canonical priority list), the
|
|
7
|
+
* write is *skipped* and the caller decides what to do.
|
|
8
|
+
*
|
|
9
|
+
* Three opt-ins are available:
|
|
10
|
+
* - `override: true` → write the target unconditionally.
|
|
11
|
+
* - `appendIfMatchTarget: true` → append the new content under a dated
|
|
12
|
+
* `## GS Discipline` header, but only
|
|
13
|
+
* when the target file already exists
|
|
14
|
+
* and is itself one of the recognised
|
|
15
|
+
* sentinels. Cross-file appends are not
|
|
16
|
+
* permitted from this helper.
|
|
17
|
+
*
|
|
18
|
+
* This module performs no integration with existing CLAUDE.md generation
|
|
19
|
+
* flows — that wiring is a separate refactor.
|
|
20
|
+
*/
|
|
21
|
+
export interface WriteWithSentinelRespectOptions {
|
|
22
|
+
/** Absolute path to the repo root used for sentinel scanning. */
|
|
23
|
+
readonly repoPath: string;
|
|
24
|
+
/** Absolute path of the file forgecraft wants to write. */
|
|
25
|
+
readonly targetPath: string;
|
|
26
|
+
/** New content to write. */
|
|
27
|
+
readonly content: string;
|
|
28
|
+
/** Force-write even when sentinels exist. Default `false`. */
|
|
29
|
+
readonly override?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* If `true` and the target itself is a recognised sentinel that already
|
|
32
|
+
* exists, append the content under a dated header instead of skipping.
|
|
33
|
+
* Has no effect when `override` is `true`.
|
|
34
|
+
*/
|
|
35
|
+
readonly appendIfMatchTarget?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export type WriteWithSentinelRespectResult = {
|
|
38
|
+
readonly action: "written";
|
|
39
|
+
readonly bytesWritten: number;
|
|
40
|
+
} | {
|
|
41
|
+
readonly action: "appended";
|
|
42
|
+
readonly existingFile: string;
|
|
43
|
+
readonly bytesWritten: number;
|
|
44
|
+
} | {
|
|
45
|
+
readonly action: "skipped";
|
|
46
|
+
readonly reason: string;
|
|
47
|
+
readonly existingFile: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Write `content` to `targetPath`, respecting any sentinel files already
|
|
51
|
+
* in the repo. See module docstring for the full policy.
|
|
52
|
+
*/
|
|
53
|
+
export declare function writeWithSentinelRespect(opts: WriteWithSentinelRespectOptions): WriteWithSentinelRespectResult;
|
|
54
|
+
//# sourceMappingURL=write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/sentinel/write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,MAAM,WAAW,+BAA+B;IAC9C,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4BAA4B;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,MAAM,MAAM,8BAA8B,GACtC;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC7D;IACE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEN;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,+BAA+B,GACpC,8BAA8B,CAuChC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentinel-respecting writer for AI behavioral instruction files.
|
|
3
|
+
*
|
|
4
|
+
* Pairs with `./detect.ts`: detection is the read-only check, this is the
|
|
5
|
+
* gated write. Default behaviour is the safe one — if any sentinel exists
|
|
6
|
+
* (at the target path or anywhere on the canonical priority list), the
|
|
7
|
+
* write is *skipped* and the caller decides what to do.
|
|
8
|
+
*
|
|
9
|
+
* Three opt-ins are available:
|
|
10
|
+
* - `override: true` → write the target unconditionally.
|
|
11
|
+
* - `appendIfMatchTarget: true` → append the new content under a dated
|
|
12
|
+
* `## GS Discipline` header, but only
|
|
13
|
+
* when the target file already exists
|
|
14
|
+
* and is itself one of the recognised
|
|
15
|
+
* sentinels. Cross-file appends are not
|
|
16
|
+
* permitted from this helper.
|
|
17
|
+
*
|
|
18
|
+
* This module performs no integration with existing CLAUDE.md generation
|
|
19
|
+
* flows — that wiring is a separate refactor.
|
|
20
|
+
*/
|
|
21
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
22
|
+
import { dirname, relative, resolve } from "node:path";
|
|
23
|
+
import { detectSentinel, SENTINEL_PRIORITY_PATHS } from "./detect.js";
|
|
24
|
+
/**
|
|
25
|
+
* Write `content` to `targetPath`, respecting any sentinel files already
|
|
26
|
+
* in the repo. See module docstring for the full policy.
|
|
27
|
+
*/
|
|
28
|
+
export function writeWithSentinelRespect(opts) {
|
|
29
|
+
const { repoPath, targetPath, content, override = false, appendIfMatchTarget = false, } = opts;
|
|
30
|
+
if (override) {
|
|
31
|
+
return writeFresh(targetPath, content);
|
|
32
|
+
}
|
|
33
|
+
const detection = detectSentinel(repoPath);
|
|
34
|
+
const targetExists = existsSync(targetPath);
|
|
35
|
+
if (!targetExists && detection.foundFiles.length === 0) {
|
|
36
|
+
return writeFresh(targetPath, content);
|
|
37
|
+
}
|
|
38
|
+
const targetRel = toRepoRelative(repoPath, targetPath);
|
|
39
|
+
const targetIsSentinel = SENTINEL_PRIORITY_PATHS.includes(targetRel);
|
|
40
|
+
if (appendIfMatchTarget && targetExists && targetIsSentinel) {
|
|
41
|
+
return appendUnderHeader(targetPath, content);
|
|
42
|
+
}
|
|
43
|
+
const blocking = targetExists && targetIsSentinel
|
|
44
|
+
? targetRel
|
|
45
|
+
: (detection.foundFiles[0]?.path ?? targetRel);
|
|
46
|
+
const reason = targetExists
|
|
47
|
+
? `Target ${targetRel} already exists; pass override:true to replace, or appendIfMatchTarget:true to append.`
|
|
48
|
+
: `Sentinel(s) detected: ${detection.foundFiles
|
|
49
|
+
.map((f) => f.path)
|
|
50
|
+
.join(", ")}. Pass override:true to write anyway.`;
|
|
51
|
+
return { action: "skipped", reason, existingFile: blocking };
|
|
52
|
+
}
|
|
53
|
+
function writeFresh(targetPath, content) {
|
|
54
|
+
mkdirSync(dirname(targetPath), { recursive: true });
|
|
55
|
+
writeFileSync(targetPath, content, "utf-8");
|
|
56
|
+
return {
|
|
57
|
+
action: "written",
|
|
58
|
+
bytesWritten: Buffer.byteLength(content, "utf-8"),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function appendUnderHeader(targetPath, content) {
|
|
62
|
+
const original = readFileSync(targetPath, "utf-8");
|
|
63
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
64
|
+
const separator = original.endsWith("\n") ? "\n" : "\n\n";
|
|
65
|
+
const header = `## GS Discipline (appended by forgecraft ${date})\n\n`;
|
|
66
|
+
const merged = `${original}${separator}${header}${content}`;
|
|
67
|
+
writeFileSync(targetPath, merged, "utf-8");
|
|
68
|
+
const bytesWritten = Buffer.byteLength(merged, "utf-8") - Buffer.byteLength(original, "utf-8");
|
|
69
|
+
return { action: "appended", existingFile: targetPath, bytesWritten };
|
|
70
|
+
}
|
|
71
|
+
/** Express `targetPath` relative to `repoPath` using POSIX separators. */
|
|
72
|
+
function toRepoRelative(repoPath, targetPath) {
|
|
73
|
+
return relative(resolve(repoPath), resolve(targetPath)).replace(/\\/g, "/");
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/sentinel/write.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,9 @@ export interface CntAuditResult {
|
|
|
24
24
|
lines: number;
|
|
25
25
|
}>;
|
|
26
26
|
readonly indexMdPresent: boolean;
|
|
27
|
+
/** Leaf nodes with no routing directive in .claude/index.md */
|
|
28
|
+
readonly unroutedLeaves: ReadonlyArray<string>;
|
|
29
|
+
readonly routingPass: boolean;
|
|
27
30
|
readonly score: number;
|
|
28
31
|
readonly issues: string[];
|
|
29
32
|
}
|
|
@@ -41,4 +44,17 @@ export declare function detectCntDrift(projectDir: string): CntDriftResult;
|
|
|
41
44
|
* @returns CntAuditResult with scores and violations
|
|
42
45
|
*/
|
|
43
46
|
export declare function auditCntHealth(projectDir: string): CntAuditResult;
|
|
47
|
+
/**
|
|
48
|
+
* Find leaf nodes that have no routing directive in .claude/index.md.
|
|
49
|
+
*
|
|
50
|
+
* A routing directive is any line in index.md that references the leaf's
|
|
51
|
+
* stem (filename without .md extension). Typical forms:
|
|
52
|
+
* - "read .claude/standards/tools-routing.md when working on tools/"
|
|
53
|
+
* - "→ standards/tools-routing.md"
|
|
54
|
+
* - "[tools-routing](standards/tools-routing.md)"
|
|
55
|
+
*
|
|
56
|
+
* @param projectDir - Absolute path to project root
|
|
57
|
+
* @returns Array of leaf filenames (without .md) that have no routing reference
|
|
58
|
+
*/
|
|
59
|
+
export declare function findUnroutedLeaves(projectDir: string): string[];
|
|
44
60
|
//# sourceMappingURL=cnt-health.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cnt-health.d.ts","sourceRoot":"","sources":["../../src/shared/cnt-health.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"cnt-health.d.ts","sourceRoot":"","sources":["../../src/shared/cnt-health.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAC9B,oDAAoD;IACpD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxE,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/C,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;CAC3B;AAyCD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAsBjE;AA6CD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CA2EjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAe/D"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
9
9
|
import { join } from "node:path";
|
|
10
|
+
import { readExceptions, findMatchingException } from "./exceptions.js";
|
|
10
11
|
/** Ignored directory names when scanning src/ */
|
|
11
12
|
const IGNORED_SRC_DIRS = new Set(["node_modules", "dist", "coverage", ".git"]);
|
|
12
13
|
/**
|
|
@@ -123,22 +124,31 @@ export function auditCntHealth(projectDir) {
|
|
|
123
124
|
coreMdPass: false,
|
|
124
125
|
leafViolations: [],
|
|
125
126
|
indexMdPresent: false,
|
|
127
|
+
unroutedLeaves: [],
|
|
128
|
+
routingPass: true,
|
|
126
129
|
score: 0,
|
|
127
130
|
issues: ["CNT not initialized — .claude/index.md missing"],
|
|
128
131
|
};
|
|
129
132
|
}
|
|
133
|
+
const exceptions = readExceptions(projectDir);
|
|
130
134
|
const claudeMdLines = countFileLines(join(projectDir, "CLAUDE.md"));
|
|
131
135
|
const coreMdLines = countFileLines(join(projectDir, ".claude", "core.md"));
|
|
132
|
-
|
|
133
|
-
const
|
|
136
|
+
// Honor exceptions: if CLAUDE.md or core.md is exempted, treat as passing.
|
|
137
|
+
const claudeMdExempt = !!findMatchingException(exceptions, "audit/cnt_claude_md", "CLAUDE.md");
|
|
138
|
+
const coreMdExempt = !!findMatchingException(exceptions, "audit/cnt_core_md", ".claude/core.md");
|
|
139
|
+
const claudeMdPass = claudeMdExempt || (claudeMdLines !== null && claudeMdLines <= 3);
|
|
140
|
+
const coreMdPass = coreMdExempt || (coreMdLines !== null && coreMdLines <= 50);
|
|
134
141
|
const indexMdPresent = true;
|
|
135
|
-
const leafViolations = findLeafViolations(projectDir);
|
|
136
|
-
const
|
|
137
|
-
const
|
|
142
|
+
const leafViolations = findLeafViolations(projectDir, exceptions);
|
|
143
|
+
const unroutedLeaves = findUnroutedLeaves(projectDir);
|
|
144
|
+
const routingPass = unroutedLeaves.length === 0;
|
|
145
|
+
const issues = buildAuditIssues(claudeMdLines, claudeMdPass, coreMdLines, coreMdPass, leafViolations, unroutedLeaves);
|
|
146
|
+
const totalChecks = 5; // CLAUDE.md, core.md, index.md, no leaf violations, routing
|
|
138
147
|
const passing = (claudeMdPass ? 1 : 0) +
|
|
139
148
|
(coreMdPass ? 1 : 0) +
|
|
140
149
|
1 + // index.md present
|
|
141
|
-
(leafViolations.length === 0 ? 1 : 0)
|
|
150
|
+
(leafViolations.length === 0 ? 1 : 0) +
|
|
151
|
+
(routingPass ? 1 : 0);
|
|
142
152
|
const score = Math.round((passing / totalChecks) * 100);
|
|
143
153
|
return {
|
|
144
154
|
hasCnt,
|
|
@@ -148,10 +158,41 @@ export function auditCntHealth(projectDir) {
|
|
|
148
158
|
coreMdPass,
|
|
149
159
|
leafViolations,
|
|
150
160
|
indexMdPresent,
|
|
161
|
+
unroutedLeaves,
|
|
162
|
+
routingPass,
|
|
151
163
|
score,
|
|
152
164
|
issues,
|
|
153
165
|
};
|
|
154
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Find leaf nodes that have no routing directive in .claude/index.md.
|
|
169
|
+
*
|
|
170
|
+
* A routing directive is any line in index.md that references the leaf's
|
|
171
|
+
* stem (filename without .md extension). Typical forms:
|
|
172
|
+
* - "read .claude/standards/tools-routing.md when working on tools/"
|
|
173
|
+
* - "→ standards/tools-routing.md"
|
|
174
|
+
* - "[tools-routing](standards/tools-routing.md)"
|
|
175
|
+
*
|
|
176
|
+
* @param projectDir - Absolute path to project root
|
|
177
|
+
* @returns Array of leaf filenames (without .md) that have no routing reference
|
|
178
|
+
*/
|
|
179
|
+
export function findUnroutedLeaves(projectDir) {
|
|
180
|
+
const indexPath = join(projectDir, ".claude", "index.md");
|
|
181
|
+
if (!existsSync(indexPath))
|
|
182
|
+
return [];
|
|
183
|
+
let indexContent = "";
|
|
184
|
+
try {
|
|
185
|
+
indexContent = readFileSync(indexPath, "utf-8").toLowerCase();
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return [];
|
|
189
|
+
}
|
|
190
|
+
const leafNames = readCntLeafNames(projectDir);
|
|
191
|
+
return leafNames.filter((leaf) => {
|
|
192
|
+
const stem = leaf.toLowerCase();
|
|
193
|
+
return !indexContent.includes(stem);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
155
196
|
/** Prefix written by the sentinel renderer on the first line of scaffold-generated files. */
|
|
156
197
|
const SCAFFOLD_SENTINEL_PREFIX = "<!-- ForgeCraft sentinel:";
|
|
157
198
|
/**
|
|
@@ -162,7 +203,7 @@ const SCAFFOLD_SENTINEL_PREFIX = "<!-- ForgeCraft sentinel:";
|
|
|
162
203
|
* @param projectDir - Absolute path to project root
|
|
163
204
|
* @returns Array of violations with file name and line count
|
|
164
205
|
*/
|
|
165
|
-
function findLeafViolations(projectDir) {
|
|
206
|
+
function findLeafViolations(projectDir, exceptions = []) {
|
|
166
207
|
const standardsDir = join(projectDir, ".claude", "standards");
|
|
167
208
|
if (!existsSync(standardsDir))
|
|
168
209
|
return [];
|
|
@@ -174,6 +215,9 @@ function findLeafViolations(projectDir) {
|
|
|
174
215
|
const content = readFileSync(fullPath, "utf-8");
|
|
175
216
|
if (content.startsWith(SCAFFOLD_SENTINEL_PREFIX))
|
|
176
217
|
return [];
|
|
218
|
+
const relPath = `.claude/standards/${f}`;
|
|
219
|
+
if (findMatchingException(exceptions, "audit/cnt_leaf_length", relPath))
|
|
220
|
+
return [];
|
|
177
221
|
const lines = countFileLines(fullPath);
|
|
178
222
|
return lines !== null && lines > 30 ? [{ file: f, lines }] : [];
|
|
179
223
|
});
|
|
@@ -192,7 +236,7 @@ function findLeafViolations(projectDir) {
|
|
|
192
236
|
* @param leafViolations - Leaf nodes exceeding 30 lines
|
|
193
237
|
* @returns Array of issue strings
|
|
194
238
|
*/
|
|
195
|
-
function buildAuditIssues(claudeMdLines, claudeMdPass, coreMdLines, coreMdPass, leafViolations) {
|
|
239
|
+
function buildAuditIssues(claudeMdLines, claudeMdPass, coreMdLines, coreMdPass, leafViolations, unroutedLeaves = []) {
|
|
196
240
|
const issues = [];
|
|
197
241
|
if (claudeMdLines === null) {
|
|
198
242
|
issues.push("CLAUDE.md missing");
|
|
@@ -209,6 +253,9 @@ function buildAuditIssues(claudeMdLines, claudeMdPass, coreMdLines, coreMdPass,
|
|
|
209
253
|
for (const v of leafViolations) {
|
|
210
254
|
issues.push(`.claude/standards/${v.file} has ${v.lines} lines (limit: 30)`);
|
|
211
255
|
}
|
|
256
|
+
if (unroutedLeaves.length > 0) {
|
|
257
|
+
issues.push(`${unroutedLeaves.length} leaf node(s) have no routing directive in .claude/index.md: ${unroutedLeaves.join(", ")} — run cnt_add_routing to generate routing block`);
|
|
258
|
+
}
|
|
212
259
|
return issues;
|
|
213
260
|
}
|
|
214
261
|
//# sourceMappingURL=cnt-health.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cnt-health.js","sourceRoot":"","sources":["../../src/shared/cnt-health.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cnt-health.js","sourceRoot":"","sources":["../../src/shared/cnt-health.ts"],"names":[],"mappings":"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"}
|
package/dist/shared/config.d.ts
CHANGED
|
@@ -12,4 +12,18 @@ import type { ExperimentConfig } from "./types.js";
|
|
|
12
12
|
* @returns Parsed ExperimentConfig, or undefined if not configured
|
|
13
13
|
*/
|
|
14
14
|
export declare function readExperimentConfig(projectDir: string): ExperimentConfig | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Reads `practitioner_level` from forgecraft.yaml.
|
|
17
|
+
* Returns "experienced" only when explicitly set. Defaults to "novice".
|
|
18
|
+
*
|
|
19
|
+
* @param projectDir - Absolute path to the project root
|
|
20
|
+
* @returns "novice" | "experienced"
|
|
21
|
+
*/
|
|
22
|
+
export declare function readPractitionerLevel(projectDir: string): "novice" | "experienced";
|
|
23
|
+
/**
|
|
24
|
+
* Returns true when forgecraft.yaml has `brownfield: true`.
|
|
25
|
+
*
|
|
26
|
+
* @param projectDir - Absolute path to the project root
|
|
27
|
+
*/
|
|
28
|
+
export declare function readBrownfieldFlag(projectDir: string): boolean;
|
|
15
29
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,GACjB,gBAAgB,GAAG,SAAS,CA6B9B"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,GACjB,gBAAgB,GAAG,SAAS,CA6B9B;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,GACjB,QAAQ,GAAG,aAAa,CAgB1B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAW9D"}
|
package/dist/shared/config.js
CHANGED
|
@@ -42,6 +42,51 @@ export function readExperimentConfig(projectDir) {
|
|
|
42
42
|
group: isValidExperimentGroup(group) ? group : "gs",
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Reads `practitioner_level` from forgecraft.yaml.
|
|
47
|
+
* Returns "experienced" only when explicitly set. Defaults to "novice".
|
|
48
|
+
*
|
|
49
|
+
* @param projectDir - Absolute path to the project root
|
|
50
|
+
* @returns "novice" | "experienced"
|
|
51
|
+
*/
|
|
52
|
+
export function readPractitionerLevel(projectDir) {
|
|
53
|
+
const yamlPath = join(projectDir, "forgecraft.yaml");
|
|
54
|
+
if (!existsSync(yamlPath))
|
|
55
|
+
return "novice";
|
|
56
|
+
let raw;
|
|
57
|
+
try {
|
|
58
|
+
raw = yaml.load(readFileSync(yamlPath, "utf-8"));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return "novice";
|
|
62
|
+
}
|
|
63
|
+
if (!raw || typeof raw !== "object")
|
|
64
|
+
return "novice";
|
|
65
|
+
const config = raw;
|
|
66
|
+
return config["practitioner_level"] === "experienced"
|
|
67
|
+
? "experienced"
|
|
68
|
+
: "novice";
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Returns true when forgecraft.yaml has `brownfield: true`.
|
|
72
|
+
*
|
|
73
|
+
* @param projectDir - Absolute path to the project root
|
|
74
|
+
*/
|
|
75
|
+
export function readBrownfieldFlag(projectDir) {
|
|
76
|
+
const yamlPath = join(projectDir, "forgecraft.yaml");
|
|
77
|
+
if (!existsSync(yamlPath))
|
|
78
|
+
return false;
|
|
79
|
+
let raw;
|
|
80
|
+
try {
|
|
81
|
+
raw = yaml.load(readFileSync(yamlPath, "utf-8"));
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
if (!raw || typeof raw !== "object")
|
|
87
|
+
return false;
|
|
88
|
+
return raw["brownfield"] === true;
|
|
89
|
+
}
|
|
45
90
|
function isValidExperimentType(value) {
|
|
46
91
|
return (value === "greenfield" ||
|
|
47
92
|
value === "brownfield" ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,IAAI,MAAM,SAAS,CAAC;AAG3B;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAClC,UAAkB;IAElB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;IACrD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IAE5C,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEtD,MAAM,MAAM,GAAG,GAA8B,CAAC;IAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IACxC,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEpE,MAAM,GAAG,GAAG,UAAqC,CAAC;IAClD,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IACrB,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAEjE,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;IAE3B,OAAO;QACL,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE;QACb,IAAI,EAAE,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY;QACvD,KAAK,EAAE,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAC5B,KAAc;IAEd,OAAO,CACL,KAAK,KAAK,YAAY;QACtB,KAAK,KAAK,YAAY;QACtB,KAAK,KAAK,UAAU;QACpB,KAAK,KAAK,WAAW,CACtB,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAC7B,KAAc;IAEd,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC;AAC/C,CAAC"}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"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"}
|