peaks-loop 3.1.1 → 4.0.0-beta
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/.claude-plugin/marketplace.json +62 -12
- package/CHANGELOG.md +74 -36
- package/README-en.md +58 -240
- package/README.md +49 -325
- package/agents/karpathy-reviewer.md +3 -3
- package/dist/src/cli/cli-helpers.d.ts +18 -0
- package/dist/src/cli/cli-helpers.js +8 -0
- package/dist/src/cli/commands/adapter-commands.d.ts +30 -0
- package/dist/src/cli/commands/adapter-commands.js +35 -0
- package/dist/src/cli/commands/context-commands.d.ts +1 -1
- package/dist/src/cli/commands/context-commands.js +1 -1
- package/dist/src/cli/commands/contract-commands.d.ts +1 -1
- package/dist/src/cli/commands/contract-commands.js +1 -1
- package/dist/src/cli/commands/core/session-command.js +12 -0
- package/dist/src/cli/commands/core/skill-command.js +4 -4
- package/dist/src/cli/commands/dispatch-commands.js +2 -2
- package/dist/src/cli/commands/job-commands.js +58 -5
- package/dist/src/cli/commands/observability-commands.js +1 -1
- package/dist/src/cli/commands/perf-audit-commands.js +2 -2
- package/dist/src/cli/commands/security-audit-commands.js +2 -2
- package/dist/src/cli/commands/sediment-commands.d.ts +80 -0
- package/dist/src/cli/commands/sediment-commands.js +640 -0
- package/dist/src/cli/commands/session-migrate-skill-name.d.ts +17 -0
- package/dist/src/cli/commands/session-migrate-skill-name.js +41 -0
- package/dist/src/cli/commands/skill-visibility.d.ts +8 -0
- package/dist/src/cli/commands/skill-visibility.js +63 -0
- package/dist/src/cli/commands/slice-commands.js +2 -2
- package/dist/src/cli/commands/solo-commands.d.ts +2 -2
- package/dist/src/cli/commands/solo-commands.js +246 -20
- package/dist/src/cli/commands/sub-agent-commands.d.ts +1 -1
- package/dist/src/cli/commands/sub-agent-commands.js +1 -1
- package/dist/src/cli/commands/understand-commands.js +1 -1
- package/dist/src/cli/commands/upgrade-commands.d.ts +1 -1
- package/dist/src/cli/commands/upgrade-commands.js +3 -3
- package/dist/src/cli/commands/user-touchpoint-commands.js +1 -1
- package/dist/src/cli/commands/verdict-aggregate-command.d.ts +1 -1
- package/dist/src/cli/commands/verdict-aggregate-command.js +2 -2
- package/dist/src/cli/commands/workflow-commands.js +2 -2
- package/dist/src/cli/commands/workspace/init-command.d.ts +3 -3
- package/dist/src/cli/commands/workspace/init-command.js +7 -7
- package/dist/src/cli/program.js +19 -2
- package/dist/src/services/adapter/adapter.d.ts +27 -0
- package/dist/src/services/adapter/adapter.js +5 -0
- package/dist/src/services/adapter/auto-adapter.d.ts +11 -0
- package/dist/src/services/adapter/auto-adapter.js +15 -0
- package/dist/src/services/adapter/claude-adapter.d.ts +14 -0
- package/dist/src/services/adapter/claude-adapter.js +40 -0
- package/dist/src/services/adapter/codex-adapter.d.ts +14 -0
- package/dist/src/services/adapter/codex-adapter.js +14 -0
- package/dist/src/services/adapter/copilot-adapter.d.ts +14 -0
- package/dist/src/services/adapter/copilot-adapter.js +14 -0
- package/dist/src/services/audit/enforcers/solo-code-ban.d.ts +1 -1
- package/dist/src/services/audit/enforcers/solo-code-ban.js +2 -2
- package/dist/src/services/audit/red-line-catalog.js +1 -1
- package/dist/src/services/audit/scanners/skills-tree-scanner.js +22 -0
- package/dist/src/services/context/auto-compact-dispatcher.d.ts +1 -1
- package/dist/src/services/dispatch/batch-counter.js +1 -1
- package/dist/src/services/dispatch/leak-detector.js +1 -1
- package/dist/src/services/doctor/doctor-service.js +2 -2
- package/dist/src/services/job/job-progress-store.d.ts +60 -0
- package/dist/src/services/job/job-progress-store.js +70 -0
- package/dist/src/services/job/job-resource-snapshot.js +29 -1
- package/dist/src/services/job/job-types.d.ts +4 -4
- package/dist/src/services/memory/project-memory-service.js +1 -1
- package/dist/src/services/migrate-skill-name/migrate.d.ts +17 -0
- package/dist/src/services/migrate-skill-name/migrate.js +152 -0
- package/dist/src/services/migrate-skill-name/schema.d.ts +42 -0
- package/dist/src/services/migrate-skill-name/schema.js +25 -0
- package/dist/src/services/observability/aggregation.d.ts +1 -1
- package/dist/src/services/observability/aggregation.js +1 -1
- package/dist/src/services/perf/perf-baseline-service.d.ts +1 -1
- package/dist/src/services/perf/perf-baseline-service.js +1 -1
- package/dist/src/services/prd/handoff-types.d.ts +1 -1
- package/dist/src/services/prd/handoff-types.js +1 -1
- package/dist/src/services/progress/progress-service.d.ts +1 -1
- package/dist/src/services/progress/progress-service.js +1 -1
- package/dist/src/services/rd/standards-diagnostic.js +1 -1
- package/dist/src/services/recommendations/capability-seed-mappings.js +1 -1
- package/dist/src/services/sc/sc-service.js +1 -1
- package/dist/src/services/sediment/dispose-confirm.d.ts +9 -0
- package/dist/src/services/sediment/dispose-confirm.js +5 -0
- package/dist/src/services/sediment/json-schema.d.ts +247 -0
- package/dist/src/services/sediment/json-schema.js +26 -0
- package/dist/src/services/sediment/manifest-lint.d.ts +13 -0
- package/dist/src/services/sediment/manifest-lint.js +11 -0
- package/dist/src/services/sediment/pool-paths.d.ts +22 -0
- package/dist/src/services/sediment/pool-paths.js +25 -0
- package/dist/src/services/sediment/pool-read.d.ts +20 -0
- package/dist/src/services/sediment/pool-read.js +73 -0
- package/dist/src/services/sediment/pool-rebuild-index.d.ts +15 -0
- package/dist/src/services/sediment/pool-rebuild-index.js +28 -0
- package/dist/src/services/sediment/pool-write.d.ts +14 -0
- package/dist/src/services/sediment/pool-write.js +25 -0
- package/dist/src/services/sediment/promotion-gate.d.ts +12 -0
- package/dist/src/services/sediment/promotion-gate.js +20 -0
- package/dist/src/services/sediment/types.d.ts +52 -0
- package/dist/src/services/sediment/types.js +1 -0
- package/dist/src/services/session/binding-store.d.ts +1 -1
- package/dist/src/services/session/binding-store.js +1 -1
- package/dist/src/services/session/caller-id-types.d.ts +1 -1
- package/dist/src/services/session/session-manager.d.ts +1 -1
- package/dist/src/services/session/session-manager.js +1 -1
- package/dist/src/services/skill/resume-detector.js +1 -1
- package/dist/src/services/skill/skill-scheduler.d.ts +1 -1
- package/dist/src/services/skill/skill-scheduler.js +1 -1
- package/dist/src/services/skillhub/release-diff.d.ts +18 -0
- package/dist/src/services/skillhub/release-diff.js +38 -0
- package/dist/src/services/skillhub/release-export.d.ts +8 -0
- package/dist/src/services/skillhub/release-export.js +31 -0
- package/dist/src/services/skillhub/release-gc-blobs.d.ts +13 -0
- package/dist/src/services/skillhub/release-gc-blobs.js +32 -0
- package/dist/src/services/skillhub/release-import.d.ts +7 -0
- package/dist/src/services/skillhub/release-import.js +59 -0
- package/dist/src/services/skillhub/release-retain.d.ts +23 -0
- package/dist/src/services/skillhub/release-retain.js +89 -0
- package/dist/src/services/skillhub/sqlite-store.d.ts +22 -0
- package/dist/src/services/skillhub/sqlite-store.js +47 -0
- package/dist/src/services/skillhub/tar-runtime.d.ts +21 -0
- package/dist/src/services/skillhub/tar-runtime.js +91 -0
- package/dist/src/services/skillhub/types.d.ts +105 -0
- package/dist/src/services/skillhub/types.js +1 -0
- package/dist/src/services/skills/skill-conformance-service.js +8 -5
- package/dist/src/services/skills/skill-presence-service.d.ts +4 -4
- package/dist/src/services/skills/skill-presence-service.js +2 -2
- package/dist/src/services/skills/skill-registry.js +27 -0
- package/dist/src/services/skills/skill-runbook-service.js +2 -2
- package/dist/src/services/slice/slice-check-service.js +1 -1
- package/dist/src/services/slice/slice-check-types.d.ts +1 -1
- package/dist/src/services/slice/slice-check-types.js +1 -1
- package/dist/src/services/slice/slice-decompose-types.d.ts +1 -1
- package/dist/src/services/slice/slice-decompose-types.js +1 -1
- package/dist/src/services/solo/auto-compact-orchestrator.d.ts +1 -1
- package/dist/src/services/solo/auto-compact-orchestrator.js +2 -2
- package/dist/src/services/solo/dag-orchestrator.d.ts +3 -3
- package/dist/src/services/solo/dag-orchestrator.js +4 -4
- package/dist/src/services/solo/emit-handoff.d.ts +49 -0
- package/dist/src/services/solo/emit-handoff.js +79 -0
- package/dist/src/services/solo/mode-gate.d.ts +2 -2
- package/dist/src/services/solo/post-compact-detector.js +2 -2
- package/dist/src/services/solo/status-line-renderer.d.ts +4 -4
- package/dist/src/services/solo/step-08-gate.d.ts +90 -0
- package/dist/src/services/solo/step-08-gate.js +136 -0
- package/dist/src/services/standards/missing-standards-detector.d.ts +1 -1
- package/dist/src/services/standards/missing-standards-detector.js +1 -1
- package/dist/src/services/standards/project-standards-service.d.ts +1 -1
- package/dist/src/services/standards/project-standards-service.js +4 -4
- package/dist/src/services/understand/understand-types.d.ts +1 -1
- package/dist/src/services/upgrade/1x-detector-service.js +1 -1
- package/dist/src/services/upgrade/upgrade-service.d.ts +34 -0
- package/dist/src/services/upgrade/upgrade-service.js +52 -30
- package/dist/src/services/verdict/verdict-aggregator.d.ts +1 -1
- package/dist/src/services/workflow/workflow-router-service.d.ts +1 -1
- package/dist/src/services/workflow/workflow-router-service.js +3 -3
- package/dist/src/services/workspace/claude-settings-template.d.ts +7 -2
- package/dist/src/services/workspace/claude-settings-template.js +42 -3
- package/dist/src/services/workspace/workspace-claude-settings-materializer.d.ts +1 -1
- package/dist/src/services/workspace/workspace-claude-settings-materializer.js +1 -1
- package/dist/src/services/workspace/workspace-service.d.ts +4 -4
- package/dist/src/services/workspace/workspace-service.js +2 -2
- package/dist/src/shared/paths.d.ts +1 -1
- package/dist/src/shared/paths.js +1 -1
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/dist/src/skills/peaks-maker/index.d.ts +5 -0
- package/dist/src/skills/peaks-maker/index.js +32 -0
- package/package.json +8 -3
- package/scripts/install-skills.mjs +29 -4
- package/skills/{peaks-prd → bee/peaks-prd}/SKILL.md +8 -2
- package/skills/{peaks-prd → bee/peaks-prd}/references/workflow.md +1 -1
- package/skills/{peaks-qa → bee/peaks-qa}/SKILL.md +10 -4
- package/skills/{peaks-qa → bee/peaks-qa}/references/browser-validation-contracts.md +2 -2
- package/skills/{peaks-qa → bee/peaks-qa}/references/external-capability-guidance.md +1 -1
- package/skills/{peaks-qa → bee/peaks-qa}/references/qa-fanout-contract.md +3 -3
- package/skills/{peaks-qa → bee/peaks-qa}/references/qa-sub-agent-dispatch.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/SKILL.md +13 -6
- package/skills/{peaks-rd → bee/peaks-rd}/references/browser-self-test-contracts.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/references/mock-data-placement.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/references/parallel-review-fanout.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/references/rd-runbook.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/references/rd-sub-agent-dispatch.md +2 -2
- package/skills/{peaks-rd → bee/peaks-rd}/references/rd-transition-gates.md +1 -1
- package/skills/{peaks-rd → bee/peaks-rd}/references/skill-presence-and-title.md +1 -1
- package/skills/{peaks-reviewer → bee/peaks-reviewer}/SKILL.md +2 -2
- package/skills/{peaks-sc → bee/peaks-sc}/SKILL.md +7 -1
- package/skills/{peaks-txt → bee/peaks-txt}/SKILL.md +9 -3
- package/skills/{peaks-ui → bee/peaks-ui}/SKILL.md +11 -5
- package/skills/peaks-audit/SKILL.md +1 -1
- package/skills/{peaks-solo → peaks-code}/SKILL.md +53 -104
- package/skills/{peaks-solo → peaks-code}/references/a2a-artifact-mapping.md +2 -2
- package/skills/{peaks-solo → peaks-code}/references/anchoring-and-session-info.md +4 -4
- package/skills/{peaks-solo → peaks-code}/references/artifact-contracts.md +2 -2
- package/skills/{peaks-solo → peaks-code}/references/browser-workflow.md +1 -1
- package/skills/peaks-code/references/command-migration.md +3 -0
- package/skills/{peaks-solo → peaks-code}/references/completion-handoff.md +2 -2
- package/skills/{peaks-solo → peaks-code}/references/context-governance.md +2 -2
- package/skills/{peaks-solo → peaks-code}/references/frontend-only-mode.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/local-artifact-workspace.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/micro-cycle.md +9 -9
- package/skills/{peaks-solo → peaks-code}/references/mode-selection-with-stale-presence.md +12 -12
- package/skills/{peaks-solo → peaks-code}/references/mode-selection.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/openspec-workflow.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/project-scan-checklist.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/refactor-mode.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/resume-detection.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/runbook.md +25 -5
- package/skills/{peaks-solo → peaks-code}/references/skill-presence-and-title.md +3 -3
- package/skills/{peaks-solo → peaks-code}/references/standards-preflight.md +1 -1
- package/skills/{peaks-solo → peaks-code}/references/step-0-55-1x-detection.md +5 -5
- package/skills/peaks-code/references/step-0-8-gate.md +60 -0
- package/skills/{peaks-solo → peaks-code}/references/sub-agent-dispatch.md +10 -10
- package/skills/{peaks-solo → peaks-code}/references/swarm-dispatch-contract.md +7 -7
- package/skills/{peaks-solo → peaks-code}/references/workflow-gates-and-types.md +3 -3
- package/skills/peaks-doctor/SKILL.md +1 -1
- package/skills/peaks-doctor/references/doctor-check-catalog.md +1 -1
- package/skills/peaks-final-review/SKILL.md +3 -3
- package/skills/peaks-final-review/references/4-dimensions.md +1 -1
- package/skills/peaks-ide/SKILL.md +1 -1
- package/skills/{peaks-solo-resume → peaks-resume}/SKILL.md +14 -14
- package/skills/peaks-sop/SKILL.md +1 -1
- package/skills/{peaks-solo-status → peaks-status}/SKILL.md +13 -13
- package/skills/{peaks-solo-test → peaks-test}/SKILL.md +11 -11
- package/skills/peaks-solo/references/command-migration.md +0 -3
- /package/skills/{peaks-perf-audit → bee/peaks-perf-audit}/SKILL.md +0 -0
- /package/skills/{peaks-perf-audit → bee/peaks-perf-audit}/references/audit-protocol.md +0 -0
- /package/skills/{peaks-prd → bee/peaks-prd}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-prd → bee/peaks-prd}/references/artifact-per-request.md +0 -0
- /package/skills/{peaks-prd → bee/peaks-prd}/references/command-migration.md +0 -0
- /package/skills/{peaks-prd → bee/peaks-prd}/references/prd-for-multi-pass.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/artifact-per-request.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/codegraph-regression-focus.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/command-migration.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/openspec-validation-gate.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-compact-handoff.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-context-governance.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-gstack-integration.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-local-artifacts.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-matt-pocock-integration.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-perf-test-plan.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-refactor-role.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-runbook.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-security-test-plan.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-skill-presence.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-standards-preflight.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/qa-transition-gates.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/reading-handoff-frontmatter.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/regression-gates.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/requirement-boundary-recheck.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/test-case-generation.md +0 -0
- /package/skills/{peaks-qa → bee/peaks-qa}/references/test-report-output.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/artifact-and-standards-output.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/artifact-per-request.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/browser-action-wrapper.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/code-reviewer-4dim-hint.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/codegraph-project-analysis.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/command-migration.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/compact-handoff.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/external-references.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/frontend-project-generation.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/karpathy-reviewer-prompt.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/library-version-awareness.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/mandatory-perf-baseline.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/matt-pocock-integration.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/ocr-integration.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/openspec-cli.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/rd-context-governance.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/rd-fanout-contracts.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/rd-gstack-integration.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/rd-standards-preflight.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/reading-v2-slice-results.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/refactor-workflow.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/v2-12-fanout-collapse.md +0 -0
- /package/skills/{peaks-rd → bee/peaks-rd}/references/writing-handoff-frontmatter.md +0 -0
- /package/skills/{peaks-reviewer → bee/peaks-reviewer}/references/reviewer-prompt.md +0 -0
- /package/skills/{peaks-reviewer → bee/peaks-reviewer}/references/reviewer-schema.md +0 -0
- /package/skills/{peaks-sc → bee/peaks-sc}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-sc → bee/peaks-sc}/references/artifact-retention.md +0 -0
- /package/skills/{peaks-sc → bee/peaks-sc}/references/command-migration.md +0 -0
- /package/skills/{peaks-sc → bee/peaks-sc}/references/openspec-commit-boundaries.md +0 -0
- /package/skills/{peaks-security-audit → bee/peaks-security-audit}/SKILL.md +0 -0
- /package/skills/{peaks-security-audit → bee/peaks-security-audit}/references/audit-protocol.md +0 -0
- /package/skills/{peaks-txt → bee/peaks-txt}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-txt → bee/peaks-txt}/references/command-migration.md +0 -0
- /package/skills/{peaks-txt → bee/peaks-txt}/references/context-capsule.md +0 -0
- /package/skills/{peaks-ui → bee/peaks-ui}/references/artifact-contracts.md +0 -0
- /package/skills/{peaks-ui → bee/peaks-ui}/references/artifact-per-request.md +0 -0
- /package/skills/{peaks-ui → bee/peaks-ui}/references/command-migration.md +0 -0
- /package/skills/{peaks-ui → bee/peaks-ui}/references/workflow.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/boundaries.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/checkpoint-resume.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/codegraph-orchestration.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/cross-date-session-check.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/dag-orchestrator.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/envelope-contract.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/existing-system-extraction.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/external-references.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/external-skill-invocation.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/fanout-mandatory.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/fast-mode.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/gstack-integration.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/headroom-integration.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/job-loop.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/periodic-checkpoint.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/playwright-mcp-multi-terminal.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/project-memory-loading.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/quality-gate-cheatsheet.md +0 -0
- /package/skills/{peaks-solo → peaks-code}/references/workflow.md +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v3.1.2 Step 11 / final handoff — Size-fear ban.
|
|
3
|
+
*
|
|
4
|
+
* Refuses to emit a final handoff while a Job has remaining slices.
|
|
5
|
+
* Closes the v3.1.0 incident pattern: LLM writes a fake-completion
|
|
6
|
+
* message at high context-fill before Job mode kicks in.
|
|
7
|
+
*
|
|
8
|
+
* Decision tree:
|
|
9
|
+
* - job-shape.json missing OR isJob === false → ALLOW (normal handoff)
|
|
10
|
+
* - isJob === true, no state.json → JOB_NOT_INITIALIZED (LLM
|
|
11
|
+
* skipped `peaks job init`)
|
|
12
|
+
* - isJob === true, state.json, remaining > 0,
|
|
13
|
+
* no --force-under-job → JOB_REMAINING_BLOCKED
|
|
14
|
+
* - isJob === true, state.json, remaining === 0 → ALLOW (Job done)
|
|
15
|
+
* - isJob === true, state.json, remaining > 0,
|
|
16
|
+
* --force-under-job → ALLOW (override path)
|
|
17
|
+
*
|
|
18
|
+
* Karpathy §2 (Simplicity First): ~70 lines, no LLM call, no regex.
|
|
19
|
+
* Pure read + arithmetic. The CLI wrapper in solo-commands.ts
|
|
20
|
+
* translates the verdict into exit code + JSON envelope.
|
|
21
|
+
*/
|
|
22
|
+
export declare const JOB_NOT_INITIALIZED: "JOB_NOT_INITIALIZED";
|
|
23
|
+
export declare const JOB_REMAINING_BLOCKED: "JOB_REMAINING_BLOCKED";
|
|
24
|
+
export type EmitHandoffVerdict = {
|
|
25
|
+
readonly kind: 'allow-not-job';
|
|
26
|
+
} | {
|
|
27
|
+
readonly kind: 'allow-done';
|
|
28
|
+
readonly remaining: number;
|
|
29
|
+
} | {
|
|
30
|
+
readonly kind: 'allow-force-override';
|
|
31
|
+
readonly remaining: number;
|
|
32
|
+
} | {
|
|
33
|
+
readonly kind: 'block-not-initialized';
|
|
34
|
+
readonly code: typeof JOB_NOT_INITIALIZED;
|
|
35
|
+
readonly jobId: string;
|
|
36
|
+
} | {
|
|
37
|
+
readonly kind: 'block-remaining';
|
|
38
|
+
readonly code: typeof JOB_REMAINING_BLOCKED;
|
|
39
|
+
readonly jobId: string;
|
|
40
|
+
readonly remaining: number;
|
|
41
|
+
};
|
|
42
|
+
export interface EvaluateEmitHandoffInput {
|
|
43
|
+
readonly projectRoot: string;
|
|
44
|
+
readonly sessionId: string;
|
|
45
|
+
/** Suggested job id — read from job-shape.json when omitted. */
|
|
46
|
+
readonly jobId?: string;
|
|
47
|
+
readonly forceUnderJob?: boolean;
|
|
48
|
+
}
|
|
49
|
+
export declare function evaluateEmitHandoff(input: EvaluateEmitHandoffInput): EmitHandoffVerdict;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v3.1.2 Step 11 / final handoff — Size-fear ban.
|
|
3
|
+
*
|
|
4
|
+
* Refuses to emit a final handoff while a Job has remaining slices.
|
|
5
|
+
* Closes the v3.1.0 incident pattern: LLM writes a fake-completion
|
|
6
|
+
* message at high context-fill before Job mode kicks in.
|
|
7
|
+
*
|
|
8
|
+
* Decision tree:
|
|
9
|
+
* - job-shape.json missing OR isJob === false → ALLOW (normal handoff)
|
|
10
|
+
* - isJob === true, no state.json → JOB_NOT_INITIALIZED (LLM
|
|
11
|
+
* skipped `peaks job init`)
|
|
12
|
+
* - isJob === true, state.json, remaining > 0,
|
|
13
|
+
* no --force-under-job → JOB_REMAINING_BLOCKED
|
|
14
|
+
* - isJob === true, state.json, remaining === 0 → ALLOW (Job done)
|
|
15
|
+
* - isJob === true, state.json, remaining > 0,
|
|
16
|
+
* --force-under-job → ALLOW (override path)
|
|
17
|
+
*
|
|
18
|
+
* Karpathy §2 (Simplicity First): ~70 lines, no LLM call, no regex.
|
|
19
|
+
* Pure read + arithmetic. The CLI wrapper in solo-commands.ts
|
|
20
|
+
* translates the verdict into exit code + JSON envelope.
|
|
21
|
+
*/
|
|
22
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
23
|
+
import { join } from 'node:path';
|
|
24
|
+
import { readJobShapeDecision, JobShapeDecisionError, JOB_SHAPE_NOT_DECIDED } from './job-shape-decision.js';
|
|
25
|
+
export const JOB_NOT_INITIALIZED = 'JOB_NOT_INITIALIZED';
|
|
26
|
+
export const JOB_REMAINING_BLOCKED = 'JOB_REMAINING_BLOCKED';
|
|
27
|
+
function countRemaining(statePath) {
|
|
28
|
+
let raw;
|
|
29
|
+
try {
|
|
30
|
+
raw = readFileSync(statePath, 'utf8');
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return Number.NaN;
|
|
34
|
+
}
|
|
35
|
+
let parsed;
|
|
36
|
+
try {
|
|
37
|
+
parsed = JSON.parse(raw);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return Number.NaN;
|
|
41
|
+
}
|
|
42
|
+
if (!Array.isArray(parsed.slices))
|
|
43
|
+
return Number.NaN;
|
|
44
|
+
return parsed.slices.filter((sl) => sl.status !== 'done' && sl.status !== 'skipped').length;
|
|
45
|
+
}
|
|
46
|
+
function statePath(projectRoot, sessionId, jobId) {
|
|
47
|
+
return join(projectRoot, '.peaks', '_runtime', sessionId, 'job', jobId, 'state.json');
|
|
48
|
+
}
|
|
49
|
+
export function evaluateEmitHandoff(input) {
|
|
50
|
+
let decision = null;
|
|
51
|
+
try {
|
|
52
|
+
const record = readJobShapeDecision(input.projectRoot, input.sessionId);
|
|
53
|
+
decision = record.decision;
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
if (err instanceof JobShapeDecisionError && err.code === JOB_SHAPE_NOT_DECIDED) {
|
|
57
|
+
return { kind: 'allow-not-job' };
|
|
58
|
+
}
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
61
|
+
if (!decision.isJob)
|
|
62
|
+
return { kind: 'allow-not-job' };
|
|
63
|
+
const jobId = input.jobId ?? decision.suggestedJobId;
|
|
64
|
+
const path = statePath(input.projectRoot, input.sessionId, jobId);
|
|
65
|
+
if (!existsSync(path)) {
|
|
66
|
+
return { kind: 'block-not-initialized', code: JOB_NOT_INITIALIZED, jobId };
|
|
67
|
+
}
|
|
68
|
+
const remaining = countRemaining(path);
|
|
69
|
+
if (!Number.isFinite(remaining)) {
|
|
70
|
+
return { kind: 'block-not-initialized', code: JOB_NOT_INITIALIZED, jobId };
|
|
71
|
+
}
|
|
72
|
+
if (remaining === 0) {
|
|
73
|
+
return { kind: 'allow-done', remaining };
|
|
74
|
+
}
|
|
75
|
+
if (input.forceUnderJob === true) {
|
|
76
|
+
return { kind: 'allow-force-override', remaining };
|
|
77
|
+
}
|
|
78
|
+
return { kind: 'block-remaining', code: JOB_REMAINING_BLOCKED, jobId, remaining };
|
|
79
|
+
}
|
|
@@ -43,7 +43,7 @@ export type GatedStepId = 'step-0.5-openspec-opt-in' | 'step-0.6-audit-goal' | '
|
|
|
43
43
|
export declare const GATED_STEPS: readonly GatedStepId[];
|
|
44
44
|
/**
|
|
45
45
|
* Slice 2026-06-28-solo-mode-bypass-fix: the kind of gate that
|
|
46
|
-
* produced this decision. The LLM-side caller (peaks-
|
|
46
|
+
* produced this decision. The LLM-side caller (peaks-code body) reads
|
|
47
47
|
* this to distinguish "you paused because the user must choose the
|
|
48
48
|
* mode" (`mode-selection-itself`) from "you paused because the mode
|
|
49
49
|
* you already chose is assisted/strict" (`mode-driven`) from "you
|
|
@@ -98,7 +98,7 @@ export declare function shouldAutoProceed(mode: SoloMode): boolean;
|
|
|
98
98
|
/**
|
|
99
99
|
* v2.15.0 slice 002 AC-4: the 5 action identifiers that qualify as
|
|
100
100
|
* commit-boundary side effects. Matched by the LLM-side caller
|
|
101
|
-
* (peaks-
|
|
101
|
+
* (peaks-code body / peaks-rd fork agent) when it is about to run a
|
|
102
102
|
* Bash command that maps to one of these. Set `commitBoundaryAction:
|
|
103
103
|
* true` on the `shouldPauseAtGate` call to trigger the hard-floor
|
|
104
104
|
* override.
|
|
@@ -146,7 +146,7 @@ export async function detectPostCompactResume(opts) {
|
|
|
146
146
|
};
|
|
147
147
|
}
|
|
148
148
|
// Active skill check (D7.a.4). Defaults to reading from skill presence.
|
|
149
|
-
const expectedActiveSkill = 'peaks-
|
|
149
|
+
const expectedActiveSkill = 'peaks-code';
|
|
150
150
|
const observedActiveSkill = opts.activeSkill ?? readActiveSkillName(opts.projectRoot);
|
|
151
151
|
if (observedActiveSkill !== expectedActiveSkill) {
|
|
152
152
|
return {
|
|
@@ -154,7 +154,7 @@ export async function detectPostCompactResume(opts) {
|
|
|
154
154
|
reason: 'active-skill-mismatch',
|
|
155
155
|
checkpointPath: file.path,
|
|
156
156
|
checkpointMtime: file.mtime.toISOString(),
|
|
157
|
-
warnings: [`active skill "${observedActiveSkill ?? 'unset'}" is not peaks-
|
|
157
|
+
warnings: [`active skill "${observedActiveSkill ?? 'unset'}" is not peaks-code`]
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
160
|
// Mode: prefer the checkpoint's mode; fall back to the presence override
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* G6.5 — status line renderer for the peaks-
|
|
2
|
+
* G6.5 — status line renderer for the peaks-code batch-sync wait period.
|
|
3
3
|
*
|
|
4
4
|
* Single line, 80-120 chars, status-line-friendly. The shape is
|
|
5
5
|
* documented in PRD §G6.5:
|
|
6
6
|
*
|
|
7
|
-
* [peaks-
|
|
8
|
-
* [peaks-
|
|
7
|
+
* [peaks-code] swarm 3/3 running | rd-planning 45% (12s ago) | qa-test-cases 30% (5s ago) | ui-design 20% (2s ago)
|
|
8
|
+
* [peaks-code] swarm 3/3 running | rd-planning 70% (8s ago) | qa-test-cases 50% (3s ago) | ui-design 30% (6s ago)
|
|
9
9
|
* ...
|
|
10
|
-
* [peaks-
|
|
10
|
+
* [peaks-code] swarm 3/3 done in 47.3s
|
|
11
11
|
*
|
|
12
12
|
* Pure helper; the poller calls it once per tick. No IO.
|
|
13
13
|
*/
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v3.1.2 Step 0.8 — Mechanical PreToolUse gate.
|
|
3
|
+
*
|
|
4
|
+
* Wire-installed by `peaks workspace init` (extends the existing hook
|
|
5
|
+
* installer; does NOT replace the Write|Edit|MultiEdit fact-forcing
|
|
6
|
+
* bypass). The hook runs `peaks solo gate-step-08 --project .` before
|
|
7
|
+
* every Bash tool call. Exit code is the load-bearing contract:
|
|
8
|
+
*
|
|
9
|
+
* exit 0 → allow (with structured stdout describing the decision)
|
|
10
|
+
* exit 2 → block (stderr contains the BLOCKED: ... reason)
|
|
11
|
+
*
|
|
12
|
+
* Three decision paths:
|
|
13
|
+
*
|
|
14
|
+
* 1. `job-shape.json` exists with `decision.isJob === true`.
|
|
15
|
+
* → allow, print `{ ok, allow, mode: 'job', decision }`. When a
|
|
16
|
+
* matching `job/<jid>/progress.json` exists, also print
|
|
17
|
+
* `Next: slice #<N+1> of <M> (<currentSlice>)` so the LLM sees
|
|
18
|
+
* its resume context BEFORE any Bash call lands.
|
|
19
|
+
* 2. `job-shape.json` exists with `decision.isJob === false`.
|
|
20
|
+
* → allow, print `{ ok, allow, mode: 'single' }`.
|
|
21
|
+
* 3. `job-shape.json` is MISSING — fail-closed guard. The LLM is the
|
|
22
|
+
* source of truth, but if it never recorded a decision we run a
|
|
23
|
+
* lightweight backup regex against the user's prompt:
|
|
24
|
+
* /until|全部|until all done|disavow cost|不用考虑费用|all of them/i
|
|
25
|
+
* match → block (exit 2) with the BLOCKED: stderr message.
|
|
26
|
+
* no match → allow (exit 0) — most prompts are not Job-shaped.
|
|
27
|
+
*
|
|
28
|
+
* Karpathy §2 (Simplicity First): ~120 lines, no LLM call inside. The
|
|
29
|
+
* regex is the FIRST time peaks-loop accepts hardcoded keywords —
|
|
30
|
+
* explicitly scoped as a *fail-closed backup* (case 3), NOT a primary
|
|
31
|
+
* judgement. The LLM still owns the semantic call via
|
|
32
|
+
* `peaks solo detect-job`. The regex is a safety net for the v3.1.1
|
|
33
|
+
* incident class (LLM under load never records the decision at all).
|
|
34
|
+
*/
|
|
35
|
+
export declare const STEP_08_GATE_FILE_NAME: "job-shape.json";
|
|
36
|
+
export declare const STEP_08_PROGRESS_FILE_NAME: "progress.json";
|
|
37
|
+
/**
|
|
38
|
+
* Fail-closed backup regex — see module docstring case 3 for why this
|
|
39
|
+
* exists. Kept short and explicit; if the prompt mentions any of these
|
|
40
|
+
* triggers and `job-shape.json` is missing, the LLM is treated as
|
|
41
|
+
* having skipped `peaks solo detect-job` and the gate blocks.
|
|
42
|
+
*
|
|
43
|
+
* The list mirrors the v3.1.0 / v3.1.1 incident triggers verbatim:
|
|
44
|
+
* 继续执行下个 slice (until next slice) → until / 直到
|
|
45
|
+
* 全部添加完 / all of them → 全部 / all of them
|
|
46
|
+
* 不用考虑费用 → 不用考虑费用 / disavow cost
|
|
47
|
+
* until all done → until all done
|
|
48
|
+
*/
|
|
49
|
+
export declare const STEP_08_BACKUP_REGEX: RegExp;
|
|
50
|
+
export interface Step08Progress {
|
|
51
|
+
readonly jobId: string;
|
|
52
|
+
readonly done: number;
|
|
53
|
+
readonly total: number;
|
|
54
|
+
readonly currentSlice: string;
|
|
55
|
+
readonly lastCommitSha: string | null;
|
|
56
|
+
readonly updatedAt: string;
|
|
57
|
+
}
|
|
58
|
+
export type Step08Verdict = {
|
|
59
|
+
readonly kind: 'allow-job';
|
|
60
|
+
readonly decision: import('./job-shape-decision.js').JobShapeDecision;
|
|
61
|
+
readonly progress: Step08Progress | null;
|
|
62
|
+
} | {
|
|
63
|
+
readonly kind: 'allow-single';
|
|
64
|
+
} | {
|
|
65
|
+
readonly kind: 'block-missing-decision';
|
|
66
|
+
readonly promptHit: boolean;
|
|
67
|
+
readonly promptSource: 'flag' | 'last-prompt-file' | 'stdin-empty';
|
|
68
|
+
};
|
|
69
|
+
export declare function runtimeSessionDir(projectRoot: string, sessionId: string): string;
|
|
70
|
+
export interface EvaluateStep08Input {
|
|
71
|
+
readonly projectRoot: string;
|
|
72
|
+
readonly sessionId: string;
|
|
73
|
+
/**
|
|
74
|
+
* Explicit prompt text. When omitted, falls back to
|
|
75
|
+
* `.peaks/_runtime/<sid>/txt/last-prompt.txt`, then to stdin (the
|
|
76
|
+
* caller passes stdin verbatim — usually empty in tests).
|
|
77
|
+
*/
|
|
78
|
+
readonly prompt?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface EvaluateStep08Result {
|
|
81
|
+
readonly allow: boolean;
|
|
82
|
+
readonly verdict: Step08Verdict;
|
|
83
|
+
readonly nextSliceLine: string | null;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Pure evaluator — does NOT write, does NOT exit. CLI wrapper in
|
|
87
|
+
* `src/cli/commands/solo-commands.ts` reads `allow` to set the process
|
|
88
|
+
* exit code (0 allow / 2 block) and prints the structured envelope.
|
|
89
|
+
*/
|
|
90
|
+
export declare function evaluateStep08(input: EvaluateStep08Input): EvaluateStep08Result;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v3.1.2 Step 0.8 — Mechanical PreToolUse gate.
|
|
3
|
+
*
|
|
4
|
+
* Wire-installed by `peaks workspace init` (extends the existing hook
|
|
5
|
+
* installer; does NOT replace the Write|Edit|MultiEdit fact-forcing
|
|
6
|
+
* bypass). The hook runs `peaks solo gate-step-08 --project .` before
|
|
7
|
+
* every Bash tool call. Exit code is the load-bearing contract:
|
|
8
|
+
*
|
|
9
|
+
* exit 0 → allow (with structured stdout describing the decision)
|
|
10
|
+
* exit 2 → block (stderr contains the BLOCKED: ... reason)
|
|
11
|
+
*
|
|
12
|
+
* Three decision paths:
|
|
13
|
+
*
|
|
14
|
+
* 1. `job-shape.json` exists with `decision.isJob === true`.
|
|
15
|
+
* → allow, print `{ ok, allow, mode: 'job', decision }`. When a
|
|
16
|
+
* matching `job/<jid>/progress.json` exists, also print
|
|
17
|
+
* `Next: slice #<N+1> of <M> (<currentSlice>)` so the LLM sees
|
|
18
|
+
* its resume context BEFORE any Bash call lands.
|
|
19
|
+
* 2. `job-shape.json` exists with `decision.isJob === false`.
|
|
20
|
+
* → allow, print `{ ok, allow, mode: 'single' }`.
|
|
21
|
+
* 3. `job-shape.json` is MISSING — fail-closed guard. The LLM is the
|
|
22
|
+
* source of truth, but if it never recorded a decision we run a
|
|
23
|
+
* lightweight backup regex against the user's prompt:
|
|
24
|
+
* /until|全部|until all done|disavow cost|不用考虑费用|all of them/i
|
|
25
|
+
* match → block (exit 2) with the BLOCKED: stderr message.
|
|
26
|
+
* no match → allow (exit 0) — most prompts are not Job-shaped.
|
|
27
|
+
*
|
|
28
|
+
* Karpathy §2 (Simplicity First): ~120 lines, no LLM call inside. The
|
|
29
|
+
* regex is the FIRST time peaks-loop accepts hardcoded keywords —
|
|
30
|
+
* explicitly scoped as a *fail-closed backup* (case 3), NOT a primary
|
|
31
|
+
* judgement. The LLM still owns the semantic call via
|
|
32
|
+
* `peaks solo detect-job`. The regex is a safety net for the v3.1.1
|
|
33
|
+
* incident class (LLM under load never records the decision at all).
|
|
34
|
+
*/
|
|
35
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
36
|
+
import { join } from 'node:path';
|
|
37
|
+
import { readJobShapeDecision, JobShapeDecisionError, JOB_SHAPE_NOT_DECIDED } from './job-shape-decision.js';
|
|
38
|
+
export const STEP_08_GATE_FILE_NAME = 'job-shape.json';
|
|
39
|
+
export const STEP_08_PROGRESS_FILE_NAME = 'progress.json';
|
|
40
|
+
/**
|
|
41
|
+
* Fail-closed backup regex — see module docstring case 3 for why this
|
|
42
|
+
* exists. Kept short and explicit; if the prompt mentions any of these
|
|
43
|
+
* triggers and `job-shape.json` is missing, the LLM is treated as
|
|
44
|
+
* having skipped `peaks solo detect-job` and the gate blocks.
|
|
45
|
+
*
|
|
46
|
+
* The list mirrors the v3.1.0 / v3.1.1 incident triggers verbatim:
|
|
47
|
+
* 继续执行下个 slice (until next slice) → until / 直到
|
|
48
|
+
* 全部添加完 / all of them → 全部 / all of them
|
|
49
|
+
* 不用考虑费用 → 不用考虑费用 / disavow cost
|
|
50
|
+
* until all done → until all done
|
|
51
|
+
*/
|
|
52
|
+
export const STEP_08_BACKUP_REGEX = /直到|全部|until all done|disavow cost|不用考虑费用|all of them/i;
|
|
53
|
+
export function runtimeSessionDir(projectRoot, sessionId) {
|
|
54
|
+
return join(projectRoot, '.peaks', '_runtime', sessionId);
|
|
55
|
+
}
|
|
56
|
+
function progressPath(projectRoot, sessionId, jid) {
|
|
57
|
+
// The progress file lives under job/<jid>/progress.json. The jid
|
|
58
|
+
// comes from job-shape.json (decision.suggestedJobId) — there is
|
|
59
|
+
// exactly one canonical jid per session under Job mode, so we read
|
|
60
|
+
// the matching path directly rather than enumerating the job/ dir.
|
|
61
|
+
// (Rotating mode spawns new jids but only one is "active" at a time;
|
|
62
|
+
// the active jid is the latest write to job-shape.json.)
|
|
63
|
+
return join(runtimeSessionDir(projectRoot, sessionId), 'job', jid, STEP_08_PROGRESS_FILE_NAME);
|
|
64
|
+
}
|
|
65
|
+
function readProgressIfAny(projectRoot, sessionId, jid) {
|
|
66
|
+
const path = progressPath(projectRoot, sessionId, jid);
|
|
67
|
+
if (!existsSync(path))
|
|
68
|
+
return null;
|
|
69
|
+
try {
|
|
70
|
+
const raw = readFileSync(path, 'utf8');
|
|
71
|
+
const parsed = JSON.parse(raw);
|
|
72
|
+
if (typeof parsed.jobId === 'string' &&
|
|
73
|
+
typeof parsed.done === 'number' &&
|
|
74
|
+
typeof parsed.total === 'number' &&
|
|
75
|
+
typeof parsed.currentSlice === 'string' &&
|
|
76
|
+
typeof parsed.updatedAt === 'string') {
|
|
77
|
+
return {
|
|
78
|
+
jobId: parsed.jobId,
|
|
79
|
+
done: parsed.done,
|
|
80
|
+
total: parsed.total,
|
|
81
|
+
currentSlice: parsed.currentSlice,
|
|
82
|
+
lastCommitSha: typeof parsed.lastCommitSha === 'string' ? parsed.lastCommitSha : null,
|
|
83
|
+
updatedAt: parsed.updatedAt
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function readPromptFromLastPromptFile(projectRoot, sessionId) {
|
|
93
|
+
const path = join(runtimeSessionDir(projectRoot, sessionId), 'txt', 'last-prompt.txt');
|
|
94
|
+
if (!existsSync(path))
|
|
95
|
+
return '';
|
|
96
|
+
try {
|
|
97
|
+
return readFileSync(path, 'utf8');
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return '';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Pure evaluator — does NOT write, does NOT exit. CLI wrapper in
|
|
105
|
+
* `src/cli/commands/solo-commands.ts` reads `allow` to set the process
|
|
106
|
+
* exit code (0 allow / 2 block) and prints the structured envelope.
|
|
107
|
+
*/
|
|
108
|
+
export function evaluateStep08(input) {
|
|
109
|
+
try {
|
|
110
|
+
const record = readJobShapeDecision(input.projectRoot, input.sessionId);
|
|
111
|
+
if (record.decision.isJob) {
|
|
112
|
+
const progress = readProgressIfAny(input.projectRoot, input.sessionId, record.decision.suggestedJobId);
|
|
113
|
+
const nextSliceLine = progress !== null
|
|
114
|
+
? `Next: slice #${progress.done + 1} of ${progress.total} (${progress.currentSlice})`
|
|
115
|
+
: null;
|
|
116
|
+
return {
|
|
117
|
+
allow: true,
|
|
118
|
+
verdict: { kind: 'allow-job', decision: record.decision, progress },
|
|
119
|
+
nextSliceLine
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return { allow: true, verdict: { kind: 'allow-single' }, nextSliceLine: null };
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
if (err instanceof JobShapeDecisionError && err.code === JOB_SHAPE_NOT_DECIDED) {
|
|
126
|
+
const promptText = input.prompt ?? readPromptFromLastPromptFile(input.projectRoot, input.sessionId);
|
|
127
|
+
const hit = promptText.length > 0 && STEP_08_BACKUP_REGEX.test(promptText);
|
|
128
|
+
const source = input.prompt !== undefined ? 'flag' : promptText.length > 0 ? 'last-prompt-file' : 'stdin-empty';
|
|
129
|
+
if (hit) {
|
|
130
|
+
return { allow: false, verdict: { kind: 'block-missing-decision', promptHit: true, promptSource: source }, nextSliceLine: null };
|
|
131
|
+
}
|
|
132
|
+
return { allow: true, verdict: { kind: 'block-missing-decision', promptHit: false, promptSource: source }, nextSliceLine: null };
|
|
133
|
+
}
|
|
134
|
+
throw err;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Slice 2026-06-16-peaks-
|
|
2
|
+
* Slice 2026-06-16-peaks-code-auto-scaffold (RD#7) — missing-standards-detector.
|
|
3
3
|
*
|
|
4
4
|
* Read-side companion to the `peaks standards init` / `peaks standards update`
|
|
5
5
|
* writers in `./project-standards-service.ts`. The writer KNOWS how to scaffold
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Slice 2026-06-16-peaks-
|
|
2
|
+
* Slice 2026-06-16-peaks-code-auto-scaffold (RD#7) — missing-standards-detector.
|
|
3
3
|
*
|
|
4
4
|
* Read-side companion to the `peaks standards init` / `peaks standards update`
|
|
5
5
|
* writers in `./project-standards-service.ts`. The writer KNOWS how to scaffold
|
|
@@ -30,7 +30,7 @@ export type ProjectStandardsSource = {
|
|
|
30
30
|
readonly usage: 'curated-baseline-reference';
|
|
31
31
|
};
|
|
32
32
|
export type StandardsSkillPreflight = {
|
|
33
|
-
readonly appliesTo: readonly ['peaks-rd', 'peaks-qa', 'peaks-
|
|
33
|
+
readonly appliesTo: readonly ['peaks-rd', 'peaks-qa', 'peaks-code'];
|
|
34
34
|
readonly summary: string;
|
|
35
35
|
};
|
|
36
36
|
export type ProjectStandardsInitPlan = {
|
|
@@ -23,8 +23,8 @@ const SOURCE = {
|
|
|
23
23
|
usage: 'curated-baseline-reference'
|
|
24
24
|
};
|
|
25
25
|
const SKILL_PREFLIGHT = {
|
|
26
|
-
appliesTo: ['peaks-rd', 'peaks-qa', 'peaks-
|
|
27
|
-
summary: 'peaks-rd、peaks-qa、peaks-
|
|
26
|
+
appliesTo: ['peaks-rd', 'peaks-qa', 'peaks-code'],
|
|
27
|
+
summary: 'peaks-rd、peaks-qa、peaks-code 进入代码仓工作流时自动 preflight 项目规范。'
|
|
28
28
|
};
|
|
29
29
|
const SUPPORTED_LANGUAGES = new Set(['generic', 'typescript', 'javascript', 'python', 'go', 'rust']);
|
|
30
30
|
function normalizeRoot(path) {
|
|
@@ -104,7 +104,7 @@ function renderHeader(title) {
|
|
|
104
104
|
`# ${title}`,
|
|
105
105
|
'',
|
|
106
106
|
'Source: Peaks curated baseline; everything-claude-code reference: https://github.com/affaan-m/everything-claude-code',
|
|
107
|
-
'Scope: project-local standards for peaks-rd, peaks-qa, and peaks-
|
|
107
|
+
'Scope: project-local standards for peaks-rd, peaks-qa, and peaks-code workflow preflight.',
|
|
108
108
|
''
|
|
109
109
|
].join('\n');
|
|
110
110
|
}
|
|
@@ -151,7 +151,7 @@ function renderClaudeMd(language, ctx) {
|
|
|
151
151
|
'Peaks workflow automation:',
|
|
152
152
|
'- peaks-rd checks these standards before RD planning or implementation work.',
|
|
153
153
|
'- peaks-qa checks code review and security guidance before verification work.',
|
|
154
|
-
'- peaks-
|
|
154
|
+
'- peaks-code summarizes RD and QA standards preflight before end-to-end code workflows.',
|
|
155
155
|
'',
|
|
156
156
|
'Rules:',
|
|
157
157
|
'- Read `.claude/rules/common/coding-style.md` before editing code.',
|
|
@@ -33,7 +33,7 @@ export type UnderstandScanReport = {
|
|
|
33
33
|
};
|
|
34
34
|
/**
|
|
35
35
|
* Slice L3.1 — opt-in prompt payload. When uaPrompt === 'unset' and UA is
|
|
36
|
-
* absent, the peaks-
|
|
36
|
+
* absent, the peaks-code / peaks-ide layer surfaces this to the user via
|
|
37
37
|
* AskUserQuestion. The CLI does not prompt directly; it returns this
|
|
38
38
|
* payload so the LLM-side UX layer can decide.
|
|
39
39
|
*/
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* The canonical implementation lives in the .mjs postinstall
|
|
8
8
|
* (because the postinstall runs before any TS compile step).
|
|
9
|
-
* This TS mirror exists so the peaks-
|
|
9
|
+
* This TS mirror exists so the peaks-code skill can call
|
|
10
10
|
* `peaks upgrade --detect-1x --project <root> --json` and
|
|
11
11
|
* read a structured JSON envelope to gate the
|
|
12
12
|
* AskUserQuestion that prompts the 1.x → 2.0 upgrade.
|
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable executor for sub-step command spawns. Production
|
|
3
|
+
* callers omit `executor` on `UpgradeInput`; the default
|
|
4
|
+
* (`defaultSubstepExecutor`) wraps `node:child_process` `spawnSync`.
|
|
5
|
+
* Tests pass a synchronous fake executor to avoid the spawn cost.
|
|
6
|
+
*
|
|
7
|
+
* Contract:
|
|
8
|
+
* - Return `status: 0` for success, non-zero for failure, `null`
|
|
9
|
+
* for synchronous spawn errors (binary not found, EACCES, …).
|
|
10
|
+
* - `stdout` / `stderr` are captured as UTF-8 strings.
|
|
11
|
+
* - `durationMs` is the wall-clock duration of the spawn
|
|
12
|
+
* (caller-facing field on `SubStepResult`).
|
|
13
|
+
*/
|
|
14
|
+
export type SubstepExecutor = (command: string, args: readonly string[], timeoutMs: number) => {
|
|
15
|
+
status: number | null;
|
|
16
|
+
stdout: string;
|
|
17
|
+
stderr: string;
|
|
18
|
+
durationMs: number;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Default substep executor — wraps `spawnSync` with the same
|
|
22
|
+
* stdio / encoding / timeout config the umbrella has used since
|
|
23
|
+
* v1. Exported for test coverage: the seam-preservation test
|
|
24
|
+
* imports this directly to verify the normalized return shape
|
|
25
|
+
* on a spawn failure (e.g. a non-existent command).
|
|
26
|
+
*/
|
|
27
|
+
export declare const defaultSubstepExecutor: SubstepExecutor;
|
|
1
28
|
export interface UpgradeInput {
|
|
2
29
|
readonly projectRoot: string;
|
|
3
30
|
/**
|
|
@@ -14,6 +41,13 @@ export interface UpgradeInput {
|
|
|
14
41
|
* install hint in `nextActions` instead.
|
|
15
42
|
*/
|
|
16
43
|
readonly peaksBin?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Optional injectable executor for sub-step command execution.
|
|
46
|
+
* When omitted, the umbrella uses `defaultSubstepExecutor`
|
|
47
|
+
* (real `spawnSync`). Tests pass a synchronous fake to avoid
|
|
48
|
+
* the per-sub-step `node peaks.js …` spawn cost.
|
|
49
|
+
*/
|
|
50
|
+
readonly executor?: SubstepExecutor;
|
|
17
51
|
}
|
|
18
52
|
export interface SubStepResult {
|
|
19
53
|
readonly name: string;
|
|
@@ -33,6 +33,38 @@ import { fileURLToPath } from 'node:url';
|
|
|
33
33
|
import { runRedLinesAudit } from '../audit/red-lines-service.js';
|
|
34
34
|
import { savePreferences } from '../preferences/preferences-service.js';
|
|
35
35
|
import { migrateGitignoreFile } from './gitignore-migrate-service.js';
|
|
36
|
+
/**
|
|
37
|
+
* Default substep executor — wraps `spawnSync` with the same
|
|
38
|
+
* stdio / encoding / timeout config the umbrella has used since
|
|
39
|
+
* v1. Exported for test coverage: the seam-preservation test
|
|
40
|
+
* imports this directly to verify the normalized return shape
|
|
41
|
+
* on a spawn failure (e.g. a non-existent command).
|
|
42
|
+
*/
|
|
43
|
+
export const defaultSubstepExecutor = (command, args, timeoutMs) => {
|
|
44
|
+
const start = Date.now();
|
|
45
|
+
try {
|
|
46
|
+
const result = spawnSync(command, args, {
|
|
47
|
+
encoding: 'utf8',
|
|
48
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
49
|
+
timeout: timeoutMs,
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
status: result.status,
|
|
53
|
+
stdout: result.stdout ?? '',
|
|
54
|
+
stderr: result.stderr ?? '',
|
|
55
|
+
durationMs: Date.now() - start,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
60
|
+
return {
|
|
61
|
+
status: null,
|
|
62
|
+
stdout: '',
|
|
63
|
+
stderr: message,
|
|
64
|
+
durationMs: Date.now() - start,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
};
|
|
36
68
|
const STEPS = [
|
|
37
69
|
{ name: 'config-migrate', args: (p) => ['config', 'migrate', '--project', p, '--apply', '--json'] },
|
|
38
70
|
{ name: 'standards-migrate', args: (p) => ['standards', 'migrate', '--from-claude-rules', '--project', p, '--apply', '--json'] },
|
|
@@ -145,8 +177,7 @@ function read1xVersion(cwd) {
|
|
|
145
177
|
}
|
|
146
178
|
return null;
|
|
147
179
|
}
|
|
148
|
-
function runStep(peaksBin, name, args, timeoutMs = 60_000) {
|
|
149
|
-
const start = Date.now();
|
|
180
|
+
function runStep(peaksBin, name, args, timeoutMs = 60_000, executor = defaultSubstepExecutor) {
|
|
150
181
|
// The global `peaks` shim is a `/bin/sh` symlink script (the
|
|
151
182
|
// npm install postinstall creates `peaks` → `peaks.sh` on
|
|
152
183
|
// Windows). cmd.exe (the default Windows shell) cannot run
|
|
@@ -168,32 +199,18 @@ function runStep(peaksBin, name, args, timeoutMs = 60_000) {
|
|
|
168
199
|
command = peaksBin;
|
|
169
200
|
spawnArgs = args;
|
|
170
201
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
durationMs: Date.now() - start,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
catch (err) {
|
|
187
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
188
|
-
return {
|
|
189
|
-
name,
|
|
190
|
-
status: 'fail',
|
|
191
|
-
exitCode: null,
|
|
192
|
-
stdout: '',
|
|
193
|
-
stderr: message,
|
|
194
|
-
durationMs: Date.now() - start,
|
|
195
|
-
};
|
|
196
|
-
}
|
|
202
|
+
// The executor normalizes spawn errors to { status: null, stderr: ... }
|
|
203
|
+
// so no try/catch wrapper is needed here — the call always returns
|
|
204
|
+
// a shaped record. See defaultSubstepExecutor for the reference impl.
|
|
205
|
+
const result = executor(command, spawnArgs, timeoutMs);
|
|
206
|
+
return {
|
|
207
|
+
name,
|
|
208
|
+
status: result.status === 0 ? 'pass' : 'fail',
|
|
209
|
+
exitCode: result.status,
|
|
210
|
+
stdout: result.stdout,
|
|
211
|
+
stderr: result.stderr,
|
|
212
|
+
durationMs: result.durationMs,
|
|
213
|
+
};
|
|
197
214
|
}
|
|
198
215
|
function writeUpgradeRecord(projectRoot, result) {
|
|
199
216
|
try {
|
|
@@ -260,6 +277,11 @@ export function runUpgrade(input) {
|
|
|
260
277
|
resolve(here, '..', '..', '..', '..', 'bin', 'peaks.js');
|
|
261
278
|
const fallbackPeaks = 'peaks';
|
|
262
279
|
const resolvedPeaksBin = existsSync(peaksBin) ? peaksBin : fallbackPeaks;
|
|
280
|
+
// Resolve the executor once at the top of runUpgrade so every
|
|
281
|
+
// sub-step call shares the same instance. Tests pass a fake
|
|
282
|
+
// executor via UpgradeInput.executor; production callers omit
|
|
283
|
+
// it and get the default spawnSync wrapper.
|
|
284
|
+
const executor = input.executor ?? defaultSubstepExecutor;
|
|
263
285
|
const fromVersion = read1xVersion(input.projectRoot);
|
|
264
286
|
const steps = [];
|
|
265
287
|
const warnings = [];
|
|
@@ -325,7 +347,7 @@ export function runUpgrade(input) {
|
|
|
325
347
|
continue;
|
|
326
348
|
}
|
|
327
349
|
const args = ['memory', 'extract', '--project', input.projectRoot, '--artifact', ...artifacts, '--apply', '--json'];
|
|
328
|
-
const r = runStep(resolvedPeaksBin, 'memory-extract', args);
|
|
350
|
+
const r = runStep(resolvedPeaksBin, 'memory-extract', args, 60_000, executor);
|
|
329
351
|
steps.push(r);
|
|
330
352
|
if (r.status === 'fail') {
|
|
331
353
|
warnings.push(`memory-extract failed: ${r.stderr.slice(0, 200)}`);
|
|
@@ -333,7 +355,7 @@ export function runUpgrade(input) {
|
|
|
333
355
|
continue;
|
|
334
356
|
}
|
|
335
357
|
const args = step.args(input.projectRoot);
|
|
336
|
-
const r = runStep(resolvedPeaksBin, step.name, args);
|
|
358
|
+
const r = runStep(resolvedPeaksBin, step.name, args, 60_000, executor);
|
|
337
359
|
steps.push(r);
|
|
338
360
|
if (r.status === 'fail') {
|
|
339
361
|
warnings.push(`${step.name} failed: ${r.stderr.slice(0, 200)}`);
|