peaks-loop 4.0.0-beta.9 → 4.0.3
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/CHANGELOG.md +572 -234
- package/README-en.md +67 -30
- package/README.md +67 -30
- package/agents/karpathy-reviewer.md +33 -0
- package/bin/peaks.js +0 -0
- package/dist/cli/cli-helpers.d.ts +31 -6
- package/dist/cli/cli-helpers.js +48 -25
- package/dist/cli/commands/_register.d.ts +3 -0
- package/dist/cli/commands/_register.js +139 -0
- package/dist/cli/commands/_super.d.ts +10 -0
- package/dist/cli/commands/_super.js +97 -0
- package/dist/cli/commands/adapter-commands-s2a.js +1 -1
- package/dist/cli/commands/asset-commands.js +33 -16
- package/dist/cli/commands/audit-commands.js +2 -2
- package/dist/cli/commands/autonomous-swarm-commands.d.ts +12 -0
- package/dist/cli/commands/autonomous-swarm-commands.js +120 -0
- package/dist/cli/commands/bee-commands.js +1 -1
- package/dist/cli/commands/capability-commands.js +1 -1
- package/dist/cli/commands/capability-worker-config-sc-commands.js +0 -2
- package/dist/cli/commands/changeset-commands.d.ts +13 -0
- package/dist/cli/commands/changeset-commands.js +46 -0
- package/dist/cli/commands/code-commands.d.ts +11 -1
- package/dist/cli/commands/code-commands.js +19 -699
- package/dist/cli/commands/code-job-shape-commands.d.ts +9 -0
- package/dist/cli/commands/code-job-shape-commands.js +164 -0
- package/dist/cli/commands/code-mode-gate-commands.d.ts +9 -0
- package/dist/cli/commands/code-mode-gate-commands.js +223 -0
- package/dist/cli/commands/code-review-commands.js +2 -2
- package/dist/cli/commands/code-run-command.d.ts +12 -0
- package/dist/cli/commands/code-run-command.js +68 -0
- package/dist/cli/commands/code-runtime-commands.d.ts +11 -0
- package/dist/cli/commands/code-runtime-commands.js +391 -0
- package/dist/cli/commands/codegraph-commands.js +1 -1
- package/dist/cli/commands/compact-command.js +53 -1
- package/dist/cli/commands/complexity-commands.js +1 -1
- package/dist/cli/commands/config-commands.js +4 -75
- package/dist/cli/commands/container-commands.d.ts +28 -0
- package/dist/cli/commands/container-commands.js +221 -0
- package/dist/cli/commands/context-commands.js +3 -2
- package/dist/cli/commands/core/artifacts-command.js +1 -1
- package/dist/cli/commands/core/binding-commands.js +1 -1
- package/dist/cli/commands/core/doctor-command.js +63 -3
- package/dist/cli/commands/core/memory-command.js +1 -1
- package/dist/cli/commands/core/profile-command.js +1 -1
- package/dist/cli/commands/core/proxy-command.js +1 -1
- package/dist/cli/commands/core/session-command.js +9 -7
- package/dist/cli/commands/core/skill-command.js +7 -4
- package/dist/cli/commands/core/standards-command.js +1 -1
- package/dist/cli/commands/cron-commands.d.ts +57 -0
- package/dist/cli/commands/cron-commands.js +257 -0
- package/dist/cli/commands/cron-scheduler-commands.d.ts +47 -0
- package/dist/cli/commands/cron-scheduler-commands.js +284 -0
- package/dist/cli/commands/dashboard-commands.d.ts +4 -0
- package/dist/cli/commands/dashboard-commands.js +10 -0
- package/dist/cli/commands/dashboard-long-run.d.ts +25 -0
- package/dist/cli/commands/dashboard-long-run.js +122 -0
- package/dist/cli/commands/dashboard-summary.d.ts +12 -0
- package/dist/cli/commands/dashboard-summary.js +58 -0
- package/dist/cli/commands/dispatch-commands.d.ts +0 -7
- package/dist/cli/commands/dispatch-commands.js +372 -8
- package/dist/cli/commands/dispatch-from-dag.js +4 -1
- package/dist/cli/commands/doc-commands.js +1 -1
- package/dist/cli/commands/ecc-commands.d.ts +30 -0
- package/dist/cli/commands/ecc-commands.js +119 -0
- package/dist/cli/commands/evolution-commands.js +1 -1
- package/dist/cli/commands/feedback-commands.js +1 -1
- package/dist/cli/commands/final-review-commands.js +1 -1
- package/dist/cli/commands/fixture-commands.js +1 -1
- package/dist/cli/commands/fork-commands.js +1 -1
- package/dist/cli/commands/gate-commands.js +128 -6
- package/dist/cli/commands/governance-classify-contract-commands.d.ts +21 -0
- package/dist/cli/commands/governance-classify-contract-commands.js +273 -0
- package/dist/cli/commands/heartbeat-commands.js +76 -5
- package/dist/cli/commands/heartbeat-watch-command.d.ts +31 -0
- package/dist/cli/commands/heartbeat-watch-command.js +146 -0
- package/dist/cli/commands/hook-handle.js +1 -1
- package/dist/cli/commands/hooks-commands.js +126 -10
- package/dist/cli/commands/ide-commands.js +1 -1
- package/dist/cli/commands/impact-commands.js +1 -1
- package/dist/cli/commands/job-commands.js +34 -1
- package/dist/cli/commands/lease-metrics-commands.d.ts +67 -0
- package/dist/cli/commands/lease-metrics-commands.js +231 -0
- package/dist/cli/commands/lease-stats-commands.d.ts +65 -0
- package/dist/cli/commands/lease-stats-commands.js +107 -0
- package/dist/cli/commands/legacy-commands.js +1 -1
- package/dist/cli/commands/log-commands.js +1 -1
- package/dist/cli/commands/loop-commands.js +1 -1
- package/dist/cli/commands/loop-eval-commands.js +1 -1
- package/dist/cli/commands/memory-commands.js +1 -1
- package/dist/cli/commands/migrate-1-4-1-command.js +1 -1
- package/dist/cli/commands/migrate-v2-10-to-v2-11-command.js +1 -1
- package/dist/cli/commands/mut-commands.d.ts +1 -1
- package/dist/cli/commands/mut-commands.js +1 -5
- package/dist/cli/commands/observability-commands.js +1 -1
- package/dist/cli/commands/openspec-commands.js +65 -4
- package/dist/cli/commands/perf-audit-commands.js +3 -3
- package/dist/cli/commands/perf-commands.js +1 -1
- package/dist/cli/commands/polyrepo-commands.js +1 -1
- package/dist/cli/commands/prd-blocks-commands.js +1 -1
- package/dist/cli/commands/prd-commands.js +4 -2
- package/dist/cli/commands/preferences-commands.js +23 -3
- package/dist/cli/commands/project-commands.js +1 -1
- package/dist/cli/commands/qa-business-review-commands.js +1 -1
- package/dist/cli/commands/qa-commands.d.ts +1 -1
- package/dist/cli/commands/qa-commands.js +39 -3
- package/dist/cli/commands/release-commands.d.ts +15 -0
- package/dist/cli/commands/release-commands.js +113 -21
- package/dist/cli/commands/request-commands.js +1 -1
- package/dist/cli/commands/retrospective-commands.js +1 -1
- package/dist/cli/commands/reviewer-commands.js +1 -1
- package/dist/cli/commands/role-commands.js +1 -1
- package/dist/cli/commands/runtime-commands-helpers.d.ts +7 -0
- package/dist/cli/commands/runtime-commands-helpers.js +24 -0
- package/dist/cli/commands/runtime-commands.js +1 -2
- package/dist/cli/commands/sc-commands.js +4 -2
- package/dist/cli/commands/scan-commands.js +1 -1
- package/dist/cli/commands/security-audit-commands.js +3 -3
- package/dist/cli/commands/sediment-commands.js +10 -1
- package/dist/cli/commands/session-24h-mode.d.ts +26 -0
- package/dist/cli/commands/session-24h-mode.js +196 -0
- package/dist/cli/commands/share-commands.d.ts +19 -0
- package/dist/cli/commands/share-commands.js +121 -2
- package/dist/cli/commands/skill-conformance-commands.js +1 -1
- package/dist/cli/commands/skill-loop-engineering-readiness-commands.js +1 -1
- package/dist/cli/commands/skill-search-commands.js +4 -1
- package/dist/cli/commands/slice-commands.js +1 -1
- package/dist/cli/commands/slice-integrate-commands.js +1 -1
- package/dist/cli/commands/slice-review-commands.js +1 -1
- package/dist/cli/commands/smoke-commands.js +1 -1
- package/dist/cli/commands/sop-commands.js +1 -1
- package/dist/cli/commands/spill-demo-command.d.ts +7 -0
- package/dist/cli/commands/spill-demo-command.js +29 -0
- package/dist/cli/commands/statusline-commands.d.ts +12 -0
- package/dist/cli/commands/statusline-commands.js +79 -17
- package/dist/cli/commands/sub-agent-commands.js +2 -1
- package/dist/cli/commands/sub-agent-shared.d.ts +10 -0
- package/dist/cli/commands/sub-agent-shared.js +24 -1
- package/dist/cli/commands/swarm-commands.d.ts +13 -0
- package/dist/cli/commands/swarm-commands.js +77 -0
- package/dist/cli/commands/tech-commands.d.ts +64 -0
- package/dist/cli/commands/tech-commands.js +195 -0
- package/dist/cli/commands/understand-commands.js +1 -1
- package/dist/cli/commands/upgrade-commands.d.ts +2 -0
- package/dist/cli/commands/upgrade-commands.js +40 -5
- package/dist/cli/commands/user-touchpoint-commands.js +1 -1
- package/dist/cli/commands/verdict-aggregate-command.js +1 -1
- package/dist/cli/commands/vm-commands.d.ts +31 -0
- package/dist/cli/commands/vm-commands.js +274 -0
- package/dist/cli/commands/workflow-commands.js +24 -1
- package/dist/cli/commands/workflow-plan-commands.js +1 -1
- package/dist/cli/commands/workspace/init-command.js +1 -1
- package/dist/cli/commands/workspace/migrate-command.js +1 -1
- package/dist/cli/commands/workspace/reconcile-command.js +1 -1
- package/dist/cli/commands/worktree-auth-commands.d.ts +29 -0
- package/dist/cli/commands/worktree-auth-commands.js +652 -0
- package/dist/cli/index.js +58 -13
- package/dist/cli/program.d.ts +2 -2
- package/dist/cli/program.js +86 -281
- package/dist/services/24h-mode/decider.d.ts +103 -0
- package/dist/services/24h-mode/decider.js +144 -0
- package/dist/services/24h-mode/index.d.ts +12 -0
- package/dist/services/24h-mode/index.js +12 -0
- package/dist/services/24h-mode/state.d.ts +48 -0
- package/dist/services/24h-mode/state.js +51 -0
- package/dist/services/24h-mode/store.d.ts +27 -0
- package/dist/services/24h-mode/store.js +119 -0
- package/dist/services/artifacts/artifact-prerequisites.js +1 -1
- package/dist/services/artifacts/request-artifact-service.js +1 -1
- package/dist/services/artifacts/workspace-service.js +1 -1
- package/dist/services/audit/enforcers/lint-bee-runtime-contract.d.ts +25 -0
- package/dist/services/audit/enforcers/lint-bee-runtime-contract.js +91 -0
- package/dist/services/audit/enforcers/lint-peaks-code-runtime.d.ts +16 -0
- package/dist/services/audit/enforcers/lint-peaks-code-runtime.js +31 -0
- package/dist/services/audit/enforcers/lint-peaks-skill-runtime.d.ts +23 -0
- package/dist/services/audit/enforcers/lint-peaks-skill-runtime.js +59 -0
- package/dist/services/audit/enforcers/lint-peaks-ui-sc-txt-runtime.d.ts +28 -0
- package/dist/services/audit/enforcers/lint-peaks-ui-sc-txt-runtime.js +86 -0
- package/dist/services/audit/enforcers/lint-prd-artifact-handoff.d.ts +16 -0
- package/dist/services/audit/enforcers/lint-prd-artifact-handoff.js +41 -0
- package/dist/services/audit/enforcers/lint-prd-source-snapshot.d.ts +27 -0
- package/dist/services/audit/enforcers/lint-prd-source-snapshot.js +47 -0
- package/dist/services/audit/enforcers/lint-qa-gateguard-and-runtime.d.ts +19 -0
- package/dist/services/audit/enforcers/lint-qa-gateguard-and-runtime.js +47 -0
- package/dist/services/audit/enforcers/lint-rd-handoff-coverage.d.ts +18 -0
- package/dist/services/audit/enforcers/lint-rd-handoff-coverage.js +70 -0
- package/dist/services/audit/enforcers/lint-skill-presence-mandatory.d.ts +25 -0
- package/dist/services/audit/enforcers/lint-skill-presence-mandatory.js +53 -0
- package/dist/services/audit/red-line-catalog-p2-a.d.ts +0 -6
- package/dist/services/audit/red-line-catalog-p2-a.js +230 -1
- package/dist/services/audit/static-service.d.ts +32 -25
- package/dist/services/audit/static-service.js +30 -109
- package/dist/services/audit-independent/index.d.ts +2 -0
- package/dist/services/audit-independent/index.js +2 -0
- package/dist/services/autonomous-swarm/autonomous-swarm-service.d.ts +127 -0
- package/dist/services/autonomous-swarm/autonomous-swarm-service.js +446 -0
- package/dist/services/changeset/changeset-check-service.d.ts +22 -0
- package/dist/services/changeset/changeset-check-service.js +47 -0
- package/dist/services/code/auto-compact-modes.d.ts +30 -0
- package/dist/services/code/auto-compact-modes.js +38 -0
- package/dist/services/code/auto-compact-orchestrator.d.ts +43 -5
- package/dist/services/code/auto-compact-orchestrator.js +101 -21
- package/dist/services/code/dag-orchestrator.d.ts +30 -1
- package/dist/services/code/dag-orchestrator.js +106 -1
- package/dist/services/code/status-line-renderer.d.ts +2 -0
- package/dist/services/code/status-line-renderer.js +21 -3
- package/dist/services/code-review/ocr-service.d.ts +1 -1
- package/dist/services/code-review/ocr-service.js +6 -3
- package/dist/services/compact-history/compact-history-service.d.ts +41 -0
- package/dist/services/compact-history/compact-history-service.js +62 -0
- package/dist/services/compact-statusline/compact-statusline-service.d.ts +16 -0
- package/dist/services/compact-statusline/compact-statusline-service.js +83 -0
- package/dist/services/config/config-service.d.ts +1 -12
- package/dist/services/config/config-service.js +3 -72
- package/dist/services/config/config-types.d.ts +2 -4
- package/dist/services/config/config-types.js +1 -1
- package/dist/services/container/container-lease.d.ts +67 -0
- package/dist/services/container/container-lease.js +135 -0
- package/dist/services/context/auto-compact-dispatcher.d.ts +40 -5
- package/dist/services/context/auto-compact-dispatcher.js +32 -102
- package/dist/services/context/auto-compact-reader.js +1 -1
- package/dist/services/context/auto-compact-types.d.ts +27 -2
- package/dist/services/context/auto-compact-types.js +8 -1
- package/dist/services/context/build-dispatch-system-prompt.d.ts +75 -0
- package/dist/services/context/build-dispatch-system-prompt.js +117 -0
- package/dist/services/context/collector.d.ts +2 -2
- package/dist/services/context/context-builder.d.ts +4 -4
- package/dist/services/context/context-schema.d.ts +48 -48
- package/dist/services/context/ide-detect.d.ts +4 -0
- package/dist/services/context/ide-detect.js +24 -0
- package/dist/services/context/main-session-monitor.d.ts +1 -4
- package/dist/services/context/main-session-monitor.js +1 -24
- package/dist/services/context/memory-index-reader.d.ts +8 -0
- package/dist/services/context/memory-index-reader.js +57 -0
- package/dist/services/context/memory-lru-cache.d.ts +12 -0
- package/dist/services/context/memory-lru-cache.js +60 -0
- package/dist/services/context/memory-preflight-config.d.ts +19 -0
- package/dist/services/context/memory-preflight-config.js +25 -0
- package/dist/services/context/memory-preflight-service.d.ts +19 -0
- package/dist/services/context/memory-preflight-service.js +120 -0
- package/dist/services/context/spillover-store.d.ts +23 -0
- package/dist/services/context/spillover-store.js +155 -0
- package/dist/services/context/spillover-types.d.ts +18 -0
- package/dist/services/context/spillover-types.js +1 -0
- package/dist/services/crystallization/crystallization-service.d.ts +22 -5
- package/dist/services/crystallization/crystallization-service.js +8 -14
- package/dist/services/crystallization/crystallization-types.d.ts +6 -6
- package/dist/services/crystallization/evidence-brief-builder.d.ts +1 -1
- package/dist/services/crystallization/index.d.ts +13 -0
- package/dist/services/crystallization/index.js +13 -0
- package/dist/services/dashboard/project-dashboard-service.js +2 -2
- package/dist/services/dispatch/await-batch.d.ts +70 -0
- package/dist/services/dispatch/await-batch.js +272 -0
- package/dist/services/dispatch/batch-counter.js +1 -1
- package/dist/services/dispatch/dispatch-record-writer.d.ts +126 -4
- package/dist/services/dispatch/dispatch-record-writer.js +239 -9
- package/dist/services/dispatch/slice-dag.d.ts +46 -0
- package/dist/services/dispatch/slice-dag.js +6 -0
- package/dist/services/dispatch/stage-enum.d.ts +27 -0
- package/dist/services/dispatch/stage-enum.js +48 -0
- package/dist/services/dispatch/startup-timeout.d.ts +86 -0
- package/dist/services/dispatch/startup-timeout.js +97 -0
- package/dist/services/dispatch/sub-agent-dispatcher.js +40 -89
- package/dist/services/dispatch/test-tool-detection.d.ts +25 -1
- package/dist/services/dispatch/test-tool-detection.js +80 -0
- package/dist/services/doctor/doctor-service/checks/check-id-schema.d.ts +18 -0
- package/dist/services/doctor/doctor-service/checks/check-id-schema.js +64 -0
- package/dist/services/doctor/doctor-service/checks/codegraph-capability.d.ts +14 -0
- package/dist/services/doctor/doctor-service/checks/codegraph-capability.js +69 -0
- package/dist/services/doctor/doctor-service/checks/dist-source-version.d.ts +32 -0
- package/dist/services/doctor/doctor-service/checks/dist-source-version.js +110 -0
- package/dist/services/doctor/doctor-service/checks/gateguard-conflict.d.ts +24 -0
- package/dist/services/doctor/doctor-service/checks/gateguard-conflict.js +164 -0
- package/dist/services/doctor/doctor-service/checks/l3-memory-health.d.ts +16 -0
- package/dist/services/doctor/doctor-service/checks/l3-memory-health.js +57 -0
- package/dist/services/doctor/doctor-service/checks/l3-orphan-sessions.d.ts +19 -0
- package/dist/services/doctor/doctor-service/checks/l3-orphan-sessions.js +66 -0
- package/dist/services/doctor/doctor-service/checks/schema-validity.d.ts +10 -0
- package/dist/services/doctor/doctor-service/checks/schema-validity.js +33 -0
- package/dist/services/doctor/doctor-service/checks/skill-apply-note.d.ts +20 -0
- package/dist/services/doctor/doctor-service/checks/skill-apply-note.js +85 -0
- package/dist/services/doctor/doctor-service/checks/skill-existence.d.ts +13 -0
- package/dist/services/doctor/doctor-service/checks/skill-existence.js +30 -0
- package/dist/services/doctor/doctor-service/checks/skill-name-match.d.ts +10 -0
- package/dist/services/doctor/doctor-service/checks/skill-name-match.js +25 -0
- package/dist/services/doctor/doctor-service/checks/skill-parse.d.ts +10 -0
- package/dist/services/doctor/doctor-service/checks/skill-parse.js +19 -0
- package/dist/services/doctor/doctor-service/checks/skill-presence.d.ts +21 -0
- package/dist/services/doctor/doctor-service/checks/skill-presence.js +75 -0
- package/dist/services/doctor/doctor-service/checks/skill-runbook.d.ts +14 -0
- package/dist/services/doctor/doctor-service/checks/skill-runbook.js +47 -0
- package/dist/services/doctor/doctor-service/checks/statusline-install.d.ts +14 -0
- package/dist/services/doctor/doctor-service/checks/statusline-install.js +32 -0
- package/dist/services/doctor/doctor-service/checks/statusline-runtime.d.ts +13 -0
- package/dist/services/doctor/doctor-service/checks/statusline-runtime.js +30 -0
- package/dist/services/doctor/doctor-service/checks/user-config.d.ts +11 -0
- package/dist/services/doctor/doctor-service/checks/user-config.js +27 -0
- package/dist/services/doctor/doctor-service/checks/workspace-init.d.ts +16 -0
- package/dist/services/doctor/doctor-service/checks/workspace-init.js +34 -0
- package/dist/services/doctor/doctor-service/checks/workspace-layout.d.ts +33 -0
- package/dist/services/doctor/doctor-service/checks/workspace-layout.js +180 -0
- package/dist/services/doctor/doctor-service/index.d.ts +48 -0
- package/dist/services/doctor/doctor-service/index.js +254 -0
- package/dist/services/doctor/doctor-service/plugin-registry.d.ts +41 -0
- package/dist/services/doctor/doctor-service/plugin-registry.js +77 -0
- package/dist/services/doctor/doctor-service/report/final-summary.d.ts +20 -0
- package/dist/services/doctor/doctor-service/report/final-summary.js +29 -0
- package/dist/services/doctor/doctor-service/types.d.ts +245 -0
- package/dist/services/doctor/doctor-service/types.js +15 -0
- package/dist/services/doctor/doctor-service.d.ts +15 -146
- package/dist/services/doctor/doctor-service.js +22 -926
- package/dist/services/doctor/index.d.ts +22 -0
- package/dist/services/doctor/index.js +22 -0
- package/dist/services/env/shell-probe.d.ts +71 -0
- package/dist/services/env/shell-probe.js +161 -0
- package/dist/services/evolution/evolution-types.d.ts +39 -39
- package/dist/services/final-review/final-review-service.d.ts +11 -1
- package/dist/services/final-review/index.d.ts +2 -0
- package/dist/services/final-review/index.js +1 -0
- package/dist/services/hooks/auto-compact-hook-install.d.ts +4 -5
- package/dist/services/hooks/auto-compact-hook-install.js +4 -5
- package/dist/services/hooks/worktree-authorization-gate.d.ts +205 -0
- package/dist/services/hooks/worktree-authorization-gate.js +492 -0
- package/dist/services/ide/adapters/claude-code-adapter.js +2 -2
- package/dist/services/ide/adapters/qoder-adapter.d.ts +25 -0
- package/dist/services/ide/adapters/qoder-adapter.js +57 -0
- package/dist/services/ide/adapters/tongyi-lingma-adapter.d.ts +16 -0
- package/dist/services/ide/adapters/tongyi-lingma-adapter.js +45 -0
- package/dist/services/ide/ide-registry.js +6 -0
- package/dist/services/ide/ide-types.d.ts +1 -1
- package/dist/services/job/job-types.d.ts +56 -56
- package/dist/services/job-snapshot/index.d.ts +8 -0
- package/dist/services/job-snapshot/index.js +7 -0
- package/dist/services/{job/job-resource-snapshot.d.ts → job-snapshot/snapshot.d.ts} +1 -1
- package/dist/services/job-snapshot/types.d.ts +7 -0
- package/dist/services/job-snapshot/types.js +1 -0
- package/dist/services/karpathy-cost/karpathy-cost-check-service.d.ts +67 -0
- package/dist/services/karpathy-cost/karpathy-cost-check-service.js +108 -0
- package/dist/services/log/retention.d.ts +16 -0
- package/dist/services/log/retention.js +17 -0
- package/dist/services/loop/loop-bee-relation-types.d.ts +6 -6
- package/dist/services/loop/loop-release-types.d.ts +24 -24
- package/dist/services/loop/monotonic-runner.d.ts +17 -11
- package/dist/services/loop/monotonic-runner.js +118 -79
- package/dist/services/memory/project-memory-service/index/kind-dispatch.d.ts +8 -0
- package/dist/services/memory/project-memory-service/index/kind-dispatch.js +253 -0
- package/dist/services/memory/project-memory-service/index/ranking.d.ts +6 -0
- package/dist/services/memory/project-memory-service/index/ranking.js +171 -0
- package/dist/services/memory/project-memory-service/index/search.d.ts +34 -0
- package/dist/services/memory/project-memory-service/index/search.js +194 -0
- package/dist/services/memory/project-memory-service/index.d.ts +9 -0
- package/dist/services/memory/project-memory-service/index.js +24 -0
- package/dist/services/memory/project-memory-service/parsers/frontmatter.d.ts +9 -0
- package/dist/services/memory/project-memory-service/parsers/frontmatter.js +106 -0
- package/dist/services/memory/project-memory-service/parsers/markdown-pure.d.ts +7 -0
- package/dist/services/memory/project-memory-service/parsers/markdown-pure.js +96 -0
- package/dist/services/memory/project-memory-service/store/atomic-write.d.ts +5 -0
- package/dist/services/memory/project-memory-service/store/atomic-write.js +56 -0
- package/dist/services/memory/project-memory-service/store/paths.d.ts +8 -0
- package/dist/services/memory/project-memory-service/store/paths.js +116 -0
- package/dist/services/memory/project-memory-service/types.d.ts +128 -0
- package/dist/services/memory/project-memory-service/types.js +9 -0
- package/dist/services/memory/project-memory-service.d.ts +1 -167
- package/dist/services/memory/project-memory-service.js +19 -816
- package/dist/services/migrate-skill-name/schema.d.ts +2 -2
- package/dist/services/observability/aggregation.d.ts +27 -0
- package/dist/services/observability/aggregation.js +72 -0
- package/dist/services/observability/observability-service.d.ts +73 -7
- package/dist/services/observability/observability-service.js +87 -1
- package/dist/services/openspec/artifact-boundary.d.ts +138 -0
- package/dist/services/openspec/artifact-boundary.js +150 -0
- package/dist/services/openspec/coverage-evidence-reader.d.ts +191 -0
- package/dist/services/openspec/coverage-evidence-reader.js +386 -0
- package/dist/services/openspec/openspec-archive-service.d.ts +70 -0
- package/dist/services/openspec/openspec-archive-service.js +320 -8
- package/dist/services/openspec/openspec-bridge-service.js +1 -1
- package/dist/services/openspec/openspec-init-service.js +1 -1
- package/dist/services/openspec/openspec-propose-from-doctor-service.js +1 -1
- package/dist/services/openspec/openspec-render-service.js +7 -4
- package/dist/services/openspec/openspec-scan-service.js +1 -1
- package/dist/services/openspec/openspec-validate-service.js +5 -4
- package/dist/services/preferences/preferences-service.js +10 -0
- package/dist/services/preferences/preferences-types.d.ts +13 -0
- package/dist/services/preferences/preferences-types.js +11 -0
- package/dist/services/qa/screenshot-archive-service.d.ts +51 -0
- package/dist/services/qa/screenshot-archive-service.js +134 -0
- package/dist/services/rd/rd-service.js +10 -11
- package/dist/services/rd/types.d.ts +32 -32
- package/dist/services/rd-swarm/rd-swarm-service.d.ts +60 -0
- package/dist/services/rd-swarm/rd-swarm-service.js +93 -0
- package/dist/services/recommendations/capability-seed-items.js +0 -1
- package/dist/services/recommendations/capability-seed-mappings.js +0 -1
- package/dist/services/recommendations/capability-seed-sources.js +0 -1
- package/dist/services/release/version-precheck-service.d.ts +51 -0
- package/dist/services/release/version-precheck-service.js +257 -0
- package/dist/services/scan/acceptance-coverage-service.js +1 -1
- package/dist/services/scan/archetype-service.js +1 -1
- package/dist/services/scan/existing-system-service.js +1 -1
- package/dist/services/scan/libraries-service.js +1 -1
- package/dist/services/sediment/json-schema.d.ts +40 -40
- package/dist/services/share/bundle-types.d.ts +12 -12
- package/dist/services/share/run-state-contract.d.ts +2 -2
- package/dist/services/skill/skill-search-service.d.ts +12 -7
- package/dist/services/skill/skill-search-service.js +8 -4
- package/dist/services/skillhub/migrations/001-initial.sql +71 -0
- package/dist/services/skillhub/migrations/002-loop-release.sql +32 -0
- package/dist/services/skillhub/migrations/003-loop-bee-relation.sql +35 -0
- package/dist/services/skillhub/migrations/004-loop-bee-extension.sql +65 -0
- package/dist/services/skillhub/migrations/005-evolution-evaluation.sql +81 -0
- package/dist/services/skillhub/migrations/006-crystallization-event.sql +92 -0
- package/dist/services/skills/hooks-settings-service.d.ts +75 -0
- package/dist/services/skills/hooks-settings-service.js +230 -2
- package/dist/services/skills/skill-registry.d.ts +1 -0
- package/dist/services/skills/skill-registry.js +6 -4
- package/dist/services/skills/skill-runbook-service.js +1 -1
- package/dist/services/slice/slice-check-service.js +1 -1
- package/dist/services/standards/main-session-monitor-ban-hook.d.ts +14 -0
- package/dist/services/standards/main-session-monitor-ban-hook.js +19 -0
- package/dist/services/standards/missing-standards-detector.d.ts +25 -0
- package/dist/services/standards/missing-standards-detector.js +43 -12
- package/dist/services/tech/tech-change-id-service.d.ts +82 -0
- package/dist/services/tech/tech-change-id-service.js +117 -0
- package/dist/services/understand/understand-hybrid-service.js +1 -1
- package/dist/services/understand/understand-scan-service.js +2 -2
- package/dist/services/upgrade/upgrade-service.js +4 -3
- package/dist/services/verdict/envelopes.d.ts +2 -2
- package/dist/services/verdict/envelopes.js +2 -2
- package/dist/services/verdict/verdict-aggregator.d.ts +3 -3
- package/dist/services/vm/vm-lease.d.ts +40 -0
- package/dist/services/vm/vm-lease.js +137 -0
- package/dist/services/workflow/autonomous-resume-writer.js +1 -1
- package/dist/services/workflow/pipeline-verify-gate-support.d.ts +47 -0
- package/dist/services/workflow/pipeline-verify-gate-support.js +194 -0
- package/dist/services/workflow/pipeline-verify-service.d.ts +17 -81
- package/dist/services/workflow/pipeline-verify-service.js +42 -218
- package/dist/services/workflow/pipeline-verify-types.d.ts +90 -0
- package/dist/services/workflow/pipeline-verify-types.js +10 -0
- package/dist/services/workflow/plan-reader.d.ts +1 -1
- package/dist/services/workflow/plan-reader.js +1 -1
- package/dist/services/workflow/plan-refresher.d.ts +1 -1
- package/dist/services/workflow/plan-refresher.js +1 -1
- package/dist/services/workflow/plan-trigger-detector.d.ts +1 -1
- package/dist/services/workflow/plan-trigger-detector.js +1 -1
- package/dist/services/workflow/workflow-autonomous-resume-helpers.d.ts +1 -1
- package/dist/services/workflow/workflow-autonomous-service.d.ts +2 -98
- package/dist/services/workflow/workflow-autonomous-types.d.ts +114 -0
- package/dist/services/workflow/workflow-autonomous-types.js +21 -0
- package/dist/services/workflow/workflow-router-service.js +18 -16
- package/dist/services/workflow/workflow-spec-lint.d.ts +13 -0
- package/dist/services/workflow/workflow-spec-lint.js +75 -0
- package/dist/services/workflow/workflow-spec-types.d.ts +100 -0
- package/dist/services/workflow/workflow-spec-types.js +13 -0
- package/dist/services/workflow/workflow-spec-yaml.d.ts +17 -0
- package/dist/services/workflow/workflow-spec-yaml.js +88 -0
- package/dist/services/workflow/workflow-spec.d.ts +11 -91
- package/dist/services/workflow/workflow-spec.js +16 -145
- package/dist/services/workspace/migrate-service.js +1 -1
- package/dist/services/workspace/workspace-service.js +1 -1
- package/dist/services/worktree/worktree-lease.d.ts +170 -0
- package/dist/services/worktree/worktree-lease.js +242 -0
- package/package.json +91 -51
- package/scripts/clean-dist.mjs +31 -1
- package/scripts/copy-templates.mjs +16 -0
- package/scripts/sync-version.mjs +53 -2
- package/skills/bee/peaks-perf-audit/SKILL.md +17 -0
- package/skills/bee/peaks-prd/SKILL.md +16 -0
- package/skills/bee/peaks-prd/test-prompts.json +12 -0
- package/skills/bee/peaks-qa/SKILL.md +16 -1
- package/skills/bee/peaks-qa/references/qa-sub-agent-dispatch.md +22 -0
- package/skills/bee/peaks-qa/test-prompts.json +12 -0
- package/skills/bee/peaks-rd/SKILL.md +29 -20
- package/skills/bee/peaks-rd/references/rd-sub-agent-dispatch.md +39 -0
- package/skills/bee/peaks-rd/test-prompts.json +12 -0
- package/skills/bee/peaks-reviewer/SKILL.md +17 -0
- package/skills/bee/peaks-sc/SKILL.md +16 -0
- package/skills/bee/peaks-security-audit/SKILL.md +17 -0
- package/skills/bee/peaks-txt/SKILL.md +16 -0
- package/skills/bee/peaks-txt/test-prompts.json +12 -0
- package/skills/bee/peaks-ui/SKILL.md +49 -43
- package/skills/bee/peaks-ui/test-prompts.json +12 -0
- package/skills/peaks-code/SKILL.md +54 -109
- package/skills/peaks-code/references/boundaries.md +15 -1
- package/skills/peaks-code/references/cron-scheduler-deployment.md +313 -0
- package/skills/peaks-code/references/external-skill-invocation.md +27 -0
- package/skills/peaks-code/references/lease-dashboard.html +224 -0
- package/skills/peaks-code/references/lease-stats.sample.json +26 -0
- package/skills/peaks-code/references/peaks-worktree-l2-enforcers.md +208 -0
- package/skills/peaks-code/references/periodic-checkpoint.md +4 -4
- package/skills/peaks-code/references/runbook.md +63 -1
- package/skills/peaks-code/references/startup-sequence.md +110 -0
- package/skills/peaks-code/references/step-0-8-gate.md +1 -1
- package/skills/peaks-code/references/sub-agent-dispatch.md +92 -1
- package/skills/peaks-code/references/worktree-governance.md +123 -0
- package/skills/peaks-code/test-prompts.json +12 -0
- package/skills/peaks-doctor/SKILL.md +1 -1
- package/skills/peaks-ide/SKILL.md +1 -1
- package/skills/peaks-solo/SKILL.md +21 -0
- package/skills/peaks-solo/references/triage-decision-table.md +6 -0
- package/skills/peaks-sop/test-prompts.json +17 -0
- package/dist/cli/commands/agent-commands.d.ts +0 -20
- package/dist/cli/commands/agent-commands.js +0 -48
- package/dist/cli/commands/classify-classify-commands.d.ts +0 -19
- package/dist/cli/commands/classify-classify-commands.js +0 -151
- package/dist/cli/commands/contract-commands.d.ts +0 -26
- package/dist/cli/commands/contract-commands.js +0 -114
- package/dist/cli/commands/session-auto-compact-hook-command.d.ts +0 -37
- package/dist/cli/commands/session-auto-compact-hook-command.js +0 -127
- package/dist/cli/commands/worker-commands.d.ts +0 -3
- package/dist/cli/commands/worker-commands.js +0 -52
- package/dist/services/agent/ecc-agent-service.d.ts +0 -47
- package/dist/services/agent/ecc-agent-service.js +0 -143
- package/dist/services/config/provider-service.d.ts +0 -48
- package/dist/services/config/provider-service.js +0 -143
- package/dist/services/context/dispatch-context-guard.d.ts +0 -27
- package/dist/services/context/dispatch-context-guard.js +0 -192
- package/dist/services/context/shared-channel.d.ts +0 -93
- package/dist/services/context/shared-channel.js +0 -308
- package/dist/services/filesystem/file-lock.d.ts +0 -11
- package/dist/services/filesystem/file-lock.js +0 -152
- package/dist/services/mut/assert-scanner.d.ts +0 -6
- package/dist/services/mut/assert-scanner.js +0 -116
- package/dist/services/mut/index.d.ts +0 -8
- package/dist/services/mut/index.js +0 -7
- package/dist/services/mut/mut-runner.d.ts +0 -39
- package/dist/services/mut/mut-runner.js +0 -29
- package/dist/services/mut/production-stryker.d.ts +0 -2
- package/dist/services/mut/production-stryker.js +0 -75
- package/dist/services/mut/report-builder.d.ts +0 -11
- package/dist/services/mut/report-builder.js +0 -110
- package/dist/services/mut/report-loader.d.ts +0 -31
- package/dist/services/mut/report-loader.js +0 -78
- package/dist/services/mut/thresholds.d.ts +0 -21
- package/dist/services/mut/thresholds.js +0 -22
- package/dist/services/mut/types.d.ts +0 -336
- package/dist/services/mut/types.js +0 -59
- package/dist/services/providers/minimax-provider-service.d.ts +0 -24
- package/dist/services/providers/minimax-provider-service.js +0 -143
- package/dist/services/providers/minimax-worker-service.d.ts +0 -21
- package/dist/services/providers/minimax-worker-service.js +0 -83
- package/dist/shared/fs.d.ts +0 -4
- package/dist/shared/fs.js +0 -26
- package/dist/shared/paths.d.ts +0 -6
- package/dist/shared/paths.js +0 -50
- package/dist/shared/result.d.ts +0 -22
- package/dist/shared/result.js +0 -46
- package/dist/shared/version.d.ts +0 -1
- package/dist/shared/version.js +0 -1
- package/examples/video-demo/README.md +0 -142
- package/examples/video-demo/out/en-closing-960.png +0 -0
- package/examples/video-demo/out/zh-closing-960.png +0 -0
- package/examples/video-demo/preview/peaks-loop-demo-en.mp4 +0 -0
- package/examples/video-demo/preview/peaks-loop-demo.mp4 +0 -0
- /package/dist/services/{job/job-resource-snapshot.js → job-snapshot/snapshot.js} +0 -0
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cross-process file lock — sync, atomic, no third-party deps.
|
|
3
|
-
*
|
|
4
|
-
* Used by writeSharedEntry (shared-channel.ts) and appendHeartbeat /
|
|
5
|
-
* markCompleted (dispatch-record-writer.ts) to guard the
|
|
6
|
-
* read-modify-write sequence against lost updates from concurrent
|
|
7
|
-
* writers (slice 2026-06-23-audit-3rd finding #2 + #3).
|
|
8
|
-
*
|
|
9
|
-
* Mechanism: write a sidecar `.lock` file next to the target via
|
|
10
|
-
* `fs.openSync(path, 'wx')`. The `wx` flag maps to O_CREAT|O_EXCL on
|
|
11
|
-
* POSIX (atomic) and `CreateFileW(... CREATE_NEW)` on Windows (also
|
|
12
|
-
* atomic). The second opener fails with EEXIST. We retry with capped
|
|
13
|
-
* exponential backoff up to MAX_LOCK_RETRIES, falling through to
|
|
14
|
-
* LOCK_TIMEOUT if the lock cannot be acquired.
|
|
15
|
-
*
|
|
16
|
-
* Stale-lock reaping: a crashed previous holder leaves a `.lock` file
|
|
17
|
-
* behind. We reap locks older than LOCK_STALE_MS by unlinking before
|
|
18
|
-
* retrying. This trades a one-time stale-lock window for bounded
|
|
19
|
-
* recovery without leaking orphan locks.
|
|
20
|
-
*
|
|
21
|
-
* Why not fs.flock? Node's `fs.flock` is POSIX-only; on Windows it
|
|
22
|
-
* throws ERR_FEATURE_UNAVAILABLE_ON_PLATFORM. The `.lock` file
|
|
23
|
-
* pattern works uniformly across platforms and survives process
|
|
24
|
-
* crashes (the file remains; the next acquirer reaps it).
|
|
25
|
-
*/
|
|
26
|
-
import { closeSync, existsSync, mkdirSync, openSync, statSync, unlinkSync } from 'node:fs';
|
|
27
|
-
import { dirname, resolve } from 'node:path';
|
|
28
|
-
const MAX_LOCK_RETRIES = 100;
|
|
29
|
-
const LOCK_RETRY_BASE_MS = 5;
|
|
30
|
-
const LOCK_RETRY_MAX_MS = 50;
|
|
31
|
-
const LOCK_STALE_MS = 30_000;
|
|
32
|
-
export class LockTimeoutError extends Error {
|
|
33
|
-
code = 'LOCK_TIMEOUT';
|
|
34
|
-
lockPath;
|
|
35
|
-
constructor(lockPath, attempts) {
|
|
36
|
-
super(`LOCK_TIMEOUT: failed to acquire ${lockPath} after ${attempts} retries ` +
|
|
37
|
-
`(a prior holder may be alive or the lock is stale; it will be reaped ` +
|
|
38
|
-
`after ${LOCK_STALE_MS}ms of inactivity)`);
|
|
39
|
-
this.lockPath = lockPath;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Run `fn` while holding an exclusive lock on a sidecar file at
|
|
44
|
-
* `<filePath>.lock`. The lock is released in `finally` (close fd +
|
|
45
|
-
* unlink lock file). Throws LockTimeoutError after MAX_LOCK_RETRIES.
|
|
46
|
-
*/
|
|
47
|
-
export function withFileLockSync(filePath, fn) {
|
|
48
|
-
const target = resolve(filePath);
|
|
49
|
-
const lockPath = `${target}.lock`;
|
|
50
|
-
// Ensure the parent dir exists before openSync('wx') — first-write
|
|
51
|
-
// callers (e.g. writeSharedEntry on a fresh batch) reach the lock
|
|
52
|
-
// BEFORE writeAtomic's mkdirSync(dir, { recursive: true }) runs.
|
|
53
|
-
const dir = dirname(target);
|
|
54
|
-
if (!existsSync(dir)) {
|
|
55
|
-
mkdirSync(dir, { recursive: true });
|
|
56
|
-
}
|
|
57
|
-
// Wall-clock guard (slice 014): in pathological slow-system cases, the
|
|
58
|
-
// retry backoff could push wall-clock above LOCK_STALE_MS. Cap the loop at
|
|
59
|
-
// LOCK_STALE_MS regardless of attempts; throw the existing LockTimeoutError.
|
|
60
|
-
//
|
|
61
|
-
// Slice 2026-07-12-fix note: the slice 014 implementation re-checked
|
|
62
|
-
// `isStaleLock(lockPath)` at the TOP of every loop iteration. Under
|
|
63
|
-
// vitest-on-Windows slowdown (each `spinSleep` actually waits hundreds of
|
|
64
|
-
// ms because of event-loop preemption), the wall clock would cross
|
|
65
|
-
// `LOCK_STALE_MS` mid-loop and the reaper would unlink a still-fresh
|
|
66
|
-
// lock — `file-lock.test.ts` "does NOT reap a fresh .lock (<30s old)"
|
|
67
|
-
// caught this: the lock was reaped at iter ~54 after 30s of retries,
|
|
68
|
-
// defeating the test that asserts the fresh lock should block. The fix
|
|
69
|
-
// is to check staleness ONCE, before the loop, and inside the loop
|
|
70
|
-
// only retry on EEXIST. A crashed previous holder is reaped at entry;
|
|
71
|
-
// after we begin the retry-backoff phase, the lock is by definition
|
|
72
|
-
// non-stale (or absent after a race with another reaper), so a stale
|
|
73
|
-
// check on each iteration only adds risk of spuriously reaping a lock
|
|
74
|
-
// we just decided was live.
|
|
75
|
-
const startedAt = Date.now();
|
|
76
|
-
let attempts = 0;
|
|
77
|
-
let fd = null;
|
|
78
|
-
// One-shot stale reap before the loop: if a previous holder crashed and
|
|
79
|
-
// left the lock older than LOCK_STALE_MS, unlink it now so the first
|
|
80
|
-
// `openSync(lockPath, 'wx')` attempt can succeed.
|
|
81
|
-
if (isStaleLock(lockPath)) {
|
|
82
|
-
try {
|
|
83
|
-
unlinkSync(lockPath);
|
|
84
|
-
}
|
|
85
|
-
catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
86
|
-
// race: another process reaped it; loop will try to acquire directly.
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
while (attempts < MAX_LOCK_RETRIES) {
|
|
90
|
-
// Wall-clock guard runs at the top of each iteration so a slow retry
|
|
91
|
-
// backoff (e.g. vitest on Windows) never lets us outlive the stale
|
|
92
|
-
// threshold and re-enter the reaper branch on a still-live lock.
|
|
93
|
-
if (Date.now() - startedAt > LOCK_STALE_MS) {
|
|
94
|
-
throw new LockTimeoutError(lockPath, attempts);
|
|
95
|
-
}
|
|
96
|
-
try {
|
|
97
|
-
fd = openSync(lockPath, 'wx');
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
catch (err) {
|
|
101
|
-
const code = err.code;
|
|
102
|
-
if (code !== 'EEXIST')
|
|
103
|
-
throw err;
|
|
104
|
-
attempts += 1;
|
|
105
|
-
// Exponential backoff capped at LOCK_RETRY_MAX_MS.
|
|
106
|
-
const wait = Math.min(LOCK_RETRY_BASE_MS * 2 ** Math.min(attempts, 6), LOCK_RETRY_MAX_MS);
|
|
107
|
-
spinSleep(wait);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (fd === null) {
|
|
111
|
-
throw new LockTimeoutError(lockPath, attempts);
|
|
112
|
-
}
|
|
113
|
-
try {
|
|
114
|
-
return fn();
|
|
115
|
-
}
|
|
116
|
-
finally {
|
|
117
|
-
try {
|
|
118
|
-
closeSync(fd);
|
|
119
|
-
}
|
|
120
|
-
catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
121
|
-
// fd may already be closed by the OS on a crash; ignore.
|
|
122
|
-
}
|
|
123
|
-
try {
|
|
124
|
-
unlinkSync(lockPath);
|
|
125
|
-
}
|
|
126
|
-
catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
127
|
-
// Best-effort: stale .lock is harmless; the next acquirer reaps.
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
function isStaleLock(lockPath) {
|
|
132
|
-
try {
|
|
133
|
-
const s = statSync(lockPath);
|
|
134
|
-
return Date.now() - s.mtimeMs > LOCK_STALE_MS;
|
|
135
|
-
}
|
|
136
|
-
catch {
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Synchronous sleep via busy-wait. Bounded by MAX_LOCK_RETRIES *
|
|
142
|
-
* LOCK_RETRY_MAX_MS = 5s worst case. The alternative — async sleep —
|
|
143
|
-
* would force every lock consumer to become async, which is a much
|
|
144
|
-
* larger refactor for a slice whose lock contention is rare (concurrent
|
|
145
|
-
* `peaks sub-agent share` for the same batch).
|
|
146
|
-
*/
|
|
147
|
-
function spinSleep(ms) {
|
|
148
|
-
const end = Date.now() + ms;
|
|
149
|
-
while (Date.now() < end) {
|
|
150
|
-
/* intentional spin */
|
|
151
|
-
}
|
|
152
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per spec §4.2 验收审计 + §7 阶段二 — 5-pattern weak-assertion AST scan.
|
|
3
|
-
*
|
|
4
|
-
* Hard constraints:
|
|
5
|
-
* H6 (CLI裁决): every detection is regex/AST-based, not LLM-judged.
|
|
6
|
-
* KISS: regex matchers on common expect() patterns. Production slice
|
|
7
|
-
* would migrate to TypeScript Compiler API; v1 ships regex for speed.
|
|
8
|
-
*
|
|
9
|
-
* Weak patterns (5):
|
|
10
|
-
* - toBeDefined()
|
|
11
|
-
* - toBeTruthy()
|
|
12
|
-
* - toEqual(x) where arg === receiver (toEqual-self)
|
|
13
|
-
* - expect.anything()
|
|
14
|
-
* - toBe(x) where arg === receiver (toBe-self)
|
|
15
|
-
*/
|
|
16
|
-
import { readFile } from 'node:fs/promises';
|
|
17
|
-
import { join } from 'node:path';
|
|
18
|
-
const WEAK_PATTERNS = [
|
|
19
|
-
{ pattern: 'toBeDefined', regex: /\.toBeDefined\s*\(\s*\)/g },
|
|
20
|
-
{ pattern: 'toBeTruthy', regex: /\.toBeTruthy\s*\(\s*\)/g },
|
|
21
|
-
{ pattern: 'expect-anything', regex: /expect\.anything\s*\(\s*\)/g },
|
|
22
|
-
// Self-equality patterns require matched-pair parsing; handled below.
|
|
23
|
-
];
|
|
24
|
-
const TO_EQUAL_SELF = /\.toEqual\s*\(\s*([a-zA-Z_$][\w$]*)\s*\)/g;
|
|
25
|
-
const TO_BE_SELF = /\.toBe\s*\(\s*([a-zA-Z_$][\w$]*)\s*\)/g;
|
|
26
|
-
async function countAssertions(content) {
|
|
27
|
-
// Approximate: count expect(...).method( occurrences.
|
|
28
|
-
// Handle nested parens by finding expect( and matching to a balanced close.
|
|
29
|
-
let count = 0;
|
|
30
|
-
const re = /expect\s*\(/g;
|
|
31
|
-
for (const m of content.matchAll(re)) {
|
|
32
|
-
let depth = 1;
|
|
33
|
-
let i = (m.index ?? 0) + m[0].length;
|
|
34
|
-
while (i < content.length && depth > 0) {
|
|
35
|
-
const ch = content[i];
|
|
36
|
-
if (ch === '(')
|
|
37
|
-
depth++;
|
|
38
|
-
else if (ch === ')')
|
|
39
|
-
depth--;
|
|
40
|
-
i++;
|
|
41
|
-
}
|
|
42
|
-
// After balanced expect(...), check for .method( pattern.
|
|
43
|
-
const tail = content.slice(i);
|
|
44
|
-
if (/^\s*\.\w+\s*\(/.test(tail)) {
|
|
45
|
-
count++;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return count;
|
|
49
|
-
}
|
|
50
|
-
function lineOf(content, offset) {
|
|
51
|
-
return content.slice(0, offset).split('\n').length;
|
|
52
|
-
}
|
|
53
|
-
export async function scanAssertions(input) {
|
|
54
|
-
let total = 0;
|
|
55
|
-
let weak = 0;
|
|
56
|
-
const byPattern = new Map();
|
|
57
|
-
for (const file of input.testFiles) {
|
|
58
|
-
const fullPath = join(input.project, file);
|
|
59
|
-
const content = await readFile(fullPath, 'utf8');
|
|
60
|
-
total += await countAssertions(content);
|
|
61
|
-
for (const { pattern, regex } of WEAK_PATTERNS) {
|
|
62
|
-
const matches = [...content.matchAll(regex)];
|
|
63
|
-
if (matches.length > 0) {
|
|
64
|
-
weak += matches.length;
|
|
65
|
-
const list = byPattern.get(pattern) ?? [];
|
|
66
|
-
for (const m of matches) {
|
|
67
|
-
const idx = m.index ?? 0;
|
|
68
|
-
list.push({ file, line: lineOf(content, idx), code: m[0] });
|
|
69
|
-
}
|
|
70
|
-
byPattern.set(pattern, list);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// toEqual-self: needs receiver extraction.
|
|
74
|
-
const eqSelf = [...content.matchAll(TO_EQUAL_SELF)];
|
|
75
|
-
for (const m of eqSelf) {
|
|
76
|
-
const receiverMatch = content.slice(0, m.index ?? 0).match(/expect\s*\(\s*([a-zA-Z_$][\w$]*)\s*\)/g);
|
|
77
|
-
if (receiverMatch && receiverMatch.length > 0) {
|
|
78
|
-
const lastReceiver = receiverMatch[receiverMatch.length - 1];
|
|
79
|
-
const receiverName = lastReceiver?.match(/expect\s*\(\s*([a-zA-Z_$][\w$]*)\s*\)/)?.[1];
|
|
80
|
-
if (receiverName && receiverName === m[1]) {
|
|
81
|
-
weak += 1;
|
|
82
|
-
const idx = m.index ?? 0;
|
|
83
|
-
const list = byPattern.get('toEqual-self') ?? [];
|
|
84
|
-
list.push({ file, line: lineOf(content, idx), code: m[0] });
|
|
85
|
-
byPattern.set('toEqual-self', list);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
// toBe-self: same pattern.
|
|
90
|
-
const beSelf = [...content.matchAll(TO_BE_SELF)];
|
|
91
|
-
for (const m of beSelf) {
|
|
92
|
-
const receiverMatch = content.slice(0, m.index ?? 0).match(/expect\s*\(\s*([a-zA-Z_$][\w$]*)\s*\)/g);
|
|
93
|
-
if (receiverMatch && receiverMatch.length > 0) {
|
|
94
|
-
const lastReceiver = receiverMatch[receiverMatch.length - 1];
|
|
95
|
-
const receiverName = lastReceiver?.match(/expect\s*\(\s*([a-zA-Z_$][\w$]*)\s*\)/)?.[1];
|
|
96
|
-
if (receiverName && receiverName === m[1]) {
|
|
97
|
-
weak += 1;
|
|
98
|
-
const idx = m.index ?? 0;
|
|
99
|
-
const list = byPattern.get('toBe-self') ?? [];
|
|
100
|
-
list.push({ file, line: lineOf(content, idx), code: m[0] });
|
|
101
|
-
byPattern.set('toBe-self', list);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
const weakPatterns = [];
|
|
107
|
-
for (const [pattern, examples] of byPattern.entries()) {
|
|
108
|
-
weakPatterns.push({ pattern, count: examples.length, examples });
|
|
109
|
-
}
|
|
110
|
-
return {
|
|
111
|
-
totalAssertions: total,
|
|
112
|
-
weakAssertions: weak,
|
|
113
|
-
weakRate: total === 0 ? 0 : weak / total,
|
|
114
|
-
weakPatterns,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { MutReportSchema } from './types.js';
|
|
2
|
-
export { scanAssertions, type ScanInput } from './assert-scanner.js';
|
|
3
|
-
export { runMutation, type RunMutationInput, type RunMutationOutput, type StrykerInvoker, type StrykerRawResult, } from './mut-runner.js';
|
|
4
|
-
export { createProductionStrykerInvoker } from './production-stryker.js';
|
|
5
|
-
export { buildMutReport, type BuildMutInput } from './report-builder.js';
|
|
6
|
-
export { loadMutReport, mutReportPath, MUT_REPORT_RELATIVE_PATH } from './report-loader.js';
|
|
7
|
-
export { DEFAULT_THRESHOLDS, evaluateThresholds, type Thresholds, type ThresholdEvaluation, type ThresholdViolation, type ThresholdViolationKind, } from './thresholds.js';
|
|
8
|
-
export type { MutReportJson, MutationReport, AssertionsReport, WeakPattern, WeakPatternCount, Followup, } from './types.js';
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { MutReportSchema } from './types.js';
|
|
2
|
-
export { scanAssertions } from './assert-scanner.js';
|
|
3
|
-
export { runMutation, } from './mut-runner.js';
|
|
4
|
-
export { createProductionStrykerInvoker } from './production-stryker.js';
|
|
5
|
-
export { buildMutReport } from './report-builder.js';
|
|
6
|
-
export { loadMutReport, mutReportPath, MUT_REPORT_RELATIVE_PATH } from './report-loader.js';
|
|
7
|
-
export { DEFAULT_THRESHOLDS, evaluateThresholds, } from './thresholds.js';
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per spec §4.2 验收审计 — Stryker wrapper for TS mutation testing.
|
|
3
|
-
*
|
|
4
|
-
* Hard constraints:
|
|
5
|
-
* H6 (CLI裁决): invokeStryker is injected; production wires it to
|
|
6
|
-
* @stryker-mutator/core programmatic API.
|
|
7
|
-
* DRY: production implementation lives in this file; tests mock the
|
|
8
|
-
* invokeStryker injection point.
|
|
9
|
-
* KISS: keep the public surface narrow — input, invoker, output.
|
|
10
|
-
*/
|
|
11
|
-
import type { MutationReport } from './types.js';
|
|
12
|
-
export interface StrykerRawResult {
|
|
13
|
-
readonly mutantsTotal: number;
|
|
14
|
-
readonly mutantsKilled: number;
|
|
15
|
-
readonly mutantsSurvived: number;
|
|
16
|
-
readonly mutantsTimeout: number;
|
|
17
|
-
readonly perFile: ReadonlyArray<{
|
|
18
|
-
readonly file: string;
|
|
19
|
-
readonly killRate: number;
|
|
20
|
-
readonly survived: ReadonlyArray<{
|
|
21
|
-
line: number;
|
|
22
|
-
mutation: string;
|
|
23
|
-
survivedBecause: string;
|
|
24
|
-
}>;
|
|
25
|
-
}>;
|
|
26
|
-
}
|
|
27
|
-
export type StrykerInvoker = (opts: {
|
|
28
|
-
project: string;
|
|
29
|
-
testFiles: ReadonlyArray<string>;
|
|
30
|
-
}) => Promise<StrykerRawResult>;
|
|
31
|
-
export interface RunMutationInput {
|
|
32
|
-
readonly project: string;
|
|
33
|
-
readonly testFiles: ReadonlyArray<string>;
|
|
34
|
-
readonly invokeStryker: StrykerInvoker;
|
|
35
|
-
}
|
|
36
|
-
export interface RunMutationOutput {
|
|
37
|
-
readonly mutation: MutationReport;
|
|
38
|
-
}
|
|
39
|
-
export declare function runMutation(input: RunMutationInput): Promise<RunMutationOutput>;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export async function runMutation(input) {
|
|
2
|
-
let raw;
|
|
3
|
-
try {
|
|
4
|
-
raw = await input.invokeStryker({
|
|
5
|
-
project: input.project,
|
|
6
|
-
testFiles: input.testFiles,
|
|
7
|
-
});
|
|
8
|
-
}
|
|
9
|
-
catch (err) {
|
|
10
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
11
|
-
throw new Error(`Stryker invocation failed: ${message}`);
|
|
12
|
-
}
|
|
13
|
-
const killRate = raw.mutantsTotal === 0 ? 0 : raw.mutantsKilled / raw.mutantsTotal;
|
|
14
|
-
return {
|
|
15
|
-
mutation: {
|
|
16
|
-
tool: 'stryker',
|
|
17
|
-
mutantsTotal: raw.mutantsTotal,
|
|
18
|
-
mutantsKilled: raw.mutantsKilled,
|
|
19
|
-
mutantsSurvived: raw.mutantsSurvived,
|
|
20
|
-
mutantsTimeout: raw.mutantsTimeout,
|
|
21
|
-
killRate,
|
|
22
|
-
byFile: raw.perFile.map((f) => ({
|
|
23
|
-
file: f.file,
|
|
24
|
-
killRate: f.killRate,
|
|
25
|
-
survived: f.survived,
|
|
26
|
-
})),
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Production Stryker invoker. Uses @stryker-mutator/core programmatic API.
|
|
3
|
-
* Note: this is a thin wrapper — actual Stryker invocation requires the
|
|
4
|
-
* Stryker config in `stryker.conf.js` to live at the project root.
|
|
5
|
-
*/
|
|
6
|
-
import { relative, isAbsolute } from 'node:path';
|
|
7
|
-
export function createProductionStrykerInvoker() {
|
|
8
|
-
return async ({ project, testFiles: _testFiles }) => {
|
|
9
|
-
// Lazy-load Stryker so unit tests don't need it installed.
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
11
|
-
const Stryker = (await import('@stryker-mutator/core')).Stryker;
|
|
12
|
-
// Mutation surface is owned by stryker.conf.js. testFiles is a runtime
|
|
13
|
-
// hint (consumed by the configured testRunner, not by Stryker's `mutate`
|
|
14
|
-
// field — `mutate` is source files to mutate, never test paths).
|
|
15
|
-
const stryker = new Stryker({});
|
|
16
|
-
const mutants = (await stryker.runMutationTest());
|
|
17
|
-
return normalize(mutants, project);
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
function normalize(mutants, project) {
|
|
21
|
-
let mutantsKilled = 0;
|
|
22
|
-
let mutantsSurvived = 0;
|
|
23
|
-
let mutantsTimeout = 0;
|
|
24
|
-
for (const m of mutants) {
|
|
25
|
-
if (m.status === 'Killed')
|
|
26
|
-
mutantsKilled++;
|
|
27
|
-
else if (m.status === 'Survived')
|
|
28
|
-
mutantsSurvived++;
|
|
29
|
-
else if (m.status === 'Timeout')
|
|
30
|
-
mutantsTimeout++;
|
|
31
|
-
}
|
|
32
|
-
// Bucket mutants by fileName to populate perFile. deriveFollowups iterates
|
|
33
|
-
// m.byFile to emit per-file followups (e.g. low_kill_rate) — leaving this
|
|
34
|
-
// empty (as v0 did) silently swallowed those followups in production.
|
|
35
|
-
const byFile = new Map();
|
|
36
|
-
for (const m of mutants) {
|
|
37
|
-
// Stryker 8 returns absolute paths in MutantResult.fileName. Strip the
|
|
38
|
-
// project root so byFile[].file is repo-relative (e.g. "src/services/loop/...").
|
|
39
|
-
// path.relative falls back to the absolute path when input is outside
|
|
40
|
-
// project, which is the safest failure mode.
|
|
41
|
-
const file = isAbsolute(m.fileName) && m.fileName.startsWith(project)
|
|
42
|
-
? relative(project, m.fileName)
|
|
43
|
-
: m.fileName;
|
|
44
|
-
let bucket = byFile.get(file);
|
|
45
|
-
if (!bucket) {
|
|
46
|
-
bucket = { killed: 0, survived: 0, survivedEntries: [] };
|
|
47
|
-
byFile.set(file, bucket);
|
|
48
|
-
}
|
|
49
|
-
if (m.status === 'Killed')
|
|
50
|
-
bucket.killed++;
|
|
51
|
-
else if (m.status === 'Survived') {
|
|
52
|
-
bucket.survived++;
|
|
53
|
-
bucket.survivedEntries.push({
|
|
54
|
-
line: m.location.start.line + 1, // Stryker is 0-based; reports are 1-based.
|
|
55
|
-
mutation: m.replacement,
|
|
56
|
-
survivedBecause: m.statusReason ?? '',
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
const perFile = [...byFile.entries()]
|
|
61
|
-
.map(([file, b]) => {
|
|
62
|
-
const total = b.killed + b.survived;
|
|
63
|
-
const killRate = total === 0 ? 0 : b.killed / total;
|
|
64
|
-
return { file, killRate, survived: b.survivedEntries };
|
|
65
|
-
})
|
|
66
|
-
// Stable order for MUT.sig / reports.
|
|
67
|
-
.sort((a, b) => a.file.localeCompare(b.file));
|
|
68
|
-
return {
|
|
69
|
-
mutantsTotal: mutants.length,
|
|
70
|
-
mutantsKilled,
|
|
71
|
-
mutantsSurvived,
|
|
72
|
-
mutantsTimeout,
|
|
73
|
-
perFile,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { type AssertionsReport, type MutationReport, type MutReportJson } from './types.js';
|
|
2
|
-
import { type Thresholds } from './thresholds.js';
|
|
3
|
-
export interface BuildMutInput {
|
|
4
|
-
readonly mutation: MutationReport;
|
|
5
|
-
readonly assertions: AssertionsReport;
|
|
6
|
-
readonly inputSig: string;
|
|
7
|
-
readonly out: string;
|
|
8
|
-
readonly thresholds?: Thresholds;
|
|
9
|
-
readonly now?: () => Date;
|
|
10
|
-
}
|
|
11
|
-
export declare function buildMutReport(input: BuildMutInput): Promise<MutReportJson>;
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Combines MutationReport + AssertionsReport into MutReportJson, computes
|
|
3
|
-
* thresholds, derives followups, computes MUT.sig, writes file atomically.
|
|
4
|
-
*
|
|
5
|
-
* Hard constraints:
|
|
6
|
-
* H8 (audit trail hashable): MUT.sig is sha256 of normalized content;
|
|
7
|
-
* generatedAt + sha256 are excluded from the digest to make the
|
|
8
|
-
* signature deterministic across runs.
|
|
9
|
-
* H6 (CLI裁决): passed boolean + followups computed by CLI, not LLM.
|
|
10
|
-
* KISS: keep composition narrow — input, thresholds, output file path.
|
|
11
|
-
*/
|
|
12
|
-
import { createHash } from 'node:crypto';
|
|
13
|
-
import { mkdir, rename, unlink, writeFile } from 'node:fs/promises';
|
|
14
|
-
import { dirname } from 'node:path';
|
|
15
|
-
import { MutReportSchema, } from './types.js';
|
|
16
|
-
import { DEFAULT_THRESHOLDS, evaluateThresholds, } from './thresholds.js';
|
|
17
|
-
function deriveFollowups(m, a, t) {
|
|
18
|
-
const out = [];
|
|
19
|
-
if (m.killRate < t.mutationKillRateMin) {
|
|
20
|
-
for (const f of m.byFile) {
|
|
21
|
-
if (f.killRate < t.mutationKillRateMin) {
|
|
22
|
-
out.push({
|
|
23
|
-
file: f.file,
|
|
24
|
-
issue: 'low_kill_rate',
|
|
25
|
-
severity: 'soft',
|
|
26
|
-
suggestion: `Add tests for ${f.survived.length} survived mutants in ${f.file}`,
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
if (a.weakRate > t.weakAssertionRateMax) {
|
|
32
|
-
for (const p of a.weakPatterns) {
|
|
33
|
-
if (p.count > 0) {
|
|
34
|
-
const exampleFile = p.examples[0]?.file ?? '<unknown>';
|
|
35
|
-
out.push({
|
|
36
|
-
file: exampleFile,
|
|
37
|
-
issue: 'high_weak_assertions',
|
|
38
|
-
severity: 'hard',
|
|
39
|
-
suggestion: `Replace ${p.count} weak assertions of type "${p.pattern}" with concrete value checks`,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return out;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Recursively sort object keys to produce a canonical JSON string.
|
|
48
|
-
* Arrays preserve order; only object keys are sorted.
|
|
49
|
-
*/
|
|
50
|
-
function canonicalize(value) {
|
|
51
|
-
if (value === null || typeof value !== 'object') {
|
|
52
|
-
return value;
|
|
53
|
-
}
|
|
54
|
-
if (Array.isArray(value)) {
|
|
55
|
-
return value.map((v) => canonicalize(v));
|
|
56
|
-
}
|
|
57
|
-
const obj = value;
|
|
58
|
-
const sorted = {};
|
|
59
|
-
for (const key of Object.keys(obj).sort()) {
|
|
60
|
-
sorted[key] = canonicalize(obj[key]);
|
|
61
|
-
}
|
|
62
|
-
return sorted;
|
|
63
|
-
}
|
|
64
|
-
function sha256OfCanonical(value) {
|
|
65
|
-
const canonical = JSON.stringify(canonicalize(value));
|
|
66
|
-
return createHash('sha256').update(canonical).digest('hex');
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Compute MUT.sig: sha256 of the report content excluding generatedAt and
|
|
70
|
-
* sha256 itself. Both fields are removed before canonicalization so the
|
|
71
|
-
* digest is stable across runs that differ only in timestamp.
|
|
72
|
-
*/
|
|
73
|
-
function computeMutSig(report) {
|
|
74
|
-
const { generatedAt: _g, ...rest } = report;
|
|
75
|
-
void _g;
|
|
76
|
-
return sha256OfCanonical(rest);
|
|
77
|
-
}
|
|
78
|
-
export async function buildMutReport(input) {
|
|
79
|
-
const thresholds = input.thresholds ?? DEFAULT_THRESHOLDS;
|
|
80
|
-
const now = input.now ?? (() => new Date());
|
|
81
|
-
const evalResult = evaluateThresholds(thresholds, input.mutation.killRate, input.assertions.weakRate);
|
|
82
|
-
const followups = deriveFollowups(input.mutation, input.assertions, thresholds);
|
|
83
|
-
const partial = {
|
|
84
|
-
version: '1.0',
|
|
85
|
-
generatedAt: now().toISOString(),
|
|
86
|
-
inputSig: input.inputSig,
|
|
87
|
-
mutation: input.mutation,
|
|
88
|
-
assertions: input.assertions,
|
|
89
|
-
thresholds: {
|
|
90
|
-
mutationKillRateMin: thresholds.mutationKillRateMin,
|
|
91
|
-
weakAssertionRateMax: thresholds.weakAssertionRateMax,
|
|
92
|
-
passed: evalResult.passed,
|
|
93
|
-
},
|
|
94
|
-
followups,
|
|
95
|
-
};
|
|
96
|
-
const sha256 = computeMutSig(partial);
|
|
97
|
-
const final = { ...partial, sha256 };
|
|
98
|
-
MutReportSchema.parse(final);
|
|
99
|
-
await mkdir(dirname(input.out), { recursive: true });
|
|
100
|
-
const tmp = `${input.out}.tmp`;
|
|
101
|
-
try {
|
|
102
|
-
await writeFile(tmp, JSON.stringify(final, null, 2), 'utf8');
|
|
103
|
-
await rename(tmp, input.out);
|
|
104
|
-
}
|
|
105
|
-
catch (err) {
|
|
106
|
-
await unlink(tmp).catch(() => undefined);
|
|
107
|
-
throw err;
|
|
108
|
-
}
|
|
109
|
-
return final;
|
|
110
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { type MutReportJson } from './types.js';
|
|
2
|
-
export declare const MUT_REPORT_RELATIVE_PATH = "mut/mut-report.json";
|
|
3
|
-
/**
|
|
4
|
-
* Build the canonical absolute path of a session's mut-report.json.
|
|
5
|
-
* Exported so the CLI surface in qa-commands can reuse the same
|
|
6
|
-
* constant for diagnostic messages.
|
|
7
|
-
*
|
|
8
|
-
* Uses POSIX separators intentionally: the one-axis envelope is
|
|
9
|
-
* documented as `.peaks/_runtime/<sid>/mut/mut-report.json` (forward
|
|
10
|
-
* slashes) and that path is what the hotfix 81f00ce audit-trail
|
|
11
|
-
* contract guarantees. `node:path` would produce backslashes on
|
|
12
|
-
* Windows, breaking the cross-platform invariant. POSIX join is
|
|
13
|
-
* correct here because the result is a logical path stored in JSON
|
|
14
|
-
* artifacts and CLI diagnostics — it never gets passed to OS
|
|
15
|
-
* syscalls directly (readFile / writeFile accept both forms).
|
|
16
|
-
*/
|
|
17
|
-
export declare function mutReportPath(sessionId: string): string;
|
|
18
|
-
/**
|
|
19
|
-
* Read and validate a session's mut-report.json.
|
|
20
|
-
*
|
|
21
|
-
* Returns `null` for any of these cases:
|
|
22
|
-
* - file does not exist (ENOENT)
|
|
23
|
-
* - file exists but JSON is malformed
|
|
24
|
-
* - file exists and parses but does not satisfy `MutReportSchema`
|
|
25
|
-
*
|
|
26
|
-
* Never throws. Never logs to stdout (per "no console.log in src/").
|
|
27
|
-
* Schema-parse failures are reported via `process.stderr` so the
|
|
28
|
-
* qa-runner operator can see why their report is being treated as
|
|
29
|
-
* absent.
|
|
30
|
-
*/
|
|
31
|
-
export declare function loadMutReport(sessionId: string): Promise<MutReportJson | null>;
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plan 2 — Task 8: peaks-qa consumes MUT.sig from peaks-mut.
|
|
3
|
-
*
|
|
4
|
-
* `loadMutReport` is the read-side counterpart of `buildMutReport`
|
|
5
|
-
* (which is the write-side). Both share the canonical path:
|
|
6
|
-
* `.peaks/_runtime/<sessionId>/mut/mut-report.json` (per hotfix 81f00ce
|
|
7
|
-
* one-axis envelope — no `.peaks/_runtime/<sessionId>/` fallback).
|
|
8
|
-
*
|
|
9
|
-
* Design contract (per spec lines 1292-1341):
|
|
10
|
-
* - Missing file → `null` (gate is skipped, NOT failed)
|
|
11
|
-
* - Schema-invalid → `null` (log via stderr; do not throw — qa is a
|
|
12
|
-
* pre-step, not a precondition)
|
|
13
|
-
* - Schema-valid → the parsed `MutReportJson`
|
|
14
|
-
*
|
|
15
|
-
* Returning `null` instead of throwing is what lets peaks-qa treat
|
|
16
|
-
* "peaks mut was not run" as a no-op. If we threw, the qa gate would
|
|
17
|
-
* crash on every session that hasn't run peaks-mut yet.
|
|
18
|
-
*/
|
|
19
|
-
import { readFile } from 'node:fs/promises';
|
|
20
|
-
import { posix as pathPosix } from 'node:path';
|
|
21
|
-
import { MutReportSchema } from './types.js';
|
|
22
|
-
export const MUT_REPORT_RELATIVE_PATH = 'mut/mut-report.json';
|
|
23
|
-
/**
|
|
24
|
-
* Build the canonical absolute path of a session's mut-report.json.
|
|
25
|
-
* Exported so the CLI surface in qa-commands can reuse the same
|
|
26
|
-
* constant for diagnostic messages.
|
|
27
|
-
*
|
|
28
|
-
* Uses POSIX separators intentionally: the one-axis envelope is
|
|
29
|
-
* documented as `.peaks/_runtime/<sid>/mut/mut-report.json` (forward
|
|
30
|
-
* slashes) and that path is what the hotfix 81f00ce audit-trail
|
|
31
|
-
* contract guarantees. `node:path` would produce backslashes on
|
|
32
|
-
* Windows, breaking the cross-platform invariant. POSIX join is
|
|
33
|
-
* correct here because the result is a logical path stored in JSON
|
|
34
|
-
* artifacts and CLI diagnostics — it never gets passed to OS
|
|
35
|
-
* syscalls directly (readFile / writeFile accept both forms).
|
|
36
|
-
*/
|
|
37
|
-
export function mutReportPath(sessionId) {
|
|
38
|
-
return pathPosix.join('.peaks', '_runtime', sessionId, MUT_REPORT_RELATIVE_PATH);
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Read and validate a session's mut-report.json.
|
|
42
|
-
*
|
|
43
|
-
* Returns `null` for any of these cases:
|
|
44
|
-
* - file does not exist (ENOENT)
|
|
45
|
-
* - file exists but JSON is malformed
|
|
46
|
-
* - file exists and parses but does not satisfy `MutReportSchema`
|
|
47
|
-
*
|
|
48
|
-
* Never throws. Never logs to stdout (per "no console.log in src/").
|
|
49
|
-
* Schema-parse failures are reported via `process.stderr` so the
|
|
50
|
-
* qa-runner operator can see why their report is being treated as
|
|
51
|
-
* absent.
|
|
52
|
-
*/
|
|
53
|
-
export async function loadMutReport(sessionId) {
|
|
54
|
-
const path = mutReportPath(sessionId);
|
|
55
|
-
let raw;
|
|
56
|
-
try {
|
|
57
|
-
raw = await readFile(path, 'utf8');
|
|
58
|
-
}
|
|
59
|
-
catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
60
|
-
// ENOENT or permission denied — both treated as "not run".
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
let parsedJson;
|
|
64
|
-
try {
|
|
65
|
-
parsedJson = JSON.parse(raw);
|
|
66
|
-
}
|
|
67
|
-
catch (err) {
|
|
68
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
69
|
-
process.stderr.write(`[peaks-qa] mut-report at ${path} is not valid JSON; treating as absent: ${message}\n`);
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
const parsed = MutReportSchema.safeParse(parsedJson);
|
|
73
|
-
if (!parsed.success) {
|
|
74
|
-
process.stderr.write(`[peaks-qa] mut-report at ${path} failed schema validation; treating as absent: ${parsed.error.message}\n`);
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
return parsed.data;
|
|
78
|
-
}
|