@pareto4/pp-core 1.19.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.
Files changed (79) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/agents/pp-phase-researcher.md +10 -0
  3. package/agents/pp-planner.md +15 -0
  4. package/agents/pp-vault-reviewer.md +2 -0
  5. package/agents/pp-verifier.md +12 -8
  6. package/commands/pp-discovery.md +3 -2
  7. package/gemini-extension.json +1 -1
  8. package/package.json +6 -3
  9. package/pareto-skills/_shared/pp-claude-md-protocol.md +1 -1
  10. package/pareto-skills/pp-project-setup/SKILL.md +18 -343
  11. package/pp-core/bin/lib/capability-registry.cjs +1 -1
  12. package/pp-core/bin/lib/discovery-access.cjs +276 -0
  13. package/pp-core/bin/lib/discovery-charter.cjs +664 -0
  14. package/pp-core/bin/lib/discovery-deviations.cjs +264 -0
  15. package/pp-core/bin/lib/discovery-entities.cjs +323 -0
  16. package/pp-core/bin/lib/discovery-for-phase.cjs +628 -0
  17. package/pp-core/bin/lib/discovery-integrations.cjs +286 -0
  18. package/pp-core/bin/lib/discovery-migration.cjs +246 -0
  19. package/pp-core/bin/lib/discovery-phases.cjs +233 -0
  20. package/pp-core/bin/lib/discovery-processes.cjs +355 -0
  21. package/pp-core/bin/lib/discovery-research-track.cjs +5 -4
  22. package/pp-core/bin/lib/discovery-rollup.cjs +8 -7
  23. package/pp-core/bin/lib/discovery-rules.cjs +216 -0
  24. package/pp-core/bin/lib/discovery-screens.cjs +1 -1
  25. package/pp-core/bin/lib/discovery-session-check.cjs +264 -0
  26. package/pp-core/bin/lib/discovery-stories.cjs +273 -0
  27. package/pp-core/bin/lib/discovery-sweep.cjs +1 -1
  28. package/pp-core/bin/lib/discovery-table.cjs +55 -0
  29. package/pp-core/bin/lib/io.cjs +22 -0
  30. package/pp-core/bin/lib/vault-standards-review.cjs +50 -2
  31. package/pp-core/bin/pp-tools.cjs +143 -1
  32. package/pp-core/references/discovery-access.md +112 -0
  33. package/pp-core/references/discovery-build-consumption.md +256 -0
  34. package/pp-core/references/discovery-charter.md +127 -0
  35. package/pp-core/references/discovery-data-model.md +145 -0
  36. package/pp-core/references/discovery-id-conventions.md +50 -14
  37. package/pp-core/references/discovery-integrations.md +151 -0
  38. package/pp-core/references/discovery-processes.md +190 -0
  39. package/pp-core/references/discovery-rebaseline.md +2 -2
  40. package/pp-core/references/discovery-research-track.md +5 -6
  41. package/pp-core/references/discovery-session-output.md +70 -0
  42. package/pp-core/references/discovery-standards.md +107 -0
  43. package/pp-core/references/discovery-traceability.md +2 -2
  44. package/pp-core/references/planner-discovery-extract.md +35 -0
  45. package/pp-core/references/verifier-discovery-conformance.md +36 -0
  46. package/pp-core/templates/project-charter.md +161 -100
  47. package/pp-core/templates/project.md +3 -3
  48. package/pp-core/templates/requirements.md +18 -0
  49. package/pp-core/templates/verification-report.md +16 -0
  50. package/pp-core/workflows/discovery-sprint/charter.md +114 -0
  51. package/pp-core/workflows/discovery-sprint/prefill.md +1 -1
  52. package/pp-core/workflows/discovery-sprint/prototype.md +4 -4
  53. package/pp-core/workflows/discovery-sprint/session-13-gates.md +10 -0
  54. package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +5 -2
  55. package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +27 -5
  56. package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +56 -31
  57. package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +1 -1
  58. package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +42 -19
  59. package/pp-core/workflows/discovery-sprint/sessions/06-security.md +27 -12
  60. package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +41 -23
  61. package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +50 -23
  62. package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +26 -11
  63. package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +28 -9
  64. package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +21 -0
  65. package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +24 -9
  66. package/pp-core/workflows/discovery-sprint.md +12 -15
  67. package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +80 -29
  68. package/pp-core/workflows/discovery-to-build/steps/{screen-inventory-gate.md → handoff-gates.md} +111 -3
  69. package/pp-core/workflows/discovery-to-build/templates/discovery-references.md +12 -9
  70. package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +27 -26
  71. package/pp-core/workflows/discovery-to-build.md +70 -34
  72. package/pp-core/workflows/discuss-phase/discovery.md +83 -0
  73. package/pp-core/workflows/discuss-phase/templates/context.md +4 -0
  74. package/pp-core/workflows/discuss-phase.md +10 -7
  75. package/pp-core/workflows/new-project.md +3 -3
  76. package/pp-core/workflows/plan-phase/steps/discovery-extract.md +41 -0
  77. package/pp-core/workflows/plan-phase.md +15 -10
  78. package/pp-core/workflows/vault-review.md +5 -0
  79. package/pp-core/workflows/discovery-sprint/templates/context-template.md +0 -272
@@ -1,7 +1,7 @@
1
1
  # Discovery ID & Decision Conventions
2
2
 
3
3
  Single source for every ID family used across discovery artifacts (TRACE-01). All
4
- discovery artifacts — session notes, `_context.md`, `_requirements.md`, research-track
4
+ discovery artifacts — session notes, `_requirements.md`, research-track
5
5
  files — cite IDs inline against this file. IDs are never renumbered: once minted, an ID
6
6
  keeps its meaning for the life of the engagement, and readers can follow any citation
7
7
  back to exactly one definition. This file is Read lazily by discovery sessions; it is
@@ -11,19 +11,26 @@ never `@`-imported.
11
11
 
12
12
  | Family | Format | Example | Used for |
13
13
  |--------|--------|---------|----------|
