@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,107 @@
|
|
|
1
|
+
# Discovery Standards First — `_deviations.md` Template, Parser Contract & the Standards Applied Table
|
|
2
|
+
|
|
3
|
+
Single home for how the Discovery Sprint treats the client's standards once a vault is bound
|
|
4
|
+
(Discovery Sprint improvement plan, Batch 3): the questions the vault already answers are not asked
|
|
5
|
+
open-ended, every session from 4 to 10 records which standard governs each area in a **Standards
|
|
6
|
+
Applied** table, and every departure from a standard is one `DEV-` row of `_deviations.md` — the
|
|
7
|
+
register the charter § 7 copies, the handoff gates on, and `pp-vault-review` reads so an approved
|
|
8
|
+
deviation is reported as a deviation on file, never as a violation. This file is Read lazily; it is
|
|
9
|
+
never `@`-imported.
|
|
10
|
+
|
|
11
|
+
## Standards first — the question rule
|
|
12
|
+
|
|
13
|
+
When a session's `## Vault Context` record names a document that already fixes what a topic asks the
|
|
14
|
+
client to decide, the facilitator does not ask the open question. The question becomes:
|
|
15
|
+
|
|
16
|
+
> The vault fixes `<what>` — `[vault: <path>]`. Does this product deviate, and why?
|
|
17
|
+
|
|
18
|
+
- **No deviation:** the Standards Applied row cites the standard, `Deviation` reads `none`. Nothing
|
|
19
|
+
else is written — the vault stays the single home of the standard (never copy its text).
|
|
20
|
+
- **A deviation:** mint one `DEV-<nn>` row in `.planning/discovery/_deviations.md` (create the file
|
|
21
|
+
from the template below on first need), record the decision as a Key Decisions row `D-<ss>-<n>` and
|
|
22
|
+
write both IDs into the Standards Applied row (`Deviation` = the `DEV-nn`, `Decision` = the `D-ss-n`).
|
|
23
|
+
- **No standard covers the area:** the Standards Applied row reads `not in vault`; the question stays
|
|
24
|
+
open-ended and the answer is a Key Decisions row; add an Action Items row for the vault owner when
|
|
25
|
+
the gap should be closed in the vault.
|
|
26
|
+
- **No vault bound** (the session record says `Index: none`, or the project runs without the vault
|
|
27
|
+
capability): every question stays open-ended, Standards Applied rows read `not in vault`, and
|
|
28
|
+
`_deviations.md` is never created — there is no standard to deviate from.
|
|
29
|
+
|
|
30
|
+
The session files phrase their stack and tooling questions in this shape; the vault document to cite
|
|
31
|
+
is the one the session's `## Vault Context` record selected for that topic.
|
|
32
|
+
|
|
33
|
+
## The Standards Applied table
|
|
34
|
+
|
|
35
|
+
Every session from 4 to 10 carries one, in its Notes Template, with the areas the session decides:
|
|
36
|
+
|
|
37
|
+
| Area | Standard | Deviation | Decision |
|
|
38
|
+
|------|----------|-----------|----------|
|
|
39
|
+
|
|
40
|
+
- **Standard** is the governing document's `[vault: <rel path>]` citation (several, space-separated,
|
|
41
|
+
when more than one applies), or `not in vault`.
|
|
42
|
+
- **Deviation** is `none`, or the `DEV-<nn>` of the `_deviations.md` row.
|
|
43
|
+
- **Decision** is `—`, or the `D-<ss>-<n>` that records the deviation or the decision taken for an
|
|
44
|
+
uncovered area.
|
|
45
|
+
|
|
46
|
+
The charter § 7 reads `_deviations.md`, not these tables; the tables are where a reader of one
|
|
47
|
+
session sees which standards bound it. Session 4 introduced the shape (frontend standards); Sessions
|
|
48
|
+
5–10 follow it.
|
|
49
|
+
|
|
50
|
+
## `_deviations.md`
|
|
51
|
+
|
|
52
|
+
A deviation is a choice that goes against a standard the vault states. The vault's own rule
|
|
53
|
+
(`architecture/deviations.md` in the Pareto vault, and its equivalent elsewhere): deviating is
|
|
54
|
+
allowed, hiding it is not; an architect signs every one; only what is **hard to reverse** waits for
|
|
55
|
+
the signature before the dependent work proceeds, and a security or compliance deviation is always
|
|
56
|
+
hard. The register carries exactly that record.
|
|
57
|
+
|
|
58
|
+
Illustration only — not part of the template:
|
|
59
|
+
|
|
60
|
+
| ID | Standard | Choice | Reason | Reversible | Approver | Decision | Status |
|
|
61
|
+
|---|---|---|---|---|---|---|---|
|
|
62
|
+
| DEV-01 | [vault: pipeline/quality-gates.md] | Trivy and CodeQL instead of SonarCloud | Free plan, one-person team | easy | Architect | D-09-3 | Approved |
|
|
63
|
+
|
|
64
|
+
Bootstrap template — the first session that records a deviation copies it verbatim to
|
|
65
|
+
`.planning/discovery/_deviations.md`, replacing `[PROJECT_NAME]`:
|
|
66
|
+
|
|
67
|
+
```markdown
|
|
68
|
+
# Deviations from standards — [PROJECT_NAME]
|
|
69
|
+
|
|
70
|
+
**Conventions:** pp-core reference `references/discovery-standards.md`. One `DEV-` row per departure from a vault standard: the standard as a `[vault: <path>]` citation, the choice made instead, why, whether it is `easy` or `hard` to reverse (a security or compliance deviation is always `hard`), who approves it (an approver of Session 1's Approval Matrix), the `D-<ss>-<n>` that recorded it and its status (`Proposed`, `Approved`, `Rejected`, `Superseded`). A hard deviation is approved before the handoff. Rows are never renumbered or deleted; a change after sign-off edits the row in place and appends `→ amended by D-<ss>-<n>`.
|
|
71
|
+
|
|
72
|
+
## Deviations
|
|
73
|
+
|
|
74
|
+
| ID | Standard | Choice | Reason | Reversible | Approver | Decision | Status |
|
|
75
|
+
|----|----------|--------|--------|------------|----------|----------|--------|
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Parser contract — `pp_run query discovery.deviations-check [--require-approved]`
|
|
79
|
+
|
|
80
|
+
No positional path. Faults name the artifact, the 1-based line, a validated ID or path, a column name
|
|
81
|
+
and the reason code — never cell prose. Absent `_deviations.md` → exit 0, `present: false`.
|
|
82
|
+
|
|
83
|
+
| Cell / field | Grammar | Fault when violated |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `## Deviations` | once, holding one table with the template's columns | `missing_section`, `bad_table_shape` |
|
|
86
|
+
| `ID` | `DEV-\d{2}`, unique, contiguous from 01 | `bad_id`, `duplicate_id`, `sequence_gap` naming the missing ID |
|
|
87
|
+
| `Standard` | at least one `[vault: <path>]`; each path relative, no `..` or dot segment, ending `.md`, and present in the vault cache when `.planning/vault/` is on disk | `bad_standard` (no citation, or an unsafe path); `unknown_standard` naming the path. **Not resolved** while there is no cache |
|
|
88
|
+
| `Choice`, `Reason` | non-empty | `empty_cell` naming the column |
|
|
89
|
+
| `Reversible` | `easy` \| `hard` | `bad_reversible` |
|
|
90
|
+
| `Approver` | non-empty; one of the `Approver` tokens of Session 1's **Approval Matrix** when that table is on file with rows | `empty_cell (Approver)`; `unknown_approver`. **Not resolved** while Session 1 has no matrix (an engagement that predates it) |
|
|
91
|
+
| `Decision` | `—`, or `D-<ss>-<n>` / `D-P<nn>-<n>` (shape only — `charter-check` resolves it) | `bad_decision`; `decision_missing` when `Status` is `Approved` or `Rejected` and the cell is `—` |
|
|
92
|
+
| `Status` | `Proposed` \| `Approved` \| `Rejected` \| `Superseded` | `bad_status` |
|
|
93
|
+
| a `hard` row still `Proposed` | approved before the handoff | `hard_deviation_unapproved` under `--require-approved` only |
|
|
94
|
+
| `session-01.md` present but unreadable | present-and-readable | `artifact_unreadable` naming the path |
|
|
95
|
+
|
|
96
|
+
**Exit identity.** `discovery_deviations_check_failed` for structural faults;
|
|
97
|
+
`discovery_deviations_unapproved` when every fault is a `hard_deviation_unapproved`. Payload: `ok`,
|
|
98
|
+
`present`, `file`, `deviations`, `approved`, `unapproved_hard`.
|
|
99
|
+
|
|
100
|
+
## Who reads it
|
|
101
|
+
|
|
102
|
+
| Reader | Contract |
|
|
103
|
+
|---|---|
|
|
104
|
+
| Project Charter § 7 | copies every row; `charter-check` resolves `DEV-` IDs against this file alone and reports `deviation_missing` for a row the charter leaves out (`references/discovery-charter.md`) |
|
|
105
|
+
| `/pp-discovery-to-build` | `deviations-check --require-approved` hard-blocks on a hard deviation still `Proposed` (`workflows/discovery-to-build/steps/handoff-gates.md`) |
|
|
106
|
+
| `pp-vault-review` | reads `Standard` and `Status` by header name; an `Approved` row covering a failed clause turns the FAIL into `N-A` "deviation on file" (`references/discovery-build-consumption.md` § `_deviations.md` read contract) |
|
|
107
|
+
| `discovery for-phase` | the register has no requirement column, so every extract lists it as not filterable — the planner reads it whole |
|
|
@@ -14,8 +14,8 @@ does not restate them. Read that file when you need an ID's shape or the reserve
|
|
|
14
14
|
|
|
15
15
|
## When these files appear
|
|
16
16
|
|
|
17
|
-
Both artifacts are bootstrapped **on first need**, exactly the way `_progress.md`
|
|
18
|
-
|
|
17
|
+
Both artifacts are bootstrapped **on first need**, exactly the way `_progress.md`
|
|
18
|
+
is in Flow 2 Step 1, and exactly the way the three research-track registers
|
|
19
19
|
are in `references/discovery-research-track.md`: if the file is absent when a session first
|
|
20
20
|
has something to put in it, create it verbatim from the template below, then add the row.
|
|
21
21
|
There is no sub-command and no setup step — an empty inventory is not a milestone, and an
|
|
@@ -15,11 +15,11 @@ If any of these is false, the gate is inactive — execution proceeds normally.
|
|
|
15
15
|
|
|
16
16
|
For each task gated by MVP+TDD, the executor MUST verify (before running the implementation step):
|
|
17
17
|
|
|
18
|
-
1. **A failing-test commit exists.** Search git log on the current branch for a commit
|
|
18
|
+
1. **A failing-test commit exists.** Search git log on the current branch for a commit of type `test` (any scope) that carries the trailer `Phase: {phase}-{plan}` for the same plan as the current task. The commit must touch a test file (`*.test.*`, `*.spec.*`, `tests/**`).
|
|
19
19
|
2. **The test was actually red.** The commit message body or the executor's recent shell history must show the test failed when first run. Acceptable evidence:
|
|
20
20
|
- Commit message contains `RED:` prefix or `(RED)` tag
|
|
21
21
|
- Recent terminal output shows `FAIL` or non-zero exit on the new test before any implementation commit
|
|
22
|
-
3. **No implementation commit yet.** No `feat
|
|
22
|
+
3. **No implementation commit yet.** No `feat` commit carrying the trailer `Phase: {phase}-{plan}` may exist before the failing-test commit.
|
|
23
23
|
|
|
24
24
|
If any check fails, the gate trips.
|
|
25
25
|
|
|
@@ -51,7 +51,7 @@ The executor MUST:
|
|
|
51
51
|
|
|
52
52
|
Required next step:
|
|
53
53
|
1. Write a failing test for the behavior above.
|
|
54
|
-
2. Commit it as: test({
|
|
54
|
+
2. Commit it as: test({area}): {short description} — with the trailer Phase: {phase}-{plan}
|
|
55
55
|
3. Re-run /pp:execute-phase
|
|
56
56
|
```
|
|
57
57
|
|
|
@@ -34,11 +34,23 @@ If NO_GIT: Run `git init` silently. pp-core projects always get their own repo.
|
|
|
34
34
|
|
|
35
35
|
<commit_formats>
|
|
36
36
|
|
|
37
|
+
<format name="scope-and-trailer">
|
|
38
|
+
## Scope and Phase Trailer
|
|
39
|
+
|
|
40
|
+
Every commit follows Conventional Commits: `{type}({scope}): {description}`, an optional body, then trailers.
|
|
41
|
+
|
|
42
|
+
- **The scope names the part of the codebase**, never a phase, plan or quick-task id: `feat(auth)`, `fix(billing)`, `test(api)`. Pick it from the files the commit touches; leave it out (`chore: ...`) when no single area fits. Commits of `.planning/` artifacts use `docs(planning)` (or `chore(planning)`).
|
|
43
|
+
- **The phase or plan goes in a git trailer**, the last paragraph of the message after a blank line: `Phase: 02-03` for a plan, `Phase: 02` for a phase-level commit, `Quick: <id>` for a quick task. `pp_run query commit` and `pp_run query commit-to-subrepo` add it with `--phase <id>` / `--quick <id>`; a raw `git commit` adds it as a second `-m "Phase: <id>"` or as the last paragraph of the message.
|
|
44
|
+
|
|
45
|
+
Why: a scope that is a phase number tells a reviewer nothing about what changed and breaks the client standard that the scope is a noun naming the part of the codebase. The trailer keeps every commit traceable to its phase and plan, and git parses it (`%(trailers:key=Phase)`, `git log --grep="^Phase: 02-03$"`), so tools no longer parse subjects.
|
|
46
|
+
|
|
47
|
+
</format>
|
|
48
|
+
|
|
37
49
|
<format name="initialization">
|
|
38
50
|
## Project Initialization (brief + roadmap together)
|
|
39
51
|
|
|
40
52
|
```
|
|
41
|
-
docs: initialize [project-name] ([N] phases)
|
|
53
|
+
docs(planning): initialize [project-name] ([N] phases)
|
|
42
54
|
|
|
43
55
|
[One-liner from PROJECT.md]
|
|
44
56
|
|
|
@@ -51,7 +63,7 @@ Phases:
|
|
|
51
63
|
What to commit:
|
|
52
64
|
|
|
53
65
|
```bash
|
|
54
|
-
|
|
66
|
+
pp_run query commit "docs(planning): initialize [project-name] ([N] phases)" --files .planning/
|
|
55
67
|
```
|
|
56
68
|
|
|
57
69
|
</format>
|
|
@@ -69,11 +81,13 @@ Each task gets its own commit immediately after completion.
|
|
|
69
81
|
> executor prompt; absent that signal, hooks run normally.
|
|
70
82
|
|
|
71
83
|
```
|
|
72
|
-
{type}({
|
|
84
|
+
{type}({area}): {task-name}
|
|
73
85
|
|
|
74
86
|
- [Key change 1]
|
|
75
87
|
- [Key change 2]
|
|
76
88
|
- [Key change 3]
|
|
89
|
+
|
|
90
|
+
Phase: {phase}-{plan}
|
|
77
91
|
```
|
|
78
92
|
|
|
79
93
|
**Commit types:**
|
|
@@ -89,29 +103,35 @@ Each task gets its own commit immediately after completion.
|
|
|
89
103
|
```bash
|
|
90
104
|
# Standard task
|
|
91
105
|
git add src/api/auth.ts src/types/user.ts
|
|
92
|
-
git commit -m "feat(
|
|
106
|
+
git commit -m "feat(auth): create user registration endpoint
|
|
93
107
|
|
|
94
108
|
- POST /auth/register validates email and password
|
|
95
109
|
- Checks for duplicate users
|
|
96
110
|
- Returns JWT token on success
|
|
111
|
+
|
|
112
|
+
Phase: 08-02
|
|
97
113
|
"
|
|
98
114
|
|
|
99
115
|
# TDD task - RED phase
|
|
100
116
|
git add src/__tests__/jwt.test.ts
|
|
101
|
-
git commit -m "test(
|
|
117
|
+
git commit -m "test(auth): add failing test for JWT generation
|
|
102
118
|
|
|
103
119
|
- Tests token contains user ID claim
|
|
104
120
|
- Tests token expires in 1 hour
|
|
105
121
|
- Tests signature verification
|
|
122
|
+
|
|
123
|
+
Phase: 07-02
|
|
106
124
|
"
|
|
107
125
|
|
|
108
126
|
# TDD task - GREEN phase
|
|
109
127
|
git add src/utils/jwt.ts
|
|
110
|
-
git commit -m "feat(
|
|
128
|
+
git commit -m "feat(auth): implement JWT generation
|
|
111
129
|
|
|
112
130
|
- Uses jose library for signing
|
|
113
131
|
- Includes user ID and expiry claims
|
|
114
132
|
- Signs with HS256 algorithm
|
|
133
|
+
|
|
134
|
+
Phase: 07-02
|
|
115
135
|
"
|
|
116
136
|
```
|
|
117
137
|
|
|
@@ -123,7 +143,7 @@ git commit -m "feat(07-02): implement JWT generation
|
|
|
123
143
|
After all tasks committed, one final metadata commit captures plan completion.
|
|
124
144
|
|
|
125
145
|
```
|
|
126
|
-
docs(
|
|
146
|
+
docs(planning): complete [plan-name] plan
|
|
127
147
|
|
|
128
148
|
Tasks completed: [N]/[N]
|
|
129
149
|
- [Task 1 name]
|
|
@@ -131,12 +151,14 @@ Tasks completed: [N]/[N]
|
|
|
131
151
|
- [Task 3 name]
|
|
132
152
|
|
|
133
153
|
SUMMARY: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
|
|
154
|
+
|
|
155
|
+
Phase: {phase}-{plan}
|
|
134
156
|
```
|
|
135
157
|
|
|
136
158
|
What to commit:
|
|
137
159
|
|
|
138
160
|
```bash
|
|
139
|
-
|
|
161
|
+
pp_run query commit "docs(planning): complete [plan-name] plan" --phase "{phase}-{plan}" --files .planning/phases/XX-name/{phase}-{plan}-PLAN.md .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md
|
|
140
162
|
```
|
|
141
163
|
|
|
142
164
|
**Note:** Code files NOT included - already committed per-task.
|
|
@@ -147,7 +169,7 @@ pp-tools query commit "docs({phase}-{plan}): complete [plan-name] plan" --files
|
|
|
147
169
|
## Handoff (WIP)
|
|
148
170
|
|
|
149
171
|
```
|
|
150
|
-
|
|
172
|
+
docs(planning): pause [phase-name] at task [X]/[Y]
|
|
151
173
|
|
|
152
174
|
Current: [task name]
|
|
153
175
|
[If blocked:] Blocked: [reason]
|
|
@@ -156,7 +178,7 @@ Current: [task name]
|
|
|
156
178
|
What to commit:
|
|
157
179
|
|
|
158
180
|
```bash
|
|
159
|
-
|
|
181
|
+
pp_run query commit "docs(planning): pause [phase-name] at task [X]/[Y]" --files .planning/
|
|
160
182
|
```
|
|
161
183
|
|
|
162
184
|
</format>
|
|
@@ -173,36 +195,38 @@ a7f2d1 feat(checkout): Stripe payments with webhook verification
|
|
|
173
195
|
2f4a8d docs: initialize ecommerce-app (5 phases)
|
|
174
196
|
```
|
|
175
197
|
|
|
176
|
-
**New approach (per-task commits):**
|
|
198
|
+
**New approach (per-task commits, phase in the trailer):**
|
|
199
|
+
|
|
200
|
+
`git log --format='%h %s [%(trailers:key=Phase,valueonly)]'` reads:
|
|
177
201
|
```
|
|
178
202
|
# Phase 04 - Checkout
|
|
179
|
-
1a2b3c docs(
|
|
180
|
-
4d5e6f feat(
|
|
181
|
-
7g8h9i feat(
|
|
182
|
-
0j1k2l feat(
|
|
203
|
+
1a2b3c docs(planning): complete checkout flow plan [04-01]
|
|
204
|
+
4d5e6f feat(checkout): add webhook signature verification [04-01]
|
|
205
|
+
7g8h9i feat(checkout): implement payment session creation [04-01]
|
|
206
|
+
0j1k2l feat(checkout): create checkout page component [04-01]
|
|
183
207
|
|
|
184
208
|
# Phase 03 - Products
|
|
185
|
-
3m4n5o docs(
|
|
186
|
-
6p7q8r feat(
|
|
187
|
-
9s0t1u feat(
|
|
188
|
-
2v3w4x feat(
|
|
209
|
+
3m4n5o docs(planning): complete product listing plan [03-02]
|
|
210
|
+
6p7q8r feat(products): add pagination controls [03-02]
|
|
211
|
+
9s0t1u feat(products): implement search and filters [03-02]
|
|
212
|
+
2v3w4x feat(products): create product catalog schema [03-01]
|
|
189
213
|
|
|
190
214
|
# Phase 02 - Auth
|
|
191
|
-
5y6z7a docs(
|
|
192
|
-
8b9c0d feat(
|
|
193
|
-
1e2f3g test(
|
|
194
|
-
4h5i6j docs(
|
|
195
|
-
7k8l9m feat(
|
|
196
|
-
0n1o2p
|
|
215
|
+
5y6z7a docs(planning): complete token refresh plan [02-02]
|
|
216
|
+
8b9c0d feat(auth): implement refresh token rotation [02-02]
|
|
217
|
+
1e2f3g test(auth): add failing test for token refresh [02-02]
|
|
218
|
+
4h5i6j docs(planning): complete JWT setup plan [02-01]
|
|
219
|
+
7k8l9m feat(auth): add JWT generation and validation [02-01]
|
|
220
|
+
0n1o2p build(deps): install jose library [02-01]
|
|
197
221
|
|
|
198
222
|
# Phase 01 - Foundation
|
|
199
|
-
3q4r5s docs(
|
|
200
|
-
6t7u8v feat(
|
|
201
|
-
9w0x1y feat(
|
|
202
|
-
2z3a4b feat
|
|
223
|
+
3q4r5s docs(planning): complete scaffold plan [01-01]
|
|
224
|
+
6t7u8v feat(ui): configure Tailwind and globals [01-01]
|
|
225
|
+
9w0x1y feat(db): set up Prisma with database [01-01]
|
|
226
|
+
2z3a4b feat: create Next.js 15 project [01-01]
|
|
203
227
|
|
|
204
228
|
# Initialization
|
|
205
|
-
5c6d7e docs: initialize ecommerce-app (5 phases)
|
|
229
|
+
5c6d7e docs(planning): initialize ecommerce-app (5 phases) []
|
|
206
230
|
```
|
|
207
231
|
|
|
208
232
|
Each plan produces 2-4 commits (tasks + metadata). Clear, granular, bisectable.
|
|
@@ -233,7 +257,7 @@ Each plan produces 2-4 commits (tasks + metadata). Clear, granular, bisectable.
|
|
|
233
257
|
|
|
234
258
|
**Context engineering for AI:**
|
|
235
259
|
- Git history becomes primary context source for future Claude sessions
|
|
236
|
-
- `git log --grep="{phase}-{plan}"` shows all work for a plan
|
|
260
|
+
- `git log --grep="^Phase: {phase}-{plan}$"` shows all work for a plan
|
|
237
261
|
- `git diff <hash>^..<hash>` shows exact changes per task
|
|
238
262
|
- Less reliance on parsing SUMMARY.md = more context for actual work
|
|
239
263
|
|
|
@@ -287,11 +311,11 @@ Set `commit_docs: false` so planning docs stay local and are not committed to an
|
|
|
287
311
|
Instead of the standard `commit` command, use `commit-to-subrepo` when `sub_repos` is configured:
|
|
288
312
|
|
|
289
313
|
```bash
|
|
290
|
-
|
|
314
|
+
pp_run query commit-to-subrepo "feat(users): add user API" --phase "02-01" \
|
|
291
315
|
--files backend/src/api/users.ts backend/src/types/user.ts frontend/src/components/UserForm.tsx
|
|
292
316
|
```
|
|
293
317
|
|
|
294
|
-
This stages `src/api/users.ts` and `src/types/user.ts` in the `backend/` repo, and `src/components/UserForm.tsx` in the `frontend/` repo, then commits each independently with the same message.
|
|
318
|
+
This stages `src/api/users.ts` and `src/types/user.ts` in the `backend/` repo, and `src/components/UserForm.tsx` in the `frontend/` repo, then commits each independently with the same message and `Phase: 02-01` trailer.
|
|
295
319
|
|
|
296
320
|
Files that don't match any configured sub-repo are reported as unmatched.
|
|
297
321
|
|
|
@@ -9,29 +9,51 @@ Pass the message first, then file paths via `--files`. Both `commit` and `commit
|
|
|
9
9
|
Always use this for `.planning/` files — it handles `commit_docs` and gitignore checks automatically:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
|
|
12
|
+
pp_run query commit "docs(planning): {description}" --phase "{phase-or-plan-id}" --files .planning/STATE.md .planning/ROADMAP.md
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
The CLI will return `skipped` (with reason) if `commit_docs` is `false` or `.planning/` is gitignored. No manual conditional checks needed.
|
|
16
16
|
|
|
17
|
+
## Scope and the Phase trailer
|
|
18
|
+
|
|
19
|
+
The Conventional Commit scope names the part of the codebase a commit changes, as in `fix(billing): round vat per line`. Planning artifacts are one such part, so every commit of `.planning/` files uses `docs(planning)` (or `chore(planning)` when the type is chore). A phase number, plan number, quick-task id or phase slug never goes in the scope.
|
|
20
|
+
|
|
21
|
+
To keep commits traceable to their phase, the phase or plan id goes in a git trailer instead:
|
|
22
|
+
|
|
23
|
+
- `--phase <id>` adds `Phase: <id>`: a plan id such as `02-03`, or a phase id such as `02` for phase-level commits. Use the same padded ids the phase directory uses.
|
|
24
|
+
- `--quick <id>` adds `Quick: <id>` for a quick task.
|
|
25
|
+
|
|
26
|
+
The trailer is the last paragraph of the message, after a blank line:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
docs(planning): complete token refresh plan
|
|
30
|
+
|
|
31
|
+
Phase: 02-03
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Readers find a phase's commits with `git log --grep="^Phase: 02-03$"`, or list each commit's trailer with `git log --format='%h %s %(trailers:key=Phase,valueonly)'`. An id may hold letters, digits, dots, dashes and underscores only; anything else (a space, a newline) is rejected before anything is staged. `--phase` and `--quick` are ignored with `--amend`, which keeps the previous message.
|
|
35
|
+
|
|
17
36
|
## Amend previous commit
|
|
18
37
|
|
|
19
38
|
To fold `.planning/` file changes into the previous commit:
|
|
20
39
|
|
|
21
40
|
```bash
|
|
41
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
22
42
|
pp-tools query commit "" --files .planning/codebase/*.md --amend
|
|
23
43
|
```
|
|
24
44
|
|
|
25
45
|
## Commit Message Patterns
|
|
26
46
|
|
|
27
|
-
| Command |
|
|
28
|
-
|
|
29
|
-
| plan-phase |
|
|
30
|
-
| execute-
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
47
|
+
| Command | Message | Trailer |
|
|
48
|
+
|---------|---------|---------|
|
|
49
|
+
| plan-phase | `docs(planning): create phase plan` | `Phase: 03` |
|
|
50
|
+
| execute-plan | `docs(planning): complete authentication plan` | `Phase: 03-02` |
|
|
51
|
+
| execute-phase | `docs(planning): complete phase execution` | `Phase: 03` |
|
|
52
|
+
| quick | `docs(planning): record quick task — fix login typo` | `Quick: 260422-abc` |
|
|
53
|
+
| new-milestone | `docs(planning): start milestone v1.1` | — |
|
|
54
|
+
| remove-phase | `chore(planning): remove phase 17 (dashboard)` | — |
|
|
55
|
+
| insert-phase | `docs(planning): insert phase 16.1 (critical fix)` | — |
|
|
56
|
+
| add-phase | `docs(planning): add phase 07 (settings page)` | — |
|
|
35
57
|
|
|
36
58
|
## When to Skip
|
|
37
59
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Discovery extract — the planner and researcher contract (R1)
|
|
2
|
+
|
|
3
|
+
**Load this file when a `{padded}-DISCOVERY-EXTRACT.md` is listed in your files to read** — the
|
|
4
|
+
plan-phase orchestrator renders it with `pp_run query discovery.for-phase <N> --markdown` on a
|
|
5
|
+
project that ran the Discovery Sprint (contract: `references/discovery-build-consumption.md`).
|
|
6
|
+
When no such file is listed, nothing described here applies.
|
|
7
|
+
|
|
8
|
+
The extract holds the rows of the Discovery registers (`_requirements.md`, `_stories.md`,
|
|
9
|
+
`_processes.md`, `_entities.md`, `_rules.md`, `_screens.md`, roles, integrations) that cite this
|
|
10
|
+
phase's requirement IDs. It is the client's signed-off fact base for this phase.
|
|
11
|
+
|
|
12
|
+
## Planner
|
|
13
|
+
|
|
14
|
+
1. **Required reading.** Read the extract in full before planning.
|
|
15
|
+
2. **Never open `.planning/discovery/session-NN.md`.** The session files are the facilitation
|
|
16
|
+
record; the registers are the source of truth, amended in place. A fact you need that the
|
|
17
|
+
extract lacks is a question for the user — surface it under Claude's Discretion or the plan's
|
|
18
|
+
open questions — not a reason to read a transcript.
|
|
19
|
+
3. **Cite rows, do not restate them.** A task that realises a step cites `MP-01 #3`; a validation
|
|
20
|
+
task cites `BR-02`; a data task cites the entity by name; a screen task cites `SCR-04`. Put the
|
|
21
|
+
row's acceptance criteria (`_requirements.md`, `_stories.md`) into the task's
|
|
22
|
+
`<acceptance_criteria>` verbatim — they are the verifier's UAT (R3).
|
|
23
|
+
4. **Embed verbatim.** Copy the file's content byte for byte, `<!-- discovery:auto -->` markers
|
|
24
|
+
included, as the `<discovery_extract>` block of every PLAN.md of this phase, after `<context>`
|
|
25
|
+
(after `<vault_standards>` when present) and before `<tasks>`. Never edit a cell: a discovery
|
|
26
|
+
fact that must change is amended in the register by `/pp-discuss-phase` (R2), then re-rendered.
|
|
27
|
+
5. **Contradictions are findings.** If the extract contradicts CONTEXT.md, the codebase or itself,
|
|
28
|
+
plan nothing on the contradiction — name both sides in the plan's open questions.
|
|
29
|
+
|
|
30
|
+
## Researcher
|
|
31
|
+
|
|
32
|
+
Research HOW to build what the rows say, never WHETHER: entities, rules, process steps, screens
|
|
33
|
+
and acceptance criteria here are decided. List the entities, integrations and rules the extract
|
|
34
|
+
names under `## User Constraints` as "Discovery facts (by row ID)" so the planner sees them beside
|
|
35
|
+
the locked decisions. Rule 2 above applies in full.
|
|
@@ -9,6 +9,7 @@ Triggered by `--gaps` flag. Creates plans to address verification or UAT failure
|
|
|
9
9
|
Use init context (from load_project_state) which provides `phase_dir`:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
12
13
|
# Check for VERIFICATION.md (code verification gaps)
|
|
13
14
|
ls "$phase_dir"/*-VERIFICATION.md 2>/dev/null
|
|
14
15
|
|
|
@@ -7,6 +7,7 @@ Triggered when orchestrator provides `<revision_context>` with checker issues. N
|
|
|
7
7
|
### Step 1: Load Existing Plans
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
10
11
|
cat .planning/phases/$PHASE-*/$PHASE-*-PLAN.md
|
|
11
12
|
```
|
|
12
13
|
|
|
@@ -55,7 +56,8 @@ Group by plan, dimension, severity.
|
|
|
55
56
|
### Step 6: Commit
|
|
56
57
|
|
|
57
58
|
```bash
|
|
58
|
-
|
|
59
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
60
|
+
pp_run query commit "docs(planning): revise plans based on checker feedback" --phase "$PHASE" --files .planning/phases/$PHASE-*/$PHASE-*-PLAN.md
|
|
59
61
|
```
|
|
60
62
|
|
|
61
63
|
### Step 7: Return Revision Summary
|
|
@@ -40,13 +40,13 @@ Output: [Working, tested feature]
|
|
|
40
40
|
|
|
41
41
|
## Red-Green-Refactor Cycle
|
|
42
42
|
|
|
43
|
-
**RED:** Create test file → write test describing expected behavior → run test (MUST fail) → commit: `test({
|
|
43
|
+
**RED:** Create test file → write test describing expected behavior → run test (MUST fail) → commit: `test({area}): add failing test for [feature]`
|
|
44
44
|
|
|
45
|
-
**GREEN:** Write minimal code to pass → run test (MUST pass) → commit: `feat({
|
|
45
|
+
**GREEN:** Write minimal code to pass → run test (MUST pass) → commit: `feat({area}): implement [feature]`
|
|
46
46
|
|
|
47
|
-
**REFACTOR (if needed):** Clean up → run tests (MUST pass) → commit: `refactor({
|
|
47
|
+
**REFACTOR (if needed):** Clean up → run tests (MUST pass) → commit: `refactor({area}): clean up [feature]`
|
|
48
48
|
|
|
49
|
-
Each TDD plan produces 2-3 atomic commits.
|
|
49
|
+
`{area}` names the part of the codebase under test (`auth`, `billing`); each commit ends with the trailer `Phase: {phase}-{plan}`. Each TDD plan produces 2-3 atomic commits.
|
|
50
50
|
|
|
51
51
|
## Context Budget for TDD
|
|
52
52
|
|
|
@@ -61,7 +61,7 @@ Configuration options for `.planning/` directory behavior.
|
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
63
|
# Commit with automatic commit_docs + gitignore checks:
|
|
64
|
-
|
|
64
|
+
pp_run query commit "docs(planning): update state" --files .planning/STATE.md
|
|
65
65
|
|
|
66
66
|
# Load config via state load (returns JSON):
|
|
67
67
|
INIT=$(pp-tools query state.load)
|
|
@@ -79,7 +79,7 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
|
79
79
|
**Commit via CLI (handles checks automatically):**
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
|
|
82
|
+
pp_run query commit "docs(planning): update state" --files .planning/STATE.md
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
The CLI checks `commit_docs` config and gitignore status internally — no manual conditionals needed.
|
|
@@ -121,7 +121,7 @@ To use uncommitted mode:
|
|
|
121
121
|
3. **Existing tracked files:** If `.planning/` was previously tracked:
|
|
122
122
|
```bash
|
|
123
123
|
git rm -r --cached .planning/
|
|
124
|
-
git commit -m "chore: stop tracking planning docs"
|
|
124
|
+
git commit -m "chore(planning): stop tracking planning docs"
|
|
125
125
|
```
|
|
126
126
|
|
|
127
127
|
4. **Branch merges:** When using `branching_strategy: phase` or `milestone`, the `complete-milestone` workflow automatically strips `.planning/` files from staging before merge commits when `commit_docs: false`.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Shell portability — commands you write yourself
|
|
2
|
+
|
|
3
|
+
The Bash tool runs the user's login shell, which is zsh on macOS. Workflow fences already
|
|
4
|
+
start with the guard line below; shell you compose yourself does not, so add it.
|
|
5
|
+
|
|
6
|
+
**Start every multi-line command with:**
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
It is a no-op under bash. Under zsh it makes the rest of the command behave like bash does:
|
|
13
|
+
|
|
14
|
+
| Without the guard, zsh… | Example that breaks |
|
|
15
|
+
|---|---|
|
|
16
|
+
| aborts the whole command on a glob that matches nothing (`nomatch`), even with `2>/dev/null \|\| true` | `for f in .planning/phases/*/*-PLAN.md; do …` |
|
|
17
|
+
| expands a word starting with `=` to a command path | `echo ====` → `==== not found` |
|
|
18
|
+
| does not split an unquoted `$var` into words | `set -- $LIST` gives one argument |
|
|
19
|
+
| indexes arrays from 1 | `${a[0]}` is empty |
|
|
20
|
+
|
|
21
|
+
For a one-line command, prefer the portable form instead:
|
|
22
|
+
|
|
23
|
+
- **No GNU-only flags.** macOS ships BSD tools: no `grep -P`, no `sed -i` without a suffix
|
|
24
|
+
argument, no `readlink -f`. Use `grep -E`, `sed -n 's/…/\1/p'`, `sed -i ''` only where you know
|
|
25
|
+
the platform.
|
|
26
|
+
- **Quote patterns and globs you don't want expanded**, and use `find … -name '*.md'` to list
|
|
27
|
+
files that may not exist.
|
|
28
|
+
- **Never begin a word with `=`.** Print separators with `printf '%s\n' '===='`.
|