godpowers 0.15.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 +37 -0
- package/CHANGELOG.md +639 -0
- package/INSPIRATION.md +52 -0
- package/LICENSE +21 -0
- package/README.md +232 -0
- package/SKILL.md +500 -0
- package/agents/god-archaeologist.md +139 -0
- package/agents/god-architect.md +92 -0
- package/agents/god-auditor.md +150 -0
- package/agents/god-browser-tester.md +144 -0
- package/agents/god-context-writer.md +137 -0
- package/agents/god-coordinator.md +138 -0
- package/agents/god-debt-assessor.md +132 -0
- package/agents/god-debugger.md +77 -0
- package/agents/god-deploy-engineer.md +87 -0
- package/agents/god-deps-auditor.md +111 -0
- package/agents/god-design-reviewer.md +137 -0
- package/agents/god-designer.md +171 -0
- package/agents/god-docs-writer.md +102 -0
- package/agents/god-executor.md +76 -0
- package/agents/god-explorer.md +110 -0
- package/agents/god-harden-auditor.md +163 -0
- package/agents/god-incident-investigator.md +144 -0
- package/agents/god-launch-strategist.md +103 -0
- package/agents/god-migration-strategist.md +126 -0
- package/agents/god-observability-engineer.md +76 -0
- package/agents/god-orchestrator.md +728 -0
- package/agents/god-org-context-loader.md +124 -0
- package/agents/god-planner.md +73 -0
- package/agents/god-pm.md +105 -0
- package/agents/god-quality-reviewer.md +74 -0
- package/agents/god-reconciler.md +230 -0
- package/agents/god-reconstructor.md +124 -0
- package/agents/god-repo-scaffolder.md +60 -0
- package/agents/god-retrospective.md +109 -0
- package/agents/god-roadmap-reconciler.md +123 -0
- package/agents/god-roadmap-updater.md +89 -0
- package/agents/god-roadmapper.md +82 -0
- package/agents/god-spec-reviewer.md +70 -0
- package/agents/god-spike-runner.md +119 -0
- package/agents/god-stack-selector.md +93 -0
- package/agents/god-standards-check.md +132 -0
- package/agents/god-storyteller.md +116 -0
- package/agents/god-updater.md +174 -0
- package/bin/install.js +514 -0
- package/extensions/data-pack/README.md +33 -0
- package/extensions/data-pack/agents/god-dashboard-builder.md +66 -0
- package/extensions/data-pack/agents/god-etl-engineer.md +64 -0
- package/extensions/data-pack/agents/god-ml-feature-engineer.md +66 -0
- package/extensions/data-pack/manifest.yaml +39 -0
- package/extensions/data-pack/package.json +42 -0
- package/extensions/data-pack/skills/god-dashboard.md +28 -0
- package/extensions/data-pack/skills/god-etl.md +28 -0
- package/extensions/data-pack/skills/god-ml-feature.md +28 -0
- package/extensions/data-pack/workflows/dashboard-arc.yaml +13 -0
- package/extensions/data-pack/workflows/etl-arc.yaml +13 -0
- package/extensions/data-pack/workflows/ml-feature-arc.yaml +13 -0
- package/extensions/launch-pack/README.md +36 -0
- package/extensions/launch-pack/agents/god-indie-hackers-strategist.md +128 -0
- package/extensions/launch-pack/agents/god-oss-release-strategist.md +125 -0
- package/extensions/launch-pack/agents/god-product-hunt-strategist.md +118 -0
- package/extensions/launch-pack/agents/god-show-hn-strategist.md +113 -0
- package/extensions/launch-pack/manifest.yaml +45 -0
- package/extensions/launch-pack/package.json +41 -0
- package/extensions/launch-pack/skills/god-indie-hackers.md +39 -0
- package/extensions/launch-pack/skills/god-oss-release.md +43 -0
- package/extensions/launch-pack/skills/god-product-hunt.md +41 -0
- package/extensions/launch-pack/skills/god-show-hn.md +40 -0
- package/extensions/launch-pack/workflows/indie-hackers.yaml +13 -0
- package/extensions/launch-pack/workflows/oss-release.yaml +13 -0
- package/extensions/launch-pack/workflows/product-hunt.yaml +13 -0
- package/extensions/launch-pack/workflows/show-hn.yaml +13 -0
- package/extensions/security-pack/README.md +48 -0
- package/extensions/security-pack/agents/god-hipaa-auditor.md +117 -0
- package/extensions/security-pack/agents/god-pci-auditor.md +100 -0
- package/extensions/security-pack/agents/god-soc2-auditor.md +107 -0
- package/extensions/security-pack/manifest.yaml +39 -0
- package/extensions/security-pack/package.json +42 -0
- package/extensions/security-pack/skills/god-hipaa-audit.md +41 -0
- package/extensions/security-pack/skills/god-pci-audit.md +40 -0
- package/extensions/security-pack/skills/god-soc2-audit.md +42 -0
- package/extensions/security-pack/workflows/hipaa-arc.yaml +15 -0
- package/extensions/security-pack/workflows/pci-arc.yaml +15 -0
- package/extensions/security-pack/workflows/soc2-arc.yaml +15 -0
- package/hooks/pre-tool-use.sh +40 -0
- package/hooks/session-start.sh +74 -0
- package/lib/README.md +28 -0
- package/lib/agent-browser-driver.js +215 -0
- package/lib/agent-cache.js +194 -0
- package/lib/agent-validator.js +275 -0
- package/lib/artifact-diff.js +168 -0
- package/lib/artifact-linter.js +142 -0
- package/lib/awesome-design.js +312 -0
- package/lib/browser-bridge.js +209 -0
- package/lib/budget.js +215 -0
- package/lib/checkpoint.js +390 -0
- package/lib/code-scanner.js +262 -0
- package/lib/context-budget.js +170 -0
- package/lib/context-writer.js +348 -0
- package/lib/cost-tracker.js +325 -0
- package/lib/cross-artifact-impact.js +162 -0
- package/lib/cross-repo-linkage.js +150 -0
- package/lib/design-detector.js +167 -0
- package/lib/design-spec.js +348 -0
- package/lib/drift-detector.js +212 -0
- package/lib/event-reader.js +174 -0
- package/lib/events.js +183 -0
- package/lib/extensions.js +257 -0
- package/lib/have-nots-validator.js +647 -0
- package/lib/impact.js +314 -0
- package/lib/impeccable-bridge.js +139 -0
- package/lib/intent.js +177 -0
- package/lib/linkage.js +232 -0
- package/lib/meta-linter.js +263 -0
- package/lib/multi-repo-detector.js +182 -0
- package/lib/otel-exporter.js +308 -0
- package/lib/recipes.js +186 -0
- package/lib/reverse-sync.js +332 -0
- package/lib/review-required.js +224 -0
- package/lib/router.js +278 -0
- package/lib/runtime-audit.js +455 -0
- package/lib/runtime-test.js +309 -0
- package/lib/skillui-bridge.js +216 -0
- package/lib/state-lock.js +201 -0
- package/lib/state.js +142 -0
- package/lib/story-validator.js +301 -0
- package/lib/suite-state.js +220 -0
- package/lib/workflow-parser.js +109 -0
- package/lib/workflow-runner.js +221 -0
- package/package.json +63 -0
- package/references/HAVE-NOTS.md +573 -0
- package/references/building/BUILD-ANTIPATTERNS.md +102 -0
- package/references/building/BUILD-VERTICAL-SLICES.md +75 -0
- package/references/building/BUILD-WAVES.md +61 -0
- package/references/building/README.md +17 -0
- package/references/design/COLOR.md +122 -0
- package/references/design/DESIGN-ANATOMY.md +121 -0
- package/references/design/DESIGN-ANTIPATTERNS.md +108 -0
- package/references/design/INTERACTION.md +148 -0
- package/references/design/MOTION.md +120 -0
- package/references/design/RESPONSIVE.md +157 -0
- package/references/design/SPATIAL.md +109 -0
- package/references/design/TYPOGRAPHY.md +121 -0
- package/references/design/UX-WRITING.md +135 -0
- package/references/orchestration/MODE-DETECTION.md +74 -0
- package/references/orchestration/README.md +18 -0
- package/references/orchestration/SCALE-DETECTION.md +81 -0
- package/references/planning/ARCH-ANATOMY.md +143 -0
- package/references/planning/ARCH-ANTIPATTERNS.md +52 -0
- package/references/planning/PRD-ANATOMY.md +117 -0
- package/references/planning/PRD-ANTIPATTERNS.md +138 -0
- package/references/planning/README.md +16 -0
- package/references/planning/ROADMAP-ANATOMY.md +43 -0
- package/references/planning/ROADMAP-ANTIPATTERNS.md +94 -0
- package/references/planning/STACK-ANATOMY.md +60 -0
- package/references/planning/STACK-ANTIPATTERNS.md +95 -0
- package/references/shared/GLOSSARY.md +80 -0
- package/references/shared/ORCHESTRATORS.md +76 -0
- package/references/shared/README.md +14 -0
- package/references/shipping/DEPLOY-ANTIPATTERNS.md +64 -0
- package/references/shipping/DEPLOY-PATTERNS.md +110 -0
- package/references/shipping/HARDEN-ANTIPATTERNS.md +66 -0
- package/references/shipping/HARDEN-OWASP-WORKSHEETS.md +89 -0
- package/references/shipping/LAUNCH-ANTIPATTERNS.md +68 -0
- package/references/shipping/OBSERVE-ANTIPATTERNS.md +62 -0
- package/references/shipping/OBSERVE-SLO-EXAMPLES.md +107 -0
- package/references/shipping/README.md +18 -0
- package/routing/god-add-backlog.yaml +24 -0
- package/routing/god-add-tests.yaml +27 -0
- package/routing/god-add-todo.yaml +24 -0
- package/routing/god-agent-audit.yaml +24 -0
- package/routing/god-arch.yaml +46 -0
- package/routing/god-archaeology.yaml +28 -0
- package/routing/god-audit.yaml +32 -0
- package/routing/god-budget.yaml +24 -0
- package/routing/god-build-agent.yaml +24 -0
- package/routing/god-build.yaml +46 -0
- package/routing/god-cache-clear.yaml +24 -0
- package/routing/god-check-todos.yaml +24 -0
- package/routing/god-context-scan.yaml +24 -0
- package/routing/god-context.yaml +44 -0
- package/routing/god-cost.yaml +24 -0
- package/routing/god-debug.yaml +28 -0
- package/routing/god-deploy.yaml +34 -0
- package/routing/god-design-impact.yaml +25 -0
- package/routing/god-design.yaml +67 -0
- package/routing/god-discuss.yaml +27 -0
- package/routing/god-docs.yaml +33 -0
- package/routing/god-doctor.yaml +27 -0
- package/routing/god-explore.yaml +27 -0
- package/routing/god-extension-add.yaml +24 -0
- package/routing/god-extension-info.yaml +24 -0
- package/routing/god-extension-list.yaml +24 -0
- package/routing/god-extension-remove.yaml +24 -0
- package/routing/god-extract-learnings.yaml +24 -0
- package/routing/god-fast.yaml +27 -0
- package/routing/god-feature.yaml +34 -0
- package/routing/god-graph.yaml +24 -0
- package/routing/god-harden.yaml +41 -0
- package/routing/god-help.yaml +27 -0
- package/routing/god-hotfix.yaml +34 -0
- package/routing/god-hygiene.yaml +28 -0
- package/routing/god-init.yaml +37 -0
- package/routing/god-intel.yaml +24 -0
- package/routing/god-launch.yaml +41 -0
- package/routing/god-lifecycle.yaml +27 -0
- package/routing/god-link.yaml +24 -0
- package/routing/god-lint.yaml +24 -0
- package/routing/god-list-assumptions.yaml +27 -0
- package/routing/god-locate.yaml +24 -0
- package/routing/god-logs.yaml +24 -0
- package/routing/god-map-codebase.yaml +24 -0
- package/routing/god-metrics.yaml +24 -0
- package/routing/god-mode.yaml +31 -0
- package/routing/god-next.yaml +27 -0
- package/routing/god-note.yaml +24 -0
- package/routing/god-observe.yaml +34 -0
- package/routing/god-org-context.yaml +28 -0
- package/routing/god-party.yaml +24 -0
- package/routing/god-pause-work.yaml +27 -0
- package/routing/god-plant-seed.yaml +24 -0
- package/routing/god-postmortem.yaml +34 -0
- package/routing/god-pr-branch.yaml +25 -0
- package/routing/god-prd.yaml +49 -0
- package/routing/god-quick.yaml +28 -0
- package/routing/god-reconcile.yaml +48 -0
- package/routing/god-reconstruct.yaml +36 -0
- package/routing/god-redo.yaml +27 -0
- package/routing/god-refactor.yaml +36 -0
- package/routing/god-repair.yaml +27 -0
- package/routing/god-repo.yaml +35 -0
- package/routing/god-restore.yaml +27 -0
- package/routing/god-resume-work.yaml +27 -0
- package/routing/god-review-changes.yaml +25 -0
- package/routing/god-review.yaml +28 -0
- package/routing/god-roadmap-check.yaml +39 -0
- package/routing/god-roadmap-update.yaml +37 -0
- package/routing/god-roadmap.yaml +42 -0
- package/routing/god-rollback.yaml +27 -0
- package/routing/god-scan.yaml +24 -0
- package/routing/god-set-profile.yaml +24 -0
- package/routing/god-settings.yaml +24 -0
- package/routing/god-skip.yaml +27 -0
- package/routing/god-smite.yaml +29 -0
- package/routing/god-spike.yaml +35 -0
- package/routing/god-sprint.yaml +25 -0
- package/routing/god-stack.yaml +41 -0
- package/routing/god-standards.yaml +24 -0
- package/routing/god-status.yaml +27 -0
- package/routing/god-stories.yaml +24 -0
- package/routing/god-story-build.yaml +25 -0
- package/routing/god-story-close.yaml +25 -0
- package/routing/god-story-verify.yaml +25 -0
- package/routing/god-story.yaml +24 -0
- package/routing/god-suite-init.yaml +24 -0
- package/routing/god-suite-patch.yaml +25 -0
- package/routing/god-suite-release.yaml +25 -0
- package/routing/god-suite-status.yaml +25 -0
- package/routing/god-suite-sync.yaml +25 -0
- package/routing/god-sync.yaml +33 -0
- package/routing/god-tech-debt.yaml +32 -0
- package/routing/god-test-extension.yaml +24 -0
- package/routing/god-test-runtime.yaml +25 -0
- package/routing/god-thread.yaml +24 -0
- package/routing/god-trace.yaml +24 -0
- package/routing/god-undo.yaml +27 -0
- package/routing/god-update-deps.yaml +39 -0
- package/routing/god-upgrade.yaml +33 -0
- package/routing/god-version.yaml +24 -0
- package/routing/god-workstream.yaml +24 -0
- package/routing/god.yaml +24 -0
- package/routing/recipes/add-feature-defer-current-milestone.yaml +21 -0
- package/routing/recipes/add-feature-future-conditional.yaml +21 -0
- package/routing/recipes/add-feature-mid-arc-pause.yaml +33 -0
- package/routing/recipes/add-feature-next-milestone.yaml +23 -0
- package/routing/recipes/add-feature-parallel.yaml +29 -0
- package/routing/recipes/add-feature-prd-update.yaml +21 -0
- package/routing/recipes/add-feature-small.yaml +24 -0
- package/routing/recipes/add-feature-tiny.yaml +24 -0
- package/routing/recipes/bluefield-org-aware.yaml +27 -0
- package/routing/recipes/broken-install.yaml +22 -0
- package/routing/recipes/brownfield-onboarding.yaml +32 -0
- package/routing/recipes/bug-no-urgency.yaml +21 -0
- package/routing/recipes/capture-idea.yaml +22 -0
- package/routing/recipes/capture-todo.yaml +21 -0
- package/routing/recipes/clean-pr.yaml +21 -0
- package/routing/recipes/code-cleanup.yaml +23 -0
- package/routing/recipes/docs-drift.yaml +21 -0
- package/routing/recipes/existing-codebase-onboarding.yaml +32 -0
- package/routing/recipes/extract-learnings.yaml +22 -0
- package/routing/recipes/greenfield-fast.yaml +25 -0
- package/routing/recipes/greenfield-manual.yaml +32 -0
- package/routing/recipes/greenfield-with-ideation.yaml +29 -0
- package/routing/recipes/incident-postmortem.yaml +24 -0
- package/routing/recipes/major-framework-upgrade.yaml +23 -0
- package/routing/recipes/monthly-deps.yaml +22 -0
- package/routing/recipes/multi-repo-suite.yaml +56 -0
- package/routing/recipes/parallel-engineers.yaml +26 -0
- package/routing/recipes/pause-handoff.yaml +21 -0
- package/routing/recipes/production-broken.yaml +26 -0
- package/routing/recipes/rerun-tier.yaml +21 -0
- package/routing/recipes/returning-after-break.yaml +31 -0
- package/routing/recipes/state-drift.yaml +21 -0
- package/routing/recipes/undo-last.yaml +21 -0
- package/routing/recipes/weekly-health-check.yaml +24 -0
- package/routing/recipes/whats-next.yaml +22 -0
- package/routing/recipes/where-am-i.yaml +21 -0
- package/schema/events.v1.json +63 -0
- package/schema/extension-manifest.v1.json +84 -0
- package/schema/intent.v1.yaml.json +116 -0
- package/schema/recipe.v1.json +120 -0
- package/schema/routing.v1.json +163 -0
- package/schema/state.v1.json +146 -0
- package/schema/workflow.v1.json +96 -0
- package/skills/god-add-backlog.md +40 -0
- package/skills/god-add-tests.md +53 -0
- package/skills/god-add-todo.md +32 -0
- package/skills/god-agent-audit.md +87 -0
- package/skills/god-arch.md +81 -0
- package/skills/god-archaeology.md +48 -0
- package/skills/god-audit.md +65 -0
- package/skills/god-budget.md +103 -0
- package/skills/god-build-agent.md +91 -0
- package/skills/god-build.md +90 -0
- package/skills/god-cache-clear.md +75 -0
- package/skills/god-check-todos.md +42 -0
- package/skills/god-context-scan.md +125 -0
- package/skills/god-context.md +147 -0
- package/skills/god-cost.md +118 -0
- package/skills/god-debug.md +30 -0
- package/skills/god-deploy.md +76 -0
- package/skills/god-design-impact.md +86 -0
- package/skills/god-design.md +275 -0
- package/skills/god-discuss.md +46 -0
- package/skills/god-docs.md +81 -0
- package/skills/god-doctor.md +94 -0
- package/skills/god-explore.md +50 -0
- package/skills/god-export-otel.md +87 -0
- package/skills/god-extension-add.md +79 -0
- package/skills/god-extension-info.md +75 -0
- package/skills/god-extension-list.md +55 -0
- package/skills/god-extension-remove.md +66 -0
- package/skills/god-extract-learnings.md +60 -0
- package/skills/god-fast.md +47 -0
- package/skills/god-feature.md +114 -0
- package/skills/god-graph.md +56 -0
- package/skills/god-harden.md +106 -0
- package/skills/god-help.md +66 -0
- package/skills/god-hotfix.md +139 -0
- package/skills/god-hygiene.md +104 -0
- package/skills/god-init.md +161 -0
- package/skills/god-intel.md +36 -0
- package/skills/god-launch.md +86 -0
- package/skills/god-lifecycle.md +119 -0
- package/skills/god-link.md +90 -0
- package/skills/god-lint.md +128 -0
- package/skills/god-list-assumptions.md +56 -0
- package/skills/god-locate.md +97 -0
- package/skills/god-logs.md +57 -0
- package/skills/god-map-codebase.md +45 -0
- package/skills/god-metrics.md +51 -0
- package/skills/god-mode.md +159 -0
- package/skills/god-next.md +257 -0
- package/skills/god-note.md +39 -0
- package/skills/god-observe.md +76 -0
- package/skills/god-org-context.md +81 -0
- package/skills/god-party.md +87 -0
- package/skills/god-pause-work.md +64 -0
- package/skills/god-plant-seed.md +59 -0
- package/skills/god-postmortem.md +103 -0
- package/skills/god-pr-branch.md +50 -0
- package/skills/god-prd.md +90 -0
- package/skills/god-quick.md +50 -0
- package/skills/god-reconcile.md +90 -0
- package/skills/god-reconstruct.md +72 -0
- package/skills/god-redo.md +73 -0
- package/skills/god-refactor.md +137 -0
- package/skills/god-repair.md +82 -0
- package/skills/god-repo.md +49 -0
- package/skills/god-restore.md +91 -0
- package/skills/god-resume-work.md +42 -0
- package/skills/god-review-changes.md +93 -0
- package/skills/god-review.md +52 -0
- package/skills/god-roadmap-check.md +66 -0
- package/skills/god-roadmap-update.md +64 -0
- package/skills/god-roadmap.md +77 -0
- package/skills/god-rollback.md +88 -0
- package/skills/god-scan.md +106 -0
- package/skills/god-set-profile.md +58 -0
- package/skills/god-settings.md +44 -0
- package/skills/god-skip.md +78 -0
- package/skills/god-smite.md +86 -0
- package/skills/god-spike.md +120 -0
- package/skills/god-sprint.md +77 -0
- package/skills/god-stack.md +74 -0
- package/skills/god-standards.md +62 -0
- package/skills/god-status.md +99 -0
- package/skills/god-stories.md +60 -0
- package/skills/god-story-build.md +76 -0
- package/skills/god-story-close.md +82 -0
- package/skills/god-story-verify.md +71 -0
- package/skills/god-story.md +55 -0
- package/skills/god-suite-init.md +75 -0
- package/skills/god-suite-patch.md +64 -0
- package/skills/god-suite-release.md +58 -0
- package/skills/god-suite-status.md +63 -0
- package/skills/god-suite-sync.md +49 -0
- package/skills/god-sync.md +102 -0
- package/skills/god-tech-debt.md +56 -0
- package/skills/god-test-extension.md +87 -0
- package/skills/god-test-runtime.md +144 -0
- package/skills/god-thread.md +39 -0
- package/skills/god-trace.md +50 -0
- package/skills/god-undo.md +68 -0
- package/skills/god-update-deps.md +134 -0
- package/skills/god-upgrade.md +139 -0
- package/skills/god-version.md +37 -0
- package/skills/god-workstream.md +61 -0
- package/skills/god.md +207 -0
- package/templates/ARCH.md +99 -0
- package/templates/DEPS-AUDIT.md +66 -0
- package/templates/DESIGN.md +71 -0
- package/templates/DOCS-UPDATE-LOG.md +64 -0
- package/templates/HARDEN-FINDINGS.md +69 -0
- package/templates/MIGRATION.md +86 -0
- package/templates/POSTMORTEM.md +88 -0
- package/templates/PRD.md +80 -0
- package/templates/PROGRESS.md +49 -0
- package/templates/ROADMAP.md +47 -0
- package/templates/SPIKE.md +72 -0
- package/templates/STACK-DECISION.md +61 -0
- package/workflows/audit-only.yaml +22 -0
- package/workflows/bluefield-arc.yaml +87 -0
- package/workflows/brownfield-arc.yaml +44 -0
- package/workflows/deps-audit.yaml +56 -0
- package/workflows/docs-arc.yaml +22 -0
- package/workflows/feature-arc.yaml +59 -0
- package/workflows/full-arc.yaml +84 -0
- package/workflows/hotfix-arc.yaml +59 -0
- package/workflows/hygiene.yaml +43 -0
- package/workflows/migration-arc.yaml +73 -0
- package/workflows/postmortem.yaml +31 -0
- package/workflows/refactor-arc.yaml +59 -0
- package/workflows/spike.yaml +23 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reverse Sync
|
|
3
|
+
*
|
|
4
|
+
* Scans the codebase, updates linkage, detects drift, and appends
|
|
5
|
+
* "Implementation:" / "Source:" / "Resolved in:" footers to artifacts
|
|
6
|
+
* inside a fenced section that does NOT touch human-written content.
|
|
7
|
+
*
|
|
8
|
+
* Per plan question 9: never overwrites human prose. Only appends inside
|
|
9
|
+
* <!-- godpowers:linkage:begin --> ... <!-- godpowers:linkage:end -->
|
|
10
|
+
* sections per artifact, same pattern as AGENTS.md fence.
|
|
11
|
+
*
|
|
12
|
+
* Public API:
|
|
13
|
+
* run(projectRoot, opts) -> { scanResult, drift, footers, reviews }
|
|
14
|
+
* appendFooters(projectRoot) -> [...]
|
|
15
|
+
* buildPrdFooter(linkage) -> string
|
|
16
|
+
* buildArchFooter(linkage) -> string
|
|
17
|
+
* ...etc
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
|
|
23
|
+
const linkage = require('./linkage');
|
|
24
|
+
const scanner = require('./code-scanner');
|
|
25
|
+
const drift = require('./drift-detector');
|
|
26
|
+
const reviewRequired = require('./review-required');
|
|
27
|
+
const impeccable = require('./impeccable-bridge');
|
|
28
|
+
|
|
29
|
+
const FENCE_BEGIN = '<!-- godpowers:linkage:begin -->';
|
|
30
|
+
const FENCE_END = '<!-- godpowers:linkage:end -->';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Read a file, find existing fenced section. Return { exists, before, fenced, after }.
|
|
34
|
+
*/
|
|
35
|
+
function readFenced(filePath) {
|
|
36
|
+
if (!fs.existsSync(filePath)) {
|
|
37
|
+
return { exists: false, before: '', fenced: '', after: '' };
|
|
38
|
+
}
|
|
39
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
40
|
+
const beginIdx = content.indexOf(FENCE_BEGIN);
|
|
41
|
+
const endIdx = content.indexOf(FENCE_END);
|
|
42
|
+
if (beginIdx === -1 || endIdx === -1 || endIdx < beginIdx) {
|
|
43
|
+
return { exists: true, before: content, fenced: '', after: '' };
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
exists: true,
|
|
47
|
+
before: content.slice(0, beginIdx),
|
|
48
|
+
fenced: content.slice(beginIdx + FENCE_BEGIN.length, endIdx),
|
|
49
|
+
after: content.slice(endIdx + FENCE_END.length)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Write fenced section into a file. Idempotent.
|
|
55
|
+
*/
|
|
56
|
+
function writeFenced(filePath, sectionContent) {
|
|
57
|
+
if (!fs.existsSync(filePath)) return { written: false, reason: 'file-missing' };
|
|
58
|
+
const parsed = readFenced(filePath);
|
|
59
|
+
const fencedBlock = `${FENCE_BEGIN}\n${sectionContent}\n${FENCE_END}`;
|
|
60
|
+
let next;
|
|
61
|
+
if (parsed.fenced === '') {
|
|
62
|
+
// No fence yet. Append at the end.
|
|
63
|
+
const sep = parsed.before.endsWith('\n\n') ? '' : (parsed.before.endsWith('\n') ? '\n' : '\n\n');
|
|
64
|
+
next = `${parsed.before}${sep}${fencedBlock}\n`;
|
|
65
|
+
} else {
|
|
66
|
+
next = `${parsed.before}${fencedBlock}${parsed.after}`;
|
|
67
|
+
}
|
|
68
|
+
fs.writeFileSync(filePath, next);
|
|
69
|
+
return { written: true, hadFenceBefore: parsed.fenced !== '' };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// Per-artifact footer builders
|
|
74
|
+
// ============================================================================
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Build PRD footer: "Implementation:" links per requirement.
|
|
78
|
+
*/
|
|
79
|
+
function buildPrdFooter(projectRoot) {
|
|
80
|
+
const fwd = linkage.readForward(projectRoot);
|
|
81
|
+
const lines = [];
|
|
82
|
+
lines.push('## Implementation Linkage');
|
|
83
|
+
lines.push('');
|
|
84
|
+
lines.push('> Auto-generated by /god-sync. Do not edit; edit your code annotations and re-sync.');
|
|
85
|
+
lines.push('');
|
|
86
|
+
// Group by P-MUST / P-SHOULD / P-COULD
|
|
87
|
+
const groups = { 'P-MUST': [], 'P-SHOULD': [], 'P-COULD': [] };
|
|
88
|
+
for (const [id, files] of Object.entries(fwd)) {
|
|
89
|
+
if (linkage.classifyId(id) !== 'prd') continue;
|
|
90
|
+
const tier = id.split('-').slice(0, 2).join('-'); // P-MUST, P-SHOULD, P-COULD
|
|
91
|
+
if (groups[tier]) groups[tier].push({ id, files });
|
|
92
|
+
}
|
|
93
|
+
for (const tier of ['P-MUST', 'P-SHOULD', 'P-COULD']) {
|
|
94
|
+
if (groups[tier].length === 0) continue;
|
|
95
|
+
lines.push(`### ${tier} requirements`);
|
|
96
|
+
lines.push('');
|
|
97
|
+
for (const { id, files } of groups[tier].sort((a, b) => a.id.localeCompare(b.id))) {
|
|
98
|
+
lines.push(`- **${id}** -> ${files.map(f => `\`${f}\``).join(', ')}`);
|
|
99
|
+
}
|
|
100
|
+
lines.push('');
|
|
101
|
+
}
|
|
102
|
+
return lines.join('\n');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Build ARCH footer: Source: per container; Pattern: per ADR.
|
|
107
|
+
*/
|
|
108
|
+
function buildArchFooter(projectRoot) {
|
|
109
|
+
const fwd = linkage.readForward(projectRoot);
|
|
110
|
+
const lines = [];
|
|
111
|
+
lines.push('## Implementation Linkage');
|
|
112
|
+
lines.push('');
|
|
113
|
+
lines.push('> Auto-generated by /god-sync. Do not edit.');
|
|
114
|
+
lines.push('');
|
|
115
|
+
|
|
116
|
+
const containers = [];
|
|
117
|
+
const adrs = [];
|
|
118
|
+
for (const [id, files] of Object.entries(fwd)) {
|
|
119
|
+
const kind = linkage.classifyId(id);
|
|
120
|
+
if (kind === 'container') containers.push({ id, files });
|
|
121
|
+
else if (kind === 'adr') adrs.push({ id, files });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (containers.length > 0) {
|
|
125
|
+
lines.push('### Containers');
|
|
126
|
+
lines.push('');
|
|
127
|
+
for (const { id, files } of containers.sort((a, b) => a.id.localeCompare(b.id))) {
|
|
128
|
+
const dirs = [...new Set(files.map(f => path.dirname(f)))].sort();
|
|
129
|
+
lines.push(`- **${id}** (Source: ${dirs.map(d => `\`${d}\``).join(', ')})`);
|
|
130
|
+
}
|
|
131
|
+
lines.push('');
|
|
132
|
+
}
|
|
133
|
+
if (adrs.length > 0) {
|
|
134
|
+
lines.push('### ADRs');
|
|
135
|
+
lines.push('');
|
|
136
|
+
for (const { id, files } of adrs.sort((a, b) => a.id.localeCompare(b.id))) {
|
|
137
|
+
lines.push(`- **${id}** Pattern: ${files.map(f => `\`${f}\``).join(', ')}`);
|
|
138
|
+
}
|
|
139
|
+
lines.push('');
|
|
140
|
+
}
|
|
141
|
+
return lines.join('\n');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Build STACK footer: per dep, count of usage files.
|
|
146
|
+
*/
|
|
147
|
+
function buildStackFooter(projectRoot) {
|
|
148
|
+
const fwd = linkage.readForward(projectRoot);
|
|
149
|
+
const lines = [];
|
|
150
|
+
lines.push('## Usage Linkage');
|
|
151
|
+
lines.push('');
|
|
152
|
+
lines.push('> Auto-generated by /god-sync. Counts of code references.');
|
|
153
|
+
lines.push('');
|
|
154
|
+
const stackEntries = [];
|
|
155
|
+
for (const [id, files] of Object.entries(fwd)) {
|
|
156
|
+
if (linkage.classifyId(id) !== 'stack') continue;
|
|
157
|
+
stackEntries.push({ id, count: files.length });
|
|
158
|
+
}
|
|
159
|
+
if (stackEntries.length > 0) {
|
|
160
|
+
for (const { id, count } of stackEntries.sort((a, b) => a.id.localeCompare(b.id))) {
|
|
161
|
+
lines.push(`- **${id}**: used in ${count} file(s)`);
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
lines.push('(no stack-decision linkage recorded yet; add `// Implements: S-{slug}` annotations)');
|
|
165
|
+
}
|
|
166
|
+
lines.push('');
|
|
167
|
+
return lines.join('\n');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Build DESIGN footer: per token, usage count; per component, implementing files.
|
|
172
|
+
*/
|
|
173
|
+
function buildDesignFooter(projectRoot) {
|
|
174
|
+
const fwd = linkage.readForward(projectRoot);
|
|
175
|
+
const lines = [];
|
|
176
|
+
lines.push('## Implementation Linkage');
|
|
177
|
+
lines.push('');
|
|
178
|
+
lines.push('> Auto-generated by /god-sync. Token usage and component implementations.');
|
|
179
|
+
lines.push('');
|
|
180
|
+
const tokens = [];
|
|
181
|
+
const components = [];
|
|
182
|
+
for (const [id, files] of Object.entries(fwd)) {
|
|
183
|
+
const kind = linkage.classifyId(id);
|
|
184
|
+
if (kind === 'token') tokens.push({ id, files });
|
|
185
|
+
else if (kind === 'design') components.push({ id, files });
|
|
186
|
+
}
|
|
187
|
+
if (tokens.length > 0) {
|
|
188
|
+
lines.push('### Token usage');
|
|
189
|
+
lines.push('');
|
|
190
|
+
for (const { id, files } of tokens.sort((a, b) => a.id.localeCompare(b.id))) {
|
|
191
|
+
lines.push(`- **${id}**: used in ${files.length} file(s)`);
|
|
192
|
+
}
|
|
193
|
+
lines.push('');
|
|
194
|
+
}
|
|
195
|
+
if (components.length > 0) {
|
|
196
|
+
lines.push('### Components');
|
|
197
|
+
lines.push('');
|
|
198
|
+
for (const { id, files } of components.sort((a, b) => a.id.localeCompare(b.id))) {
|
|
199
|
+
lines.push(`- **${id}** Implements: ${files.map(f => `\`${f}\``).join(', ')}`);
|
|
200
|
+
}
|
|
201
|
+
lines.push('');
|
|
202
|
+
}
|
|
203
|
+
return lines.join('\n');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Build ROADMAP footer: milestones with "Closed by:" if linked code commits known.
|
|
208
|
+
* V1: just lists linked files.
|
|
209
|
+
*/
|
|
210
|
+
function buildRoadmapFooter(projectRoot) {
|
|
211
|
+
const fwd = linkage.readForward(projectRoot);
|
|
212
|
+
const lines = [];
|
|
213
|
+
lines.push('## Implementation Linkage');
|
|
214
|
+
lines.push('');
|
|
215
|
+
lines.push('> Auto-generated by /god-sync. Files implementing each milestone.');
|
|
216
|
+
lines.push('');
|
|
217
|
+
for (const [id, files] of Object.entries(fwd)) {
|
|
218
|
+
if (linkage.classifyId(id) !== 'milestone') continue;
|
|
219
|
+
lines.push(`- **${id}** -> ${files.map(f => `\`${f}\``).join(', ')}`);
|
|
220
|
+
}
|
|
221
|
+
lines.push('');
|
|
222
|
+
return lines.join('\n');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ============================================================================
|
|
226
|
+
// Top-level orchestration
|
|
227
|
+
// ============================================================================
|
|
228
|
+
|
|
229
|
+
const ARTIFACT_TARGETS = [
|
|
230
|
+
{ type: 'prd', path: '.godpowers/prd/PRD.md', build: buildPrdFooter },
|
|
231
|
+
{ type: 'arch', path: '.godpowers/arch/ARCH.md', build: buildArchFooter },
|
|
232
|
+
{ type: 'roadmap', path: '.godpowers/roadmap/ROADMAP.md', build: buildRoadmapFooter },
|
|
233
|
+
{ type: 'stack', path: '.godpowers/stack/DECISION.md', build: buildStackFooter },
|
|
234
|
+
{ type: 'design', path: 'DESIGN.md', build: buildDesignFooter }
|
|
235
|
+
];
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Append fenced footers to all artifacts based on the current linkage map.
|
|
239
|
+
*/
|
|
240
|
+
function appendFooters(projectRoot) {
|
|
241
|
+
const results = [];
|
|
242
|
+
for (const t of ARTIFACT_TARGETS) {
|
|
243
|
+
const full = path.join(projectRoot, t.path);
|
|
244
|
+
if (!fs.existsSync(full)) continue;
|
|
245
|
+
const footer = t.build(projectRoot);
|
|
246
|
+
const r = writeFenced(full, footer);
|
|
247
|
+
results.push({ type: t.type, path: t.path, ...r });
|
|
248
|
+
}
|
|
249
|
+
return results;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Run a full reverse-sync cycle.
|
|
254
|
+
*
|
|
255
|
+
* 1. Scan code for linkage signals
|
|
256
|
+
* 2. Apply scan to linkage map
|
|
257
|
+
* 3. Run drift detection
|
|
258
|
+
* 4. Run impeccable detect on UI files (when installed)
|
|
259
|
+
* 5. Append fenced footers to artifacts
|
|
260
|
+
* 6. Surface drift findings to REVIEW-REQUIRED.md
|
|
261
|
+
*
|
|
262
|
+
* Returns aggregate summary.
|
|
263
|
+
*/
|
|
264
|
+
function run(projectRoot, opts = {}) {
|
|
265
|
+
const scanResult = scanner.scan(projectRoot, opts);
|
|
266
|
+
const applyResult = scanner.applyScan(projectRoot, scanResult);
|
|
267
|
+
|
|
268
|
+
const driftResult = drift.detectAll(projectRoot);
|
|
269
|
+
|
|
270
|
+
let impeccableFindings = [];
|
|
271
|
+
if (opts.runImpeccable !== false) {
|
|
272
|
+
const isInstalled = impeccable.isInstalled(projectRoot);
|
|
273
|
+
if (isInstalled && opts.uiFiles && opts.uiFiles.length > 0) {
|
|
274
|
+
for (const f of opts.uiFiles) {
|
|
275
|
+
const r = impeccable.runDetect(f, { cwd: projectRoot });
|
|
276
|
+
if (r.findings) impeccableFindings.push(...r.findings.map(x => ({ ...x, file: f })));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const footers = appendFooters(projectRoot);
|
|
282
|
+
|
|
283
|
+
// Surface drift + impeccable findings to REVIEW-REQUIRED.md
|
|
284
|
+
const reviewItems = [];
|
|
285
|
+
for (const f of driftResult.findings) {
|
|
286
|
+
reviewItems.push({
|
|
287
|
+
severity: f.severity,
|
|
288
|
+
id: f.artifactId,
|
|
289
|
+
file: f.file,
|
|
290
|
+
message: f.message
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
for (const f of impeccableFindings) {
|
|
294
|
+
reviewItems.push({
|
|
295
|
+
severity: f.severity || 'warning',
|
|
296
|
+
id: f.id || null,
|
|
297
|
+
file: f.file,
|
|
298
|
+
message: f.message || JSON.stringify(f)
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
if (reviewItems.length > 0) {
|
|
302
|
+
reviewRequired.appendBatch(projectRoot, {
|
|
303
|
+
source: 'reverse-sync',
|
|
304
|
+
summary: `${driftResult.summary.errors} drift errors, ${driftResult.summary.warnings} drift warnings, ${impeccableFindings.length} impeccable findings`,
|
|
305
|
+
items: reviewItems
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return {
|
|
310
|
+
scanResult,
|
|
311
|
+
applyResult,
|
|
312
|
+
driftResult,
|
|
313
|
+
impeccableFindings,
|
|
314
|
+
footers,
|
|
315
|
+
reviewItems
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
module.exports = {
|
|
320
|
+
run,
|
|
321
|
+
appendFooters,
|
|
322
|
+
buildPrdFooter,
|
|
323
|
+
buildArchFooter,
|
|
324
|
+
buildRoadmapFooter,
|
|
325
|
+
buildStackFooter,
|
|
326
|
+
buildDesignFooter,
|
|
327
|
+
readFenced,
|
|
328
|
+
writeFenced,
|
|
329
|
+
FENCE_BEGIN,
|
|
330
|
+
FENCE_END,
|
|
331
|
+
ARTIFACT_TARGETS
|
|
332
|
+
};
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REVIEW-REQUIRED.md manager.
|
|
3
|
+
*
|
|
4
|
+
* Append-only registry of pending reviews. Cleared by /god-review-changes.
|
|
5
|
+
* Populated by:
|
|
6
|
+
* - god-updater on /god-sync (after impact analysis from forward propagation)
|
|
7
|
+
* - god-updater on reverse-sync (drift detection findings)
|
|
8
|
+
* - god-design-reviewer with WARN verdicts (warnings flow here; BLOCKs go
|
|
9
|
+
* to .godpowers/design/REJECTED.md instead)
|
|
10
|
+
*
|
|
11
|
+
* File format: append-only markdown with section per review batch.
|
|
12
|
+
*
|
|
13
|
+
* Public API:
|
|
14
|
+
* path(projectRoot) -> string
|
|
15
|
+
* appendBatch(projectRoot, batch) -> void
|
|
16
|
+
* readEntries(projectRoot) -> [{ batchId, timestamp, source, items }]
|
|
17
|
+
* clear(projectRoot) -> void
|
|
18
|
+
* itemCount(projectRoot) -> number
|
|
19
|
+
* formatBatch(batch) -> markdown
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
const path = require('path');
|
|
24
|
+
|
|
25
|
+
function filePath(projectRoot) {
|
|
26
|
+
return path.join(projectRoot, 'REVIEW-REQUIRED.md');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function rejectedPath(projectRoot) {
|
|
30
|
+
return path.join(projectRoot, '.godpowers', 'design', 'REJECTED.md');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Append a review batch to REVIEW-REQUIRED.md.
|
|
35
|
+
*
|
|
36
|
+
* batch = {
|
|
37
|
+
* source: 'design-impact' | 'prd-change' | 'arch-change' | 'reverse-sync-drift' | ...
|
|
38
|
+
* summary: 'one-line description',
|
|
39
|
+
* items: [{ id, file, severity: 'error'|'warning'|'info', message, suggestion? }]
|
|
40
|
+
* }
|
|
41
|
+
*/
|
|
42
|
+
function appendBatch(projectRoot, batch) {
|
|
43
|
+
const file = filePath(projectRoot);
|
|
44
|
+
const ts = new Date().toISOString();
|
|
45
|
+
const id = `${ts.replace(/[:.]/g, '-')}-${batch.source}`;
|
|
46
|
+
|
|
47
|
+
const header = fs.existsSync(file) ? '' : `# Review Required
|
|
48
|
+
|
|
49
|
+
> Pending reviews surfaced by /god-sync, design changes, and drift detection.
|
|
50
|
+
> Each batch documents what changed, why it needs review, and what to do.
|
|
51
|
+
> Cleared by \`/god-review-changes\` when items are resolved.
|
|
52
|
+
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
const body = formatBatch({ ...batch, id, timestamp: ts });
|
|
56
|
+
fs.writeFileSync(file, header + (fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : '') + body + '\n');
|
|
57
|
+
return { id, path: file, items: batch.items.length };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Format a batch as markdown.
|
|
62
|
+
*/
|
|
63
|
+
function formatBatch(batch) {
|
|
64
|
+
const lines = [];
|
|
65
|
+
lines.push(`## Batch: ${batch.id || 'unnamed'}`);
|
|
66
|
+
lines.push('');
|
|
67
|
+
lines.push(`- **Timestamp**: ${batch.timestamp || new Date().toISOString()}`);
|
|
68
|
+
lines.push(`- **Source**: ${batch.source}`);
|
|
69
|
+
lines.push(`- **Summary**: ${batch.summary}`);
|
|
70
|
+
lines.push('');
|
|
71
|
+
if (batch.items && batch.items.length > 0) {
|
|
72
|
+
lines.push('### Items');
|
|
73
|
+
lines.push('');
|
|
74
|
+
for (const item of batch.items) {
|
|
75
|
+
const sev = (item.severity || 'info').toUpperCase();
|
|
76
|
+
const id = item.id ? `[${item.id}]` : '';
|
|
77
|
+
const msg = `[${sev}] ${id} ${item.file ? '`' + item.file + '`' : ''}: ${item.message}`;
|
|
78
|
+
lines.push(`- ${msg.trim()}`);
|
|
79
|
+
if (item.suggestion) {
|
|
80
|
+
lines.push(` - Suggestion: ${item.suggestion}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
lines.push('### Items');
|
|
85
|
+
lines.push('');
|
|
86
|
+
lines.push('(none)');
|
|
87
|
+
}
|
|
88
|
+
lines.push('');
|
|
89
|
+
return lines.join('\n');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Parse REVIEW-REQUIRED.md back into structured batches. Best-effort.
|
|
94
|
+
*/
|
|
95
|
+
function readEntries(projectRoot) {
|
|
96
|
+
const file = filePath(projectRoot);
|
|
97
|
+
if (!fs.existsSync(file)) return [];
|
|
98
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
99
|
+
const batches = [];
|
|
100
|
+
const lines = content.split('\n');
|
|
101
|
+
let current = null;
|
|
102
|
+
for (let i = 0; i < lines.length; i++) {
|
|
103
|
+
const line = lines[i];
|
|
104
|
+
if (line.startsWith('## Batch:')) {
|
|
105
|
+
if (current) batches.push(current);
|
|
106
|
+
current = {
|
|
107
|
+
batchId: line.replace('## Batch:', '').trim(),
|
|
108
|
+
timestamp: '',
|
|
109
|
+
source: '',
|
|
110
|
+
summary: '',
|
|
111
|
+
items: []
|
|
112
|
+
};
|
|
113
|
+
} else if (current) {
|
|
114
|
+
const tsMatch = line.match(/\*\*Timestamp\*\*:\s*(.+)/);
|
|
115
|
+
if (tsMatch) current.timestamp = tsMatch[1].trim();
|
|
116
|
+
const srcMatch = line.match(/\*\*Source\*\*:\s*(.+)/);
|
|
117
|
+
if (srcMatch) current.source = srcMatch[1].trim();
|
|
118
|
+
const sumMatch = line.match(/\*\*Summary\*\*:\s*(.+)/);
|
|
119
|
+
if (sumMatch) current.summary = sumMatch[1].trim();
|
|
120
|
+
if (line.startsWith('- [')) {
|
|
121
|
+
const m = line.match(/^- \[(\w+)\]\s*(?:\[([^\]]+)\])?\s*(?:`([^`]+)`)?\s*:\s*(.+)$/);
|
|
122
|
+
if (m) {
|
|
123
|
+
current.items.push({
|
|
124
|
+
severity: m[1].toLowerCase(),
|
|
125
|
+
id: m[2] || null,
|
|
126
|
+
file: m[3] || null,
|
|
127
|
+
message: m[4].trim()
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (current) batches.push(current);
|
|
134
|
+
return batches;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Clear all review-required entries (after they've been addressed).
|
|
139
|
+
*/
|
|
140
|
+
function clear(projectRoot) {
|
|
141
|
+
const file = filePath(projectRoot);
|
|
142
|
+
if (!fs.existsSync(file)) return { cleared: false, reason: 'missing' };
|
|
143
|
+
fs.unlinkSync(file);
|
|
144
|
+
return { cleared: true };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Count of pending items (across all batches).
|
|
149
|
+
*/
|
|
150
|
+
function itemCount(projectRoot) {
|
|
151
|
+
return readEntries(projectRoot).reduce((sum, b) => sum + b.items.length, 0);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ============================================================================
|
|
155
|
+
// REJECTED.md (design-reviewer BLOCK verdicts)
|
|
156
|
+
// ============================================================================
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Append a rejected design change.
|
|
160
|
+
*
|
|
161
|
+
* rejection = {
|
|
162
|
+
* verdict: 'BLOCK',
|
|
163
|
+
* stage1: 'misaligned' | 'needs-discussion',
|
|
164
|
+
* stage2: 'errors' | 'warnings' | 'passes',
|
|
165
|
+
* diffSummary: 'short summary',
|
|
166
|
+
* findings: [{ severity, code, message }],
|
|
167
|
+
* resolutionRequired: 'what to fix before resubmitting'
|
|
168
|
+
* }
|
|
169
|
+
*/
|
|
170
|
+
function appendRejection(projectRoot, rejection) {
|
|
171
|
+
const file = rejectedPath(projectRoot);
|
|
172
|
+
const dir = path.dirname(file);
|
|
173
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
174
|
+
const ts = new Date().toISOString();
|
|
175
|
+
|
|
176
|
+
const header = fs.existsSync(file) ? '' : `# Design Changes Rejected
|
|
177
|
+
|
|
178
|
+
> Append-only audit trail of DESIGN.md / PRODUCT.md changes that
|
|
179
|
+
> god-design-reviewer blocked. Each entry documents what was attempted,
|
|
180
|
+
> why it was rejected, and what must change before resubmission.
|
|
181
|
+
|
|
182
|
+
`;
|
|
183
|
+
|
|
184
|
+
const lines = [];
|
|
185
|
+
lines.push(`## Rejected: ${ts}`);
|
|
186
|
+
lines.push('');
|
|
187
|
+
lines.push(`### Verdict`);
|
|
188
|
+
lines.push(`${rejection.verdict || 'BLOCK'}`);
|
|
189
|
+
lines.push('');
|
|
190
|
+
lines.push(`### Stages`);
|
|
191
|
+
lines.push(`- Stage 1 (spec): ${rejection.stage1 || 'unknown'}`);
|
|
192
|
+
lines.push(`- Stage 2 (quality): ${rejection.stage2 || 'unknown'}`);
|
|
193
|
+
lines.push('');
|
|
194
|
+
lines.push(`### Diff scope`);
|
|
195
|
+
lines.push(rejection.diffSummary || '(no summary)');
|
|
196
|
+
lines.push('');
|
|
197
|
+
if (rejection.findings && rejection.findings.length > 0) {
|
|
198
|
+
lines.push(`### Findings`);
|
|
199
|
+
for (const f of rejection.findings) {
|
|
200
|
+
lines.push(`- [${(f.severity || 'error').toUpperCase()}] ${f.code || ''} ${f.message}`);
|
|
201
|
+
}
|
|
202
|
+
lines.push('');
|
|
203
|
+
}
|
|
204
|
+
if (rejection.resolutionRequired) {
|
|
205
|
+
lines.push(`### Resolution required`);
|
|
206
|
+
lines.push(rejection.resolutionRequired);
|
|
207
|
+
lines.push('');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const existing = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : '';
|
|
211
|
+
fs.writeFileSync(file, header + existing + lines.join('\n') + '\n');
|
|
212
|
+
return { path: file, timestamp: ts };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
module.exports = {
|
|
216
|
+
path: filePath,
|
|
217
|
+
rejectedPath,
|
|
218
|
+
appendBatch,
|
|
219
|
+
formatBatch,
|
|
220
|
+
readEntries,
|
|
221
|
+
clear,
|
|
222
|
+
itemCount,
|
|
223
|
+
appendRejection
|
|
224
|
+
};
|