14
- | Decisions | `D-<ss>-<n>` — `<ss>` = zero-padded 2-digit session number, `<n>` = unpadded per-session sequence. Regex: `D-\d{2}-\d+` | `D-04-2` (Session 4, decision 2) | Decisions recorded during any session; cited by requirements, actions, and later sessions |
14
+ | Decisions | `D-<ss>-<n>` — `<ss>` = zero-padded 2-digit session number, or `P<nn>` for a build phase (§ Precedence), `<n>` = unpadded per-session sequence. Regex: `D-(\d{2}|P\d{2})-\d+` | `D-04-2` (Session 4, decision 2); `D-P03-2` (phase 3, decision 2) | Decisions recorded during any session, and build-phase decisions that amend a discovery fact; cited by requirements, actions, and later sessions |
15
15
  | Actions | `A-<ss>-<n>` — same shape as decisions. Regex: `A-\d{2}-\d+` | `A-03-1` | Action items owned by a person, minted in the session that raised them |
16
16
  | Sparring positions | `SP-<nn>` — zero-padded 2-digit global sequence, no session component. Regex: `SP-\d{2}` | `SP-03` | Positions taken in the sparring tracker `_sparring.md` |
17
17
  | Data-gathering items | `DG-<nn>` — same shape as SP. Regex: `DG-\d{2}` | `DG-07` | Open data-gathering items in `_risks.md` |
18
18
  | Research items | `RS-<nn>` — same shape as SP/DG: zero-padded 2-digit global sequence, no session component. Regex: `RS-\d{2}` | `RS-01` | Rows of `_research.md`, the research-only backlog |
19
19
  | Screens | `SCR-<nn>` — zero-padded 2-digit global sequence, no session and no role component, minted by scan (D-12). Regex: `SCR-\d{2}` | `SCR-01` | Rows of `_screens.md`, the requirement-to-screen inventory; Role is a grouping column, not part of the ID (D-50) |
20
- | Processes | `PRC-<nn>` — zero-padded 2-digit global sequence. Regex: `PRC-\d{2}` | `PRC-03` | Rows of the Session 2 **Process Inventory**, the as-is processes Session 3 transforms |
20
+ | Processes (as-is) | `PRC-<nn>` — zero-padded 2-digit global sequence. Regex: `PRC-\d{2}` | `PRC-03` | Rows of `_processes.md` § As-is (Session 2), the processes Session 3 transforms (`references/discovery-processes.md`) |
21
+ | Main processes (to-be) | `MP-<nn>` — same shape. Regex: `MP-\d{2}` | `MP-01` | Rows of `_processes.md` § To-be (Session 3 Step 5A); each names the `PRC-` rows it replaces or `new` |
22
+ | Business rules | `BR-<nn>` — same shape. Regex: `BR-\d{2}` | `BR-01` | Rows of `_rules.md` (Session 3 Step 5D′); every rule cites at least one requirement |
23
+ | Entities | named, never numbered — one PascalCase token, cited exactly as `_entities.md` § Entities spells it (`references/discovery-data-model.md`) | `Task`, `AuditEntry` | Rows of `_entities.md`; step matrices cite them as `Task [C]` |
24
+ | Interfaces | `IF-<nn>` — same shape as SP. Regex: `IF-\d{2}` | `IF-01` | Rows of `_integrations.md` § Interfaces (Session 5 mints, Session 8 completes); step matrices cite them in their `Integration` cell (`references/discovery-integrations.md`) |
25
+ | Migration rows | `MG-<nn>` — same shape. Regex: `MG-\d{2}` | `MG-01` | Rows of `_migration.md` (Session 2 seeds, Session 8 completes) |
26
+ | Deviations | `DEV-<nn>` — same shape. Regex: `DEV-\d{2}` | `DEV-01` | Rows of `_deviations.md`, the agreed departures from vault standards (Sessions 1, 4–10; `references/discovery-standards.md`); the charter § 7 copies them |
27
+ | Roles | named, never numbered — a Session 2 persona, a step-matrix actor or `System`, spelled as `_roles.md` § Roles spells it (`references/discovery-access.md`) | `Team lead` | Rows of `_roles.md` |
21
28
  | Requirements | `<PREFIX><n>` — PREFIX is a registered domain prefix (uppercase letters/digits ending in `-`, e.g. a stakeholder-domain prefix, `N-` non-functional, `T-` technical); `<n>` is a numeric sequence, zero-padded to 2 digits by convention (`01`..`99`, then `100`). Regex: `[A-Z][A-Z0-9]*-\d+` | `N-01` | Rows of `_requirements.md`; the prefix carries the classification — there is no separate Type column |
22
29
  | Input-package accessions | `NN` — zero-padded 2-digit number, assigned in arrival order and never renumbered; a mid-sprint document takes the next number (D-16). Regex: `\d{2}` | `03` | Numbered documents in `.planning/discovery-input/` (including its `confidential/` subdir — one number space spans both locations, D-21). Reading order is a README column, not the number |
23
30
 
24
31
  ## Reserved Prefixes
25
32
 
26
- Seven prefixes are reserved by the ID families above and MUST NOT be registered as
33
+ Twelve prefixes are reserved by the ID families above and MUST NOT be registered as
27
34
  domain prefixes in the `_requirements.md` Prefix Registry:
28
35
 
29
36
  | Reserved | Owned by |
@@ -34,7 +41,12 @@ domain prefixes in the `_requirements.md` Prefix Registry:
34
41
  | `DG-` | Data-gathering items |
35
42
  | `RS-` | Research items |
36
43
  | `SCR-` | Screens |
37
- | `PRC-` | Processes |
44
+ | `PRC-` | Processes (as-is) |
45
+ | `MP-` | Main processes (to-be) |
46
+ | `BR-` | Business rules |
47
+ | `IF-` | Interfaces |
48
+ | `MG-` | Migration rows |
49
+ | `DEV-` | Deviations |
38
50
 
39
51
  Every one of them satisfies the requirement-ID regex `[A-Z][A-Z0-9]*-\d+`, so a
40
52
  registry that claims one mints requirement IDs indistinguishable from the family that
@@ -47,9 +59,12 @@ and a requirement — the same collision, one artifact further along the traceab
47
59
 
48
60
  `PRC-` followed with issue #12: Session 2 used to number processes `P-<nn>`, which an
49
61
  engagement had also registered as a domain prefix, so `P-03` meant two things. Process IDs
