@zigrivers/scaffold 3.28.0 → 3.30.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/README.md +5 -1
- package/content/guides/.gitkeep +0 -0
- package/content/guides/AUTHORING.md +143 -0
- package/content/guides/cli/index.html +1502 -0
- package/content/guides/cli/index.md +206 -0
- package/content/guides/concepts/index.html +1617 -0
- package/content/guides/concepts/index.md +347 -0
- package/content/guides/dashboard/index.html +1560 -0
- package/content/guides/dashboard/index.md +264 -0
- package/content/guides/index.html +1188 -0
- package/content/guides/install/.diagrams/diagram-0.svg +1 -0
- package/content/guides/install/.diagrams/manifest.json +3 -0
- package/content/guides/install/index.html +1300 -0
- package/content/guides/install/index.md +186 -0
- package/content/guides/knowledge/.diagrams/diagram-0.svg +1 -0
- package/content/guides/knowledge/.diagrams/manifest.json +3 -0
- package/content/guides/knowledge/index.html +1412 -0
- package/content/guides/knowledge/index.md +209 -0
- package/content/guides/knowledge-freshness/.diagrams/diagram-0.svg +1 -0
- package/content/guides/knowledge-freshness/.diagrams/manifest.json +3 -0
- package/content/guides/knowledge-freshness/index.html +2442 -0
- package/content/guides/knowledge-freshness/index.md +893 -0
- package/content/guides/mmr/.diagrams/diagram-0.svg +1 -0
- package/content/guides/mmr/.diagrams/manifest.json +3 -0
- package/content/guides/mmr/index.html +1746 -0
- package/content/guides/mmr/index.md +426 -0
- package/content/guides/multi-agent/.diagrams/diagram-0.svg +1 -0
- package/content/guides/multi-agent/.diagrams/manifest.json +3 -0
- package/content/guides/multi-agent/index.html +1362 -0
- package/content/guides/multi-agent/index.md +243 -0
- package/content/guides/observability/.diagrams/diagram-0.svg +1 -0
- package/content/guides/observability/.diagrams/diagram-1.svg +1 -0
- package/content/guides/observability/.diagrams/diagram-2.svg +1 -0
- package/content/guides/observability/.diagrams/diagram-3.svg +1 -0
- package/content/guides/observability/.diagrams/manifest.json +6 -0
- package/content/guides/observability/index.html +2904 -0
- package/content/guides/observability/index.md +1097 -0
- package/content/guides/pipeline/.diagrams/diagram-0.svg +1 -0
- package/content/guides/pipeline/.diagrams/diagram-1.svg +1 -0
- package/content/guides/pipeline/.diagrams/manifest.json +4 -0
- package/content/guides/pipeline/index.html +1632 -0
- package/content/guides/pipeline/index.md +387 -0
- package/content/guides/review-workflow/.diagrams/diagram-0.svg +1 -0
- package/content/guides/review-workflow/.diagrams/diagram-1.svg +1 -0
- package/content/guides/review-workflow/.diagrams/manifest.json +4 -0
- package/content/guides/review-workflow/index.html +1437 -0
- package/content/guides/review-workflow/index.md +248 -0
- package/content/knowledge/VERSION +1 -0
- package/content/knowledge/backend/backend-api-design.md +8 -0
- package/content/knowledge/backend/backend-architecture.md +8 -0
- package/content/knowledge/backend/backend-async-patterns.md +7 -0
- package/content/knowledge/backend/backend-auth-patterns.md +9 -0
- package/content/knowledge/backend/backend-conventions.md +6 -0
- package/content/knowledge/backend/backend-data-modeling.md +7 -0
- package/content/knowledge/backend/backend-deployment.md +8 -0
- package/content/knowledge/backend/backend-dev-environment.md +5 -0
- package/content/knowledge/backend/backend-fintech-broker-integration.md +6 -0
- package/content/knowledge/backend/backend-fintech-compliance.md +10 -2
- package/content/knowledge/backend/backend-fintech-data-modeling.md +6 -0
- package/content/knowledge/backend/backend-fintech-ledger.md +6 -0
- package/content/knowledge/backend/backend-fintech-observability.md +6 -0
- package/content/knowledge/backend/backend-fintech-order-lifecycle.md +6 -0
- package/content/knowledge/backend/backend-fintech-risk-management.md +6 -0
- package/content/knowledge/backend/backend-fintech-testing.md +6 -0
- package/content/knowledge/backend/backend-observability.md +7 -0
- package/content/knowledge/backend/backend-project-structure.md +6 -0
- package/content/knowledge/backend/backend-requirements.md +6 -0
- package/content/knowledge/backend/backend-security.md +7 -0
- package/content/knowledge/backend/backend-testing.md +7 -0
- package/content/knowledge/backend/backend-worker-patterns.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-architecture.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-content-scripts.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-conventions.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-cross-browser.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-dev-environment.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-manifest.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-project-structure.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-requirements.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-security.md +7 -0
- package/content/knowledge/browser-extension/browser-extension-service-workers.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-store-submission.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-testing.md +6 -0
- package/content/knowledge/cli/cli-architecture.md +4 -0
- package/content/knowledge/cli/cli-conventions.md +4 -0
- package/content/knowledge/cli/cli-dev-environment.md +5 -0
- package/content/knowledge/cli/cli-distribution-patterns.md +5 -0
- package/content/knowledge/cli/cli-interactivity-patterns.md +4 -0
- package/content/knowledge/cli/cli-output-patterns.md +4 -0
- package/content/knowledge/cli/cli-project-structure.md +4 -0
- package/content/knowledge/cli/cli-requirements.md +4 -0
- package/content/knowledge/cli/cli-shell-integration.md +4 -0
- package/content/knowledge/cli/cli-testing.md +4 -0
- package/content/knowledge/core/adr-craft.md +8 -0
- package/content/knowledge/core/ai-memory-management.md +6 -0
- package/content/knowledge/core/api-design.md +6 -0
- package/content/knowledge/core/automated-review-tooling.md +8 -0
- package/content/knowledge/core/claude-md-patterns.md +8 -0
- package/content/knowledge/core/coding-conventions.md +8 -0
- package/content/knowledge/core/database-design.md +8 -0
- package/content/knowledge/core/design-system-tokens.md +8 -0
- package/content/knowledge/core/dev-environment.md +4 -0
- package/content/knowledge/core/domain-modeling.md +6 -0
- package/content/knowledge/core/eval-craft.md +6 -0
- package/content/knowledge/core/git-workflow-patterns.md +8 -0
- package/content/knowledge/core/multi-model-research-dispatch.md +6 -0
- package/content/knowledge/core/multi-model-review-dispatch.md +6 -0
- package/content/knowledge/core/multi-service-api-contracts.md +5 -0
- package/content/knowledge/core/multi-service-architecture.md +5 -0
- package/content/knowledge/core/multi-service-auth.md +6 -0
- package/content/knowledge/core/multi-service-data-ownership.md +8 -0
- package/content/knowledge/core/multi-service-observability.md +8 -0
- package/content/knowledge/core/multi-service-resilience.md +5 -0
- package/content/knowledge/core/multi-service-task-decomposition.md +8 -0
- package/content/knowledge/core/multi-service-testing.md +5 -0
- package/content/knowledge/core/operations-runbook.md +8 -0
- package/content/knowledge/core/project-structure-patterns.md +4 -0
- package/content/knowledge/core/review-step-template.md +4 -0
- package/content/knowledge/core/security-best-practices.md +6 -0
- package/content/knowledge/core/system-architecture.md +6 -0
- package/content/knowledge/core/task-decomposition.md +5 -0
- package/content/knowledge/core/task-tracking.md +8 -0
- package/content/knowledge/core/tech-stack-selection.md +8 -0
- package/content/knowledge/core/test-skeleton-generation.md +4 -0
- package/content/knowledge/core/testing-strategy.md +8 -0
- package/content/knowledge/core/user-stories.md +8 -0
- package/content/knowledge/core/user-story-innovation.md +4 -0
- package/content/knowledge/core/ux-specification.md +5 -0
- package/content/knowledge/data-pipeline/data-pipeline-architecture.md +5 -0
- package/content/knowledge/data-pipeline/data-pipeline-batch-patterns.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-conventions.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-dev-environment.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-orchestration.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-project-structure.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-quality.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-requirements.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-schema-management.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-security.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-streaming-patterns.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-testing.md +4 -0
- package/content/knowledge/data-science/data-science-architecture.md +5 -0
- package/content/knowledge/data-science/data-science-conventions.md +6 -0
- package/content/knowledge/data-science/data-science-data-versioning.md +6 -0
- package/content/knowledge/data-science/data-science-dev-environment.md +6 -0
- package/content/knowledge/data-science/data-science-experiment-tracking.md +8 -0
- package/content/knowledge/data-science/data-science-model-evaluation.md +5 -0
- package/content/knowledge/data-science/data-science-notebook-discipline.md +5 -0
- package/content/knowledge/data-science/data-science-observability.md +6 -0
- package/content/knowledge/data-science/data-science-project-structure.md +5 -0
- package/content/knowledge/data-science/data-science-reproducibility.md +8 -0
- package/content/knowledge/data-science/data-science-requirements.md +5 -0
- package/content/knowledge/data-science/data-science-security.md +8 -0
- package/content/knowledge/data-science/data-science-testing.md +5 -0
- package/content/knowledge/execution/enhancement-workflow.md +4 -0
- package/content/knowledge/execution/multi-agent-coordination.md +12 -1
- package/content/knowledge/execution/task-claiming-strategy.md +4 -0
- package/content/knowledge/execution/tdd-execution-loop.md +5 -0
- package/content/knowledge/execution/worktree-management.md +5 -0
- package/content/knowledge/finalization/apply-fixes-and-freeze.md +4 -0
- package/content/knowledge/finalization/developer-onboarding.md +4 -0
- package/content/knowledge/finalization/implementation-playbook.md +4 -0
- package/content/knowledge/game/game-accessibility.md +4 -0
- package/content/knowledge/game/game-ai-patterns.md +4 -0
- package/content/knowledge/game/game-asset-pipeline.md +4 -0
- package/content/knowledge/game/game-audio-design.md +4 -0
- package/content/knowledge/game/game-binary-vcs-strategy.md +5 -0
- package/content/knowledge/game/game-design-document.md +4 -0
- package/content/knowledge/game/game-domain-patterns.md +4 -0
- package/content/knowledge/game/game-economy-design.md +4 -0
- package/content/knowledge/game/game-engine-selection.md +4 -0
- package/content/knowledge/game/game-ideation.md +4 -0
- package/content/knowledge/game/game-input-systems.md +4 -0
- package/content/knowledge/game/game-level-content-design.md +4 -0
- package/content/knowledge/game/game-liveops-analytics.md +4 -0
- package/content/knowledge/game/game-localization.md +4 -0
- package/content/knowledge/game/game-milestone-definitions.md +4 -0
- package/content/knowledge/game/game-modding-ugc.md +4 -0
- package/content/knowledge/game/game-narrative-design.md +4 -0
- package/content/knowledge/game/game-networking.md +4 -0
- package/content/knowledge/game/game-performance-budgeting.md +4 -0
- package/content/knowledge/game/game-platform-certification.md +6 -0
- package/content/knowledge/game/game-project-structure.md +4 -0
- package/content/knowledge/game/game-save-systems.md +4 -0
- package/content/knowledge/game/game-testing-strategy.md +4 -0
- package/content/knowledge/game/game-ui-patterns.md +4 -0
- package/content/knowledge/game/game-vr-ar-design.md +6 -0
- package/content/knowledge/library/library-api-design.md +4 -0
- package/content/knowledge/library/library-architecture.md +4 -0
- package/content/knowledge/library/library-bundling.md +4 -0
- package/content/knowledge/library/library-conventions.md +5 -0
- package/content/knowledge/library/library-dev-environment.md +4 -0
- package/content/knowledge/library/library-documentation.md +4 -0
- package/content/knowledge/library/library-project-structure.md +4 -0
- package/content/knowledge/library/library-requirements.md +4 -0
- package/content/knowledge/library/library-security.md +4 -0
- package/content/knowledge/library/library-testing.md +4 -0
- package/content/knowledge/library/library-type-definitions.md +4 -0
- package/content/knowledge/library/library-versioning.md +5 -0
- package/content/knowledge/ml/ml-architecture.md +4 -0
- package/content/knowledge/ml/ml-conventions.md +4 -0
- package/content/knowledge/ml/ml-dev-environment.md +4 -0
- package/content/knowledge/ml/ml-experiment-tracking.md +6 -0
- package/content/knowledge/ml/ml-model-evaluation.md +4 -0
- package/content/knowledge/ml/ml-observability.md +5 -0
- package/content/knowledge/ml/ml-project-structure.md +4 -0
- package/content/knowledge/ml/ml-requirements.md +4 -0
- package/content/knowledge/ml/ml-security.md +5 -0
- package/content/knowledge/ml/ml-serving-patterns.md +4 -0
- package/content/knowledge/ml/ml-testing.md +4 -0
- package/content/knowledge/ml/ml-training-patterns.md +4 -0
- package/content/knowledge/mobile-app/mobile-app-architecture.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-conventions.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-deployment.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-dev-environment.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-distribution.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-observability.md +7 -0
- package/content/knowledge/mobile-app/mobile-app-offline-patterns.md +7 -0
- package/content/knowledge/mobile-app/mobile-app-project-structure.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-push-notifications.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-requirements.md +7 -0
- package/content/knowledge/mobile-app/mobile-app-security.md +8 -0
- package/content/knowledge/mobile-app/mobile-app-testing.md +6 -0
- package/content/knowledge/product/gap-analysis.md +4 -0
- package/content/knowledge/product/ideation-craft.md +4 -0
- package/content/knowledge/product/prd-craft.md +4 -0
- package/content/knowledge/product/prd-innovation.md +4 -0
- package/content/knowledge/product/vision-craft.md +4 -0
- package/content/knowledge/product/vision-innovation.md +4 -0
- package/content/knowledge/research/research-architecture.md +4 -0
- package/content/knowledge/research/research-conventions.md +6 -0
- package/content/knowledge/research/research-dev-environment.md +6 -0
- package/content/knowledge/research/research-experiment-loop.md +4 -0
- package/content/knowledge/research/research-experiment-tracking.md +6 -0
- package/content/knowledge/research/research-ml-architecture-search.md +4 -0
- package/content/knowledge/research/research-ml-evaluation.md +4 -0
- package/content/knowledge/research/research-ml-experiment-tracking.md +6 -0
- package/content/knowledge/research/research-ml-training-patterns.md +4 -0
- package/content/knowledge/research/research-observability.md +5 -0
- package/content/knowledge/research/research-overfitting-prevention.md +5 -0
- package/content/knowledge/research/research-project-structure.md +5 -0
- package/content/knowledge/research/research-quant-backtesting.md +4 -0
- package/content/knowledge/research/research-quant-market-data.md +4 -0
- package/content/knowledge/research/research-quant-metrics.md +4 -0
- package/content/knowledge/research/research-quant-requirements.md +4 -0
- package/content/knowledge/research/research-quant-risk.md +4 -0
- package/content/knowledge/research/research-quant-strategy-patterns.md +4 -0
- package/content/knowledge/research/research-requirements.md +5 -0
- package/content/knowledge/research/research-security.md +5 -0
- package/content/knowledge/research/research-sim-compute-management.md +4 -0
- package/content/knowledge/research/research-sim-engine-patterns.md +4 -0
- package/content/knowledge/research/research-sim-parameter-spaces.md +4 -0
- package/content/knowledge/research/research-sim-validation.md +4 -0
- package/content/knowledge/research/research-testing.md +5 -0
- package/content/knowledge/review/review-adr.md +6 -0
- package/content/knowledge/review/review-api-design.md +6 -0
- package/content/knowledge/review/review-art-bible.md +4 -0
- package/content/knowledge/review/review-database-design.md +5 -0
- package/content/knowledge/review/review-domain-modeling.md +5 -0
- package/content/knowledge/review/review-game-design.md +4 -0
- package/content/knowledge/review/review-game-economy.md +4 -0
- package/content/knowledge/review/review-game-ui.md +5 -0
- package/content/knowledge/review/review-implementation-tasks.md +5 -0
- package/content/knowledge/review/review-methodology.md +4 -0
- package/content/knowledge/review/review-netcode.md +4 -0
- package/content/knowledge/review/review-operations.md +6 -0
- package/content/knowledge/review/review-platform-cert.md +4 -0
- package/content/knowledge/review/review-prd.md +4 -0
- package/content/knowledge/review/review-security.md +7 -0
- package/content/knowledge/review/review-system-architecture.md +6 -0
- package/content/knowledge/review/review-testing-strategy.md +6 -0
- package/content/knowledge/review/review-user-stories.md +5 -0
- package/content/knowledge/review/review-ux-specification.md +6 -0
- package/content/knowledge/review/review-vision.md +4 -0
- package/content/knowledge/tools/post-implementation-review-methodology.md +4 -0
- package/content/knowledge/tools/release-management.md +5 -0
- package/content/knowledge/tools/session-analysis.md +4 -0
- package/content/knowledge/tools/version-strategy.md +4 -0
- package/content/knowledge/validation/critical-path-analysis.md +4 -0
- package/content/knowledge/validation/cross-phase-consistency.md +4 -0
- package/content/knowledge/validation/decision-completeness.md +5 -0
- package/content/knowledge/validation/dependency-validation.md +4 -0
- package/content/knowledge/validation/implementability-review.md +4 -0
- package/content/knowledge/validation/scope-management.md +4 -0
- package/content/knowledge/validation/traceability.md +4 -0
- package/content/knowledge/web-app/web-app-api-patterns.md +6 -0
- package/content/knowledge/web-app/web-app-architecture.md +6 -0
- package/content/knowledge/web-app/web-app-auth-patterns.md +9 -0
- package/content/knowledge/web-app/web-app-conventions.md +5 -0
- package/content/knowledge/web-app/web-app-data-patterns.md +6 -0
- package/content/knowledge/web-app/web-app-deployment-workflow.md +6 -0
- package/content/knowledge/web-app/web-app-deployment.md +6 -0
- package/content/knowledge/web-app/web-app-design-system.md +6 -0
- package/content/knowledge/web-app/web-app-dev-environment.md +6 -0
- package/content/knowledge/web-app/web-app-observability.md +6 -0
- package/content/knowledge/web-app/web-app-project-structure.md +5 -0
- package/content/knowledge/web-app/web-app-rendering-strategies.md +6 -0
- package/content/knowledge/web-app/web-app-requirements.md +6 -0
- package/content/knowledge/web-app/web-app-security.md +8 -0
- package/content/knowledge/web-app/web-app-session-patterns.md +7 -0
- package/content/knowledge/web-app/web-app-testing.md +6 -0
- package/content/knowledge/web-app/web-app-ux-patterns.md +6 -0
- package/content/knowledge/web3/web3-access-control.md +8 -0
- package/content/knowledge/web3/web3-architecture.md +7 -0
- package/content/knowledge/web3/web3-audit-workflow.md +7 -0
- package/content/knowledge/web3/web3-common-vulnerabilities.md +8 -0
- package/content/knowledge/web3/web3-conventions.md +6 -0
- package/content/knowledge/web3/web3-deployment-and-verification.md +7 -0
- package/content/knowledge/web3/web3-dev-environment.md +6 -0
- package/content/knowledge/web3/web3-gas-optimization.md +7 -0
- package/content/knowledge/web3/web3-oracles-and-external-data.md +7 -0
- package/content/knowledge/web3/web3-project-structure.md +6 -0
- package/content/knowledge/web3/web3-requirements.md +6 -0
- package/content/knowledge/web3/web3-security.md +8 -0
- package/content/knowledge/web3/web3-testing.md +6 -0
- package/content/knowledge/web3/web3-upgradeability.md +7 -0
- package/content/tools/knowledge-audit-entry.md +79 -0
- package/content/tools/review-code.md +41 -14
- package/content/tools/review-pr.md +32 -14
- package/dist/cli/commands/dashboard.d.ts +1 -1
- package/dist/cli/commands/dashboard.d.ts.map +1 -1
- package/dist/cli/commands/dashboard.js +10 -10
- package/dist/cli/commands/dashboard.js.map +1 -1
- package/dist/cli/commands/dashboard.test.js +1 -1
- package/dist/cli/commands/dashboard.test.js.map +1 -1
- package/dist/cli/commands/guides.d.ts +24 -0
- package/dist/cli/commands/guides.d.ts.map +1 -0
- package/dist/cli/commands/guides.js +103 -0
- package/dist/cli/commands/guides.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.d.ts +9 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.js +112 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.d.ts +8 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.js +96 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.d.ts +7 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.js +42 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.d.ts +9 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.js +63 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.d.ts +8 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.js +34 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.d.ts +7 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.js +51 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-link-check.d.ts +7 -0
- package/dist/cli/commands/knowledge-freshness-link-check.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-link-check.js +57 -0
- package/dist/cli/commands/knowledge-freshness-link-check.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.d.ts +8 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.js +58 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness.d.ts +4 -0
- package/dist/cli/commands/knowledge-freshness.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness.js +25 -0
- package/dist/cli/commands/knowledge-freshness.js.map +1 -0
- package/dist/cli/commands/observe.d.ts +4 -0
- package/dist/cli/commands/observe.d.ts.map +1 -1
- package/dist/cli/commands/observe.js +13 -0
- package/dist/cli/commands/observe.js.map +1 -1
- package/dist/cli/commands/observe.test.js +46 -0
- package/dist/cli/commands/observe.test.js.map +1 -1
- package/dist/cli/commands/validate-knowledge.d.ts +4 -0
- package/dist/cli/commands/validate-knowledge.d.ts.map +1 -0
- package/dist/cli/commands/validate-knowledge.js +32 -0
- package/dist/cli/commands/validate-knowledge.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +6 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/adapters/claude-code.d.ts.map +1 -1
- package/dist/core/adapters/claude-code.js +6 -3
- package/dist/core/adapters/claude-code.js.map +1 -1
- package/dist/core/adapters/claude-code.test.js +45 -1
- package/dist/core/adapters/claude-code.test.js.map +1 -1
- package/dist/core/assembly/engine.d.ts.map +1 -1
- package/dist/core/assembly/engine.js +7 -3
- package/dist/core/assembly/engine.js.map +1 -1
- package/dist/core/assembly/engine.test.js +45 -1
- package/dist/core/assembly/engine.test.js.map +1 -1
- package/dist/core/assembly/gap-signal-tail.d.ts +18 -0
- package/dist/core/assembly/gap-signal-tail.d.ts.map +1 -0
- package/dist/core/assembly/gap-signal-tail.js +43 -0
- package/dist/core/assembly/gap-signal-tail.js.map +1 -0
- package/dist/core/assembly/gap-signal-tail.test.d.ts +2 -0
- package/dist/core/assembly/gap-signal-tail.test.d.ts.map +1 -0
- package/dist/core/assembly/gap-signal-tail.test.js +49 -0
- package/dist/core/assembly/gap-signal-tail.test.js.map +1 -0
- package/dist/core/assembly/knowledge-loader.d.ts +11 -0
- package/dist/core/assembly/knowledge-loader.d.ts.map +1 -1
- package/dist/core/assembly/knowledge-loader.js +54 -1
- package/dist/core/assembly/knowledge-loader.js.map +1 -1
- package/dist/core/assembly/knowledge-loader.test.js +73 -0
- package/dist/core/assembly/knowledge-loader.test.js.map +1 -1
- package/dist/guides/build.d.ts +12 -0
- package/dist/guides/build.d.ts.map +1 -0
- package/dist/guides/build.js +55 -0
- package/dist/guides/build.js.map +1 -0
- package/dist/guides/build.test.d.ts +2 -0
- package/dist/guides/build.test.d.ts.map +1 -0
- package/dist/guides/build.test.js +82 -0
- package/dist/guides/build.test.js.map +1 -0
- package/dist/guides/chrome.d.ts +24 -0
- package/dist/guides/chrome.d.ts.map +1 -0
- package/dist/guides/chrome.js +118 -0
- package/dist/guides/chrome.js.map +1 -0
- package/dist/guides/cli-guides.test.d.ts +2 -0
- package/dist/guides/cli-guides.test.d.ts.map +1 -0
- package/dist/guides/cli-guides.test.js +41 -0
- package/dist/guides/cli-guides.test.js.map +1 -0
- package/dist/guides/dashboard-theme.css +1073 -0
- package/dist/guides/directives-callout.test.d.ts +2 -0
- package/dist/guides/directives-callout.test.d.ts.map +1 -0
- package/dist/guides/directives-callout.test.js +22 -0
- package/dist/guides/directives-callout.test.js.map +1 -0
- package/dist/guides/directives-chart.test.d.ts +2 -0
- package/dist/guides/directives-chart.test.d.ts.map +1 -0
- package/dist/guides/directives-chart.test.js +25 -0
- package/dist/guides/directives-chart.test.js.map +1 -0
- package/dist/guides/directives-cite.test.d.ts +2 -0
- package/dist/guides/directives-cite.test.d.ts.map +1 -0
- package/dist/guides/directives-cite.test.js +26 -0
- package/dist/guides/directives-cite.test.js.map +1 -0
- package/dist/guides/directives-filter-table.test.d.ts +2 -0
- package/dist/guides/directives-filter-table.test.d.ts.map +1 -0
- package/dist/guides/directives-filter-table.test.js +22 -0
- package/dist/guides/directives-filter-table.test.js.map +1 -0
- package/dist/guides/directives-sev.test.d.ts +2 -0
- package/dist/guides/directives-sev.test.d.ts.map +1 -0
- package/dist/guides/directives-sev.test.js +15 -0
- package/dist/guides/directives-sev.test.js.map +1 -0
- package/dist/guides/directives-tabs.test.d.ts +2 -0
- package/dist/guides/directives-tabs.test.d.ts.map +1 -0
- package/dist/guides/directives-tabs.test.js +52 -0
- package/dist/guides/directives-tabs.test.js.map +1 -0
- package/dist/guides/directives.d.ts +8 -0
- package/dist/guides/directives.d.ts.map +1 -0
- package/dist/guides/directives.js +182 -0
- package/dist/guides/directives.js.map +1 -0
- package/dist/guides/fs-guides.test.d.ts +2 -0
- package/dist/guides/fs-guides.test.d.ts.map +1 -0
- package/dist/guides/fs-guides.test.js +14 -0
- package/dist/guides/fs-guides.test.js.map +1 -0
- package/dist/guides/index-page.d.ts +3 -0
- package/dist/guides/index-page.d.ts.map +1 -0
- package/dist/guides/index-page.js +14 -0
- package/dist/guides/index-page.js.map +1 -0
- package/dist/guides/links.d.ts +14 -0
- package/dist/guides/links.d.ts.map +1 -0
- package/dist/guides/links.js +56 -0
- package/dist/guides/links.js.map +1 -0
- package/dist/guides/links.test.d.ts +2 -0
- package/dist/guides/links.test.d.ts.map +1 -0
- package/dist/guides/links.test.js +72 -0
- package/dist/guides/links.test.js.map +1 -0
- package/dist/guides/lint.d.ts +6 -0
- package/dist/guides/lint.d.ts.map +1 -0
- package/dist/guides/lint.js +27 -0
- package/dist/guides/lint.js.map +1 -0
- package/dist/guides/lint.test.d.ts +2 -0
- package/dist/guides/lint.test.d.ts.map +1 -0
- package/dist/guides/lint.test.js +24 -0
- package/dist/guides/lint.test.js.map +1 -0
- package/dist/guides/loader.d.ts +4 -0
- package/dist/guides/loader.d.ts.map +1 -0
- package/dist/guides/loader.js +63 -0
- package/dist/guides/loader.js.map +1 -0
- package/dist/guides/loader.test.d.ts +2 -0
- package/dist/guides/loader.test.d.ts.map +1 -0
- package/dist/guides/loader.test.js +85 -0
- package/dist/guides/loader.test.js.map +1 -0
- package/dist/guides/mermaid-sanitize.test.d.ts +2 -0
- package/dist/guides/mermaid-sanitize.test.d.ts.map +1 -0
- package/dist/guides/mermaid-sanitize.test.js +57 -0
- package/dist/guides/mermaid-sanitize.test.js.map +1 -0
- package/dist/guides/mermaid.d.ts +18 -0
- package/dist/guides/mermaid.d.ts.map +1 -0
- package/dist/guides/mermaid.js +137 -0
- package/dist/guides/mermaid.js.map +1 -0
- package/dist/guides/mermaid.test.d.ts +2 -0
- package/dist/guides/mermaid.test.d.ts.map +1 -0
- package/dist/guides/mermaid.test.js +105 -0
- package/dist/guides/mermaid.test.js.map +1 -0
- package/dist/guides/render.d.ts +13 -0
- package/dist/guides/render.d.ts.map +1 -0
- package/dist/guides/render.js +58 -0
- package/dist/guides/render.js.map +1 -0
- package/dist/guides/render.test.d.ts +2 -0
- package/dist/guides/render.test.d.ts.map +1 -0
- package/dist/guides/render.test.js +46 -0
- package/dist/guides/render.test.js.map +1 -0
- package/dist/guides/sanitize.d.ts +3 -0
- package/dist/guides/sanitize.d.ts.map +1 -0
- package/dist/guides/sanitize.js +77 -0
- package/dist/guides/sanitize.js.map +1 -0
- package/dist/guides/sanitize.test.d.ts +2 -0
- package/dist/guides/sanitize.test.d.ts.map +1 -0
- package/dist/guides/sanitize.test.js +45 -0
- package/dist/guides/sanitize.test.js.map +1 -0
- package/dist/guides/template.d.ts +11 -0
- package/dist/guides/template.d.ts.map +1 -0
- package/dist/guides/template.js +38 -0
- package/dist/guides/template.js.map +1 -0
- package/dist/guides/template.test.d.ts +2 -0
- package/dist/guides/template.test.d.ts.map +1 -0
- package/dist/guides/template.test.js +41 -0
- package/dist/guides/template.test.js.map +1 -0
- package/dist/guides/types.d.ts +20 -0
- package/dist/guides/types.d.ts.map +1 -0
- package/dist/guides/types.js +2 -0
- package/dist/guides/types.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.d.ts +64 -0
- package/dist/knowledge-freshness/audit-apply-pr.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.js +309 -0
- package/dist/knowledge-freshness/audit-apply-pr.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.js +211 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply.d.ts +16 -0
- package/dist/knowledge-freshness/audit-apply.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply.js +193 -0
- package/dist/knowledge-freshness/audit-apply.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-apply.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply.test.js +482 -0
- package/dist/knowledge-freshness/audit-apply.test.js.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.d.ts +12 -0
- package/dist/knowledge-freshness/audit-prefilter.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.js +74 -0
- package/dist/knowledge-freshness/audit-prefilter.js.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-prefilter.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.test.js +78 -0
- package/dist/knowledge-freshness/audit-prefilter.test.js.map +1 -0
- package/dist/knowledge-freshness/audit-runner.d.ts +135 -0
- package/dist/knowledge-freshness/audit-runner.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-runner.js +168 -0
- package/dist/knowledge-freshness/audit-runner.js.map +1 -0
- package/dist/knowledge-freshness/audit-runner.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-runner.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-runner.test.js +130 -0
- package/dist/knowledge-freshness/audit-runner.test.js.map +1 -0
- package/dist/knowledge-freshness/bump-version.d.ts +24 -0
- package/dist/knowledge-freshness/bump-version.d.ts.map +1 -0
- package/dist/knowledge-freshness/bump-version.js +69 -0
- package/dist/knowledge-freshness/bump-version.js.map +1 -0
- package/dist/knowledge-freshness/bump-version.test.d.ts +2 -0
- package/dist/knowledge-freshness/bump-version.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/bump-version.test.js +82 -0
- package/dist/knowledge-freshness/bump-version.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.d.ts +86 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.js +210 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.js.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.js +115 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/changed-files.d.ts +53 -0
- package/dist/knowledge-freshness/gates/changed-files.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/changed-files.js +128 -0
- package/dist/knowledge-freshness/gates/changed-files.js.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.d.ts +23 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.js +27 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.js.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.js +23 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.d.ts +55 -0
- package/dist/knowledge-freshness/gates/link-check.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.js +161 -0
- package/dist/knowledge-freshness/gates/link-check.js.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/link-check.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.test.js +76 -0
- package/dist/knowledge-freshness/gates/link-check.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.d.ts +40 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.js +143 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.js.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.js +68 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.d.ts +25 -0
- package/dist/knowledge-freshness/gates/parse-entry.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.js +41 -0
- package/dist/knowledge-freshness/gates/parse-entry.js.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.js +34 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.js.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.d.ts +33 -0
- package/dist/knowledge-freshness/providers/anthropic.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.js +36 -0
- package/dist/knowledge-freshness/providers/anthropic.js.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.test.d.ts +2 -0
- package/dist/knowledge-freshness/providers/anthropic.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.test.js +32 -0
- package/dist/knowledge-freshness/providers/anthropic.test.js.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.d.ts +33 -0
- package/dist/knowledge-freshness/providers/deepseek.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.js +157 -0
- package/dist/knowledge-freshness/providers/deepseek.js.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.test.d.ts +2 -0
- package/dist/knowledge-freshness/providers/deepseek.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.test.js +142 -0
- package/dist/knowledge-freshness/providers/deepseek.test.js.map +1 -0
- package/dist/knowledge-freshness/providers/index.d.ts +41 -0
- package/dist/knowledge-freshness/providers/index.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/index.js +108 -0
- package/dist/knowledge-freshness/providers/index.js.map +1 -0
- package/dist/knowledge-freshness/providers/index.test.d.ts +2 -0
- package/dist/knowledge-freshness/providers/index.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/index.test.js +97 -0
- package/dist/knowledge-freshness/providers/index.test.js.map +1 -0
- package/dist/knowledge-freshness/source-hash.d.ts +39 -0
- package/dist/knowledge-freshness/source-hash.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-hash.js +180 -0
- package/dist/knowledge-freshness/source-hash.js.map +1 -0
- package/dist/knowledge-freshness/source-hash.test.d.ts +2 -0
- package/dist/knowledge-freshness/source-hash.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-hash.test.js +63 -0
- package/dist/knowledge-freshness/source-hash.test.js.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.d.ts +57 -0
- package/dist/knowledge-freshness/source-url-validator.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.js +304 -0
- package/dist/knowledge-freshness/source-url-validator.js.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.test.d.ts +2 -0
- package/dist/knowledge-freshness/source-url-validator.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.test.js +167 -0
- package/dist/knowledge-freshness/source-url-validator.test.js.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.d.ts +3 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.js +165 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.js.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.d.ts +2 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.js +421 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.js.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.d.ts +16 -0
- package/dist/observability/checks/lens-i-lessons-scanner.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.js +106 -0
- package/dist/observability/checks/lens-i-lessons-scanner.js.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.d.ts +2 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.js +174 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.js.map +1 -0
- package/dist/observability/engine/api.d.ts +4 -0
- package/dist/observability/engine/api.d.ts.map +1 -1
- package/dist/observability/engine/api.js +17 -1
- package/dist/observability/engine/api.js.map +1 -1
- package/dist/observability/engine/checks/observability-config.d.ts +4 -0
- package/dist/observability/engine/checks/observability-config.d.ts.map +1 -1
- package/dist/observability/engine/checks/observability-config.js +1 -0
- package/dist/observability/engine/checks/observability-config.js.map +1 -1
- package/dist/observability/engine/checks/registry.d.ts.map +1 -1
- package/dist/observability/engine/checks/registry.js +7 -0
- package/dist/observability/engine/checks/registry.js.map +1 -1
- package/dist/observability/engine/checks/registry.test.js +3 -2
- package/dist/observability/engine/checks/registry.test.js.map +1 -1
- package/dist/observability/engine/checks/runner.d.ts +30 -0
- package/dist/observability/engine/checks/runner.d.ts.map +1 -1
- package/dist/observability/engine/checks/runner.js +8 -1
- package/dist/observability/engine/checks/runner.js.map +1 -1
- package/dist/observability/engine/checks/runner.test.js +74 -0
- package/dist/observability/engine/checks/runner.test.js.map +1 -1
- package/dist/observability/engine/event-schemas.d.ts.map +1 -1
- package/dist/observability/engine/event-schemas.js +41 -3
- package/dist/observability/engine/event-schemas.js.map +1 -1
- package/dist/observability/engine/event-schemas.test.js +105 -0
- package/dist/observability/engine/event-schemas.test.js.map +1 -1
- package/dist/observability/engine/fix-flow.d.ts +7 -0
- package/dist/observability/engine/fix-flow.d.ts.map +1 -1
- package/dist/observability/engine/fix-flow.js +5 -3
- package/dist/observability/engine/fix-flow.js.map +1 -1
- package/dist/observability/engine/knowledge-root-integration.test.d.ts +2 -0
- package/dist/observability/engine/knowledge-root-integration.test.d.ts.map +1 -0
- package/dist/observability/engine/knowledge-root-integration.test.js +103 -0
- package/dist/observability/engine/knowledge-root-integration.test.js.map +1 -0
- package/dist/observability/engine/types.d.ts +20 -1
- package/dist/observability/engine/types.d.ts.map +1 -1
- package/dist/observability/engine/types.test.js +1 -1
- package/dist/observability/engine/types.test.js.map +1 -1
- package/dist/observability/knowledge-index.d.ts +145 -0
- package/dist/observability/knowledge-index.d.ts.map +1 -0
- package/dist/observability/knowledge-index.js +353 -0
- package/dist/observability/knowledge-index.js.map +1 -0
- package/dist/observability/knowledge-index.test.d.ts +2 -0
- package/dist/observability/knowledge-index.test.d.ts.map +1 -0
- package/dist/observability/knowledge-index.test.js +364 -0
- package/dist/observability/knowledge-index.test.js.map +1 -0
- package/dist/observability/renderers/markdown.d.ts.map +1 -1
- package/dist/observability/renderers/markdown.js +14 -0
- package/dist/observability/renderers/markdown.js.map +1 -1
- package/dist/observability/renderers/markdown.test.js +30 -0
- package/dist/observability/renderers/markdown.test.js.map +1 -1
- package/dist/types/assembly.d.ts +10 -0
- package/dist/types/assembly.d.ts.map +1 -1
- package/dist/utils/fs.d.ts +6 -0
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +13 -0
- package/dist/utils/fs.js.map +1 -1
- package/dist/validation/knowledge-frontmatter-validator.d.ts +15 -0
- package/dist/validation/knowledge-frontmatter-validator.d.ts.map +1 -0
- package/dist/validation/knowledge-frontmatter-validator.js +131 -0
- package/dist/validation/knowledge-frontmatter-validator.js.map +1 -0
- package/dist/validation/knowledge-frontmatter-validator.test.d.ts +2 -0
- package/dist/validation/knowledge-frontmatter-validator.test.d.ts.map +1 -0
- package/dist/validation/knowledge-frontmatter-validator.test.js +66 -0
- package/dist/validation/knowledge-frontmatter-validator.test.js.map +1 -0
- package/package.json +13 -4
|
@@ -0,0 +1,1097 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Build Observability
|
|
3
|
+
topic: observability
|
|
4
|
+
description: A durable ledger of build decisions, fused with git/GitHub/MMR/state and audited against the planning docs by nine lenses
|
|
5
|
+
category: tools
|
|
6
|
+
order: 40
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Why Build Observability exists
|
|
10
|
+
|
|
11
|
+
When several agents (and humans) build a project in parallel worktrees, the
|
|
12
|
+
*reasoning* behind the build evaporates. A decision gets made in a throwaway
|
|
13
|
+
branch, a blocker is hit and worked around, a story is silently dropped — and
|
|
14
|
+
none of it survives the squash-merge. The docs say one thing; the code drifts to
|
|
15
|
+
another. Build Observability turns those ephemeral moments into a durable,
|
|
16
|
+
queryable record, then audits the record against the planning docs.
|
|
17
|
+
|
|
18
|
+
### What goes wrong without it
|
|
19
|
+
|
|
20
|
+
- **Decisions die at teardown.** An agent records "we switched the cache to
|
|
21
|
+
Redis" in its head, opens a PR, the worktree is removed — and the rationale is
|
|
22
|
+
gone. The next agent re-litigates it.
|
|
23
|
+
- **Blockers go unaddressed.** A dependency block is hit at hour 0 and nobody
|
|
24
|
+
notices it is still open at hour 6.
|
|
25
|
+
- **Phase boundaries pass unaudited.** `tech-stack.md` is marked complete while
|
|
26
|
+
it still contradicts the PRD; the contradiction is found three phases later.
|
|
27
|
+
- **Doc/code drift accumulates.** A component is used outside its declared
|
|
28
|
+
layer; an acceptance criterion never gets a test; a coding-standard erodes
|
|
29
|
+
file by file.
|
|
30
|
+
|
|
31
|
+
The classic failure mode is a worktree teardown that takes the ledger with it:
|
|
32
|
+
an agent worktree's `.scaffold/activity.jsonl` is lost the moment the worktree
|
|
33
|
+
is removed, *unless* it is harvested into the primary archive first. The
|
|
34
|
+
harvester (`src/observability/engine/harvester.ts`) and
|
|
35
|
+
`scripts/teardown-agent-worktree.sh` exist precisely to close this gap — see
|
|
36
|
+
[Harvest, recover & teardown](#harvest-recover--teardown).
|
|
37
|
+
|
|
38
|
+
### What good build observability produces
|
|
39
|
+
|
|
40
|
+
- **Decisions captured** the moment they're made (`decision_recorded`),
|
|
41
|
+
surviving teardown via harvest.
|
|
42
|
+
- **Blockers surfaced** when they linger past a threshold (stall detection).
|
|
43
|
+
- **Phase-boundary audits** that run automatically when a planning doc is
|
|
44
|
+
completed, non-gating so they never block progress.
|
|
45
|
+
- **Doc/code drift caught** by the nine-lens audit and routed into code review
|
|
46
|
+
via the MMR `doc-conformance` channel.
|
|
47
|
+
|
|
48
|
+
The system ships **9 durable event types**, **8 adapters** fusing external
|
|
49
|
+
signals, a **9-lens audit (A–I)**, and **5 active stall signals** (a 6th reserved) on the "Needs
|
|
50
|
+
Attention" surface.
|
|
51
|
+
|
|
52
|
+
:::callout{type=note}
|
|
53
|
+
**Two subsystems, one config file.** Build Observability and the separate
|
|
54
|
+
*knowledge-freshness* system both read `.scaffold/observability.yaml`. This guide
|
|
55
|
+
documents Build Observability; the shared config keys are reconciled in
|
|
56
|
+
[Config reference](#config-reference).
|
|
57
|
+
:::
|
|
58
|
+
|
|
59
|
+
## System map
|
|
60
|
+
|
|
61
|
+
One write path, one fusion point, two read paths. Agents write events to the
|
|
62
|
+
append-only ledger; adapters synthesize events from git, GitHub, MMR and
|
|
63
|
+
pipeline state; the synthesizer fuses them with correlation-id dedup; the engine
|
|
64
|
+
API drives the audit lenses and the progress timeline; renderers emit terminal,
|
|
65
|
+
markdown, dashboard and MMR-findings output.
|
|
66
|
+
|
|
67
|
+
```mermaid
|
|
68
|
+
flowchart TB
|
|
69
|
+
subgraph write[write]
|
|
70
|
+
LW["ledger writer
|
|
71
|
+
ledger-writer.ts · 4 KiB cap"]
|
|
72
|
+
HV["harvester
|
|
73
|
+
harvester.ts"]
|
|
74
|
+
LF[".scaffold/activity.jsonl
|
|
75
|
+
append-only · redacted"]
|
|
76
|
+
end
|
|
77
|
+
subgraph adapters[adapters]
|
|
78
|
+
A1["git · priority 3"]
|
|
79
|
+
A2["gh · priority 2"]
|
|
80
|
+
A3["mmr · priority 1"]
|
|
81
|
+
A4["state · priority 4"]
|
|
82
|
+
A5["tests · priority 5"]
|
|
83
|
+
A6["pipeline_docs · probe"]
|
|
84
|
+
A7["beads · probe"]
|
|
85
|
+
A8["audit_history · probe"]
|
|
86
|
+
end
|
|
87
|
+
SY["synthesizer
|
|
88
|
+
composeReplay · correlation_id dedup · source priority"]
|
|
89
|
+
API["engine API
|
|
90
|
+
runAudit · runProgress"]
|
|
91
|
+
LENS["checks — lenses A–I
|
|
92
|
+
registry · runner"]
|
|
93
|
+
FIX["--fix loop
|
|
94
|
+
plan · dispatch · verify"]
|
|
95
|
+
subgraph render[render]
|
|
96
|
+
R1["terminal · ANSI"]
|
|
97
|
+
R2["markdown + sidecar"]
|
|
98
|
+
R3["dashboard fragment"]
|
|
99
|
+
R4["mmr-findings"]
|
|
100
|
+
end
|
|
101
|
+
LW --> LF
|
|
102
|
+
HV --> LF
|
|
103
|
+
LF --> SY
|
|
104
|
+
A1 --> SY
|
|
105
|
+
A2 --> SY
|
|
106
|
+
A3 --> SY
|
|
107
|
+
A4 --> SY
|
|
108
|
+
A5 --> SY
|
|
109
|
+
SY --> API
|
|
110
|
+
API --> LENS
|
|
111
|
+
LENS --> FIX
|
|
112
|
+
API --> R1
|
|
113
|
+
API --> R2
|
|
114
|
+
API --> R3
|
|
115
|
+
LENS --> R4
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The boxes labelled *probe* (`pipeline_docs`, `beads`, `audit_history`)
|
|
119
|
+
contribute availability checks — and, for `audit_history`, trend data — but do
|
|
120
|
+
not emit events into the replay timeline. The five remaining adapters (`git`,
|
|
121
|
+
`gh`, `mmr`, `state`, `tests`) synthesize replay events that flow into the
|
|
122
|
+
synthesizer.
|
|
123
|
+
|
|
124
|
+
## The ledger
|
|
125
|
+
|
|
126
|
+
Every durable observation is one JSON object on one line of
|
|
127
|
+
`.scaffold/activity.jsonl`. Writes are append-only and lock-guarded so parallel
|
|
128
|
+
worktrees never corrupt the file; each event is capped at **4 KiB**; and secrets
|
|
129
|
+
and home-directory paths are scrubbed both when the event is written and again
|
|
130
|
+
when output is rendered.
|
|
131
|
+
|
|
132
|
+
### How a write happens
|
|
133
|
+
|
|
134
|
+
- **Validate** against the per-type payload allow-list
|
|
135
|
+
(`src/observability/engine/event-schemas.ts`). Unknown payload keys are dropped
|
|
136
|
+
(reported in `dropped_fields`); a bad `ts` or missing required field rejects
|
|
137
|
+
the event.
|
|
138
|
+
- **Redact** the payload (`src/observability/engine/redact.ts`) — see below.
|
|
139
|
+
- **Size-check**: `Buffer.byteLength(line, 'utf8')` must be ≤ 4096, else the
|
|
140
|
+
write throws (:cite[src/observability/engine/ledger-writer.ts:10],
|
|
141
|
+
:cite[src/observability/engine/ledger-writer.ts:58]).
|
|
142
|
+
- **Append** under a `proper-lockfile` lock (10 retries, exponential backoff) so
|
|
143
|
+
concurrent agents serialize cleanly.
|
|
144
|
+
- **Link (fail-soft)**: a `task_claimed` event with a `task_id` also links the
|
|
145
|
+
task into Beads via `bd` (`beadsAdapter.claimWithEvent`); any Beads error is
|
|
146
|
+
swallowed — the ledger write already succeeded.
|
|
147
|
+
|
|
148
|
+
### The nine event types
|
|
149
|
+
|
|
150
|
+
Each event carries a common envelope — `event_id` (ULID), `worktree_id`,
|
|
151
|
+
`actor_label`, `branch`, `task_id` (string *or null*), `type`, `ts` (ISO-8601
|
|
152
|
+
UTC) — plus a type-specific `payload`. The CLI verb is
|
|
153
|
+
`scaffold observe event <type> …`.
|
|
154
|
+
|
|
155
|
+
:::filter-table
|
|
156
|
+
| event_type | payload fields | key constraints |
|
|
157
|
+
| --- | --- | --- |
|
|
158
|
+
| `task_claimed` | `task_title`*, `story_id`, `wave`, `unplanned` | if `task_id` is null, `unplanned` must be true |
|
|
159
|
+
| `task_completed` | `outcome`*, `pr_number`, `commit_sha` | outcome ∈ {pr_submitted, dropped, superseded}; `pr_number` required if pr_submitted |
|
|
160
|
+
| `decision_recorded` | `key`*, `summary`*, `affects`* (string[]), `links` | summary ≤ 500 chars; consumed by Lens G |
|
|
161
|
+
| `blocker_hit` | `kind`*, `summary`* | kind ∈ {dependency, ambiguity, external, environment}; summary ≤ 500 chars |
|
|
162
|
+
| `blocker_resolved` | `summary`*, `references`* (string[]) | closes a prior blocker_hit |
|
|
163
|
+
| `pr_opened` | `pr_number`* | positive integer |
|
|
164
|
+
| `progress_heartbeat` | `note`* | note ≤ 200 chars; resets task_stale clock |
|
|
165
|
+
| `finding_acknowledged` | `finding_id`*, `status`*, `note` | task_id must be null; status ∈ {acknowledged, open}; written by `observe ack` |
|
|
166
|
+
| `knowledge_gap_signal` | `topic`*, `source`*, `project_id`*, `step_name`, `agent_excerpt` | topic kebab-case ≤ 80 chars; consumed by Lens I |
|
|
167
|
+
:::
|
|
168
|
+
|
|
169
|
+
`*` marks required fields. Allow-lists live in `EVENT_PAYLOAD_KEYS` at
|
|
170
|
+
:cite[src/observability/engine/event-schemas.ts:3-13].
|
|
171
|
+
|
|
172
|
+
:::callout{type=warning}
|
|
173
|
+
**Naming note.** The PR-opened event is `pr_opened` (past tense) in code, not
|
|
174
|
+
`pr_open` as the CLAUDE.md prose abbreviates it. The ledger never emits
|
|
175
|
+
`pr_open`.
|
|
176
|
+
:::
|
|
177
|
+
|
|
178
|
+
### Building a `scaffold observe event` command
|
|
179
|
+
|
|
180
|
+
`--branch` is required; `--task-id` is optional (it correlates the event to a
|
|
181
|
+
claimed task) but must be *omitted* for `finding_acknowledged` (whose `task_id`
|
|
182
|
+
must be null), and a `task_claimed` without one must pass `--unplanned true`.
|
|
183
|
+
Payload keys are passed as `--kebab-case` flags, snake-cased before validation;
|
|
184
|
+
unknown keys are dropped.
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
scaffold observe event task_claimed --branch <branch> --task-id <id> \
|
|
188
|
+
--task-title "<title>" [--story-id <id>] [--wave <n>] [--unplanned true]
|
|
189
|
+
scaffold observe event task_completed --branch <branch> --task-id <id> \
|
|
190
|
+
--outcome pr_submitted --pr-number <n> [--commit-sha <sha>]
|
|
191
|
+
scaffold observe event decision_recorded --branch <branch> --task-id <id> \
|
|
192
|
+
--key <key> --summary "<text>" --affects "src/**,docs/**" [--links "ADR-1,ADR-2"]
|
|
193
|
+
scaffold observe event blocker_hit --branch <branch> --task-id <id> \
|
|
194
|
+
--kind dependency --summary "<text>"
|
|
195
|
+
scaffold observe event blocker_resolved --branch <branch> --task-id <id> \
|
|
196
|
+
--summary "<text>" --references "ref1,ref2"
|
|
197
|
+
scaffold observe event pr_opened --branch <branch> --task-id <id> --pr-number <n>
|
|
198
|
+
scaffold observe event progress_heartbeat --branch <branch> --task-id <id> --note "<text>"
|
|
199
|
+
scaffold observe event finding_acknowledged --branch <branch> \
|
|
200
|
+
--finding-id <id> --status acknowledged [--note "<text>"]
|
|
201
|
+
scaffold observe event knowledge_gap_signal --branch <branch> \
|
|
202
|
+
--topic <kebab-slug> --source agent_search --project-id <sha256> \
|
|
203
|
+
[--step-name <name>] [--agent-excerpt "<text>"]
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
`finding_acknowledged` is normally written by `scaffold observe ack`, not by
|
|
207
|
+
hand.
|
|
208
|
+
|
|
209
|
+
:::callout{type=note}
|
|
210
|
+
**Value coercion** (`src/cli/commands/observe.ts`): `--pr-number` is parsed
|
|
211
|
+
numeric (a non-number is dropped); `--unplanned` is boolean (`true` ⇒ true,
|
|
212
|
+
anything else ⇒ false); `--affects`, `--links`, `--references` are comma-split
|
|
213
|
+
into arrays; everything else stays a string. Exit codes: `0` written · `2`
|
|
214
|
+
validation failed / payload > 4 KiB · `3` other error.
|
|
215
|
+
:::
|
|
216
|
+
|
|
217
|
+
### Redaction — write time and render time
|
|
218
|
+
|
|
219
|
+
Redaction runs twice. **Write-time** redaction (recursive over the payload tree)
|
|
220
|
+
scrubs the event before it lands on disk; **render-time** redaction
|
|
221
|
+
(`redactEngineOutput` / `redactRendered`) scrubs string values again before any
|
|
222
|
+
report is shown, catching anything synthesized after the fact.
|
|
223
|
+
|
|
224
|
+
Order matters: a bare `ghp_…` matches the GitHub-token pattern, but inside a
|
|
225
|
+
`token=…` pair the key/value rule wins first — so `token=ghp_…` redacts to
|
|
226
|
+
`[REDACTED:kv-secret]`, not `[REDACTED:github-token]` (leftmost-match
|
|
227
|
+
alternation, :cite[src/observability/engine/redact.ts:16]).
|
|
228
|
+
|
|
229
|
+
| pattern | matches | replacement |
|
|
230
|
+
| --- | --- | --- |
|
|
231
|
+
| AWS key | `AKIA[0-9A-Z]{16}` | `[REDACTED:aws-key]` |
|
|
232
|
+
| GitHub token | `gh[pousr]_[A-Za-z0-9]{36,}` | `[REDACTED:github-token]` |
|
|
233
|
+
| key/value secret | key matches `secret\|token\|password\|api[_-]?key` | `[REDACTED:kv-secret]` (key + separator preserved) |
|
|
234
|
+
| sensitive object key | object key matches the same pattern | all descendant primitive values masked |
|
|
235
|
+
| home path | `/Users/<name>`, `/home/<name>`, `C:\Users\<name>` | `~` (Windows keeps the drive: `C:\~`) |
|
|
236
|
+
|
|
237
|
+
A redacted `decision_recorded` event on disk (one line, shown pretty-printed):
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"event_id": "01H5ZABCDEFGHJKMNPQRSTVWX",
|
|
242
|
+
"worktree_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
|
243
|
+
"actor_label": "agent-alice",
|
|
244
|
+
"branch": "alice-feat/cache",
|
|
245
|
+
"task_id": "T-014",
|
|
246
|
+
"type": "decision_recorded",
|
|
247
|
+
"ts": "2026-05-04T12:00:00Z",
|
|
248
|
+
"payload": {
|
|
249
|
+
"key": "cache-backend",
|
|
250
|
+
"summary": "Switched to Redis; token=[REDACTED:kv-secret]",
|
|
251
|
+
"affects": ["~/repo/src/cache/**"],
|
|
252
|
+
"links": ["ADR-021"]
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Worktree identity
|
|
258
|
+
|
|
259
|
+
Each worktree gets a stable identity on first write — `.scaffold/identity.json`
|
|
260
|
+
holds `worktree_id` (a UUID), `worktree_label` (derived from the directory name,
|
|
261
|
+
or `primary`), and `created_at` (`src/observability/engine/identity.ts`). The id
|
|
262
|
+
is what lets the harvester tell one worktree's events from another's, and what
|
|
263
|
+
stamps every event's `worktree_id`.
|
|
264
|
+
|
|
265
|
+
## Adapters
|
|
266
|
+
|
|
267
|
+
The ledger only holds what agents *chose* to record. Adapters fill in the rest by
|
|
268
|
+
synthesizing events from the surrounding tools — commits, PRs, MMR jobs, pipeline
|
|
269
|
+
state, test runs. There are eight adapters (`AdapterId` at
|
|
270
|
+
:cite[src/observability/engine/types.ts:69]), but only five emit events into the
|
|
271
|
+
timeline; the other three are availability probes / trend helpers.
|
|
272
|
+
|
|
273
|
+
:::callout{type=note}
|
|
274
|
+
**Five emit, three probe.** `git`, `gh`, `mmr`, `state`, `tests` each implement
|
|
275
|
+
`replayEvents()` and appear in the source-priority chain. `pipeline_docs`
|
|
276
|
+
(probes 9 planning-doc roles; 5 of them are the canonical-required set that gates
|
|
277
|
+
available vs degraded), `beads` (task-tracker linkage), and `audit_history`
|
|
278
|
+
(reads `docs/audits/*.json` for trends + lens-skip streaks) do *not* emit replay
|
|
279
|
+
events.
|
|
280
|
+
:::
|
|
281
|
+
|
|
282
|
+
| adapter | source of truth | emits | correlation_id / dedup |
|
|
283
|
+
| --- | --- | --- | --- |
|
|
284
|
+
| `git` | `git log`, `git worktree list` (30 s timeout) | `commit` | none (`null`); per-SHA seen-set within the window |
|
|
285
|
+
| `gh` | `gh pr list --state {open,merged,closed}` (needs auth) | `pr_opened`, `pr_merged`, `pr_closed` | `pr:<n>:<state>` — dedups against the ledger's own PR events |
|
|
286
|
+
| `mmr` | `.mmr/jobs/*/result.json` (replay keyed on each job's `completed_at`) | `job_completed` | none |
|
|
287
|
+
| `state` | `.scaffold/state.json` + `services/*/state.json` | `step_completed`, `step_in_progress` | none; per-step timestamp, mtime fallback |
|
|
288
|
+
| `tests` | `.scaffold/last-test-run.json` | `test_run_completed`, `test_run_failed` | none |
|
|
289
|
+
| `pipeline_docs` | candidate `docs/*.md` artifact paths | — (probe: available / degraded / unavailable) | n/a |
|
|
290
|
+
| `beads` | `.beads/` + `bd` CLI (≥ v1.0.0) | — (task claim ↔ event-id linkage) | n/a |
|
|
291
|
+
| `audit_history` | `docs/audits/*.json` (≤ 100 scanned) | — (trends + `lensSkippedStreaks`) | n/a |
|
|
292
|
+
|
|
293
|
+
### Source priority
|
|
294
|
+
|
|
295
|
+
When two events describe the same thing (same `correlation_id`), the synthesizer
|
|
296
|
+
keeps the one from the most authoritative source. The order is fixed in
|
|
297
|
+
`SOURCE_PRIORITY` at :cite[src/observability/engine/synthesizer.ts:254] — lower
|
|
298
|
+
number wins, ties broken by earliest `ts`:
|
|
299
|
+
|
|
300
|
+
| rank | source | why it wins |
|
|
301
|
+
| --- | --- | --- |
|
|
302
|
+
| `0` | `ledger` | the agent said so — first-party intent |
|
|
303
|
+
| `1` | `mmr` | authoritative build verdict |
|
|
304
|
+
| `2` | `gh` | GitHub PR state of record |
|
|
305
|
+
| `3` | `git` | local commit history |
|
|
306
|
+
| `4` | `state` | pipeline step status |
|
|
307
|
+
| `5` | `tests` | cached test run |
|
|
308
|
+
|
|
309
|
+
The three probe-only adapters are intentionally absent from this table — they
|
|
310
|
+
never produce a replay event to dedup.
|
|
311
|
+
|
|
312
|
+
## The nine-lens audit
|
|
313
|
+
|
|
314
|
+
The audit reads the planning docs (PRD, stories, tech-stack, standards, design
|
|
315
|
+
system, plan, playbook) into a document graph, then runs a set of independent
|
|
316
|
+
*lenses* over the graph, the code, the ledger and adapter data. The design spec
|
|
317
|
+
calls it the "eight-lens audit" (A–H); a ninth lens — `I-knowledge-gaps` —
|
|
318
|
+
joined the suite after v3.26.0.
|
|
319
|
+
|
|
320
|
+
:::callout{type=note}
|
|
321
|
+
**8 in the spec, 9 in the code.**
|
|
322
|
+
`docs/superpowers/specs/2026-04-30-build-observability-design.md` titles §3 "The
|
|
323
|
+
Eight Audit Lenses" and its `LENS_REGISTRY` stops at H. The shipped
|
|
324
|
+
:cite[src/observability/engine/checks/registry.ts:44] adds `I-knowledge-gaps`.
|
|
325
|
+
Treat Lens I as the ninth lens that joined the suite — documented here as a
|
|
326
|
+
first-class member.
|
|
327
|
+
:::
|
|
328
|
+
|
|
329
|
+
### Scope, order and skips
|
|
330
|
+
|
|
331
|
+
- **Scope → lenses** (:cite[src/observability/engine/api.ts:72]): `--scope code`
|
|
332
|
+
runs **A–G**; `--scope docs` runs **H, I**; `--scope all` runs all nine. An
|
|
333
|
+
explicit `--lens <id>` overrides the scope selection.
|
|
334
|
+
- **Registry order**: A → B → C → D → E → F → G → H → I. `G-decisions` declares
|
|
335
|
+
`depends_on: ['D-stack']` so it runs after D and can consume D's
|
|
336
|
+
unsanctioned-dependency findings.
|
|
337
|
+
- **Missing adapter → skip**: if a lens's *required* adapters are unavailable it
|
|
338
|
+
is skipped and emits a :sev[P3]{level=p3} finding with
|
|
339
|
+
`evidence.kind = lens_skipped`. Skipped lenses (not blocking findings) are what
|
|
340
|
+
turn a `pass` into a `degraded-pass`.
|
|
341
|
+
|
|
342
|
+
### What feeds the doc-graph
|
|
343
|
+
|
|
344
|
+
Before any lens runs, the planning docs and the working tree are parsed into a
|
|
345
|
+
single graph (`src/observability/engine/doc-graph/index.ts`). Every lens's
|
|
346
|
+
"Reads:" line refers to nodes and edges built here:
|
|
347
|
+
|
|
348
|
+
| source | parser / detector | graph nodes & edges |
|
|
349
|
+
| --- | --- | --- |
|
|
350
|
+
| PRD | `parseFeatures` | `features` (with priority) |
|
|
351
|
+
| user-stories | `parseStories` | `stories`, `acceptance_criteria`, `feature_to_story` |
|
|
352
|
+
| tech-stack | `parseSanctionedComponents` | `components` (with `layer`) |
|
|
353
|
+
| coding-standards + tdd-standards | `parseRules` | `rules` |
|
|
354
|
+
| design-system | `parseDesignTokens` | `tokens` (priority, category) |
|
|
355
|
+
| implementation-plan | `parsePlanTasks` | `plan_tasks`, `story_to_plan_task` |
|
|
356
|
+
| implementation-playbook | `parsePlaybookTasks` | `playbook_tasks`, `playbook_task_to_story` |
|
|
357
|
+
| decision docs (`decisions.jsonl`, `docs/decisions/*.md`) | `parseDecisions` | `decisions` |
|
|
358
|
+
| working tree | `discoverTests`, `discoverFiles` | `tests` (with `last_status`), `files`, `ac_to_test` |
|
|
359
|
+
| source files | `detectCss/JsxTokenUses`, `detectComponentUses` | `file_to_token_use`, `file_to_component_use` |
|
|
360
|
+
|
|
361
|
+
### All nine at a glance
|
|
362
|
+
|
|
363
|
+
:::filter-table
|
|
364
|
+
| lens | question | scope | severities | ships in |
|
|
365
|
+
| --- | --- | --- | --- | --- |
|
|
366
|
+
| `A-tdd` | Are tests being skipped? | code | P0 P1 | #331 |
|
|
367
|
+
| `B-ac-coverage` | Is every AC covered by a passing test? | code | P0 P1 | #331 |
|
|
368
|
+
| `C-standards` | Are coding standards being violated? | code | P0–P3 | #332 |
|
|
369
|
+
| `D-stack` | Unsanctioned deps / out-of-layer use? | code | P0 P1 | #332 |
|
|
370
|
+
| `E-design` | Ad-hoc values bypassing design tokens? | code | P0 P1 | #332 |
|
|
371
|
+
| `F-scope` | High-priority work without a story/plan? | code | P0 P1 P2 | #332 |
|
|
372
|
+
| `G-decisions` | Decisions made but not documented? | code | P0 P1 P2 | #332 |
|
|
373
|
+
| `H-cross-doc` | Are the docs internally consistent? | docs | P0 P1 P2 | #331 · #336 |
|
|
374
|
+
| `I-knowledge-gaps` | Repeated needs with no KB entry? | docs | P1 P2 | #397 · #406 |
|
|
375
|
+
:::
|
|
376
|
+
|
|
377
|
+
### Lens by lens
|
|
378
|
+
|
|
379
|
+
**A-tdd — TDD violations** (`src/observability/checks/lens-a-tdd.ts`). *Are there
|
|
380
|
+
skipped tests?* **Reads:** the doc-graph's discovered tests (with `last_status`),
|
|
381
|
+
ACs, stories, and `ac_to_test` edges. **Tunes:** none. **Severity:**
|
|
382
|
+
:sev[P0]{level=p0} skipped test on a must-priority story; :sev[P1]{level=p1}
|
|
383
|
+
otherwise.
|
|
384
|
+
|
|
385
|
+
**B-ac-coverage — AC completion**
|
|
386
|
+
(`src/observability/checks/lens-b-ac-coverage.ts`). *Is every acceptance
|
|
387
|
+
criterion covered by a passing test?* **Reads:** ACs, tests, `ac_to_test` edges;
|
|
388
|
+
optional `tests` adapter for live status. **Tunes:** none. **Severity:**
|
|
389
|
+
:sev[P0]{level=p0} AC's test is failing; :sev[P1]{level=p1} AC has no test edge
|
|
390
|
+
or unknown status.
|
|
391
|
+
|
|
392
|
+
**C-standards — coding-standards drift**
|
|
393
|
+
(`src/observability/checks/lens-c-standards.ts`). *Are coding standards being
|
|
394
|
+
violated across files?* **Reads:** graph `rules` + `files`. **Tunes:**
|
|
395
|
+
`lenses.C-standards.rule_overrides` (per-rule severity), `escalation_threshold`
|
|
396
|
+
(default 5 — more than N violations of a rule escalates to P1).
|
|
397
|
+
(`enforce_via_linter` is accepted in config but not read by the lens.)
|
|
398
|
+
**Severity:** rule-specific :sev[P0]{level=p0}–:sev[P3]{level=p3}.
|
|
399
|
+
|
|
400
|
+
**D-stack — tech-stack drift**
|
|
401
|
+
(`src/observability/checks/lens-d-stack.ts`). *Unsanctioned dependencies, or
|
|
402
|
+
components used outside their layer?* **Reads:** `file_to_component_use` edges,
|
|
403
|
+
components (with `layer`), and `decision_recorded` ledger events (which can
|
|
404
|
+
sanction a dependency). **Tunes:** `lenses.D-stack.path_to_layer` (default 7
|
|
405
|
+
glob→layer mappings). **Severity:** :sev[P0]{level=p0} unsanctioned dependency;
|
|
406
|
+
:sev[P1]{level=p1} out-of-layer use.
|
|
407
|
+
|
|
408
|
+
**E-design — design-system drift**
|
|
409
|
+
(`src/observability/checks/lens-e-design.ts`). *Are ad-hoc design values
|
|
410
|
+
bypassing tokens?* **Reads:** `file_to_token_use` edges, tokens (with priority +
|
|
411
|
+
category). **Tunes:** `lenses.E-design.ad_hoc_token_threshold` (default 3),
|
|
412
|
+
`ui_glob` (default `src/components/**/*.tsx`, consumed by the doc-graph builder).
|
|
413
|
+
**Severity:** :sev[P1]{level=p1} ad-hoc count over threshold; :sev[P0]{level=p0}
|
|
414
|
+
must-priority token category bypassed.
|
|
415
|
+
|
|
416
|
+
**F-scope — missing scope** (`src/observability/checks/lens-f-scope.ts`). *Is
|
|
417
|
+
high-priority work missing stories/plans, or are planned stories untouched?*
|
|
418
|
+
**Reads:** features, stories, plan-tasks and their edges; `task_claimed` ledger
|
|
419
|
+
events; optional `state` adapter. **Tunes:**
|
|
420
|
+
`lenses.F-scope.untouched_story_grace_hours` (default 168 = 7 days). **Severity:**
|
|
421
|
+
:sev[P0]{level=p0} must-feature without story/plan; :sev[P1]{level=p1}
|
|
422
|
+
should-feature; :sev[P2]{level=p2} planned-but-untouched story past grace.
|
|
423
|
+
|
|
424
|
+
**G-decisions — undocumented decisions**
|
|
425
|
+
(`src/observability/checks/lens-g-decisions.ts`). *Decisions made in the
|
|
426
|
+
ledger/commits but not documented (or vice versa)?* **Reads:** graph decisions,
|
|
427
|
+
`decision_recorded` events, recent git commits (keyword scan), and D-stack's
|
|
428
|
+
findings. **Tunes:** none effective (see note). **Severity:** :sev[P0]{level=p0}
|
|
429
|
+
unsanctioned dep from D with no decision; :sev[P1]{level=p1} ledger↔doc mismatch;
|
|
430
|
+
:sev[P2]{level=p2} decision-keyword commit with no event/doc.
|
|
431
|
+
|
|
432
|
+
:::callout{type=warning}
|
|
433
|
+
**Inert override.** The spec advertises a `lenses.G-decisions.keywords_file`
|
|
434
|
+
override and ships `src/observability/checks/data/decision-keywords.txt`, but
|
|
435
|
+
`loadKeywords()` hard-codes its keyword list and never reads the config key or
|
|
436
|
+
the file. The override and the bundled file are currently inert.
|
|
437
|
+
:::
|
|
438
|
+
|
|
439
|
+
**H-cross-doc — cross-doc inconsistency**
|
|
440
|
+
(`src/observability/checks/lens-h-cross-doc.ts`). *Are features, stories, plans,
|
|
441
|
+
playbook and decisions internally consistent?* **Reads:** the full structural
|
|
442
|
+
doc-graph + unresolved globs. **Severity:** :sev[P0]{level=p0} decision supersedes
|
|
443
|
+
a non-existent decision, or a *must*-priority story uncovered by plan/playbook;
|
|
444
|
+
:sev[P1]{level=p1} feature with no story / orphan story / *should*-priority
|
|
445
|
+
uncovered story; :sev[P2]{level=p2} plan task not in playbook, unresolved glob.
|
|
446
|
+
|
|
447
|
+
Under `--profile=full` only, Lens H runs three extra checks via an LLM dispatcher
|
|
448
|
+
(all silently return `[]` if the dispatcher fails, so the audit never breaks):
|
|
449
|
+
|
|
450
|
+
- **tech-stack ↔ PRD** — contradictions (:sev[P0]{level=p0}) or tensions
|
|
451
|
+
(:sev[P2]{level=p2}) between PRD prose and the chosen stack.
|
|
452
|
+
- **PRD → stories coverage** — a prose feature with no covering story
|
|
453
|
+
(:sev[P1]{level=p1}).
|
|
454
|
+
- **terminology drift** — one concept named inconsistently across docs
|
|
455
|
+
(:sev[P2]{level=p2}).
|
|
456
|
+
|
|
457
|
+
:::callout{type=danger}
|
|
458
|
+
**Security — the LLM dispatcher command is hard-coded.** Lens H passes the
|
|
459
|
+
literal `claude -p` (:cite[src/observability/checks/lens-h-cross-doc.ts:164]) into
|
|
460
|
+
the shared dispatcher (`src/observability/engine/llm-dispatcher.ts`, which runs
|
|
461
|
+
it through a fixed subprocess). The command is *deliberately not*
|
|
462
|
+
project-config-overridable, because the audit may run against untrusted
|
|
463
|
+
third-party repos and a repo-controlled command would be arbitrary code
|
|
464
|
+
execution. Only `llm.timeout_s` (and `llm.parallel_checks`) are configurable.
|
|
465
|
+
Contrast the `--fix` dispatcher, which *is* configurable — see
|
|
466
|
+
[The --fix flow](#the---fix-flow).
|
|
467
|
+
:::
|
|
468
|
+
|
|
469
|
+
**I-knowledge-gaps — the ninth lens**
|
|
470
|
+
(`src/observability/checks/lens-i-knowledge-gaps.ts`). *What topics have agents
|
|
471
|
+
repeatedly needed (over a 90-day window) with no knowledge-base entry?* **Reads:**
|
|
472
|
+
`knowledge_gap_signal` ledger events + synthetic signals scanned from
|
|
473
|
+
`tasks/lessons.md` (`src/observability/checks/lens-i-lessons-scanner.ts`).
|
|
474
|
+
**Severity:** :sev[P1]{level=p1} ≥5 signals from ≥3 projects; :sev[P2]{level=p2}
|
|
475
|
+
≥3 signals from ≥2 projects.
|
|
476
|
+
|
|
477
|
+
:::callout{type=note}
|
|
478
|
+
**Lens I — `--knowledge-root` and existing-entry suppression.** The lens resolves
|
|
479
|
+
the knowledge directory in three tiers (`src/observability/knowledge-index.ts`):
|
|
480
|
+
the `--knowledge-root` CLI flag → `lenses.I-knowledge-gaps.knowledge_root` in
|
|
481
|
+
config → auto-detect by walking up for `content/knowledge/`. If a gap's topic
|
|
482
|
+
slug already exists in the resolved knowledge index, the finding is
|
|
483
|
+
**suppressed** (no P1/P2). If no root resolves, suppression is disabled and the
|
|
484
|
+
lens warns once per audit. Shipped in #397 (lens + lessons scanner) and #406
|
|
485
|
+
(`--knowledge-root` + suppression).
|
|
486
|
+
:::
|
|
487
|
+
|
|
488
|
+
## The `observe audit` CLI
|
|
489
|
+
|
|
490
|
+
One command runs the lenses and reports findings. Its exit code is the verdict
|
|
491
|
+
gate: `0` on a non-blocked verdict (or any `mmr-findings` run), `1` when blocked
|
|
492
|
+
or when a `--fix` pass still failed, `3` on an audit error.
|
|
493
|
+
|
|
494
|
+
### Every flag
|
|
495
|
+
|
|
496
|
+
| flag | values / default | effect |
|
|
497
|
+
| --- | --- | --- |
|
|
498
|
+
| `--scope` | `code` · `docs` · `all` (default `all`) | which lens set runs |
|
|
499
|
+
| `--lens <id>` | repeatable | run exactly these lenses, overriding scope |
|
|
500
|
+
| `--profile` | `fast` (default) · `full` | `full` enables Lens H's LLM-graded sub-checks |
|
|
501
|
+
| `--fix` | flag | after auditing, dispatch the fix loop for blocking findings |
|
|
502
|
+
| `--fix-threshold` | `P0`–`P3` | override the blocking cutoff for this run |
|
|
503
|
+
| `--output=<path>` | path | override markdown destination (sidecar unaffected) |
|
|
504
|
+
| `--render` | `dashboard-fragment-audit` | emit HTML to stdout; skip markdown + sidecar |
|
|
505
|
+
| `--output-mode` | `mmr-findings` | emit MMR Finding JSON to stdout (always exit 0); skip markdown + sidecar |
|
|
506
|
+
| `--knowledge-root=<path>` | path | tier-1 knowledge dir for Lens I suppression |
|
|
507
|
+
| `--json` · `--mask-paths` · `--show-acknowledged` · `--since-hours` | flags / N | raw JSON output · redact paths · include acked findings · activity window |
|
|
508
|
+
|
|
509
|
+
```bash
|
|
510
|
+
# A docs-only full audit including LLM-graded checks
|
|
511
|
+
scaffold observe audit --scope docs --profile full
|
|
512
|
+
|
|
513
|
+
# Audit, then dispatch a fix agent for each blocking finding
|
|
514
|
+
scaffold observe audit --fix --fix-threshold P1
|
|
515
|
+
|
|
516
|
+
# Lens I only, with an explicit knowledge root for suppression
|
|
517
|
+
scaffold observe audit --lens I-knowledge-gaps --knowledge-root content/knowledge
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### Verdict taxonomy
|
|
521
|
+
|
|
522
|
+
The engine computes exactly three verdicts (`Verdict` at
|
|
523
|
+
:cite[src/observability/engine/types.ts:6]):
|
|
524
|
+
|
|
525
|
+
| verdict | when | exit |
|
|
526
|
+
| --- | --- | --- |
|
|
527
|
+
| :sev[pass]{level=pass} | no blocking findings, no skipped lenses | `0` |
|
|
528
|
+
| :sev[degraded-pass]{level=p2} | no blocking findings, but ≥1 lens skipped (missing required adapter) | `0` |
|
|
529
|
+
| :sev[blocked]{level=p0} | ≥1 *open* finding at or above `fix_threshold` | `1` |
|
|
530
|
+
|
|
531
|
+
:::callout{type=note}
|
|
532
|
+
**"needs-user-decision" is not an engine verdict.** The code-review workflow has
|
|
533
|
+
a `needs-user-decision` outcome, but that is an *MMR review* verdict, not one the
|
|
534
|
+
audit engine emits. The audit engine's universe is exactly the three above.
|
|
535
|
+
:::
|
|
536
|
+
|
|
537
|
+
#### `fix_threshold`
|
|
538
|
+
|
|
539
|
+
A finding is *blocking* when its status is `open` and its severity is at or above
|
|
540
|
+
the threshold (`src/observability/engine/checks/fix-threshold.ts`). Resolution
|
|
541
|
+
order: `--fix-threshold` flag → `.mmr.yaml`
|
|
542
|
+
(`audit_fix_threshold` / `fix_threshold`) → default **P2**. The threshold never
|
|
543
|
+
*hides* findings — every finding is still reported; it only decides which ones
|
|
544
|
+
count toward `blocked`.
|
|
545
|
+
|
|
546
|
+
:::callout{type=note}
|
|
547
|
+
**How the counts are computed**
|
|
548
|
+
(`src/observability/engine/checks/findings-aggregator.ts`): `blocking` counts a
|
|
549
|
+
finding only when `status === 'open'` *and* its severity is at or above
|
|
550
|
+
`fix_threshold`; `acknowledged` counts only findings silenced by a
|
|
551
|
+
`finding_acknowledged` ledger event (latest event per id wins); `skipped`
|
|
552
|
+
findings (missing-adapter lenses) ignore acks entirely. The renderers'
|
|
553
|
+
`(blocking · ack · total)` line is this tally.
|
|
554
|
+
:::
|
|
555
|
+
|
|
556
|
+
### Companion verb — `scaffold observe ack`
|
|
557
|
+
|
|
558
|
+
Acknowledge (or reopen) a finding by ID prefix; it writes a
|
|
559
|
+
`finding_acknowledged` event the aggregator reads on the next audit.
|
|
560
|
+
|
|
561
|
+
| arg / flag | effect |
|
|
562
|
+
| --- | --- |
|
|
563
|
+
| `<prefix-or-id>` | matched against all finding IDs in `docs/audits/*.json`; an ambiguous prefix exits `2` |
|
|
564
|
+
| `--status acknowledged|open` | `acknowledged` (default) silences it; `open` reopens it |
|
|
565
|
+
| `--note "…"` | optional rationale recorded on the event |
|
|
566
|
+
|
|
567
|
+
Branch is auto-derived (`git rev-parse --abbrev-ref HEAD`, fallback `main`); the
|
|
568
|
+
event's `task_id` is null.
|
|
569
|
+
|
|
570
|
+
### Exit codes across `observe` verbs
|
|
571
|
+
|
|
572
|
+
| verb | 0 | 1 | 2 | 3 |
|
|
573
|
+
| --- | --- | --- | --- | --- |
|
|
574
|
+
| `audit` | not blocked, or any `mmr-findings` run | blocked, or `--fix` left a blocker | — | audit error (130 on SIGINT mid-`--fix`, snapshot restored) |
|
|
575
|
+
| `event` | written | — | validation failed / payload > 4 KiB | other error |
|
|
576
|
+
| `ack` | written | — | no match / ambiguous prefix | no audit sidecars / write error |
|
|
577
|
+
| `progress` | ok | — | — | markdown/sidecar write error (with `--output`) |
|
|
578
|
+
| `harvest` | harvested / recovered | — | — | no `identity.json`, or primary root is itself a worktree |
|
|
579
|
+
|
|
580
|
+
## Progress, replay & stall
|
|
581
|
+
|
|
582
|
+
`scaffold observe progress` shows what's in flight. With `--replay` it fuses the
|
|
583
|
+
ledger with synthesized git/gh/mmr/state/tests events into one timeline; when
|
|
584
|
+
`scaffold observe progress` runs it also evaluates stall detection and surfaces a
|
|
585
|
+
"Needs Attention" panel (suppress with `--no-stall-check`).
|
|
586
|
+
|
|
587
|
+
### Fusion — how the timeline is built
|
|
588
|
+
|
|
589
|
+
The synthesizer's `composeReplay`
|
|
590
|
+
(:cite[src/observability/engine/synthesizer.ts:294]) converts each ledger `Event`
|
|
591
|
+
to a `ReplayEvent`, concatenates the adapter events, filters to the time window,
|
|
592
|
+
then dedups:
|
|
593
|
+
|
|
594
|
+
- Events with a `null` `correlation_id` pass through untouched.
|
|
595
|
+
- Events that share a `correlation_id` collapse to one — the synthesizer keeps
|
|
596
|
+
the lowest `SOURCE_PRIORITY` number (`ledger` 0 → `tests` 5), breaking ties by
|
|
597
|
+
earliest `ts`.
|
|
598
|
+
- The surviving events sort by `(ts, source-priority, sort_id)`.
|
|
599
|
+
|
|
600
|
+
So a PR that the agent recorded (`pr_opened` in the ledger) and that the `gh`
|
|
601
|
+
adapter also reports collapses to the single ledger event, because `ledger` (0)
|
|
602
|
+
outranks `gh` (2).
|
|
603
|
+
|
|
604
|
+
### Stall detection — the six signals
|
|
605
|
+
|
|
606
|
+
When `scaffold observe progress` runs (unless `--no-stall-check`) the engine
|
|
607
|
+
checks for staleness and builds `needs_attention`
|
|
608
|
+
(`src/observability/engine/stall.ts`). The type declares six
|
|
609
|
+
signals; **five fire today** — `pr_review_stale` is reserved (deferred pending a
|
|
610
|
+
per-PR correlation_id on the mmr adapter,
|
|
611
|
+
:cite[src/observability/engine/stall.ts:119]). Thresholds accept `'Nh'`, `'Nd'`,
|
|
612
|
+
or `'off'` under `stall.*`:
|
|
613
|
+
|
|
614
|
+
| signal | fires when | config key · default |
|
|
615
|
+
| --- | --- | --- |
|
|
616
|
+
| `task_stale` | task claimed, no commit/heartbeat/completion since | `stall.task_stale` · `4h` |
|
|
617
|
+
| `pr_stale` | ledger `pr_opened` recorded, PR not merged/closed since | `stall.pr_stale` · `48h` |
|
|
618
|
+
| `blocker_unaddressed` | `blocker_hit` with no `blocker_resolved` | `stall.blocker_unaddressed` · `2h` |
|
|
619
|
+
| `audit_findings_unresolved` | open finding past threshold age, severity at or above `fix_threshold` | `stall.audit_findings_unresolved` · `24h` |
|
|
620
|
+
| `lens_skipped_repeatedly` | a lens skipped on ≥3 consecutive audits | hard-coded streak ≥ 3 (no config key) |
|
|
621
|
+
| `pr_review_stale` (reserved) | — not yet emitted — | `stall.pr_review_stale` · `24h` (defined, unused) |
|
|
622
|
+
|
|
623
|
+
### Flags
|
|
624
|
+
|
|
625
|
+
| flag | effect |
|
|
626
|
+
| --- | --- |
|
|
627
|
+
| `--replay` | include the fused timeline in the output |
|
|
628
|
+
| `--no-stall-check` | suppress the "Needs Attention" surface (empty `needs_attention`) |
|
|
629
|
+
| `--render=dashboard-fragment` | emit the progress HTML panel to stdout; skip markdown + sidecar |
|
|
630
|
+
| `--output=<path>` · `--json` · `--since-hours N` | override markdown path · raw JSON · activity window (default 24) |
|
|
631
|
+
|
|
632
|
+
Stall thresholds are configurable under `stall:` in
|
|
633
|
+
`.scaffold/observability.yaml` — see [Config reference](#config-reference).
|
|
634
|
+
|
|
635
|
+
## Phase-boundary triggers
|
|
636
|
+
|
|
637
|
+
Completing a planning document should re-check the docs for drift —
|
|
638
|
+
automatically, but never blocking the build. When a pipeline step at a phase
|
|
639
|
+
boundary is marked complete, the state manager fires a docs audit and prints a
|
|
640
|
+
one-line summary.
|
|
641
|
+
|
|
642
|
+
### The hook
|
|
643
|
+
|
|
644
|
+
`StateManager.markCompleted()` is **async**
|
|
645
|
+
(:cite[src/state/state-manager.ts:175]): it saves state, then awaits
|
|
646
|
+
`runPhaseAudit({ primaryRoot, step })` for *every* completed step — the
|
|
647
|
+
phase-boundary gate lives inside `runPhaseAudit`, which returns a no-op result
|
|
648
|
+
unless the step is one of the six boundaries
|
|
649
|
+
(`src/observability/engine/phase-subsets.ts`): `user-stories`, `tech-stack`,
|
|
650
|
+
`coding-standards`, `design-system`, `implementation-plan`,
|
|
651
|
+
`implementation-playbook`.
|
|
652
|
+
|
|
653
|
+
```mermaid
|
|
654
|
+
flowchart LR
|
|
655
|
+
CLI["scaffold complete"] --> MC["markCompleted (async)
|
|
656
|
+
saveState → set completed_at"]
|
|
657
|
+
MC --> RPA["runPhaseAudit
|
|
658
|
+
H-cross-doc · docs · fast"]
|
|
659
|
+
RPA --> OUT["docs/audits/id.md + .json
|
|
660
|
+
PhaseAuditResult → stdout line"]
|
|
661
|
+
MC -.->|state already saved — audit error never rolls it back| NG["non-gating"]
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
The audit is fixed to `H-cross-doc`, `scope=docs`, `profile=fast`
|
|
665
|
+
(`src/observability/engine/phase-audit.ts`). It is **non-gating**:
|
|
666
|
+
`markCompleted` catches any audit error and returns a result object, so a state
|
|
667
|
+
transition never fails because of the audit.
|
|
668
|
+
|
|
669
|
+
The stdout line:
|
|
670
|
+
|
|
671
|
+
```text
|
|
672
|
+
# normal
|
|
673
|
+
[audit] 3 findings (1 blocking, verdict=blocked) — see docs/audits/audit-…-fast-lens-H-cross-doc-….md
|
|
674
|
+
# detached (fire-and-forget)
|
|
675
|
+
[audit] dispatched in background (step: tech-stack)
|
|
676
|
+
# timed out
|
|
677
|
+
[audit] timed out after 60500ms — partial findings may not be written
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### Config & timestamps
|
|
681
|
+
|
|
682
|
+
| key | default | effect |
|
|
683
|
+
| --- | --- | --- |
|
|
684
|
+
| `phase_audit.enabled` | `true` | master switch |
|
|
685
|
+
| `phase_audit.timeout_s` | `60` | race budget; over → `timed_out` |
|
|
686
|
+
| `phase_audit.detached` | `false` | fire-and-forget when true |
|
|
687
|
+
|
|
688
|
+
Step state (`src/types/state.ts`) now carries `completed_at` (set once, on first
|
|
689
|
+
completion) and `in_progress_started_at` (set on first entry to in-progress). The
|
|
690
|
+
`state` adapter's `replayEvents` prefers these per-step timestamps and only falls
|
|
691
|
+
back to the file's mtime when they're absent — so the timeline reflects when each
|
|
692
|
+
step actually transitioned, not when the file was last written.
|
|
693
|
+
|
|
694
|
+
## MMR `doc-conformance` channel
|
|
695
|
+
|
|
696
|
+
The audit plugs into multi-model review as a built-in channel.
|
|
697
|
+
`scaffold observe audit --output-mode=mmr-findings` emits findings in MMR's
|
|
698
|
+
`Finding` shape (`src/observability/renderers/mmr-findings.ts`), always exiting 0
|
|
699
|
+
so the dispatcher captures stdout regardless of verdict. Only `open` findings are
|
|
700
|
+
emitted (acknowledged and skipped are dropped).
|
|
701
|
+
|
|
702
|
+
### Finding translation
|
|
703
|
+
|
|
704
|
+
The composite `location` — `<source_doc>::<lens_id>::<short_id>` — gives each
|
|
705
|
+
finding a stable identity across audit runs, so MMR can track the same defect
|
|
706
|
+
over time.
|
|
707
|
+
|
|
708
|
+
| MMR field | derived from |
|
|
709
|
+
| --- | --- |
|
|
710
|
+
| `severity` | `finding.severity` (P0–P3) |
|
|
711
|
+
| `location` | `${source_doc \|\| '(no-source-doc)'}::${lens_id}::${id.slice(0,8)}` |
|
|
712
|
+
| `description` | `[doc-conformance/${lens_id}] ${title}` + optional `— ${description}` |
|
|
713
|
+
| `suggestion` | `fix_hint?.prompt ?? fix_hint?.target ?? ''` |
|
|
714
|
+
| `category` | literal `'doc-conformance'` |
|
|
715
|
+
|
|
716
|
+
A Lens-B engine `Finding` like this:
|
|
717
|
+
|
|
718
|
+
```json
|
|
719
|
+
{
|
|
720
|
+
"id": "3a8c1f0211223344", "lens_id": "B-ac-coverage", "severity": "P0",
|
|
721
|
+
"title": "AC has failing test", "description": "Test refresh.spec.ts is failing.",
|
|
722
|
+
"source_doc": "docs/user-stories.md#user-auth-1",
|
|
723
|
+
"fix_hint": { "prompt": "Re-enable the test", "target": "src/auth/test.spec.ts" }
|
|
724
|
+
}
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
translates to this MMR Finding:
|
|
728
|
+
|
|
729
|
+
```json
|
|
730
|
+
{
|
|
731
|
+
"location": "docs/user-stories.md#user-auth-1::B-ac-coverage::3a8c1f02",
|
|
732
|
+
"severity": "P0",
|
|
733
|
+
"description": "[doc-conformance/B-ac-coverage] AC has failing test — Test refresh.spec.ts is failing.",
|
|
734
|
+
"suggestion": "Re-enable the test",
|
|
735
|
+
"category": "doc-conformance"
|
|
736
|
+
}
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
### Enabling it
|
|
740
|
+
|
|
741
|
+
The `doc-conformance` channel is **disabled by default**. Enable it per-project in
|
|
742
|
+
`.mmr.yaml` or for a single run with `--channels=doc-conformance`; if it's
|
|
743
|
+
globally enabled you can opt a project out via
|
|
744
|
+
`channels_disabled: ["doc-conformance"]`.
|
|
745
|
+
|
|
746
|
+
```bash
|
|
747
|
+
mmr review --channels=doc-conformance --diff <(git diff main...HEAD) --sync --format json
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
Under the hood the built-in channel runs `scaffold observe audit --profile=full
|
|
751
|
+
--scope=all --output-mode=mmr-findings` and parses its stdout. See the MMR guide
|
|
752
|
+
([../mmr/index.md](../mmr/index.md)) for the channel architecture this plugs
|
|
753
|
+
into.
|
|
754
|
+
|
|
755
|
+
## The `--fix` flow
|
|
756
|
+
|
|
757
|
+
`scaffold observe audit --fix` doesn't just report blocking findings — it
|
|
758
|
+
dispatches an agent to fix each one, verifies the fix with a single-lens
|
|
759
|
+
re-audit, and writes a post-fix report. The loop is abort-aware: an interrupt
|
|
760
|
+
un-stages what the loop staged and re-applies the original stash (see the
|
|
761
|
+
limitation in [Abort safety](#abort-safety)).
|
|
762
|
+
|
|
763
|
+
```mermaid
|
|
764
|
+
flowchart LR
|
|
765
|
+
P1["1 · audit
|
|
766
|
+
collect findings + verdict"] --> P2["2 · buildFixPlan
|
|
767
|
+
keep open & ≥ threshold;
|
|
768
|
+
order by severity then lens"]
|
|
769
|
+
P2 --> P3["3 · dispatchFixAgent
|
|
770
|
+
subprocess, prompt on stdin"]
|
|
771
|
+
P3 --> P4["4 · verify
|
|
772
|
+
re-run that one lens; retry ≤ 3"]
|
|
773
|
+
P4 --> P5["5 · post-fix report
|
|
774
|
+
docs/audits/id-postfix.{md,json}"]
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
### The five phases
|
|
778
|
+
|
|
779
|
+
- **1 · audit** — run the audit to get findings and the verdict
|
|
780
|
+
(`src/observability/engine/fix-flow.ts`).
|
|
781
|
+
- **2 · `buildFixPlan`** (`src/observability/engine/fix-plan.ts`) — keep findings
|
|
782
|
+
that are `open` and at/above `fix_threshold`, ordered by severity ascending (P0
|
|
783
|
+
first) then `lens_id`.
|
|
784
|
+
- **3 · `dispatchFixAgent`** (`src/observability/engine/fix-agent-dispatcher.ts`)
|
|
785
|
+
— spawn the dispatcher command, write the per-finding prompt to stdin, stream
|
|
786
|
+
stdout/stderr to the user.
|
|
787
|
+
- **4 · single-lens verify** — re-run only the finding's lens; if the finding is
|
|
788
|
+
gone, mark fixed; else retry, up to `per_finding_max_attempts` (default 3).
|
|
789
|
+
- **5 · post-fix report** — a final `scope=all` audit, written to
|
|
790
|
+
`docs/audits/<id>-postfix.{md,json}`.
|
|
791
|
+
|
|
792
|
+
### Abort safety
|
|
793
|
+
|
|
794
|
+
Before dispatching, `captureSnapshot`
|
|
795
|
+
(`src/observability/engine/abort-snapshot.ts`) records a `git stash create` SHA
|
|
796
|
+
plus the set of pre-existing staged files. Newly staged paths are tracked per
|
|
797
|
+
attempt. On `SIGINT`, `restoreSnapshot` un-stages the paths the loop recorded as
|
|
798
|
+
newly staged and re-applies the original stash tree. **Limitation:** edits the
|
|
799
|
+
dispatcher made but that the loop did not record as staged are not actively
|
|
800
|
+
reverted and may need manual cleanup — recovery is scoped to the recorded
|
|
801
|
+
staged paths plus the stash, not a guaranteed full reset.
|
|
802
|
+
|
|
803
|
+
### Config — the `fix:` block
|
|
804
|
+
|
|
805
|
+
| key | default | effect |
|
|
806
|
+
| --- | --- | --- |
|
|
807
|
+
| `fix.dispatcher_command` | `claude -p` | the agent command (configurable — see note) |
|
|
808
|
+
| `fix.timeout_s` | `300` | per-finding subprocess budget |
|
|
809
|
+
| `fix.per_finding_max_attempts` | `3` | verify retries before giving up |
|
|
810
|
+
|
|
811
|
+
:::callout{type=note}
|
|
812
|
+
**The fix dispatcher IS configurable — unlike Lens H's.**
|
|
813
|
+
`fix.dispatcher_command` is read from project config because the fix loop only
|
|
814
|
+
runs against the maintainer's own repo, not untrusted third-party code
|
|
815
|
+
(`src/observability/engine/fix-agent-dispatcher.ts`). This is the opposite of the
|
|
816
|
+
Lens H LLM dispatcher, which hard-codes its command for untrusted-repo safety.
|
|
817
|
+
CLAUDE.md's `--fix` note describing the dispatcher as "not
|
|
818
|
+
project-config-overridable" conflates the two.
|
|
819
|
+
:::
|
|
820
|
+
|
|
821
|
+
Exit code: `1` if any blocking finding survived the loop, else `0`.
|
|
822
|
+
|
|
823
|
+
## Harvest, recover & teardown
|
|
824
|
+
|
|
825
|
+
A worktree's ledger is local to that worktree. Harvest copies it into the primary
|
|
826
|
+
repo's archive before the worktree is removed; recover sweeps up ledgers whose
|
|
827
|
+
worktrees vanished without being harvested; teardown does the whole dance in one
|
|
828
|
+
command.
|
|
829
|
+
|
|
830
|
+
```mermaid
|
|
831
|
+
flowchart LR
|
|
832
|
+
WT["worktree ledger
|
|
833
|
+
.scaffold/activity.jsonl"] -->|harvest| AA["active-archive
|
|
834
|
+
activity-archive/active/id.jsonl"]
|
|
835
|
+
AA -->|"recover (worktree gone)"| MA["monthly archive
|
|
836
|
+
activity-archive/YYYY-MM.jsonl"]
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
### Commands
|
|
840
|
+
|
|
841
|
+
- **`scaffold observe harvest --worktree=<path>`** — read the worktree's
|
|
842
|
+
`identity.json`, then copy its `activity.jsonl` to
|
|
843
|
+
`.scaffold/activity-archive/active/<worktree_id>.jsonl` in the primary repo
|
|
844
|
+
(atomic temp-file + rename under a lock; keyed by `worktree_id`, idempotent
|
|
845
|
+
full-file replace). Requires the primary root to be a real repo, not itself a
|
|
846
|
+
worktree.
|
|
847
|
+
- **`scaffold observe harvest --recover`** — list live worktrees
|
|
848
|
+
(`git worktree list --porcelain`), read each one's `worktree_id`, then scan
|
|
849
|
+
`active/` for entries whose worktree is no longer live and rotate each into
|
|
850
|
+
`activity-archive/<YYYY-MM>.jsonl` (bucketed by the file's mtime), deleting the
|
|
851
|
+
active entry. Returns the rotated ids.
|
|
852
|
+
- **`scripts/teardown-agent-worktree.sh <path>`** — derives the primary repo via
|
|
853
|
+
`git -C <path> rev-parse --git-common-dir` (so it works from anywhere),
|
|
854
|
+
harvests (fail-soft), runs `git worktree remove`, then deletes the workspace
|
|
855
|
+
branch if it differs from the primary HEAD.
|
|
856
|
+
|
|
857
|
+
:::callout{type=note}
|
|
858
|
+
**Empty ledgers are fine.** If a worktree never wrote an `activity.jsonl`,
|
|
859
|
+
harvest is a clean no-op and teardown proceeds.
|
|
860
|
+
:::
|
|
861
|
+
|
|
862
|
+
## Renderers
|
|
863
|
+
|
|
864
|
+
One `EngineOutput`, several surfaces. The terminal renderer is for humans at a
|
|
865
|
+
prompt; the markdown renderer writes a durable report plus a machine-readable
|
|
866
|
+
JSON sidecar; the dashboard-fragment renderer emits an HTML panel that
|
|
867
|
+
`scripts/generate-dashboard.sh` injects at named anchors.
|
|
868
|
+
|
|
869
|
+
Default audit/progress runs write both a markdown report and a JSON sidecar:
|
|
870
|
+
audits to `docs/audits/<id>.{md,json}`, progress to
|
|
871
|
+
`docs/build-status/<id>.{md,json}` (`src/observability/renderers/sidecar.ts`).
|
|
872
|
+
`--render` and `--output-mode` bypass the files and print to stdout instead.
|
|
873
|
+
|
|
874
|
+
The same blocked audit renders three ways. As terminal ANSI:
|
|
875
|
+
|
|
876
|
+
```text
|
|
877
|
+
build observability — audit
|
|
878
|
+
(profile: fast · scope: all)
|
|
879
|
+
|
|
880
|
+
[P0] AC has failing test
|
|
881
|
+
lens: B-ac-coverage
|
|
882
|
+
fix: Re-enable the test
|
|
883
|
+
|
|
884
|
+
verdict: blocked
|
|
885
|
+
(blocking 1 · ack 0 · total 1)
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
As markdown (`docs/audits/<id>.md`):
|
|
889
|
+
|
|
890
|
+
```text
|
|
891
|
+
# Build Observability — Audit
|
|
892
|
+
|
|
893
|
+
**Verdict:** blocked
|
|
894
|
+
|
|
895
|
+
## Summary
|
|
896
|
+
1 findings · 1 blocking (at or above P2) · 0 acknowledged · 0 skipped lenses
|
|
897
|
+
|
|
898
|
+
### [P0] B-ac-coverage — AC has failing test
|
|
899
|
+
`3a8c1f02` · *source:* `…#user-auth-1` · *confidence:* high
|
|
900
|
+
```
|
|
901
|
+
|
|
902
|
+
As a dashboard fragment, an HTML `<section id="build-audit" data-verdict="blocked">`
|
|
903
|
+
panel injected into the dashboard.
|
|
904
|
+
|
|
905
|
+
| renderer | file | destination | notes |
|
|
906
|
+
| --- | --- | --- | --- |
|
|
907
|
+
| terminal | `src/observability/renderers/terminal.ts` | stdout | ANSI, "Needs Attention" banner + timeline |
|
|
908
|
+
| markdown | `src/observability/renderers/markdown.ts` | `docs/audits/` · `docs/build-status/` | full findings, evidence, fix hints |
|
|
909
|
+
| sidecar JSON | `src/observability/renderers/sidecar.ts` | alongside the markdown | redacted `EngineOutput`; read by the `audit_history` adapter |
|
|
910
|
+
| dashboard fragment | `src/observability/renderers/dashboard.ts` | stdout → dashboard | sections `build-progress` / `build-audit` injected by `scripts/generate-dashboard.sh` |
|
|
911
|
+
| mmr-findings | `src/observability/renderers/mmr-findings.ts` | stdout | MMR Finding shape |
|
|
912
|
+
|
|
913
|
+
## Config reference
|
|
914
|
+
|
|
915
|
+
All tunables live in `.scaffold/observability.yaml`. The file is optional — when
|
|
916
|
+
absent, `DEFAULT_CONFIG` applies wholesale
|
|
917
|
+
(`src/observability/engine/checks/observability-config.ts`). A malformed or
|
|
918
|
+
unreadable file *silently* falls back to defaults. Merging is a deep merge where
|
|
919
|
+
objects merge key-by-key but **arrays and scalars replace wholesale** — so
|
|
920
|
+
setting `disabled_lenses` or `rule_overrides` overwrites the default rather than
|
|
921
|
+
extending it.
|
|
922
|
+
|
|
923
|
+
:::callout{type=warning}
|
|
924
|
+
**The shipped example file is misleading.** The repo's
|
|
925
|
+
`.scaffold/observability.yaml` contains only `knowledge_freshness.link_check.skip`
|
|
926
|
+
and a comment claiming "other observability features read configuration from
|
|
927
|
+
elsewhere." In fact the code reads many more keys — the example file simply omits
|
|
928
|
+
them because they all have working defaults. The defaults documented here come
|
|
929
|
+
from the code, which is ground truth.
|
|
930
|
+
:::
|
|
931
|
+
|
|
932
|
+
:::filter-table
|
|
933
|
+
| key | type | default | read by |
|
|
934
|
+
| --- | --- | --- | --- |
|
|
935
|
+
| `lenses.C-standards.enforce_via_linter` | boolean | `true` | (accepted, not read) |
|
|
936
|
+
| `lenses.C-standards.rule_overrides` | map<rule, P0–P3> | `{}` | lenses · Lens C |
|
|
937
|
+
| `lenses.C-standards.escalation_threshold` | number | `5` | lenses · Lens C |
|
|
938
|
+
| `lenses.D-stack.path_to_layer` | {glob,layer}[] | 7 default mappings | lenses · Lens D |
|
|
939
|
+
| `lenses.E-design.ad_hoc_token_threshold` | number | `3` | lenses · Lens E |
|
|
940
|
+
| `lenses.E-design.ui_glob` | glob | `src/components/**/*.tsx` | lenses · doc-graph builder |
|
|
941
|
+
| `lenses.F-scope.untouched_story_grace_hours` | number | `168` | lenses · Lens F |
|
|
942
|
+
| `lenses.G-decisions.keywords_file` | path | — (inert) | lenses · (no reader) |
|
|
943
|
+
| `lenses.H-cross-doc.skip_phase_subsets` | string[] | — (inert) | lenses · (no reader) |
|
|
944
|
+
| `lenses.I-knowledge-gaps.knowledge_root` | path | auto-detect | lenses · Lens I |
|
|
945
|
+
| `disabled_lenses` | string[] | `[]` | lenses · runner |
|
|
946
|
+
| `phase_audit.enabled` | boolean | `true` | phase_audit |
|
|
947
|
+
| `phase_audit.timeout_s` | number | `60` | phase_audit |
|
|
948
|
+
| `phase_audit.detached` | boolean | `false` | phase_audit |
|
|
949
|
+
| `stall.task_stale` | 'Nh'·'Nd'·'off' | `4h` | stall |
|
|
950
|
+
| `stall.pr_stale` | 'Nh'·'Nd'·'off' | `48h` | stall |
|
|
951
|
+
| `stall.pr_review_stale` | 'Nh'·'Nd'·'off' | `24h` (reserved) | stall (signal not yet emitted) |
|
|
952
|
+
| `stall.blocker_unaddressed` | 'Nh'·'Nd'·'off' | `2h` | stall |
|
|
953
|
+
| `stall.audit_findings_unresolved` | 'Nh'·'Nd'·'off' | `24h` | stall |
|
|
954
|
+
| `llm.timeout_s` | number | `60` | llm · Lens H dispatcher |
|
|
955
|
+
| `llm.parallel_checks` | boolean | `false` | llm · Lens H |
|
|
956
|
+
| `fix.dispatcher_command` | shell command | `claude -p` | fix · dispatcher |
|
|
957
|
+
| `fix.timeout_s` | number | `300` | fix |
|
|
958
|
+
| `fix.per_finding_max_attempts` | number | `3` | fix |
|
|
959
|
+
| `knowledge_freshness.link_check.skip` | string[] | `[]` | knowledge-freshness (separate loader) |
|
|
960
|
+
:::
|
|
961
|
+
|
|
962
|
+
:::callout{type=note}
|
|
963
|
+
**No `llm.dispatcher_command`, no `F-scope.wave_budget`.** Two keys you might
|
|
964
|
+
expect are deliberately absent. The Lens H LLM command is hard-coded (security) —
|
|
965
|
+
there is no `llm.dispatcher_command` key. And there is no wave/phase-budget key at
|
|
966
|
+
all: `F-scope` reads only `untouched_story_grace_hours` from this file, so the
|
|
967
|
+
"wave budget" CLAUDE.md implies does not exist in the config.
|
|
968
|
+
:::
|
|
969
|
+
|
|
970
|
+
Example:
|
|
971
|
+
|
|
972
|
+
```yaml
|
|
973
|
+
lenses:
|
|
974
|
+
C-standards:
|
|
975
|
+
enforce_via_linter: true
|
|
976
|
+
rule_overrides:
|
|
977
|
+
no-console: P1
|
|
978
|
+
E-design:
|
|
979
|
+
ad_hoc_token_threshold: 5
|
|
980
|
+
disabled_lenses: []
|
|
981
|
+
phase_audit:
|
|
982
|
+
enabled: true
|
|
983
|
+
timeout_s: 60
|
|
984
|
+
stall:
|
|
985
|
+
task_stale: '6h'
|
|
986
|
+
fix:
|
|
987
|
+
per_finding_max_attempts: 3
|
|
988
|
+
# shared with the knowledge-freshness subsystem
|
|
989
|
+
knowledge_freshness:
|
|
990
|
+
link_check:
|
|
991
|
+
skip:
|
|
992
|
+
- platform.openai.com
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
## Where it lives
|
|
996
|
+
|
|
997
|
+
The whole system lives under `src/observability/`, plus the state-manager hook
|
|
998
|
+
and two shell scripts.
|
|
999
|
+
|
|
1000
|
+
| file | purpose |
|
|
1001
|
+
| --- | --- |
|
|
1002
|
+
| `src/observability/engine/ledger-writer.ts` | validate → redact → 4 KiB check → locked append |
|
|
1003
|
+
| `src/observability/engine/event-schemas.ts` | per-type payload allow-lists + validation |
|
|
1004
|
+
| `src/observability/engine/redact.ts` | write-time + render-time secret/path scrubbing |
|
|
1005
|
+
| `src/observability/engine/identity.ts` | worktree identity.json |
|
|
1006
|
+
| `src/observability/engine/harvester.ts` | harvest worktree ledger + `--recover` rotation |
|
|
1007
|
+
| `src/observability/engine/synthesizer.ts` | composeReplay: fuse + correlation_id dedup + source priority |
|
|
1008
|
+
| `src/observability/engine/api.ts` | runAudit / runProgress; scope→lens; verdict |
|
|
1009
|
+
| `src/observability/engine/stall.ts` | the stall signals + Needs-Attention surface |
|
|
1010
|
+
| `src/observability/engine/phase-audit.ts` | runPhaseAudit + formatPhaseAuditLine |
|
|
1011
|
+
| `src/observability/engine/phase-subsets.ts` | PHASE_BOUNDARY_STEPS + isPhaseBoundary |
|
|
1012
|
+
| `src/observability/engine/fix-flow.ts` | the five-phase `--fix` loop |
|
|
1013
|
+
| `src/observability/engine/fix-plan.ts` | buildFixPlan: filter + order findings |
|
|
1014
|
+
| `src/observability/engine/fix-agent-dispatcher.ts` | configurable subprocess fix dispatcher |
|
|
1015
|
+
| `src/observability/engine/abort-snapshot.ts` | capture/restore git stash on SIGINT |
|
|
1016
|
+
| `src/observability/engine/llm-dispatcher.ts` | hard-coded `claude -p` for Lens H full profile |
|
|
1017
|
+
| `src/observability/engine/types.ts` | Verdict, AdapterId, EngineOutput, Finding |
|
|
1018
|
+
| `src/observability/engine/checks/registry.ts` | LENS_REGISTRY (A–I) + implementations |
|
|
1019
|
+
| `src/observability/engine/checks/fix-threshold.ts` | resolve fix_threshold (default P2) |
|
|
1020
|
+
| `src/observability/engine/checks/findings-aggregator.ts` | tally blocking/acked; compute verdict |
|
|
1021
|
+
| `src/observability/engine/checks/observability-config.ts` | DEFAULT_CONFIG + deep-merge loader |
|
|
1022
|
+
| `src/observability/engine/doc-graph/index.ts` | build the doc graph from planning docs |
|
|
1023
|
+
| `src/observability/checks/lens-a-tdd.ts` | A · skipped tests |
|
|
1024
|
+
| `src/observability/checks/lens-b-ac-coverage.ts` | B · AC ↔ test coverage |
|
|
1025
|
+
| `src/observability/checks/lens-c-standards.ts` | C · coding-standards drift |
|
|
1026
|
+
| `src/observability/checks/lens-d-stack.ts` | D · tech-stack drift |
|
|
1027
|
+
| `src/observability/checks/lens-e-design.ts` | E · design-system drift |
|
|
1028
|
+
| `src/observability/checks/lens-f-scope.ts` | F · missing scope |
|
|
1029
|
+
| `src/observability/checks/lens-g-decisions.ts` | G · undocumented decisions |
|
|
1030
|
+
| `src/observability/checks/lens-h-cross-doc.ts` | H · cross-doc consistency + LLM checks |
|
|
1031
|
+
| `src/observability/checks/lens-i-knowledge-gaps.ts` | I · knowledge gaps |
|
|
1032
|
+
| `src/observability/checks/lens-i-lessons-scanner.ts` | scan tasks/lessons.md for gap signals |
|
|
1033
|
+
| `src/observability/knowledge-index.ts` | resolveKnowledgeRoot (3 tiers) + index for Lens I |
|
|
1034
|
+
| `src/observability/renderers/terminal.ts` | ANSI output |
|
|
1035
|
+
| `src/observability/renderers/markdown.ts` | markdown report |
|
|
1036
|
+
| `src/observability/renderers/dashboard.ts` | build-progress / build-audit HTML fragments |
|
|
1037
|
+
| `src/observability/renderers/sidecar.ts` | JSON sidecar + report-id derivation |
|
|
1038
|
+
| `src/observability/renderers/mmr-findings.ts` | MMR Finding shape |
|
|
1039
|
+
| `src/state/state-manager.ts` | async markCompleted → runPhaseAudit hook |
|
|
1040
|
+
| `scripts/teardown-agent-worktree.sh` | harvest → remove → delete branch |
|
|
1041
|
+
| `scripts/generate-dashboard.sh` | injects the dashboard fragments |
|
|
1042
|
+
|
|
1043
|
+
The full design lives in
|
|
1044
|
+
`docs/superpowers/specs/2026-04-30-build-observability-design.md`.
|
|
1045
|
+
|
|
1046
|
+
## Shipping history
|
|
1047
|
+
|
|
1048
|
+
Build Observability shipped as eight plans (Foundation → Fix-flow), released
|
|
1049
|
+
together as `v3.26.0 — Build Observability` on 2026-05-07, with Lens I and
|
|
1050
|
+
refinements following after.
|
|
1051
|
+
|
|
1052
|
+
:::filter-table
|
|
1053
|
+
| plan | subsystem | squash | PR | added to the on-disk surface |
|
|
1054
|
+
| --- | --- | --- | --- | --- |
|
|
1055
|
+
| spec + plans | design doc + 8 plans | `5cf689c4` | #319 | `docs/superpowers/specs` + 8 plan files |
|
|
1056
|
+
| 1 · Foundation | identity, validation, redaction, ledger, harvester, adapters, synthesizer, API, CLI, renderers | `21124010` (+ #320–328) | #320–329 | most of `src/observability/engine`, `adapters`, `renderers`; `scaffold observe` |
|
|
1057
|
+
| 2 · Audit MVP | doc-graph, checks framework, lenses A/B/H, `audit`+`ack` | `8eb70986` | #331 | `engine/doc-graph`, `engine/checks`, `lens-a/b/h` |
|
|
1058
|
+
| 3 · Full lens suite | lenses C/D/E/F/G + registry + config | `bd014634` | #332 | `lens-c…g`, `registry.ts`, `.scaffold/observability.yaml` |
|
|
1059
|
+
| 4 · Renderers + history | markdown, JSON sidecars, dashboard fragments, audit-history | `37f63ae4` | #333 | `docs/build-status`, `docs/audits`, `audit-history` adapter |
|
|
1060
|
+
| 5 · Replay + stall | replay timeline, stall detection, Lens G keyword scan | `cdbfd1de` | #334 | `synthesizer.composeReplay`, `stall.ts`, Needs-Attention surfaces |
|
|
1061
|
+
| 6 · Phase triggers | `markCompleted` async → `runPhaseAudit` | `ff04a1a6` | #335 | `phase-audit.ts`, `phase-subsets.ts`, step timestamps |
|
|
1062
|
+
| 7 · MMR channel | `doc-conformance` channel + Lens H full-profile LLM checks | `8b723617` | #336 | `mmr-findings.ts`, `llm-dispatcher.ts`, Lens H sub-checks |
|
|
1063
|
+
| 8 · Fix flow + teardown | `--fix` loop, `harvest --recover`, teardown script | `06fca3ef` (v3.26.0) | #337 | `fix-flow.ts`, `fix-plan.ts`, `fix-agent-dispatcher.ts`, `abort-snapshot.ts`, `teardown-agent-worktree.sh` |
|
|
1064
|
+
| follow-on | Lens I — knowledge gaps + lessons scanner | `31e45f03` | #397 | `lens-i-knowledge-gaps.ts`, `lens-i-lessons-scanner.ts` |
|
|
1065
|
+
| follow-on | Lens I — `--knowledge-root` + existing-entry suppression | `46a47037` | #406 | `knowledge-index.ts` resolver tiers |
|
|
1066
|
+
| follow-on | TypeScript cleanup (`as never` → typed `isOneOf`) | `362c7f93` | #411 | type-safety refactor across observability |
|
|
1067
|
+
:::
|
|
1068
|
+
|
|
1069
|
+
## Known divergences
|
|
1070
|
+
|
|
1071
|
+
The audit's own rule — "code is ground truth where it disagrees with the spec or
|
|
1072
|
+
the docs" — surfaced these mismatches. They are deferred findings to resolve in
|
|
1073
|
+
the code/docs:
|
|
1074
|
+
|
|
1075
|
+
- **9 lenses, not 8.** The design spec and CLAUDE.md enumerate A–H;
|
|
1076
|
+
`I-knowledge-gaps` shipped and is registered.
|
|
1077
|
+
- **`pr_opened` vs `pr_open`.** CLAUDE.md abbreviates the event type as
|
|
1078
|
+
`pr_open`; the code only emits `pr_opened`.
|
|
1079
|
+
- **Three engine verdicts, not four.** `needs-user-decision` is an MMR review
|
|
1080
|
+
verdict; the audit engine emits only `pass` / `degraded-pass` / `blocked`.
|
|
1081
|
+
- **Two dispatchers — don't conflate them.** CLAUDE.md's "not
|
|
1082
|
+
project-config-overridable" note is about the **Lens H LLM dispatcher**
|
|
1083
|
+
(`llm-dispatcher.ts`, hard-coded `claude -p` by design). It does **not** apply
|
|
1084
|
+
to the separate **`--fix` agent dispatcher**, whose `fix.dispatcher_command`
|
|
1085
|
+
*is* project-configurable. The divergence is that the two are easy to conflate.
|
|
1086
|
+
- **`pr_review_stale` reserved.** The sixth stall signal has a config default but
|
|
1087
|
+
is not yet emitted (deferred pending a per-PR correlation_id on the mmr
|
|
1088
|
+
adapter).
|
|
1089
|
+
- **Inert config keys.** `lenses.G-decisions.keywords_file` and
|
|
1090
|
+
`lenses.H-cross-doc.skip_phase_subsets` are typed but unread; the bundled
|
|
1091
|
+
`decision-keywords.txt` is not loaded.
|
|
1092
|
+
- **No `F-scope.wave_budget` key.** CLAUDE.md implies a wave budget in
|
|
1093
|
+
`observability.yaml`; in fact no wave/phase budget is read anywhere — Lens F
|
|
1094
|
+
reads only `untouched_story_grace_hours`.
|
|
1095
|
+
- **`ui_glob` default narrower than spec.** Spec default covers
|
|
1096
|
+
`{tsx,jsx,vue,svelte}` + styles; shipped default is just
|
|
1097
|
+
`src/components/**/*.tsx`.
|