@pareto4/pp-core 1.18.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/agents/pp-code-fixer.md +9 -5
- package/agents/pp-code-reviewer.md +1 -0
- package/agents/pp-codebase-mapper.md +3 -0
- package/agents/pp-debugger.md +3 -2
- package/agents/pp-executor.md +16 -7
- package/agents/pp-integration-checker.md +1 -0
- package/agents/pp-phase-researcher.md +13 -1
- package/agents/pp-plan-checker.md +3 -0
- package/agents/pp-planner.md +20 -1
- package/agents/pp-research-synthesizer.md +1 -1
- package/agents/pp-ui-auditor.md +1 -0
- package/agents/pp-ui-researcher.md +3 -1
- package/agents/pp-vault-reviewer.md +2 -0
- package/agents/pp-verifier.md +22 -10
- package/commands/pp-add-tests.md +1 -1
- package/commands/pp-debug.md +1 -0
- package/commands/pp-discovery.md +3 -2
- package/commands/pp-init.md +4 -3
- package/commands/pp-quick.md +3 -0
- package/commands/pp-review-backlog.md +2 -1
- package/gemini-extension.json +1 -1
- package/package.json +6 -3
- package/pareto-skills/_shared/pp-claude-md-protocol.md +1 -1
- package/pareto-skills/pp-project-setup/SKILL.md +18 -343
- package/pp-core/bin/lib/capability-registry.cjs +3 -3
- package/pp-core/bin/lib/check-command-router.cjs +60 -20
- package/pp-core/bin/lib/commands.cjs +79 -4
- package/pp-core/bin/lib/compose-bindings.cjs +97 -14
- package/pp-core/bin/lib/discovery-access.cjs +276 -0
- package/pp-core/bin/lib/discovery-charter.cjs +664 -0
- package/pp-core/bin/lib/discovery-deviations.cjs +264 -0
- package/pp-core/bin/lib/discovery-entities.cjs +323 -0
- package/pp-core/bin/lib/discovery-for-phase.cjs +628 -0
- package/pp-core/bin/lib/discovery-integrations.cjs +286 -0
- package/pp-core/bin/lib/discovery-migration.cjs +246 -0
- package/pp-core/bin/lib/discovery-phases.cjs +233 -0
- package/pp-core/bin/lib/discovery-processes.cjs +355 -0
- package/pp-core/bin/lib/discovery-research-track.cjs +5 -4
- package/pp-core/bin/lib/discovery-rollup.cjs +12 -8
- package/pp-core/bin/lib/discovery-rules.cjs +216 -0
- package/pp-core/bin/lib/discovery-screens.cjs +21 -3
- package/pp-core/bin/lib/discovery-session-check.cjs +264 -0
- package/pp-core/bin/lib/discovery-stories.cjs +273 -0
- package/pp-core/bin/lib/discovery-sweep.cjs +13 -4
- package/pp-core/bin/lib/discovery-table.cjs +55 -0
- package/pp-core/bin/lib/discovery-vault-check.cjs +37 -3
- package/pp-core/bin/lib/init-contract.cjs +48 -7
- package/pp-core/bin/lib/io.cjs +22 -0
- package/pp-core/bin/lib/vault-coordinates.cjs +1 -1
- package/pp-core/bin/lib/vault-index.cjs +18 -5
- package/pp-core/bin/lib/vault-standards-review.cjs +50 -2
- package/pp-core/bin/lib/vault-update.cjs +4 -0
- package/pp-core/bin/lib/vault.cjs +2 -2
- package/pp-core/bin/pp-tools.cjs +153 -5
- package/pp-core/org-profile.json +1 -1
- package/pp-core/references/autonomous-best-effort.md +3 -2
- package/pp-core/references/autonomous-lifecycle.md +1 -0
- package/pp-core/references/autonomous-smart-discuss.md +5 -1
- package/pp-core/references/discovery-access.md +112 -0
- package/pp-core/references/discovery-build-consumption.md +256 -0
- package/pp-core/references/discovery-charter.md +127 -0
- package/pp-core/references/discovery-data-model.md +145 -0
- package/pp-core/references/discovery-id-conventions.md +77 -8
- package/pp-core/references/discovery-integrations.md +151 -0
- package/pp-core/references/discovery-processes.md +190 -0
- package/pp-core/references/discovery-rebaseline.md +2 -2
- package/pp-core/references/discovery-research-track.md +5 -6
- package/pp-core/references/discovery-session-output.md +70 -0
- package/pp-core/references/discovery-standards.md +107 -0
- package/pp-core/references/discovery-traceability.md +2 -2
- package/pp-core/references/execute-mvp-tdd.md +3 -3
- package/pp-core/references/git-integration.md +57 -33
- package/pp-core/references/git-planning-commit.md +31 -9
- package/pp-core/references/phase-argument-parsing.md +1 -0
- package/pp-core/references/planner-discovery-extract.md +35 -0
- package/pp-core/references/planner-gap-closure.md +1 -0
- package/pp-core/references/planner-revision.md +3 -1
- package/pp-core/references/planner-tdd.md +4 -4
- package/pp-core/references/planning-config.md +3 -3
- package/pp-core/references/shell-portability.md +28 -0
- package/pp-core/references/tdd.md +20 -16
- package/pp-core/references/verifier-discovery-conformance.md +36 -0
- package/pp-core/references/worktree-path-safety.md +1 -0
- package/pp-core/templates/milestone.md +5 -5
- package/pp-core/templates/project-charter.md +161 -100
- package/pp-core/templates/project.md +3 -3
- package/pp-core/templates/requirements.md +18 -0
- package/pp-core/templates/verification-report.md +16 -0
- package/pp-core/workflows/add-backlog.md +1 -1
- package/pp-core/workflows/add-tests.md +5 -2
- package/pp-core/workflows/add-todo.md +3 -1
- package/pp-core/workflows/ai-integration-phase.md +2 -1
- package/pp-core/workflows/audit-fix.md +4 -3
- package/pp-core/workflows/audit-milestone.md +1 -0
- package/pp-core/workflows/autonomous.md +6 -0
- package/pp-core/workflows/check-todos.md +2 -1
- package/pp-core/workflows/cleanup.md +3 -1
- package/pp-core/workflows/code-review-fix.md +12 -5
- package/pp-core/workflows/code-review.md +15 -1
- package/pp-core/workflows/complete-milestone.md +13 -3
- package/pp-core/workflows/debug.md +2 -0
- package/pp-core/workflows/diagnose-issues.md +1 -1
- package/pp-core/workflows/discovery-sprint/charter.md +114 -0
- package/pp-core/workflows/discovery-sprint/prefill.md +1 -1
- package/pp-core/workflows/discovery-sprint/prototype.md +4 -4
- package/pp-core/workflows/discovery-sprint/session-13-gates.md +11 -1
- package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +54 -7
- package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +31 -7
- package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +64 -37
- package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +12 -3
- package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +45 -22
- package/pp-core/workflows/discovery-sprint/sessions/06-security.md +30 -15
- package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +43 -25
- package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +63 -24
- package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +28 -13
- package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +35 -16
- package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +32 -8
- package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +21 -18
- package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +29 -12
- package/pp-core/workflows/discovery-sprint/vault-context.md +14 -3
- package/pp-core/workflows/discovery-sprint.md +23 -23
- package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +81 -29
- package/pp-core/workflows/discovery-to-build/steps/{screen-inventory-gate.md → handoff-gates.md} +111 -3
- package/pp-core/workflows/discovery-to-build/templates/discovery-references.md +12 -9
- package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +27 -26
- package/pp-core/workflows/discovery-to-build.md +70 -34
- package/pp-core/workflows/discuss-phase/discovery.md +83 -0
- package/pp-core/workflows/discuss-phase/templates/context.md +4 -0
- package/pp-core/workflows/discuss-phase-assumptions.md +5 -3
- package/pp-core/workflows/discuss-phase.md +18 -10
- package/pp-core/workflows/docs-update.md +1 -0
- package/pp-core/workflows/eval-review.md +2 -1
- package/pp-core/workflows/execute-phase/steps/check-query-gate.md +7 -6
- package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +1 -0
- package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -0
- package/pp-core/workflows/execute-phase/steps/vault-fetch.md +12 -0
- package/pp-core/workflows/execute-phase.md +19 -7
- package/pp-core/workflows/execute-plan.md +18 -7
- package/pp-core/workflows/explore.md +1 -1
- package/pp-core/workflows/forensics.md +4 -2
- package/pp-core/workflows/health.md +1 -0
- package/pp-core/workflows/import.md +2 -1
- package/pp-core/workflows/ingest-docs.md +1 -0
- package/pp-core/workflows/init/steps/client-context-capture.md +1 -0
- package/pp-core/workflows/init/steps/github-provisioning.md +145 -0
- package/pp-core/workflows/init/steps/gitlab-provisioning.md +18 -4
- package/pp-core/workflows/init/steps/reachability-outcome.md +3 -1
- package/pp-core/workflows/init.md +56 -66
- package/pp-core/workflows/map-codebase.md +5 -1
- package/pp-core/workflows/milestone-summary.md +2 -1
- package/pp-core/workflows/mvp-phase.md +1 -0
- package/pp-core/workflows/new-milestone.md +9 -5
- package/pp-core/workflows/new-project.md +12 -11
- package/pp-core/workflows/new-workspace.md +1 -0
- package/pp-core/workflows/next.md +2 -1
- package/pp-core/workflows/pause-work.md +6 -4
- package/pp-core/workflows/plan-milestone-gaps.md +3 -1
- package/pp-core/workflows/plan-phase/steps/chunked-planning.md +1 -1
- package/pp-core/workflows/plan-phase/steps/discovery-extract.md +41 -0
- package/pp-core/workflows/plan-phase.md +36 -16
- package/pp-core/workflows/plan-review-convergence.md +2 -0
- package/pp-core/workflows/plant-seed.md +4 -2
- package/pp-core/workflows/pr-branch.md +2 -0
- package/pp-core/workflows/progress.md +5 -0
- package/pp-core/workflows/quick.md +11 -4
- package/pp-core/workflows/reapply-patches.md +3 -0
- package/pp-core/workflows/remove-phase.md +1 -1
- package/pp-core/workflows/resume-project.md +3 -0
- package/pp-core/workflows/review.md +7 -1
- package/pp-core/workflows/secure-phase.md +2 -1
- package/pp-core/workflows/session-report.md +1 -0
- package/pp-core/workflows/ship.md +8 -1
- package/pp-core/workflows/sketch-wrap-up.md +1 -1
- package/pp-core/workflows/sketch.md +3 -2
- package/pp-core/workflows/spec-phase.md +2 -1
- package/pp-core/workflows/spike-wrap-up.md +1 -1
- package/pp-core/workflows/spike.md +4 -3
- package/pp-core/workflows/sync-skills.md +5 -2
- package/pp-core/workflows/thread.md +3 -2
- package/pp-core/workflows/transition.md +6 -0
- package/pp-core/workflows/ui-phase.md +3 -1
- package/pp-core/workflows/ui-review.md +2 -1
- package/pp-core/workflows/ultraplan-phase.md +1 -0
- package/pp-core/workflows/undo.md +14 -10
- package/pp-core/workflows/update.md +5 -0
- package/pp-core/workflows/validate-phase.md +6 -3
- package/pp-core/workflows/vault-review.md +7 -1
- package/pp-core/workflows/vault-write-back.md +5 -0
- package/pp-core/workflows/verify-phase.md +5 -0
- package/pp-core/workflows/verify-work.md +8 -1
- package/scripts/prompt-injection-scan.sh +1 -1
- package/scripts/sync-runtime-launcher.cjs +115 -5
- package/pp-core/workflows/discovery-sprint/templates/context-template.md +0 -266
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Plan-phase step — Discovery extract (R1)
|
|
2
|
+
|
|
3
|
+
> Read and executed from `workflows/plan-phase.md` §7 after the context paths are extracted and
|
|
4
|
+
> before the researcher (§5.1) and planner (§8) prompts are built. Inert on a project without
|
|
5
|
+
> `.planning/discovery/`. Contract: `references/discovery-build-consumption.md`.
|
|
6
|
+
|
|
7
|
+
Render the phase's discovery rows fresh — the registers may have been amended since
|
|
8
|
+
`/pp-discuss-phase` wrote CONTEXT.md — into one file the researcher and the planner read:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
_PP_SHIM_NAME="pp-tools.cjs"; _pp_root() { ( for _v in $(env | sed -n 's/^\(GIT_[A-Za-z0-9_]*\)=.*/\1/p'); do unset "$_v"; done; _c=$(git rev-parse --git-common-dir 2>/dev/null); if [ "${_c##*/}" = .git ] && cd "$_c/.." 2>/dev/null; then pwd -P; else git rev-parse --show-toplevel 2>/dev/null || pwd; fi ); }; pp_run() { case "$PP_TOOLS" in *.cjs) node "$PP_TOOLS" "$@";; *) "$PP_TOOLS" "$@";; esac; }; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(_pp_root)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then :; elif [ -f "${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}"; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; else echo "ERROR: pp-tools.cjs not found at $PP_TOOLS and pp-tools is not on PATH. Run: npx -y @pareto4/pp-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${PP_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${PP_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
12
|
+
DISCOVERY_EXTRACT_PATH=""
|
|
13
|
+
_DX_JSON=$(pp_run query discovery.for-phase "${PHASE_NUMBER}" 2>/dev/null || true)
|
|
14
|
+
if [[ "$_DX_JSON" == @file:* ]]; then _DX_JSON=$(cat "${_DX_JSON#@file:}"); fi
|
|
15
|
+
_DX_PRESENT=$(printf '%s' "$_DX_JSON" | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{try{const o=JSON.parse(s);console.log(o.present===true&&o.ok===true?'true':'false')}catch{console.log('false')}})")
|
|
16
|
+
if [ "$_DX_PRESENT" = true ]; then
|
|
17
|
+
DISCOVERY_EXTRACT_PATH="${PHASE_DIR}/${PADDED_PHASE}-DISCOVERY-EXTRACT.md"
|
|
18
|
+
pp_run query discovery.for-phase "${PHASE_NUMBER}" --markdown > "${DISCOVERY_EXTRACT_PATH}"
|
|
19
|
+
echo "DISCOVERY_EXTRACT_PATH=${DISCOVERY_EXTRACT_PATH}"
|
|
20
|
+
else
|
|
21
|
+
rm -f "${PHASE_DIR}/${PADDED_PHASE}-DISCOVERY-EXTRACT.md"
|
|
22
|
+
fi
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
A non-zero exit from the first command is a structural fault in a discovery artifact
|
|
26
|
+
(`discovery_for_phase_failed`): print the fault list and stop. Planning on a malformed register
|
|
27
|
+
copies the malformation into the build; the sprint's own check names the row to fix.
|
|
28
|
+
|
|
29
|
+
When `DISCOVERY_EXTRACT_PATH` is non-empty:
|
|
30
|
+
|
|
31
|
+
- add `- {DISCOVERY_EXTRACT_PATH} (Discovery extract — register rows citing this phase's
|
|
32
|
+
requirement IDs; required reading, never open a session-NN.md)` to the `<files_to_read>` of
|
|
33
|
+
the researcher prompt (§5.1) and the planner prompt (§8);
|
|
34
|
+
- the planner embeds the file's content verbatim — markers included — as the `<discovery_extract>`
|
|
35
|
+
block of every PLAN.md it writes, after `<context>` (and after `<vault_standards>` when present)
|
|
36
|
+
and before `<tasks>`;
|
|
37
|
+
- the file is a render and is never committed: it is regenerated on every planning run and
|
|
38
|
+
`*-DISCOVERY-EXTRACT.md` is not a phase artifact.
|
|
39
|
+
|
|
40
|
+
The name is deliberate: `{padded}-DISCOVERY.md` already belongs to the planner's library
|
|
41
|
+
discovery protocol and is a different thing.
|
|
@@ -63,7 +63,7 @@ for the plan-checker gate to be meaningful.
|
|
|
63
63
|
|
|
64
64
|
## 0. Git Branch Invariant
|
|
65
65
|
|
|
66
|
-
**Do not create, rename, or switch git branches during plan-phase.** Branch identity is established at discuss-phase and
|
|
66
|
+
**Do not create, rename, or switch git branches during plan-phase.** Branch identity is established at discuss-phase and owned by the user's git workflow. A phase rename in ROADMAP.md is a plan-level change only — it never mutates branch names. A `phase_slug` differing from the current branch name is expected; leave the branch unchanged.
|
|
67
67
|
|
|
68
68
|
## 1. Initialize
|
|
69
69
|
|
|
@@ -71,6 +71,7 @@ Load all context in one call (paths only to minimize orchestrator context):
|
|
|
71
71
|
|
|
72
72
|
```bash
|
|
73
73
|
_PP_SHIM_NAME="pp-tools.cjs"; _pp_root() { ( for _v in $(env | sed -n 's/^\(GIT_[A-Za-z0-9_]*\)=.*/\1/p'); do unset "$_v"; done; _c=$(git rev-parse --git-common-dir 2>/dev/null); if [ "${_c##*/}" = .git ] && cd "$_c/.." 2>/dev/null; then pwd -P; else git rev-parse --show-toplevel 2>/dev/null || pwd; fi ); }; pp_run() { case "$PP_TOOLS" in *.cjs) node "$PP_TOOLS" "$@";; *) "$PP_TOOLS" "$@";; esac; }; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(_pp_root)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then :; elif [ -f "${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}"; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; else echo "ERROR: pp-tools.cjs not found at $PP_TOOLS and pp-tools is not on PATH. Run: npx -y @pareto4/pp-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${PP_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${PP_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
74
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
74
75
|
GRAN_PARAM=""; if [[ "$ARGUMENTS" =~ (^|[[:space:]])--granularity[[:space:]]+([^[:space:]-][^[:space:]]*) ]]; then GRAN_PARAM="--granularity ${BASH_REMATCH[2]}"; fi
|
|
75
76
|
INIT=$(pp_run query init.plan-phase "$PHASE" $GRAN_PARAM)
|
|
76
77
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
@@ -83,7 +84,7 @@ MVP_MODE_CFG=$(pp_run query config-get workflow.mvp_mode 2>/dev/null || echo "fa
|
|
|
83
84
|
|
|
84
85
|
When the tdd capability's `workflow.tdd_mode` is active (resolved via the plan:pre render-hooks), the planner agent is instructed to apply `type: tdd` to eligible tasks using heuristics from `references/tdd.md`. The TDD guidance is injected via the tdd capability's contribution hook at §5.6; no inline config-get is needed.
|
|
85
86
|
|
|
86
|
-
When `CONTEXT_WINDOW >= 500000`, the planner prompt includes the 3 most recent prior phase CONTEXT.md and SUMMARY.md files PLUS any phases explicitly listed in the current phase's `Depends on:` field in ROADMAP.md. Explicit dependencies always load regardless of recency (e.g., Phase 7 declaring `Depends on: Phase 2` always sees Phase 2's context).
|
|
87
|
+
When `CONTEXT_WINDOW >= 500000`, the planner prompt includes the 3 most recent prior phase CONTEXT.md and SUMMARY.md files PLUS any phases explicitly listed in the current phase's `Depends on:` field in ROADMAP.md. Explicit dependencies always load regardless of recency (e.g., Phase 7 declaring `Depends on: Phase 2` always sees Phase 2's context).
|
|
87
88
|
|
|
88
89
|
Parse JSON for: `researcher_model`, `planner_model`, `checker_model`, `research_enabled`, `plan_checker_enabled`, `nyquist_validation_enabled`, `commit_docs`, `text_mode`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `has_research`, `has_context`, `has_reviews`, `has_plans`, `plan_count`, `phase_status` (#3569), `planning_exists`, `roadmap_exists`, `phase_req_ids`, `response_language`, `granularity`.
|
|
89
90
|
|
|
@@ -95,11 +96,12 @@ Parse JSON for: `researcher_model`, `planner_model`, `checker_model`, `research_
|
|
|
95
96
|
|
|
96
97
|
## 1.5. Closed-Phase Gate (#3569)
|
|
97
98
|
|
|
98
|
-
The init JSON includes `phase_status` — one of `Pending | Planned | In Progress | Executed | Complete | Needs Review`. `Complete` means
|
|
99
|
+
The init JSON includes `phase_status` — one of `Pending | Planned | In Progress | Executed | Complete | Needs Review`. `Complete` means all summaries exist AND a `VERIFICATION.md` with `status: passed`. Replanning a closed phase silently rewrites plan docs that no longer match the shipped code; the workflow hard-stops here unless the operator overrides.
|
|
99
100
|
|
|
100
101
|
Parse `phase_status` from the init JSON, then:
|
|
101
102
|
|
|
102
103
|
```bash
|
|
104
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
103
105
|
FORCE_REPLAN=false
|
|
104
106
|
if [[ "$ARGUMENTS" =~ (^|[[:space:]])--force([[:space:]]|$) ]]; then
|
|
105
107
|
FORCE_REPLAN=true
|
|
@@ -140,7 +142,7 @@ The gate fires only on `Complete`. `Executed` and `Needs Review` are not gated
|
|
|
140
142
|
|
|
141
143
|
Extract from $ARGUMENTS: phase number (integer or decimal like `2.1`), flags (`--research`, `--skip-research`, `--research-phase <N>`, `--gaps`, `--skip-verify`, `--skip-ui`, `--prd <filepath>`, `--ingest <path-or-glob>`, `--ingest-format <auto|nygard|madr|narrative>`, `--reviews`, `--text`, `--bounce`, `--skip-bounce`, `--chunked`, `--mvp`, `--tdd`, `--granularity <coarse|standard|fine>`, `--force` (override closed-phase gate, see §1.5), `--unattended`).
|
|
142
144
|
|
|
143
|
-
**`--research-phase <N>` — research-only mode (#3042 + #3044).** When
|
|
145
|
+
**`--research-phase <N>` — research-only mode (#3042 + #3044).** When present, parse `<N>` as the phase number (overrides any positional phase argument), set `RESEARCH_ONLY=true`, and treat the rest of this workflow as a research dispatch only — the planner spawn (step 8), plan-checker, verification, gaps, bounce and post-planning-gaps blocks all skip on `RESEARCH_ONLY`. Use it for cross-phase research, doc review before committing to an approach, and correction-without-replanning loops. Replaces the deleted `/pp-research-phase` command.
|
|
144
146
|
|
|
145
147
|
In research-only mode, two modifiers control behavior when `RESEARCH.md` already exists:
|
|
146
148
|
|
|
@@ -148,6 +150,7 @@ In research-only mode, two modifiers control behavior when `RESEARCH.md` already
|
|
|
148
150
|
- **`--view`** — view-only: print existing `RESEARCH.md` to stdout, do **not** spawn the researcher. Sets `VIEW_ONLY=true`. Cheapest mode for the correction-without-replanning loop. If `RESEARCH.md` does not exist, error with a hint to drop `--view`.
|
|
149
151
|
|
|
150
152
|
```bash
|
|
153
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
151
154
|
RESEARCH_ONLY=false
|
|
152
155
|
VIEW_ONLY=false
|
|
153
156
|
if [[ "$ARGUMENTS" =~ --research-phase[[:space:]]+([0-9]+(\.[0-9]+)?) ]]; then
|
|
@@ -159,9 +162,9 @@ if $RESEARCH_ONLY && [[ "$ARGUMENTS" =~ (^|[[:space:]])--view([[:space:]]|$) ]];
|
|
|
159
162
|
fi
|
|
160
163
|
```
|
|
161
164
|
|
|
162
|
-
**`--granularity <coarse|standard|fine>` — CLI override (#703).** When present, this
|
|
165
|
+
**`--granularity <coarse|standard|fine>` — CLI override (#703).** When present, this is the resolved granularity passed to the planner — it wins over per-phase `granularities.<type>` config, top-level `granularity` config and project defaults. The init JSON always carries the resolved `granularity` field; read it from there. Any other value (not `coarse`, `standard`, `fine`) errors at the CLI boundary.
|
|
163
166
|
|
|
164
|
-
**`--unattended`** — set by `/pp:autonomous` (never `--auto`, which would auto-advance into execute-phase). At each prompt site marked `U-Pn` below, do not prompt: apply rule `U-Pn` from `pp-core/references/autonomous-best-effort.md` (Read
|
|
167
|
+
**`--unattended`** — set by `/pp:autonomous` (never `--auto`, which would auto-advance into execute-phase). At each prompt site marked `U-Pn` below, do not prompt: apply rule `U-Pn` from `pp-core/references/autonomous-best-effort.md` (Read at first use) and append the record it names to the phase's AUTONOMOUS-REPORT. It does not touch `workflow._auto_chain_active`.
|
|
165
168
|
|
|
166
169
|
Set `TEXT_MODE=true` if `--text` is present in $ARGUMENTS OR `text_mode` from init JSON is `true`. When `TEXT_MODE` is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for Claude Code remote sessions (`/rc` mode) where TUI menus don't work through the Claude App.
|
|
167
170
|
|
|
@@ -191,7 +194,7 @@ When `WALKING_SKELETON=true`:
|
|
|
191
194
|
- Planner is instructed to produce `SKELETON.md` in the phase directory alongside `PLAN.md`. The template lives at `~/.claude/pp-core/references/skeleton-template.md` — the planner reads it when producing SKELETON.md (lazy; not loaded on non-skeleton runs).
|
|
192
195
|
- The plan must scaffold project + routing + one real DB read/write + one real UI interaction + dev deployment — the thinnest possible end-to-end working slice.
|
|
193
196
|
|
|
194
|
-
**Interaction with `--prd <filepath>`.** `--mvp` and `--prd` compose
|
|
197
|
+
**Interaction with `--prd <filepath>`.** `--mvp` and `--prd` compose: the PRD express path (Step 3.5) creates `CONTEXT.md` from the PRD file and continues to research; the Walking Skeleton gate fires independently. On Phase 1 of a new project the planner receives `WALKING_SKELETON=true` and PRD-derived context together — the PRD informs *what the skeleton should prove*; the two signals are orthogonal. See [`references/mvp-concepts.md`](../references/mvp-concepts.md).
|
|
195
198
|
|
|
196
199
|
Extract express-path args from $ARGUMENTS: `PRD_FILE` (`--prd <filepath>`), `INGEST_PATH` (`--ingest <path-or-glob>`), and optional `INGEST_FORMAT` (`--ingest-format <auto|nygard|madr|narrative>`, default `auto`).
|
|
197
200
|
|
|
@@ -246,6 +249,7 @@ PHASE_INFO=$(pp_run query roadmap.get-phase "${PHASE}")
|
|
|
246
249
|
|
|
247
250
|
Now that `PHASE` is finalized, resolve MVP mode:
|
|
248
251
|
```bash
|
|
252
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
249
253
|
MVP_MODE=$(pp_run query phase.mvp-mode "${PHASE}" $MVP_FLAG_ARG --pick active)
|
|
250
254
|
```
|
|
251
255
|
|
|
@@ -346,7 +350,7 @@ Use full relative paths. Group by topic area.]
|
|
|
346
350
|
|
|
347
351
|
5. Commit:
|
|
348
352
|
```bash
|
|
349
|
-
pp_run query commit "docs(
|
|
353
|
+
pp_run query commit "docs(planning): generate context from PRD" --phase "${padded_phase}" --files "${phase_dir}/${padded_phase}-CONTEXT.md"
|
|
350
354
|
```
|
|
351
355
|
|
|
352
356
|
6. Set `context_content` to the generated CONTEXT.md content and continue to step 5 (Handle Research).
|
|
@@ -364,7 +368,7 @@ pp_run query commit "docs(${padded_phase}): generate context from PRD" --files "
|
|
|
364
368
|
3. Status gate: reject `superseded`/`rejected`/`deprecated`; warn on `proposed`; missing status defaults to `accepted`.
|
|
365
369
|
4. Empty-decisions fallback: if all parsed ADRs have zero `decisions[]`, emit `ADR ingest produced no locked decisions; fall back to discuss-phase for this phase.` and exit with `/pp:discuss-phase {N}` guidance.
|
|
366
370
|
5. Generate CONTEXT.md using `<domain>`, `<decisions>`, `<canonical_refs>`, `<specifics>`, `<deferred>`, `<scope_fence>`, map `consequences_positive[]` to Success Criteria and `consequences_negative[]` to Risk Summary, and include `**Source:** ADR Ingest Express Path ({INGEST_PATH})`.
|
|
367
|
-
6. Commit with `pp-tools.cjs query commit "docs(
|
|
371
|
+
6. Commit with `pp-tools.cjs query commit "docs(planning): generate context from ADR ingest" --phase "${padded_phase}" --files "${phase_dir}/${padded_phase}-CONTEXT.md"` and set `context_content`; continue to step 5.
|
|
368
372
|
|
|
369
373
|
**Effect:** This bypasses step 4 (Load CONTEXT.md) since CONTEXT.md was synthesized from ADR input.
|
|
370
374
|
|
|
@@ -415,6 +419,7 @@ If "Run discuss-phase first":
|
|
|
415
419
|
AI integration activation is owned by the `ai-integration` capability's `plan:pre` step hook. The plan-phase host only discovers existing artifacts here so the planner can consume them; it must not read the capability's config key directly.
|
|
416
420
|
|
|
417
421
|
```bash
|
|
422
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
418
423
|
AI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-AI-SPEC.md 2>/dev/null | head -1)
|
|
419
424
|
AI_SPEC_PATH="${AI_SPEC_FILE}"
|
|
420
425
|
FRAMEWORK_LINE=""
|
|
@@ -522,7 +527,9 @@ Read and execute `pp-core/workflows/execute-phase/steps/vault-fetch.md` — the
|
|
|
522
527
|
|
|
523
528
|
### into:researcher contributions
|
|
524
529
|
|
|
525
|
-
In `PLAN_PRE_HOOKS_JSON`, read active plan:pre entries where `kind == "contribution"` and `into == "researcher"` (in array order). If none, inject nothing. If present, append each entry's `fragment.inline` verbatim to `filled_research_hook_fragment` (or
|
|
530
|
+
In `PLAN_PRE_HOOKS_JSON`, read active plan:pre entries where `kind == "contribution"` and `into == "researcher"` (in array order). If none, inject nothing. If present, append each entry's `fragment.inline` verbatim to `filled_research_hook_fragment` (or as a `<files_to_read>` line in the researcher prompt) — typically a pointer to `.planning/vault/SUMMARY.md`. Inject verbatim — do not paraphrase.
|
|
531
|
+
|
|
532
|
+
When `DISCOVERY_EXTRACT_PATH` (§7) is set, add `- {DISCOVERY_EXTRACT_PATH} (Discovery extract — required reading)` to the researcher `<files_to_read>`.
|
|
526
533
|
|
|
527
534
|
Find the active `research` step hook in `PLAN_PRE_HOOKS_JSON`. Use the hook's `fragment.inline` as the prompt template and substitute the phase fields below before spawning its declared `ref.agent`.
|
|
528
535
|
|
|
@@ -578,6 +585,7 @@ If `research_enabled` is false and `nyquist_validation_enabled` is true: warn "N
|
|
|
578
585
|
In that case: **skip validation-strategy creation entirely**. Do **not** expect `RESEARCH.md` or `VALIDATION.md` for this run, and continue to Step 6.
|
|
579
586
|
|
|
580
587
|
```bash
|
|
588
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
581
589
|
grep -l "## Validation Architecture" "${PHASE_DIR}"/*-RESEARCH.md 2>/dev/null || true
|
|
582
590
|
```
|
|
583
591
|
|
|
@@ -590,7 +598,7 @@ grep -l "## Validation Architecture" "${PHASE_DIR}"/*-RESEARCH.md 2>/dev/null ||
|
|
|
590
598
|
test -f "${PHASE_DIR}/${PADDED_PHASE}-VALIDATION.md" && echo "VALIDATION_CREATED=true" || echo "VALIDATION_CREATED=false"
|
|
591
599
|
```
|
|
592
600
|
5. If `VALIDATION_CREATED=false`: STOP — do not proceed to Step 6
|
|
593
|
-
6. If `commit_docs`: `commit "docs(
|
|
601
|
+
6. If `commit_docs`: `commit "docs(planning): add validation strategy" --phase "${PADDED_PHASE}"`
|
|
594
602
|
|
|
595
603
|
**If not found:** Warn and continue — plans may fail Dimension 8.
|
|
596
604
|
|
|
@@ -606,7 +614,7 @@ Resolve active contribution hooks from `PLAN_PRE_HOOKS_JSON` where `kind == "con
|
|
|
606
614
|
|
|
607
615
|
**If no active security contribution hook exists:** Skip to step 5.6.
|
|
608
616
|
|
|
609
|
-
**If an active security contribution hook exists:** Read `SECURITY_ASVS` from the active hook's `configValues.security_asvs_level` (default: `1`) and `SECURITY_BLOCK` from `configValues.security_block_on` (default: `"high"`).
|
|
617
|
+
**If an active security contribution hook exists:** Read `SECURITY_ASVS` from the active hook's `configValues.security_asvs_level` (default: `1`) and `SECURITY_BLOCK` from `configValues.security_block_on` (default: `"high"`). The registry resolves them from user config with the same four-level precedence as hook activation — no inline `config-get` is needed.
|
|
610
618
|
|
|
611
619
|
Display banner:
|
|
612
620
|
|
|
@@ -660,6 +668,7 @@ Read `frontend`, `hasUiSpec`, and `block` from `GATE`.
|
|
|
660
668
|
**Branch 3 — UI-SPEC already exists (`hasUiSpec` is `true`):**
|
|
661
669
|
|
|
662
670
|
```bash
|
|
671
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
663
672
|
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
664
673
|
UI_SPEC_PATH="${UI_SPEC_FILE}"
|
|
665
674
|
```
|
|
@@ -685,6 +694,7 @@ Skill(skill="pp-${ref.skill}", args="${PHASE} --auto ${GSD_WS}")
|
|
|
685
694
|
After all UI step hooks return, re-read:
|
|
686
695
|
|
|
687
696
|
```bash
|
|
697
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
688
698
|
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
689
699
|
UI_SPEC_PATH="${UI_SPEC_FILE}"
|
|
690
700
|
```
|
|
@@ -729,6 +739,7 @@ In `PLAN_PRE_HOOKS_JSON` (already loaded), find active plan:pre entries where `k
|
|
|
729
739
|
## 6. Check Existing Plans
|
|
730
740
|
|
|
731
741
|
```bash
|
|
742
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
732
743
|
ls "${PHASE_DIR}"/*-PLAN.md 2>/dev/null || true
|
|
733
744
|
```
|
|
734
745
|
|
|
@@ -741,6 +752,7 @@ ls "${PHASE_DIR}"/*-PLAN.md 2>/dev/null || true
|
|
|
741
752
|
Extract from INIT JSON:
|
|
742
753
|
|
|
743
754
|
```bash
|
|
755
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
744
756
|
_gsd_field() { node -e "const o=JSON.parse(process.argv[1]); const v=o[process.argv[2]]; process.stdout.write(v==null?'':String(v))" "$1" "$2"; }
|
|
745
757
|
STATE_PATH=$(_gsd_field "$INIT" state_path)
|
|
746
758
|
ROADMAP_PATH=$(_gsd_field "$INIT" roadmap_path)
|
|
@@ -765,6 +777,8 @@ SPEC_FILE=$(ls "${PHASE_DIR_FOR_SPEC}"/*-SPEC.md 2>/dev/null | grep -Ev -- '-(AI
|
|
|
765
777
|
SPEC_PATH="${SPEC_FILE}"
|
|
766
778
|
```
|
|
767
779
|
|
|
780
|
+
Then Read and execute `pp-core/workflows/plan-phase/steps/discovery-extract.md` (sets `DISCOVERY_EXTRACT_PATH`; inert without `.planning/discovery/`).
|
|
781
|
+
|
|
768
782
|
## 7.5. Verify Nyquist Artifacts
|
|
769
783
|
|
|
770
784
|
Skip if `nyquist_validation_enabled` is false OR `research_enabled` is false.
|
|
@@ -777,6 +791,7 @@ Also skip if all of the following are true:
|
|
|
777
791
|
In that no-research path, Nyquist artifacts are **not required** for this run.
|
|
778
792
|
|
|
779
793
|
```bash
|
|
794
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
780
795
|
VALIDATION_EXISTS=$(ls "${PHASE_DIR}"/*-VALIDATION.md 2>/dev/null | head -1)
|
|
781
796
|
```
|
|
782
797
|
|
|
@@ -879,6 +894,7 @@ Planner prompt:
|
|
|
879
894
|
- {AI_SPEC_PATH} (AI Design Contract — framework and evaluation strategy, if exists)
|
|
880
895
|
- {UI_SPEC_PATH} (UI Design Contract — visual/interaction specs, if exists)
|
|
881
896
|
- {SPEC_PATH} (Phase SPEC — carries the ## Edge Coverage section to lift covered/backstop edges from, if exists)
|
|
897
|
+
- {DISCOVERY_EXTRACT_PATH} (Discovery extract — required reading, embed verbatim as <discovery_extract>; if exists)
|
|
882
898
|
- {SPIKE_FINDINGS_PATH} (Spike Findings — validated patterns, constraints, landmines from experiments, if exists)
|
|
883
899
|
- {SKETCH_FINDINGS_PATH} (Sketch Findings — validated design decisions, CSS patterns, visual direction, if exists)
|
|
884
900
|
- {API_SURFACE_PATH} (API Surface — HINT ONLY, when intel capability is active; see <intel_surface_hint> below)
|
|
@@ -893,7 +909,7 @@ ${CONTEXT_WINDOW >= 500000 ? `
|
|
|
893
909
|
</files_to_read>
|
|
894
910
|
${API_SURFACE_PATH ? `
|
|
895
911
|
<intel_surface_hint>
|
|
896
|
-
**API Surface (HINT — may be incomplete):** When \`intel.enabled\` is true, \`.planning/intel/API-SURFACE.md\` lists symbols extracted from the codebase by regex/JS analysis. Prefer symbols
|
|
912
|
+
**API Surface (HINT — may be incomplete):** When \`intel.enabled\` is true, \`.planning/intel/API-SURFACE.md\` lists symbols extracted from the codebase by regex/JS analysis. Prefer its symbols when referencing existing code. The surface is regex/JS-derived and MAY BE INCOMPLETE — a symbol's absence means *unknown*, not *nonexistent*; never treat it as exhaustive. If you reference a symbol not in the surface that this phase creates, list it under "Artifacts this phase produces".
|
|
897
913
|
</intel_surface_hint>
|
|
898
914
|
` : ''}
|
|
899
915
|
${AGENT_SKILLS_PLANNER}
|
|
@@ -933,7 +949,7 @@ Output consumed by /pp:execute-phase. Plans need:
|
|
|
933
949
|
- Verification criteria
|
|
934
950
|
- must_haves for goal-backward verification
|
|
935
951
|
- If the SPEC has an `## Edge Coverage` section, lift every `covered` edge's acceptance criterion into `must_haves.truths`, and every `backstop` edge into `must_haves.truths` as a non-inferable check (note it needs a held-out/property-based test). `unresolved` edges are explicit assumptions — surface them in the plan, do not silently drop them.
|
|
936
|
-
- If the SPEC has a `## Prohibitions` section, lift every resolved prohibition into the `must_haves.prohibitions:` sibling block (NOT `truths` — ADR-550 D3) carrying `statement` + `status` + `verification`; unresolved prohibitions are explicit assumptions — surface them in the plan, do not silently drop them. A prohibition is a must-NOT (negative) check
|
|
952
|
+
- If the SPEC has a `## Prohibitions` section, lift every resolved prohibition into the `must_haves.prohibitions:` sibling block (NOT `truths` — ADR-550 D3) carrying `statement` + `status` + `verification`; unresolved prohibitions are explicit assumptions — surface them in the plan, do not silently drop them. A prohibition is a must-NOT (negative) check with its own `must_haves.prohibitions` block. Never place one under `must_haves.truths`, which keeps positive-observable semantics only.
|
|
937
953
|
- **"Artifacts this phase produces" section (MANDATORY)** — list every symbol this phase creates: decorators, classes, functions, CLI flags, struct/dataclass fields, new file paths. The plan-review-convergence source-grounding pass reads this section to exclude newly-created symbols from drift verification; omitting it causes new symbols to be flagged for acknowledgement.
|
|
938
954
|
</downstream_consumer>
|
|
939
955
|
|
|
@@ -1017,6 +1033,7 @@ Read and execute `pp-core/workflows/plan-phase/steps/chunked-planning.md` — th
|
|
|
1017
1033
|
**Triggered when:** Agent() returns but the return contains no recognized marker (`## PLANNING COMPLETE`, `## PHASE SPLIT RECOMMENDED`, `## ⚠ Source Audit`, `## CHECKPOINT REACHED`, `## PLANNING INCONCLUSIVE`).
|
|
1018
1034
|
|
|
1019
1035
|
```bash
|
|
1036
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
1020
1037
|
DISK_PLANS=$(ls "${PHASE_DIR}"/*-PLAN.md 2>/dev/null | wc -l | tr -d ' ')
|
|
1021
1038
|
```
|
|
1022
1039
|
|
|
@@ -1216,6 +1233,7 @@ If thinking_partner disabled: skip this block entirely.
|
|
|
1216
1233
|
**Triggered when:** Checker Agent() returns but the return contains neither `## VERIFICATION PASSED` nor `## ISSUES FOUND`.
|
|
1217
1234
|
|
|
1218
1235
|
```bash
|
|
1236
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
1219
1237
|
DISK_PLANS=$(ls "${PHASE_DIR}"/*-PLAN.md 2>/dev/null | wc -l | tr -d ' ')
|
|
1220
1238
|
```
|
|
1221
1239
|
|
|
@@ -1370,7 +1388,7 @@ After the script returns, check that the bounced file still has valid YAML front
|
|
|
1370
1388
|
|
|
1371
1389
|
6. **Commit surviving bounced plans:** If at least one plan survived both the frontmatter validation and the checker re-run, commit the changes:
|
|
1372
1390
|
```bash
|
|
1373
|
-
pp_run query commit "
|
|
1391
|
+
pp_run query commit "docs(planning): bounce plans through external refinement" --phase "${padded_phase}" --files "${PHASE_DIR}/*-PLAN.md"
|
|
1374
1392
|
```
|
|
1375
1393
|
|
|
1376
1394
|
Display summary:
|
|
@@ -1388,6 +1406,7 @@ After plans pass the checker (or checker is skipped), verify that all phase requ
|
|
|
1388
1406
|
|
|
1389
1407
|
**Step 1: Extract requirement IDs claimed by plans**
|
|
1390
1408
|
```bash
|
|
1409
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
1391
1410
|
# Collect all requirement IDs from plan frontmatter
|
|
1392
1411
|
PLAN_REQS=$(grep -h "^requirements_addressed\|^requirements:" ${PHASE_DIR}/*-PLAN.md 2>/dev/null | tr -d '[]' | tr ',' '\n' | sed 's/^[[:space:]]*//' | sort -u)
|
|
1393
1412
|
```
|
|
@@ -1526,7 +1545,8 @@ This operation is idempotent: if wave headers or cross-cutting constraints alrea
|
|
|
1526
1545
|
If `commit_docs` is true (from the init JSON parsed in step 1), commit the generated plan artifacts (including any ROADMAP.md annotations from step 13c):
|
|
1527
1546
|
|
|
1528
1547
|
```bash
|
|
1529
|
-
|
|
1548
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
1549
|
+
pp_run query commit "docs(planning): create phase plan" --phase "${PADDED_PHASE}" --files "${PHASE_DIR}"/*-PLAN.md .planning/STATE.md .planning/ROADMAP.md
|
|
1530
1550
|
```
|
|
1531
1551
|
|
|
1532
1552
|
This commits all PLAN.md files for the phase plus the updated STATE.md and ROADMAP.md to version-control the planning artifacts. Skip this step if `commit_docs` is false.
|
|
@@ -109,6 +109,7 @@ Run plan-phase **inline** (do NOT wrap it in Agent()). The convergence orchestra
|
|
|
109
109
|
|
|
110
110
|
After plan-phase completes, verify plans were created:
|
|
111
111
|
```bash
|
|
112
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
112
113
|
PLAN_COUNT=$(ls ${phase_dir}/${padded_phase}-*-PLAN.md 2>/dev/null | wc -l)
|
|
113
114
|
```
|
|
114
115
|
|
|
@@ -207,6 +208,7 @@ Run this pass unless `plan_review.source_grounding` is `false`. It verifies ever
|
|
|
207
208
|
|
|
208
209
|
After agent returns, verify REVIEWS.md exists:
|
|
209
210
|
```bash
|
|
211
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
210
212
|
REVIEWS_FILE=$(ls ${phase_dir}/${padded_phase}-REVIEWS.md 2>/dev/null)
|
|
211
213
|
```
|
|
212
214
|
|
|
@@ -22,6 +22,7 @@ Parse `$ARGUMENTS` for the idea summary.
|
|
|
22
22
|
First, check for an enrich flag:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
25
26
|
if echo "$ARGUMENTS" | grep -qE '\-\-enrich[[:space:]]+SEED-[0-9]+'; then
|
|
26
27
|
ENRICH_TARGET=$(echo "$ARGUMENTS" | grep -oE 'SEED-[0-9]+')
|
|
27
28
|
SEED_FILE=$(ls .planning/seeds/${ENRICH_TARGET}-*.md 2>/dev/null | head -1)
|
|
@@ -52,6 +53,7 @@ mkdir -p .planning/seeds
|
|
|
52
53
|
|
|
53
54
|
<step name="generate-seed-id">
|
|
54
55
|
```bash
|
|
56
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
55
57
|
# Find next seed number
|
|
56
58
|
EXISTING=$( (ls .planning/seeds/SEED-*.md 2>/dev/null || true) | wc -l )
|
|
57
59
|
NEXT=$((EXISTING + 1))
|
|
@@ -136,7 +138,7 @@ Store relevant file paths as `$BREADCRUMBS`.
|
|
|
136
138
|
<step name="commit-seed">
|
|
137
139
|
```bash
|
|
138
140
|
_PP_SHIM_NAME="pp-tools.cjs"; _pp_root() { ( for _v in $(env | sed -n 's/^\(GIT_[A-Za-z0-9_]*\)=.*/\1/p'); do unset "$_v"; done; _c=$(git rev-parse --git-common-dir 2>/dev/null); if [ "${_c##*/}" = .git ] && cd "$_c/.." 2>/dev/null; then pwd -P; else git rev-parse --show-toplevel 2>/dev/null || pwd; fi ); }; pp_run() { case "$PP_TOOLS" in *.cjs) node "$PP_TOOLS" "$@";; *) "$PP_TOOLS" "$@";; esac; }; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(_pp_root)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then :; elif [ -f "${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}"; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; else echo "ERROR: pp-tools.cjs not found at $PP_TOOLS and pp-tools is not on PATH. Run: npx -y @pareto4/pp-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${PP_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${PP_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
139
|
-
pp_run query commit "docs: plant seed — {$IDEA}" --files .planning/seeds/SEED-{PADDED}-{slug}.md
|
|
141
|
+
pp_run query commit "docs(planning): plant seed — {$IDEA}" --files .planning/seeds/SEED-{PADDED}-{slug}.md
|
|
140
142
|
```
|
|
141
143
|
</step>
|
|
142
144
|
|
|
@@ -207,7 +209,7 @@ Update the seed file's frontmatter and sections with the gathered values:
|
|
|
207
209
|
|
|
208
210
|
Commit the update:
|
|
209
211
|
```bash
|
|
210
|
-
pp_run query commit "docs: enrich seed ${SEED_ID} — trigger + why + scope" --files "$SEED_FILE"
|
|
212
|
+
pp_run query commit "docs(planning): enrich seed ${SEED_ID} — trigger + why + scope" --files "$SEED_FILE"
|
|
211
213
|
```
|
|
212
214
|
|
|
213
215
|
Confirm:
|
|
@@ -74,6 +74,7 @@ git log --oneline "$TARGET".."$CURRENT_BRANCH" --no-merges
|
|
|
74
74
|
For each commit, check what it touches:
|
|
75
75
|
|
|
76
76
|
```bash
|
|
77
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
77
78
|
# For each commit hash
|
|
78
79
|
FILES=$(git diff-tree --no-commit-id --name-only -r $HASH)
|
|
79
80
|
NON_PLANNING=$(echo "$FILES" | grep -v "^\.planning/" | wc -l)
|
|
@@ -107,6 +108,7 @@ git checkout -b "$PR_BRANCH" "$TARGET"
|
|
|
107
108
|
Cherry-pick code commits and structural planning commits (in order):
|
|
108
109
|
|
|
109
110
|
```bash
|
|
111
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
110
112
|
for HASH in $CODE_AND_STRUCTURAL_COMMITS; do
|
|
111
113
|
git cherry-pick "$HASH" --no-commit
|
|
112
114
|
# Remove only transient .planning/ subdirectories that came along in mixed commits.
|
|
@@ -227,6 +227,7 @@ Then exit the route step. Do NOT run Steps 1 through Routes A-F.
|
|
|
227
227
|
List files in the current phase directory:
|
|
228
228
|
|
|
229
229
|
```bash
|
|
230
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
230
231
|
(ls -1 .planning/phases/[current-phase-dir]/*-PLAN.md 2>/dev/null || true) | wc -l
|
|
231
232
|
(ls -1 .planning/phases/[current-phase-dir]/*-SUMMARY.md 2>/dev/null || true) | wc -l
|
|
232
233
|
(ls -1 .planning/phases/[current-phase-dir]/*-UAT.md 2>/dev/null || true) | wc -l
|
|
@@ -239,6 +240,7 @@ State: "This phase has {X} plans, {Y} summaries."
|
|
|
239
240
|
Check for UAT.md files with status "diagnosed" (has gaps needing fixes).
|
|
240
241
|
|
|
241
242
|
```bash
|
|
243
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
242
244
|
# Check for diagnosed UAT with gaps or partial (incomplete) testing
|
|
243
245
|
grep -l "status: diagnosed\|status: partial" .planning/phases/[current-phase-dir]/*-UAT.md 2>/dev/null || true
|
|
244
246
|
```
|
|
@@ -660,6 +662,7 @@ Read STATE.md `status` / `stopped_at` fields (from the STATE snapshot already lo
|
|
|
660
662
|
|
|
661
663
|
Check for existence of:
|
|
662
664
|
```bash
|
|
665
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
663
666
|
ls .planning/HANDOFF.json .planning/phases/*/.continue-here.md .planning/phases/*/*HANDOFF*.md 2>/dev/null || true
|
|
664
667
|
```
|
|
665
668
|
Also check `.planning/continue-here.md`.
|
|
@@ -685,6 +688,7 @@ Emit:
|
|
|
685
688
|
|
|
686
689
|
Check if `.planning/MEMORY.md` or `.planning/memory/` exists:
|
|
687
690
|
```bash
|
|
691
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
688
692
|
ls .planning/MEMORY.md .planning/memory/*.md 2>/dev/null || true
|
|
689
693
|
```
|
|
690
694
|
|
|
@@ -698,6 +702,7 @@ Emit:
|
|
|
698
702
|
|
|
699
703
|
Check for pending todos:
|
|
700
704
|
```bash
|
|
705
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
701
706
|
ls .planning/todos/pending/*.md 2>/dev/null || true
|
|
702
707
|
```
|
|
703
708
|
|
|
@@ -208,6 +208,7 @@ workflow byte-identically to how it ran before this gate existed (GATE-04).
|
|
|
208
208
|
**Otherwise, fetch and load-gate at `plan:pre`:**
|
|
209
209
|
|
|
210
210
|
```bash
|
|
211
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
211
212
|
QUICK_PLAN_PRE_HOOKS_JSON=$(pp_run loop render-hooks plan:pre --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
|
|
212
213
|
printf '%s' "$QUICK_PLAN_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('QUICK_PLAN_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
213
214
|
```
|
|
@@ -513,6 +514,7 @@ Step 2.4 printed `VAULT_ADMIT=on`. The fence prints the fragments; put that prin
|
|
|
513
514
|
the prompt says `${QUICK_PLANNER_HOOK_FRAGMENTS}` (nothing when it printed nothing).
|
|
514
515
|
|
|
515
516
|
```bash
|
|
517
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
516
518
|
QUICK_PLANNER_HOOK_FRAGMENTS=$(pp_run loop render-hooks plan:pre --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const h=(JSON.parse(d).activeHooks||[]).filter((x)=>x&&x.kind==='contribution'&&x.into==='planner'&&x.fragment&&typeof x.fragment.inline==='string');process.stdout.write(h.map((x)=>x.fragment.inline).join('\n\n'));}catch{process.stdout.write('');}")
|
|
517
519
|
if [ -n "$QUICK_PLANNER_HOOK_FRAGMENTS" ]; then printf '%s\n' "$QUICK_PLANNER_HOOK_FRAGMENTS"; fi
|
|
518
520
|
```
|
|
@@ -696,6 +698,7 @@ Skip silently unless Step 2.4 printed `VAULT_ADMIT=on`. Runs after the planner (
|
|
|
696
698
|
committed and no executor spawned (D-02, D-34).
|
|
697
699
|
|
|
698
700
|
```bash
|
|
701
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
699
702
|
QUICK_PLAN_POST_HOOKS_JSON=$(pp_run loop render-hooks plan:post --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
|
|
700
703
|
printf '%s' "$QUICK_PLAN_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('QUICK_PLAN_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
701
704
|
```
|
|
@@ -731,10 +734,10 @@ if [ "${USE_WORKTREES}" != "false" ]; then
|
|
|
731
734
|
# workflow.worktree_skip_hooks=true, honor that opt-in only.
|
|
732
735
|
SKIP_HOOKS=$(pp_run query config-get workflow.worktree_skip_hooks 2>/dev/null || echo "false")
|
|
733
736
|
if [ "$SKIP_HOOKS" = "true" ]; then
|
|
734
|
-
git commit --no-verify -m "docs(
|
|
737
|
+
git commit --no-verify -m "docs(planning): pre-dispatch plan for ${DESCRIPTION}" -m "Quick: ${quick_id}" -- "${QUICK_DIR}/${quick_id}-PLAN.md" \
|
|
735
738
|
|| { echo "ERROR: pre-dispatch PLAN.md commit failed (--no-verify path). Aborting before executor dispatch." >&2; exit 1; }
|
|
736
739
|
else
|
|
737
|
-
git commit -m "docs(
|
|
740
|
+
git commit -m "docs(planning): pre-dispatch plan for ${DESCRIPTION}" -m "Quick: ${quick_id}" -- "${QUICK_DIR}/${quick_id}-PLAN.md" \
|
|
738
741
|
|| { echo "ERROR: pre-dispatch PLAN.md commit failed — likely a pre-commit hook failure. Fix the hook output above (or set workflow.worktree_skip_hooks=true to bypass) and re-run." >&2; exit 1; }
|
|
739
742
|
fi
|
|
740
743
|
QUICK_PLAN_COMMIT=$(git rev-parse HEAD)
|
|
@@ -771,6 +774,7 @@ Step 2.4 printed `VAULT_ADMIT=on`. The fence prints the fragments; put that prin
|
|
|
771
774
|
prompt says `${QUICK_EXECUTOR_HOOK_FRAGMENTS}` (nothing when it printed nothing).
|
|
772
775
|
|
|
773
776
|
```bash
|
|
777
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
774
778
|
QUICK_EXECUTOR_HOOK_FRAGMENTS=$(pp_run loop render-hooks execute:pre --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const h=(JSON.parse(d).activeHooks||[]).filter((x)=>x&&x.kind==='contribution'&&x.into==='executor'&&x.fragment&&typeof x.fragment.inline==='string');process.stdout.write(h.map((x)=>x.fragment.inline).join('\n\n'));}catch{process.stdout.write('');}")
|
|
775
779
|
if [ -n "$QUICK_EXECUTOR_HOOK_FRAGMENTS" ]; then printf '%s\n' "$QUICK_EXECUTOR_HOOK_FRAGMENTS"; fi
|
|
776
780
|
```
|
|
@@ -851,7 +855,7 @@ SUMMARY.md and stop — the user must rerun with worktrees disabled.
|
|
|
851
855
|
|
|
852
856
|
<constraints>
|
|
853
857
|
- Execute all tasks in the plan
|
|
854
|
-
- Commit each task atomically (code changes only)
|
|
858
|
+
- Commit each task atomically (code changes only); the scope names the part of the codebase (e.g. `fix(auth)`), and each message ends with the trailer `Quick: ${quick_id}` (after a blank line) in place of the `Phase:` trailer
|
|
855
859
|
- Run the <submodule_commit_guard> bash block before every \`git commit\` if SUBMODULE_PATHS is non-empty
|
|
856
860
|
- Create summary at: ${QUICK_DIR}/${quick_id}-SUMMARY.md with `status: complete` in SUMMARY frontmatter (required so the audit-open milestone-close scanner recognises the task as done, not [unknown])
|
|
857
861
|
- Do NOT commit docs artifacts (SUMMARY.md, STATE.md, PLAN.md) — the orchestrator handles the docs commit in Step 8
|
|
@@ -872,6 +876,7 @@ If the executor ran with `isolation="worktree"`, append its returned `{agent_id,
|
|
|
872
876
|
After executor returns:
|
|
873
877
|
1. **Worktree cleanup:** If the executor ran with `isolation="worktree"`, merge the worktree branch back and clean up:
|
|
874
878
|
```bash
|
|
879
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
875
880
|
QUICK_WORKTREE_MANIFEST=${QUICK_WORKTREE_MANIFEST:-$WAVE_WORKTREE_MANIFEST}
|
|
876
881
|
[ -n "${QUICK_WORKTREE_MANIFEST:-}" ] && [ -f "$QUICK_WORKTREE_MANIFEST" ] || {
|
|
877
882
|
echo "BLOCKED: missing QUICK_WORKTREE_MANIFEST; refusing broad worktree cleanup (#3384)." >&2
|
|
@@ -908,6 +913,7 @@ so a blocked task never gets a STATE.md row and never reaches the final commit (
|
|
|
908
913
|
the executor already made stay in history, and the SEAL-01 check names them (D-02).
|
|
909
914
|
|
|
910
915
|
```bash
|
|
916
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
911
917
|
QUICK_EXECUTE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:post --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
|
|
912
918
|
printf '%s' "$QUICK_EXECUTE_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('QUICK_EXECUTE_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
913
919
|
```
|
|
@@ -1093,6 +1099,7 @@ Build file list:
|
|
|
1093
1099
|
- If `${QUICK_DIR}/${quick_id}-deferred-items.md` exists: `${QUICK_DIR}/${quick_id}-deferred-items.md`
|
|
1094
1100
|
|
|
1095
1101
|
```bash
|
|
1102
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
1096
1103
|
# Explicitly stage all artifacts before commit — PLAN.md may be untracked
|
|
1097
1104
|
# if the executor ran without worktree isolation and committed docs early
|
|
1098
1105
|
# Filter .planning/ files from staging if commit_docs is disabled (#1783)
|
|
@@ -1103,7 +1110,7 @@ if [ "$COMMIT_DOCS" = "false" ]; then
|
|
|
1103
1110
|
else
|
|
1104
1111
|
git add ${file_list} 2>/dev/null
|
|
1105
1112
|
fi
|
|
1106
|
-
pp_run query commit "docs(
|
|
1113
|
+
pp_run query commit "docs(planning): record quick task — ${DESCRIPTION}" --quick "${quick_id}" --files ${file_list}
|
|
1107
1114
|
```
|
|
1108
1115
|
|
|
1109
1116
|
Get final commit hash:
|
|
@@ -13,6 +13,7 @@ After a pp-core update wipes and reinstalls files, this workflow merges user's p
|
|
|
13
13
|
Check for local patches directory:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
16
17
|
expand_home() {
|
|
17
18
|
case "$1" in
|
|
18
19
|
"~/"*) printf '%s/%s\n' "$HOME" "${1#~/}" ;;
|
|
@@ -278,6 +279,7 @@ Run the deterministic verifier script. Do NOT rely solely on the free-text `veri
|
|
|
278
279
|
Run the verifier as a child process (the pp-tools binary directory is not required — the script ships under 'pp-core/bin/' in the source repo and is installed to '/pp-core/bin/'; it is also exposed via the SDK at `sdk/dist/cli.js verify-reapply` when present):
|
|
279
280
|
|
|
280
281
|
```bash
|
|
282
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
281
283
|
PRISTINE_DIR="${CONFIG_DIR}/pp-pristine"
|
|
282
284
|
|
|
283
285
|
# Build args as a bash array so paths with spaces survive expansion intact
|
|
@@ -302,6 +304,7 @@ VERIFY_STATUS=$?
|
|
|
302
304
|
**Step 5a: drift check** — even when `VERIFY_STATUS` is 0, the report may signal that one or more files were skipped due to pristine-snapshot drift (Bug #3657) or a missing baseline (Bug #934). Parse the JSON and check:
|
|
303
305
|
|
|
304
306
|
```bash
|
|
307
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
305
308
|
DRIFTED_COUNT="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(String(d.drifted||0))")"
|
|
306
309
|
DRIFTED_FILES="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));(d.drifted_files||[]).forEach(f=>process.stdout.write(f+'\n'))")"
|
|
307
310
|
NO_BASELINE_COUNT="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(String(d.no_baseline||0))")"
|
|
@@ -104,7 +104,7 @@ Extract from result: `removed`, `directory_deleted`, `renamed_directories`, `ren
|
|
|
104
104
|
Stage and commit the removal:
|
|
105
105
|
|
|
106
106
|
```bash
|
|
107
|
-
pp_run query commit "chore: remove phase {target} ({original-phase-name})" --files .planning/
|
|
107
|
+
pp_run query commit "chore(planning): remove phase {target} ({original-phase-name})" --files .planning/
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
The commit message preserves the historical record of what was removed.
|
|
@@ -68,6 +68,7 @@ cat .planning/PROJECT.md
|
|
|
68
68
|
Look for incomplete work that needs attention:
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
71
72
|
# Check for structured handoff (preferred — machine-readable)
|
|
72
73
|
cat .planning/HANDOFF.json 2>/dev/null || true
|
|
73
74
|
|
|
@@ -244,6 +245,7 @@ What would you like to do?
|
|
|
244
245
|
**Note:** When offering phase planning, check for CONTEXT.md existence first:
|
|
245
246
|
|
|
246
247
|
```bash
|
|
248
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
247
249
|
ls .planning/phases/XX-name/*-CONTEXT.md 2>/dev/null || true
|
|
248
250
|
```
|
|
249
251
|
|
|
@@ -297,6 +299,7 @@ Resume-specific exception: do **not** emit `/clear then:` here. Resume is alread
|
|
|
297
299
|
Before proceeding to routed workflow, record session continuity through the state verb, never by hand (a hand edit leaves the stored `stopped_at` behind, so `state json` and `state-snapshot` keep the older value):
|
|
298
300
|
|
|
299
301
|
```bash
|
|
302
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
300
303
|
pp_run query state.record-session --stopped-at "Session resumed, proceeding to [action]" ${GSD_WS}
|
|
301
304
|
```
|
|
302
305
|
|