50
- moved to `PRC-` and the prefix is reserved so the clash cannot come back.
62
+ moved to `PRC-` and the prefix is reserved so the clash cannot come back. `MP-` and `BR-`
63
+ joined when `_processes.md` and `_rules.md` became artifacts of their own (improvement plan,
64
+ Batch 2), `IF-`, `MG-` and `DEV-` when `_integrations.md`, `_migration.md` and `_deviations.md`
65
+ did (Batch 3): an artifact ID family is reserved the day it gets a check.
51
66
 
52
- Session 1's kick-off prefix selection (D-09) must refuse all seven: pick a different
67
+ Session 1's kick-off prefix selection (D-09) must refuse all twelve: pick a different
53
68
  domain prefix (any other uppercase letters/digits ending in `-`, e.g. `K-` for *Klant*).
54
69
  Non-reserved prefixes are unaffected.
55
70
 
@@ -71,21 +86,42 @@ citation such as `C-01` reads two ways.
71
86
  | `CON-` | Constraints and Risks Register (constraints) | 1 |
72
87
  | `R-` | Constraints and Risks Register (risks), continued by the Risk Register | 1, 11 |
73
88
  | `PP-` | Pain Points Register | 2 |
74
- | `MP-` | Main Process Register | 3 |
75
89
  | `BO-` | Business Objectives | 3 |
76
90
  | `E-` | EPIC Register | 3 |
77
91
  | `US-` | User Stories | 3 |
78
92
  | `C-` | Component Inventory | 5 |
79
- | `INT-` | Integration Points Map | 5 |
80
93
  | `ADR-` | Architecture Decision Records | 5 |
81
94
  | `CR-` | Compliance Requirements Register | 6 |
82
- | `IF-` | Integration Design Register | 8 |
83
95
  | `OI-` | Open Items Register | 13 |
84
96
 
85
97
  Non-functional requirements are not in this list: they are `N-` rows of
86
98
  `_requirements.md`, minted like every other requirement, and Session 3's
87
99
  **Non-Functional Requirements** table cites them by that ID.
88
100
 
101
+ ## Precedence — one source of truth, amended in place (R2)
102
+
103
+ The canonical artifacts — `_requirements.md`, `_screens.md`, `_feedback.md`, `_sweep.md`,
104
+ `_processes.md`, `_entities.md`, `_rules.md`, `_glossary.md`, `_stories.md`, `_phases.md`,
105
+ `_roles.md`, `_integrations.md`, `_migration.md`, `_deviations.md`, the research registers and
106
+ the Project Charter — are the single source of truth for the life of the engagement, through the
107
+ build and after it. The session files are the facilitation record behind them.
108
+
109
+ - **A decision that changes a recorded fact edits the row where the fact lives** — a field, a
110
+ rule, a role, a flow step, a requirement — and appends ` → amended by D-<ss>-<n>` to the changed
111
+ cell. That is the back-amend rule Flow 2 Step 6 applies to session notes, applied to artifacts.
112
+ The old text stays readable before the arrow; the artifact is its own changelog.
113
+ - **Never a second copy.** CONTEXT.md and PLAN.md hold an *extract* of the rows a phase needs
114
+ (the `discovery for-phase` output); they never hold an override. A build that wants a different
115
+ answer changes the artifact, then re-runs the artifact's check.
116
+ - **In build, `<ss>` is `P<nn>`**: the zero-padded number of the pp-core phase whose
117
+ `/pp-discuss-phase` minted the decision, so `D-P03-2` is the second decision of phase 3, recorded
118
+ in that phase's CONTEXT.md **Decisions** table. Every engine that reads a decision ID accepts both
119
+ shapes (`D-(\d{2}|P\d{2})-\d+`); `charter-check` resolves `D-<ss>-` IDs against the session
120
+ files and takes `D-P` IDs on shape, because their mint lives outside `.planning/discovery/`.
121
+ - **The charter follows.** An amendment to a fact the charter states adds a § 20 Version history
122
+ row citing the decision and bumps the version (`workflows/discovery-sprint/charter.md`
123
+ § Redraft).
124
+
89
125
  ## Citation Rules
90
126
 
91
127
  - Requirement IDs are never renumbered and never reused (REQM-02). A gap in a sequence
@@ -144,14 +180,14 @@ counts as NOT covered. `⚠️ CONDITIONAL` means a real decision was made in th
144
180
  knowingly contingent on outside work — that IS the answer, honestly qualified, and it
145
181
  counts as COVERED for the Step 7 completeness score.
146
182
 
147
- Where markers may live (D-46): **prose sections only** — session notes, `_context.md`
148
- sections, and (Phase 4) mockup surfaces. They are explicitly forbidden inside
183
+ Where markers may live (D-46): **prose sections only** — session notes and (Phase 4)
184
+ mockup surfaces. They are explicitly forbidden inside
149
185
  `_requirements.md` table cells; the closed requirements grammar already rejects a marker
150
186
  in any structured cell. The join for a research-dependent requirement is an `_research.md`
151
187
  row citing that requirement in its `Gates what?` cell, not a marker in the row itself.
152
188
 
153
- A marker travels with the content it qualifies: when Step 7 propagates a session answer
154
- into a `_context.md` section, the marker propagates with it.
189
+ A marker travels with the content it qualifies: when an answer is copied into a register
190
+ row or a later session, the marker goes with it.
155
191
 
156
192
  The three research-track register templates (`_research.md`, `_risks.md`, `_sparring.md`),
157
193
  their cell grammars, and the `research-check` parser contract live in the sibling
@@ -0,0 +1,151 @@
1
+ # Discovery Integrations & Migration — Templates & Parser Contracts
2
+
3
+ Single home for two artifacts the build reads instead of session files (Discovery Sprint improvement
4
+ plan, Batch 3): `_integrations.md` (interfaces with other systems, their contracts and error
5
+ handling) and `_migration.md` (data the new solution takes over from existing systems). Each has a
6
+ `pp_run query discovery.*-check` gate. This file is Read lazily; it is never `@`-imported.
7
+
8
+ ## When the files appear
9
+
10
+ | Session | `_integrations.md` | `_migration.md` |
11
+ |---|---|---|
12
+ | 2 | — | created from the template; topic 7 writes one `MG-` row per source system and entity set, `Requirements` `—` |
13
+ | 3 | step matrices name a system in their `Integration` cell (prose until Session 5) | — |
14
+ | 5 | created from the template; topic 4 mints one `IF-` row per external system (system, direction, pattern, owner, requirements), `Protocol`/`Format`/`Idempotency` `—`, and back-fills the step matrices' `Integration` cells with the `IF-nn` | — |
15
+ | 8 | topics 2–4 fill `Protocol`, `Format`, `Idempotency`, `## Contract` and `## Errors`; `integrations-check --require-cited` in the session | topic 6 fills `Mapping`, `Cut-over`, `Reconciliation` and back-fills `Requirements`; `migration-check --require-cited` in the session |
16
+ | 8 | both checks in the Closing Step (reporting) | |
17
+ | 13 | both in the Step 0 gates (reporting) | |
18
+ | handoff | `integrations-check --require-cited` and `migration-check --require-cited` hard-block | |
19
+
20
+ Session 5's **Integration Points Map** and Session 8's **Integration Design Register**, **Data
21
+ Transformation Map** and **Error Handling Strategy** keep their headings as reading summaries that
22
+ point here; Session 2's **Data to Migrate** and Session 8's **Migration and Cut-over** do the same.
23
+ `IF-` and `MG-` are reserved prefixes (`references/discovery-id-conventions.md`); the old `INT-`
24
+ numbering of the Session 5 map is retired — an interface has one ID from Session 5 to go-live.
25
+
26
+ ## Shared grammar
27
+
28
+ - **Nothing is renumbered and nothing is deleted.** `IF-` and `MG-` run contiguously from 01; a
29
+ hole is reported naming the missing ID. A retired interface keeps its row.
30
+ - **`—` is a pending cell**, allowed until the session that owns the cell runs; the handoff refuses a
31
+ pending `Requirements` with `--require-cited`.
32
+ - **Requirements** cites `_requirements.md` IDs, comma-separated.
33
+ - **A change after sign-off edits the row in place** and appends `→ amended by D-<ss>-<n>`
34
+ (`references/discovery-id-conventions.md` § Precedence).
35
+
36
+ ## `_integrations.md`
37
+
38
+ Illustration only — not part of the template, names invented:
39
+
40
+ | ID | System | Direction | Pattern | Protocol | Format | Idempotency | Owner | Requirements |
41
+ |---|---|---|---|---|---|---|---|---|
42
+ | IF-01 | Entra ID | inbound | sign-in | OIDC | JWT | n/a (read-only) | Identity team | N-05 |
43
+
44
+ | Interface | Field | Type | Required | Mapping | Validation |
45
+ |---|---|---|---|---|---|
46
+ | IF-01 | oid | string | yes | User.entra_object_id | GUID |
47
+
48
+ | Interface | Failure | Handling | Retry | Dead letter | Alert |
49
+ |---|---|---|---|---|---|
50
+ | IF-01 | Token invalid | 401, sign-in page | none | — | none |
51
+
52
+ Bootstrap template — Session 5 copies it verbatim to `.planning/discovery/_integrations.md`,
53
+ replacing `[PROJECT_NAME]`:
54
+
55
+ ```markdown
56
+ # Integrations — [PROJECT_NAME]
57
+
58
+ **Conventions:** pp-core reference `references/discovery-integrations.md`. One `IF-` row per interface with another system; `Direction` is `inbound`, `outbound` or `bidirectional` from the product's side; `## Contract` lists the fields exchanged and `## Errors` the failures handled, both keyed by interface. Step matrices cite an interface by its `IF-nn`. Rows are never renumbered or deleted; a change after sign-off edits the row in place and appends `→ amended by D-<ss>-<n>`.
59
+
60
+ ## Interfaces
61
+
62
+ | ID | System | Direction | Pattern | Protocol | Format | Idempotency | Owner | Requirements |
63
+ |----|--------|-----------|---------|----------|--------|-------------|-------|--------------|
64
+
65
+ ## Contract
66
+
67
+ | Interface | Field | Type | Required | Mapping | Validation |
68
+ |-----------|-------|------|----------|---------|------------|
69
+
70
+ ## Errors
71
+
72
+ | Interface | Failure | Handling | Retry | Dead letter | Alert |
73
+ |-----------|---------|----------|-------|-------------|-------|
74
+ ```
75
+
76
+ ### Parser contract — `pp_run query discovery.integrations-check [--require-cited]`
77
+
78
+ No positional path. Faults name the artifact, the 1-based line, a validated ID, a section or column
79
+ name and the reason code — never cell prose. Absent `_integrations.md` → exit 0, `present: false`.
80
+
81
+ | Cell / field | Grammar | Fault when violated |
82
+ |---|---|---|
83
+ | `## Interfaces`, `## Contract`, `## Errors` | each once as a `##` heading holding one table with the template's columns | `missing_section`, `bad_table_shape` naming the section |
84
+ | Interfaces `ID` | `IF-\d{2}`, unique, contiguous from 01 | `bad_id`, `duplicate_id`, `sequence_gap` naming the missing ID |
85
+ | `System`, `Pattern`, `Protocol`, `Format`, `Idempotency`, `Owner` | non-empty (`—` is a pending cell) | `empty_cell` naming the column |
86
+ | `Direction` | `inbound` \| `outbound` \| `bidirectional` | `bad_direction` |
87
+ | Interfaces `Requirements` | `—` (uncited), or a comma list of requirement IDs each present in `_requirements.md` when on file and parseable | `unknown_requirement_id`; `uncited_interface` under `--require-cited` only |
88
+ | Contract / Errors `Interface` | an `IF-nn` present in `## Interfaces` | `unknown_interface` |
89
+ | Contract `Field`, `Type` | non-empty | `empty_cell` |
90
+ | Contract `Required` | `yes` \| `no` | `bad_required` |
91
+ | Contract `Mapping`, `Validation`; Errors `Retry`, `Dead letter`, `Alert` | free text (`—` allowed) | **not mechanically checked** |
92
+ | Errors `Failure`, `Handling` | non-empty | `empty_cell` |
93
+ | a step matrix `Integration` cell in `_processes.md` | `—`, or text naming at least one `IF-nn` present in `## Interfaces` | `unknown_interface` located in `_processes.md`; `step_integration_unlinked` (a non-`—` cell with no `IF-`) under `--require-cited` only |
94
+ | `_requirements.md` present but unparseable | the rollup grammar is owned by `discovery rollup` | `requirements_unparseable`, once |
95
+ | a source present but unreadable | present-and-readable | `artifact_unreadable` naming the path |
96
+
97
+ **Exit identity.** `discovery_integrations_check_failed` for structural faults;
98
+ `discovery_integrations_uncited` when every fault was raised by `--require-cited`. Payload: `ok`,
99
+ `present`, `file`, `interfaces`, `contract_rows`, `error_rows`, `uncited`.
100
+
101
+ ## `_migration.md`
102
+
103
+ A migration row is one source system and the entities the new solution takes over from it: how much
104
+ (volume), how each field maps, how the cut-over runs (big bang, parallel run, phased) and how the move
105
+ is proven (reconciliation counts, spot checks). Most engagements migrate nothing — the file is then
106
+ never created and every check exits 0.
107
+
108
+ Illustration only:
109
+
110
+ | ID | Source system | Entity | Volume | Mapping | Cut-over | Reconciliation | Requirements |
111
+ |---|---|---|---|---|---|---|---|
112
+ | MG-01 | Legacy tracker | Task, Comment | 12k tasks, 40k comments | tracker.csv → Task (title, status map), Comment | Big bang on go-live weekend; tracker read-only from Friday | Row counts per status; 50 tasks compared by hand | T-07 |
113
+
114
+ Bootstrap template — Session 2 topic 7 copies it verbatim to `.planning/discovery/_migration.md` when
115
+ there is data to migrate:
116
+
117
+ ```markdown
118
+ # Migration — [PROJECT_NAME]
119
+
120
+ **Conventions:** pp-core reference `references/discovery-integrations.md` § `_migration.md`. One `MG-` row per source system and entity set; `Source system` is a row of Session 2's Systems Landscape, `Entity` names rows of `_entities.md`. Session 2 fills what moves and how much; Session 8 fills mapping, cut-over and reconciliation and cites the requirements. Rows are never renumbered or deleted; a change after sign-off edits the row in place and appends `→ amended by D-<ss>-<n>`.
121
+
122
+ ## Migration
123
+
124
+ | ID | Source system | Entity | Volume | Mapping | Cut-over | Reconciliation | Requirements |
125
+ |----|---------------|--------|--------|---------|----------|----------------|--------------|
126
+ ```
127
+
128
+ ### Parser contract — `pp_run query discovery.migration-check [--require-cited]`
129
+
130
+ | Cell / field | Grammar | Fault when violated |
131
+ |---|---|---|
132
+ | `## Migration` | once, holding one table with the template's columns | `missing_section`, `bad_table_shape` |
133
+ | `ID` | `MG-\d{2}`, unique, contiguous from 01 | `bad_id`, `duplicate_id`, `sequence_gap` |
134
+ | `Source system` | non-empty; a first-column value of Session 2's **Systems Landscape** when that table is on file with rows | `empty_cell (Source system)`; `unknown_system` naming the system |
135
+ | `Entity` | a comma list of PascalCase names, each present in `_entities.md` § Entities when on file | `bad_entity`; `unknown_entity` naming the entity |
136
+ | `Volume`, `Mapping`, `Cut-over`, `Reconciliation` | non-empty (`—` is a pending cell) | `empty_cell` naming the column |
137
+ | `Requirements` | `—` (uncited), or a comma list of requirement IDs each present in `_requirements.md` when on file and parseable | `unknown_requirement_id`; `uncited_migration` under `--require-cited` only |
138
+ | `_requirements.md` present but unparseable | owned by `discovery rollup` | `requirements_unparseable`, once |
139
+ | a source present but unreadable | present-and-readable | `artifact_unreadable` naming the path |
140
+
141
+ **Exit identity.** `discovery_migration_check_failed` for structural faults;
142
+ `discovery_migration_uncited` when every fault is an `uncited_migration`. Payload: `ok`, `present`,
143
+ `file`, `rows`, `uncited`.
144
+
145
+ ## How the build reads them
146
+
147
+ `pp_run query discovery.for-phase <N>` selects the § Interfaces rows that cite the phase's requirement
148
+ IDs or that a selected step names in its `Integration` cell, with their § Contract and § Errors rows;
149
+ `_migration.md` rows reach the phase through their `Requirements` column
150
+ (`references/discovery-build-consumption.md`). The handoff's C4 Context diagram draws its
151
+ `System_Ext` nodes from § Interfaces (`workflows/discovery-to-build/steps/architecture-deliverables.md`).
@@ -0,0 +1,190 @@
1
+ # Discovery Processes, Rules & Glossary — Templates & Parser Contracts
2
+
3
+ Single home for three artifacts the build reads instead of session files (Discovery Sprint
4
+ improvement plan, Batch 2): `_processes.md` (as-is and to-be processes, swimlanes, step
5
+ matrices), `_rules.md` (business rules) and `_glossary.md` (the ubiquitous language). The first
6
+ two have a `pp_run query discovery.*-check` gate; the glossary deliberately has none. This file is Read
7
+ lazily; it is never `@`-imported.
8
+
9
+ ## When the files appear
10
+
11
+ | Session | `_processes.md` | `_rules.md` | `_glossary.md` |
12
+ |---|---|---|---|
13
+ | 2 | created from the template; `## As-is` rows (`PRC-`) from topic 1 | — | created from the template; terms the client used for the same thing |
14
+ | 3 | Step 5A `## To-be` rows (`MP-`, each with `Replaces`); 5B one swimlane per main process under `## Flows`; 5C one step matrix per main process under `## Steps`, `Exception` column filled; 5D back-fills `Requirements` | Step 5D′ mints `BR-` rows from the step matrices | topic 1 glossary sweep: one row per term, synonyms under `Do not use` |
15
+ | 8 | `process-check` and `rules-check` in the Closing Step (reporting) | | |
16
+ | 13 | both in the Step 0 gates (reporting) | | |
17
+ | handoff | `process-check --require-cited` and `rules-check` hard-block | | |
18
+
19
+ **The session files keep their Notes Template headings as pointers** (Main Process Register,
20
+ Sub-Process Flows, Step Matrices, Process Inventory): the canonical rows live here, exactly as the
21
+ requirements table lives in `_requirements.md`. `PRC-`, `MP-` and `BR-` are reserved prefixes
22
+ (`references/discovery-id-conventions.md`), so none of them can collide with a requirement ID.
23
+
24
+ ## Shared grammar
25
+
26
+ - Closed cells and free-text cells are not the same kind of cell; the contract tables say which.
27
+ - **Nothing is renumbered and nothing is deleted.** `PRC-`, `MP-` and `BR-` run contiguously from
28
+ 01; a hole is reported naming the missing ID. A retired process or rule keeps its row.
29
+ - **An actor is a Session 2 persona or `System`**, spelled as the User Personas table spells it;
30
+ a step two actors perform together names both, comma-separated (`Team lead, System`). A
31
+ qualifier in parentheses or a slash-joined pair is not a persona and is refused.
32
+ - **A data object is `Name [C/R/U/D]`** (`references/discovery-data-model.md`); `—` when a step
33
+ touches none.
34
+ - **A step cites requirements by ID**, comma-separated, after Step 5D; `—` before it. The handoff
35
+ refuses an uncited step.
36
+ - **A swimlane is a Mermaid `flowchart` with one `subgraph` per actor**, so the lane shows who does
37
+ the step; a flowchart without a `subgraph` is a decision tree, not a swimlane, and is refused.
38
+
39
+ ## `_processes.md`
40
+
41
+ Illustration only — not part of the template, names invented:
42
+
43
+ | ID | Main process | Replaces | Trigger | End state | Primary actor | EPICs |
44
+ |---|---|---|---|---|---|---|
45
+ | MP-01 | Handle a task from request to done | PRC-02, PRC-03 | A team member needs work tracked | Task closed with an outcome | Team member | E-01 |
46
+
47
+ | # | Step | Actor | UI | Data objects | Integration | Exception | Requirements |
48
+ |---|---|---|---|---|---|---|---|
49
+ | 01.1 | Create task | Team member | Task form | Task [C] | — | Title missing → form error, nothing saved | K-06 |
50
+
51
+ Bootstrap template — Session 2 copies it verbatim to `.planning/discovery/_processes.md`, replacing
52
+ `[PROJECT_NAME]`:
53
+
54
+ ```markdown
55
+ # Processes — [PROJECT_NAME]
56
+
57
+ **Conventions:** pp-core reference `references/discovery-processes.md`. `PRC-` rows are the as-is processes (Session 2), `MP-` rows the to-be main processes (Session 3) with the as-is processes each replaces or `new`. One swimlane and one step matrix per main process. Nothing is renumbered or deleted; a change after sign-off edits the row in place and appends `→ amended by D-<ss>-<n>`.
58
+
59
+ ## As-is
60
+
61
+ | ID | Process | Owner | Trigger | End state | Frequency | Avg duration | Criticality |
62
+ |----|---------|-------|---------|-----------|-----------|--------------|-------------|
63
+
64
+ ## To-be
65
+
66
+ | ID | Main process | Replaces | Trigger | End state | Primary actor | EPICs |
67
+ |----|--------------|----------|---------|-----------|---------------|-------|
68
+
69
+ ## Flows
70
+
71
+ ## Steps
72
+ ```
73
+
74
+ Under `## Flows`, Step 5B adds one `### MP-nn — <name>` heading per main process holding a swimlane:
75
+
76
+ ````markdown
77
+ ### MP-01 — Handle a task
78
+
79
+ ```mermaid
80
+ flowchart LR
81
+ subgraph Team member
82
+ S1[Create task] --> S2[Assign]
83
+ end
84
+ subgraph System
85
+ S3[Notify assignee]
86
+ end
87
+ S2 --> S3
88
+ ```
89
+ ````
90
+
91
+ Under `## Steps`, Step 5C adds one `### MP-nn — <name>` heading per main process holding its matrix:
92
+
93
+ ```markdown
94
+ ### MP-01 — Handle a task
95
+
96
+ | # | Step | Actor | UI | Data objects | Integration | Exception | Requirements |
97
+ |---|------|-------|----|--------------|-------------|-----------|--------------|
98
+ ```
99
+
100
+ ### Parser contract — `pp_run query discovery.process-check [--require-cited]`
101
+
102
+ No positional path. Faults name the artifact, the 1-based line, a validated ID, a section or
103
+ column name and the reason code — never cell prose. Absent `_processes.md` → exit 0, `present: false`.
104
+
105
+ | Cell / field | Grammar | Fault when violated |
106
+ |---|---|---|
107
+ | `## As-is`, `## To-be`, `## Flows`, `## Steps` | each once as a `##` heading; As-is and To-be hold one table | `missing_section` |
108
+ | table headers | the template's columns, in order | `bad_table_shape` naming the section, or `Steps · MP-nn` |
109
+ | As-is `ID` | `PRC-\d{2}`, unique, contiguous from 01 | `bad_id`, `duplicate_id`, `sequence_gap` naming the missing ID |
110
+ | As-is `Process` | non-empty | `empty_cell (Process)` |
111
+ | As-is other columns | free text | **not mechanically checked** |
112
+ | To-be `ID` | `MP-\d{2}`, unique, contiguous from 01 | `bad_id`, `duplicate_id`, `sequence_gap` |
113
+ | To-be `Main process` | non-empty | `empty_cell (Main process)` |
114
+ | `Replaces` | `new`, or a comma list of `PRC-` IDs present in `## As-is` | `bad_replaces` (empty, or a token of the wrong shape), `unknown_process` naming the PRC |
115
+ | `Primary actor`, step `Actor` | a comma list of `System` and names from Session 2's User Personas table (first column), spelled exactly | `bad_actor` (empty, or any token that is neither). **Not resolved** while `session-02.md` or its table is absent — the cell is then only required non-empty |
116
+ | `Trigger`, `End state`, `EPICs` | free text | **not mechanically checked** (EPIC IDs are not resolved against Session 3) |
117
+ | `### MP-nn — <name>` under Flows and Steps | names a To-be row | `unknown_process` |
118
+ | a main process without a `### MP-nn` under Flows / Steps | one swimlane and one matrix each | `flow_missing`, `steps_missing` naming the MP |
119
+ | a flow body | a ```` ```mermaid ```` block opening with `flowchart` and holding at least one `subgraph` | `flow_not_swimlane` |
120
+ | step `#`, `Step` | non-empty | `empty_cell (Step)` |
121
+ | `UI`, `Integration`, `Exception` | free text (`—` allowed) | **not mechanically checked** — the Exception column must exist, its content is the facilitator's |
122
+ | `Data objects` | `—`, or a comma list of `Name [C/R/U/D]` tokens | `bad_data_object`; whether each name is an entity is `entity-check`'s `unknown_entity` |
123
+ | `Requirements` | `—` (uncited), or a comma list of requirement IDs, each present in `_requirements.md` when it is on file and parseable | `unknown_requirement_id`; `uncited_step` under `--require-cited` only |
124
+ | `_requirements.md` present but unparseable | the rollup grammar is owned by `discovery rollup` | `requirements_unparseable`, once; IDs are then shape-checked only |
125
+ | a source present but unreadable | present-and-readable | `artifact_unreadable` naming the path |
126
+
127
+ **Exit identity.** `discovery_process_check_failed` for structural faults;
128
+ `discovery_process_steps_uncited` when every fault is an `uncited_step`. Payload: `ok`, `present`,
129
+ `file`, `as_is`, `to_be`, `flows`, `steps`, `uncited`.
130
+
131
+ ## `_rules.md`
132
+
133
+ A business rule is a validation, a calculation or an invariant the system enforces. It applies to
134
+ an entity or a process, is checked in exactly the layers named (the vault's "one owning layer per
135
+ check"), and realises at least one requirement — a rule nothing requires is a rule nobody asked for.
136
+
137
+ Illustration only:
138
+
139
+ | ID | Rule | Applies to | Checked at | Requirements | Source |
140
+ |---|---|---|---|---|---|
141
+ | BR-01 | A team has exactly one Lead | Membership | service, DB | K-15 | S3 |
142
+
143
+ Bootstrap template — Session 3 Step 5D′ copies it verbatim to `.planning/discovery/_rules.md`:
144
+
145
+ ```markdown
146
+ # Business Rules — [PROJECT_NAME]
147
+
148
+ **Conventions:** pp-core reference `references/discovery-processes.md` § `_rules.md`. `BR-` is reserved; rows are never renumbered or deleted; a change after sign-off edits the row in place and appends `→ amended by D-<ss>-<n>`.
149
+
150
+ ## Rules
151
+
152
+ | ID | Rule | Applies to | Checked at | Requirements | Source |
153
+ |----|------|------------|------------|--------------|--------|
154
+ ```
155
+
156
+ ### Parser contract — `pp_run query discovery.rules-check`
157
+
158
+ | Cell / field | Grammar | Fault when violated |
159
+ |---|---|---|
160
+ | `## Rules` | once, holding one table with the template's columns | `missing_section`, `bad_table_shape` |
161
+ | `ID` | `BR-\d{2}`, unique, contiguous from 01 | `bad_id`, `duplicate_id`, `sequence_gap` |
162
+ | `Rule` | non-empty | `empty_cell (Rule)` |
163
+ | `Applies to` | a comma list; each token an entity name (`^[A-Z][A-Za-z0-9]*$`) present in `_entities.md` § Entities, or a `PRC-`/`MP-` ID present in `_processes.md` | `bad_subject` (empty, or a token of neither shape); `unknown_subject` naming the token. **Not resolved** while the owning artifact is absent |
164
+ | `Checked at` | a comma list from `UI` \| `service` \| `DB` | `bad_checked_at` |
165
+ | `Requirements` | at least one requirement ID, each present in `_requirements.md` when on file and parseable | `no_requirement`, `unknown_requirement_id` |
166
+ | `Source` | free text | **not mechanically checked** |
167
+
168
+ **Exit identity.** `discovery_rules_check_failed`. Payload: `ok`, `present`, `file`, `rules`.
169
+
170
+ ## `_glossary.md`
171
+
172
+ One word per concept (the vault's naming rule). A term the requirements use must be defined once;
173
+ every other word for it goes under `Do not use`, so the build inherits the vocabulary instead of
174
+ re-deriving it. Rows are keyed by `Term`, not by an ID.
175
+
176
+ Bootstrap template — Session 2 copies it verbatim to `.planning/discovery/_glossary.md`:
177
+
178
+ ```markdown
179
+ # Glossary — [PROJECT_NAME]
180
+
181
+ **Conventions:** pp-core reference `references/discovery-processes.md` § `_glossary.md`. One row per concept; the term is the one the requirements and the code use; `Do not use` lists the synonyms heard in the room.
182
+
183
+ | Term | Definition | Do not use | Source |
184
+ |------|------------|------------|--------|
185
+ ```
186
+
187
+ **Not mechanically checked — deliberately.** A definition has no closed grammar, and a check that
188
+ only counted rows would reward padding. The glossary is read by every agent and reviewed in the
189
+ Session 13 cross-reference ("Stakeholder names" and "KPIs and metrics" rows), where a term with
190
+ two spellings is a finding.
@@ -20,8 +20,8 @@ changes on account of this file.
20
20
 
21
21
  ## When this file appears
22
22
 
23
- `_rebaseline.md` is bootstrapped **on first need** (D-31), exactly the way `_progress.md` and
24
- `_context.md` are in Flow 2 Step 1, and exactly the way `_screens.md`, `_feedback.md` and the
23
+ `_rebaseline.md` is bootstrapped **on first need** (D-31), exactly the way `_progress.md`
24
+ is in Flow 2 Step 1, and exactly the way `_screens.md`, `_feedback.md` and the
25
25
  three research-track registers are: the file does not exist until the first re-baselining round
26
26
  runs, and if it is absent when a round first has something to put in it, create it verbatim from
27
27
  the template below and then add the rows. There is no setup step and no separate sub-command. An
@@ -17,7 +17,7 @@ restate them. Read that file when you need an ID's shape or the reserved set.
17
17
  ## When these files appear
18
18
 
19
19
  The three registers are bootstrapped **on first need**, exactly the way `_progress.md`
20
- and `_context.md` are in Flow 2 Step 1: if the file is absent when a session first has
20
+ is in Flow 2 Step 1: if the file is absent when a session first has
21
21
  something to put in it, create it verbatim from the template below, then add the row.
22
22
  There is no `/pp-discovery research` sub-command and no setup step — an empty register
23
23
  is not a milestone, and a register that exists with zero rows is indistinguishable from
@@ -231,8 +231,7 @@ qualifies (D-45). Three engine consequences:
231
231
  frontmatter ID with no marker in the body — is `conditional_frontmatter_drift`. The
232
232
  frontmatter is derived state and must match what is actually marked.
233
233
 
234
- **Where markers may live (D-46): prose sections only.** Session notes and `_context.md`
235
- sections carry markers; `_requirements.md` table cells never do. The closed requirements
234
+ **Where markers may live (D-46): prose sections only.** Session notes carry markers; `_requirements.md` table cells never do. The closed requirements
236
235
  grammar already rejects a marker in any structured cell, and the correct join for a
237
236
  research-dependent requirement already exists: an `_research.md` row citing that
238
237
  requirement in its `Gates what?` cell.
@@ -244,9 +243,9 @@ paper that no human has confirmed. `⚠️ CONDITIONAL` means a real decision wa
244
243
  the room and is knowingly contingent on outside work — that *is* the answer, honestly
245
244
  qualified.
246
245
 
247
- **A marker travels with the content it qualifies.** When Step 7 propagates a session
248
- answer into a `_context.md` section, the marker propagates with it; the marker is part
249
- of the answer, not an annotation on the session file.
246
+ **A marker travels with the content it qualifies.** When an answer is copied into a
247
+ register row or a later session, the marker goes with it; the marker is part of the
248
+ answer, not an annotation on the session file.
250
249
 
251
250
  ## Parser contract — `pp-tools discovery research-check`
252
251
 
@@ -0,0 +1,70 @@
1
+ # Discovery Session Output Gate
2
+
3
+ > **Lazy-loaded.** Read from `workflows/discovery-sprint.md` Flow 2 Step 7 when a session
4
+ > closes, from Session 8's Closing Step and from `session-13-gates.md`. Never `@`-import it.
5
+ > Single home for what `pp_run query discovery.session-check` measures and for the one rule that
6
+ > keeps the session files the only source of what a session produced (Discovery Sprint
7
+ > improvement plan, Batch 5; review findings F-6 and F-7).
8
+
9
+ ## The contract
10
+
11
+ A session's **Notes Template** in `workflows/discovery-sprint/sessions/NN-*.md` is the
12
+ list of what the session must leave behind. Each whole-line bold title under
13
+ `**Notes Template:**` names one section of `.planning/discovery/session-NN.md`:
14
+
15
+ - the section is present **exactly once** — written as `**Title**` or as a heading
16
+ `## Title`, titled exactly as the template spells it; never append a second copy, edit the
17
+ one that is there;
18
+ - a section that is a table in the template keeps the template's column count and holds
19
+ **at least one data row** — a row with two or more filled cells; a pre-filled label with
20
+ nothing beside it (`| PRC-01 | | |`, `| Business problem / opportunity | |`) is the
21
+ template, not data;
22
+ - a section that is prose in the template holds at least one line of prose (or a table
23
+ with a data row); an HTML comment is not prose;
24
+ - a section the session genuinely found nothing for says so on one line under its title:
25
+ `None identified in Discovery.` — the literal, so a reader and the check both know the
26
+ room was asked;
27
+ - a parked topic's section carries `PARKED — needs business/senior input` (Flow 2
28
+ Step 5.3); the section is accounted for, the score is not.
29
+
30
+ The check reads the template from the pp-core install, so the required-section list cannot
31
+ drift from the file the facilitator reads. It checks structure, never judgement: it does not
32
+ read what a row says.
33
+
34
+ ## The command
35
+
36
+ ```
37
+ pp_run query discovery.session-check <N> [<N>…] # named sessions, whatever their status
38
+ pp_run query discovery.session-check --all # every session-NN.md whose status is Completed
39
+ ```
40
+
41
+ Exit 0 → the payload lists each session's `required`, `filled` and `empty` sections. Non-zero
42
+ (`discovery_session_check_failed`) → one line per fault:
43
+
44
+ | Fault | Meaning | Fix |
45
+ |-------|---------|-----|
46
+ | `missing_section (Title)` | the title is not in the session file | add the section, titled as the template spells it |
47
+ | `duplicate_section (Title)` | the title appears twice | merge into the first copy |
48
+ | `bad_table_shape (Title)` | the table's column count is off the template | restore the template's columns |
49
+ | `empty_section (Title)` | no data row or prose, and no literal | fill it from what the room said, or write the literal |
50
+ | `session_missing` | `session-NN.md` does not exist | the session has not started |
51
+ | `template_missing` | the install has no content file for that session | reinstall pp-core |
52
+
53
+ ## The score
54
+
55
+ `discovery-sprint.md` Step 7 computes `completeness_score` from the topics covered. A topic
56
+ whose Notes Template section the check reports `empty_section` counts as **not covered**,
57
+ however long it was discussed — the output is the measure, not the conversation. Run the check
58
+ before setting the score; it exits 0 before a session may read 100.
59
+
60
+ ## One source of truth
61
+
62
+ The session files and the registers they point at (`_requirements.md`, `_entities.md`,
63
+ `_processes.md`, `_rules.md`, `_glossary.md`, `_screens.md`, `_roles.md`,
64
+ `_integrations.md`, `_migration.md`, `_deviations.md`) are the only record of what a session
65
+ produced. Nothing is summarised into a second file at session close: later sessions read the
66
+ earlier session's Notes Template sections (the **Context-Awareness Rules** table names
67
+ which), the Session 13 cross-reference reads the session files, and `/pp-discovery-to-build`
68
+ reads the session files and the registers. A `.planning/discovery/_context.md` left by an
69
+ engagement that predates this rule is neither read nor maintained; its content was always a
70
+ copy of the session tables.