@pareto4/pp-core 1.19.0 → 1.21.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-nyquist-auditor.md +19 -14
- package/agents/pp-phase-researcher.md +10 -0
- package/agents/pp-plan-checker.md +59 -36
- package/agents/pp-planner.md +49 -53
- package/agents/pp-vault-reviewer.md +2 -0
- package/agents/pp-verifier.md +15 -60
- package/commands/pp-autonomous.md +2 -1
- package/commands/pp-discovery.md +3 -2
- package/commands/pp-plan-phase.md +2 -1
- package/commands/pp-plan-review-convergence.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-activation.cjs +77 -0
- package/pp-core/bin/lib/capability-registry.cjs +15 -15
- package/pp-core/bin/lib/capability-state.cjs +8 -18
- package/pp-core/bin/lib/ceremony.cjs +1342 -0
- package/pp-core/bin/lib/check-command-router.cjs +62 -1
- package/pp-core/bin/lib/commands.cjs +29 -3
- package/pp-core/bin/lib/config.cjs +5 -0
- 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 +8 -7
- package/pp-core/bin/lib/discovery-rules.cjs +216 -0
- package/pp-core/bin/lib/discovery-screens.cjs +1 -1
- 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 +1 -1
- package/pp-core/bin/lib/discovery-table.cjs +55 -0
- package/pp-core/bin/lib/init.cjs +50 -1
- package/pp-core/bin/lib/io.cjs +24 -0
- package/pp-core/bin/lib/loop-resolver.cjs +26 -12
- package/pp-core/bin/lib/phase.cjs +39 -3
- package/pp-core/bin/lib/plan-sizing.cjs +346 -0
- package/pp-core/bin/lib/test-substance.cjs +3190 -0
- package/pp-core/bin/lib/timeline.cjs +605 -0
- package/pp-core/bin/lib/vault-standards-review.cjs +50 -2
- package/pp-core/bin/pp-tools.cjs +214 -5
- package/pp-core/bin/shared/ceremony-gates.json +17 -0
- package/pp-core/bin/shared/config-schema.manifest.json +1 -0
- package/pp-core/references/ceremony.md +81 -0
- 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 +50 -14
- 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/few-shot-examples/plan-checker.md +8 -8
- package/pp-core/references/phase-timeline.md +107 -0
- package/pp-core/references/planner-antipatterns.md +32 -0
- package/pp-core/references/planner-discovery-extract.md +35 -0
- package/pp-core/references/planner-guidance.md +17 -14
- package/pp-core/references/planner-revision.md +1 -1
- package/pp-core/references/planning-config.md +3 -2
- package/pp-core/references/test-substance.md +324 -0
- package/pp-core/references/verifier-discovery-conformance.md +36 -0
- package/pp-core/references/verifier-stub-patterns.md +51 -0
- package/pp-core/templates/VALIDATION.md +1 -0
- package/pp-core/templates/phase-prompt.md +19 -7
- 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/roadmap.md +1 -1
- package/pp-core/templates/verification-report.md +17 -1
- package/pp-core/workflows/audit-milestone.md +4 -1
- package/pp-core/workflows/autonomous.md +11 -8
- package/pp-core/workflows/code-review.md +15 -6
- 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 +10 -0
- package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +5 -2
- package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +27 -5
- package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +56 -31
- package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +1 -1
- package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +42 -19
- package/pp-core/workflows/discovery-sprint/sessions/06-security.md +27 -12
- package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +41 -23
- package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +50 -23
- package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +26 -11
- package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +28 -9
- package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +21 -0
- package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +24 -9
- package/pp-core/workflows/discovery-sprint.md +12 -15
- package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +80 -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.md +10 -7
- package/pp-core/workflows/execute-phase/steps/check-query-gate.md +7 -7
- package/pp-core/workflows/execute-phase/steps/codebase-drift-gate.md +3 -2
- package/pp-core/workflows/execute-phase.md +14 -3
- package/pp-core/workflows/new-project.md +3 -3
- package/pp-core/workflows/plan-phase/steps/chunked-planning.md +7 -3
- package/pp-core/workflows/plan-phase/steps/discovery-extract.md +41 -0
- package/pp-core/workflows/plan-phase/steps/prd-express.md +104 -0
- package/pp-core/workflows/plan-phase.md +62 -124
- package/pp-core/workflows/plan-review-convergence.md +6 -3
- package/pp-core/workflows/ship.md +2 -2
- package/pp-core/workflows/stats.md +19 -4
- package/pp-core/workflows/validate-phase.md +19 -4
- package/pp-core/workflows/vault-review.md +5 -0
- package/pp-core/workflows/verify-phase.md +1 -1
- package/pp-core/workflows/verify-work.md +1 -1
- package/scripts/gen-capability-registry.cjs +43 -45
- package/scripts/run-tests.cjs +54 -30
- package/pp-core/workflows/discovery-sprint/templates/context-template.md +0 -272
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Discovery → Build Consumption Contract
|
|
2
|
+
|
|
3
|
+
> Lazy-loaded reference. Single home for how a build phase reads the Discovery Sprint's
|
|
4
|
+
> canonical artifacts (Discovery Sprint improvement plan, Batch 4 — §5.5 rules R1 and R3), for the
|
|
5
|
+
> two registers that batch adds (`_stories.md`, `_phases.md`) and for the three commands that serve
|
|
6
|
+
> them: `pp_run query discovery.stories-check`, `pp_run query discovery.phases-check` and
|
|
7
|
+
> `pp_run query discovery.for-phase <N>`. The `_screens.md` recipe in
|
|
8
|
+
> `references/discovery-traceability.md` is the pattern every artifact here follows: a bootstrap
|
|
9
|
+
> template with no example rows, a closed cell grammar, a parser contract, a check that fails on
|
|
10
|
+
> structure and never on judgement.
|
|
11
|
+
|
|
12
|
+
## The three rules
|
|
13
|
+
|
|
14
|
+
**R1 — Reference artifacts by ID, filtered per phase; never session files.** A phase's
|
|
15
|
+
`**Requirements**: [K-03, N-02]` line in `ROADMAP.md` is the key (before the handoff, the phase's
|
|
16
|
+
row in `_phases.md`). `for-phase <N>` returns the rows of every canonical artifact that cite those
|
|
17
|
+
IDs as one markdown extract between `<!-- discovery:auto -->` and `<!-- /discovery:auto -->`.
|
|
18
|
+
`/pp-discuss-phase` writes the extract into CONTEXT.md; `/pp-plan-phase` renders it fresh into
|
|
19
|
+
`{padded}-DISCOVERY-EXTRACT.md` for the researcher and the planner, and the planner embeds it in
|
|
20
|
+
every PLAN.md of the phase. No agent opens `.planning/discovery/session-NN.md`.
|
|
21
|
+
|
|
22
|
+
**R2 — One source of truth, amended in place** (`references/discovery-id-conventions.md`
|
|
23
|
+
§ Precedence). A build decision that changes a discovery fact edits the artifact row and appends
|
|
24
|
+
`→ amended by D-P<nn>-<n>`; the extract is re-rendered, never edited. § R2 in build, below.
|
|
25
|
+
|
|
26
|
+
**R3 — Report at planning, enforce at verification.** Planning reads discovery; execution is not
|
|
27
|
+
blocked by it. The verifier takes the acceptance criteria of the extract's `_requirements.md` and
|
|
28
|
+
`_stories.md` rows as the UAT and writes a **Discovery conformance** block naming every extract row
|
|
29
|
+
`honoured`, `amended (D-P<nn>-<n>)` or `missed`. A `missed` row is a gap.
|
|
30
|
+
|
|
31
|
+
**Boundary:** a project without `.planning/discovery/` sees none of this. Every command below exits
|
|
32
|
+
0 with an empty result there, exactly as the vault capability is inert without bindings.
|
|
33
|
+
|
|
34
|
+
## Consumption table
|
|
35
|
+
|
|
36
|
+
| Artifact | Rows the extract carries for a phase | Consumer |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `_requirements.md` § Requirements | rows whose ID is in the phase's set — all six columns, acceptance criteria verbatim | REQUIREMENTS.md rows (handoff 5e); planner acceptance criteria; verifier UAT |
|
|
39
|
+
| `_stories.md` § Stories | rows whose `Requirements` cites one | planner; verifier UAT |
|
|
40
|
+
| `_processes.md` § To-be, § Steps | the step rows whose `Requirements` cites one, under their `### MP-nn — <name>` heading, preceded by the § To-be row of each main process touched | planner tasks; UAT scripts |
|
|
41
|
+
| `_entities.md` | the entities the selected steps name as data objects: § Entities row, attribute table, relationships touching them, lifecycles | planner data phases; ERD |
|
|
42
|
+
| `_rules.md` § Rules | rows whose `Requirements` cites one | planner; tests |
|
|
43
|
+
| `_screens.md` § Screens, § No screen (still MVP) | screens whose `Requirements` cites one; no-screen rows keyed by one | ui-phase (exists); planner |
|
|
44
|
+
| `_roles.md` § Permissions, § Roles, § Screens | the permission rows whose `Requirements` cites one; the § Roles row of every role those permissions name; the § Screens rows of those roles and of the phase's screens (`references/discovery-access.md`) | planner auth phase; forbidden-path tests |
|
|
45
|
+
| `_integrations.md` § Interfaces, § Contract, § Errors | the interface rows whose `Requirements` cites one or that a selected step names in its `Integration` cell (`IF-nn`); their contract and error rows (`references/discovery-integrations.md`) | planner integration phases |
|
|
46
|
+
| `_migration.md`, `_deviations.md` | generic: every table carrying a `Requirements` (or `Requirement IDs`) column contributes its citing rows. A table with no requirement column is listed as *not filterable* in the extract, never silently dropped — `_deviations.md § Deviations` always is | planner migration phase; `pp-vault-review` reads `_deviations.md` whole (§ Deviations read contract) |
|
|
47
|
+
| `_phases.md` § Phases | the phase's requirement IDs when ROADMAP.md has none yet | ROADMAP.md (handoff 5f, verbatim); `for-phase` |
|
|
48
|
+
|
|
49
|
+
The grammars of `_roles.md`, `_integrations.md`, `_migration.md` and `_deviations.md` live in
|
|
50
|
+
`references/discovery-access.md`, `references/discovery-integrations.md` and
|
|
51
|
+
`references/discovery-standards.md` (Batch 3). For a generic register's rows to reach a phase the
|
|
52
|
+
table must carry a `Requirements` column; the column name is the join, not the position.
|
|
53
|
+
|
|
54
|
+
## `_stories.md` — user stories (Session 3 Step 5E)
|
|
55
|
+
|
|
56
|
+
```markdown
|
|
57
|
+
# User Stories — [PROJECT_NAME]
|
|
58
|
+
|
|
59
|
+
## Stories
|
|
60
|
+
|
|
61
|
+
| ID | EPIC | Requirements | Story | Acceptance criteria | Source step |
|
|
62
|
+
|----|------|--------------|-------|---------------------|-------------|
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
| Cell | Grammar |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `ID` | `US-<nn>`, zero-padded two digits, global sequence, contiguous from `US-01` |
|
|
68
|
+
| `EPIC` | one `E-<nn>` from Session 3's EPIC Register |
|
|
69
|
+
| `Requirements` | comma list of `_requirements.md` IDs (`[A-Z][A-Z0-9]*-\d+`), at least one |
|
|
70
|
+
| `Story` | free text — `As a <persona>, I want <goal> so that <benefit>`; pipes escaped `\|` |
|
|
71
|
+
| `Acceptance criteria` | free text, non-empty, and a criterion — never a pointer such as `As in F-01`; the verifier reads it verbatim as the UAT |
|
|
72
|
+
| `Source step` | comma list of `MP-<nn> #<cell>` — the main process and the `#` cell of the step-matrix row the story was derived from, copied verbatim (`MP-05 #05.1`, `MP-01 #3`) — or `—` |
|
|
73
|
+
|
|
74
|
+
### Parser contract — `pp_run query discovery.stories-check`
|
|
75
|
+
|
|
76
|
+
| Fault | Raised when |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `missing_section` | no `## Stories` heading, or no table under it |
|
|
79
|
+
| `bad_table_shape` | the header is not the template's six columns |
|
|
80
|
+
| `bad_id` / `duplicate_id` / `sequence_gap` | the `US-` family rules above |
|
|
81
|
+
| `bad_epic` | `EPIC` is not one `E-nn` |
|
|
82
|
+
| `empty_cell` | `Story` or `Acceptance criteria` is empty (the cell is named) |
|
|
83
|
+
| `acceptance_is_pointer` | `Acceptance criteria` starts with `As in`, `See`, `Zie` or `Idem` — a pointer, not a criterion the verifier can run |
|
|
84
|
+
| `no_requirement` / `unknown_requirement_id` | no requirement cited, or one of the wrong shape or absent from `_requirements.md` (resolution skipped when that file is absent) |
|
|
85
|
+
| `bad_source_step` / `unknown_process_id` / `unknown_process_step` | a `Source step` token is neither `—` nor `MP-nn #<cell>`; the main process is not in `_processes.md` § To-be; the step row is not in its matrix (both resolutions skipped when `_processes.md` is absent) |
|
|
86
|
+
| `mvp_requirement_without_story` | an `MVP` requirement that at least one persona-actor step row cites has no story. Mirrors Step 5E: stories come from the step rows whose actor is not `System`, so a requirement realised only by `System` steps, or cited by no step at all (engagement process rows), needs none; `N-`/`T-` rows never do. Without `_processes.md` only the prefix exemption applies |
|
|
87
|
+
| `requirements_unparseable` / `artifact_unreadable` | `_requirements.md` present but failing `rollup --check`; an artifact present but unreadable |
|
|
88
|
+
|
|
89
|
+
Exit identity `discovery_stories_check_failed`. Absent `_stories.md` → exit 0, `present: false`.
|
|
90
|
+
Reports at Sessions 8 and 13; hard-blocks at `/pp-discovery-to-build`.
|
|
91
|
+
|
|
92
|
+
## `_phases.md` — the Phase Plan (Session 11 Closing Step)
|
|
93
|
+
|
|
94
|
+
```markdown
|
|
95
|
+
# Phase Plan — [PROJECT_NAME]
|
|
96
|
+
|
|
97
|
+
## Phases
|
|
98
|
+
|
|
99
|
+
| Phase | Goal | EPICs | Requirement IDs | Success criteria | Depends on |
|
|
100
|
+
|-------|------|-------|-----------------|------------------|------------|
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
| Cell | Grammar |
|
|
104
|
+
|---|---|
|
|
105
|
+
| `Phase` | positive integer, unique, contiguous from 1 — the pp-core phase number ROADMAP.md will carry |
|
|
106
|
+
| `Goal` | free text, one sentence — copied verbatim into ROADMAP.md `**Goal**:` |
|
|
107
|
+
| `EPICs` | comma list of `E-<nn>`, or `—` for a phase that realises no EPIC (infrastructure, migration) |
|
|
108
|
+
| `Requirement IDs` | comma list of `_requirements.md` IDs, none `Dropped`, or `—` for a phase that realises no requirement (setup, infrastructure) — copied verbatim into `**Requirements**:` |
|
|
109
|
+
| `Success criteria` | observable statements separated by ` · ` (space, middle dot U+00B7, space) — each becomes one numbered line under `**Success Criteria**` |
|
|
110
|
+
| `Depends on` | `—`, or a comma list of earlier phase numbers — `**Depends on**:` |
|
|
111
|
+
|
|
112
|
+
### Parser contract — `pp_run query discovery.phases-check`
|
|
113
|
+
|
|
114
|
+
| Fault | Raised when |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `missing_section` / `bad_table_shape` | no `## Phases` table, or a header off the template |
|
|
117
|
+
| `bad_phase_number` / `duplicate_phase` / `sequence_gap` | the `Phase` rules above (a malformed number contributes nothing else) |
|
|
118
|
+
| `empty_cell` | `Goal` or `Success criteria` empty |
|
|
119
|
+
| `bad_epic` | an `EPICs` token is not `E-nn` |
|
|
120
|
+
| `no_requirement` / `unknown_requirement_id` | an empty `Requirement IDs` cell (write `—` for a phase with none), or an ID of the wrong shape or absent from `_requirements.md` (resolution skipped when absent) |
|
|
121
|
+
| `dropped_requirement_planned` | a planned requirement's disposition is `Dropped (…)` |
|
|
122
|
+
| `requirement_in_multiple_phases` | the same ID in two rows (the phases are named) |
|
|
123
|
+
| `mvp_requirement_unplanned` | an `MVP` requirement appears in no phase — the roadmap template's own rule, now mechanical |
|
|
124
|
+
| `bad_dependency` | a `Depends on` token is not an earlier, existing phase number |
|
|
125
|
+
| `requirements_unparseable` / `artifact_unreadable` | as for `stories-check` |
|
|
126
|
+
|
|
127
|
+
Exit identity `discovery_phases_check_failed`. Absent `_phases.md` → exit 0. Reports at Sessions 11
|
|
128
|
+
and 13; hard-blocks at `/pp-discovery-to-build`, whose Step 5f copies the table into ROADMAP.md.
|
|
129
|
+
|
|
130
|
+
## `pp_run query discovery.for-phase <N>`
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
pp_run query discovery.for-phase <N> # JSON: ids, artifacts, rows, markdown
|
|
134
|
+
pp_run query discovery.for-phase <N> --markdown # the extract alone, for injection
|
|
135
|
+
pp_run query discovery.for-phase <N> --conformance-template # the verifier's block, every row `missed`
|
|
136
|
+
pp_run query discovery.for-phase <N> --verify <VERIFICATION.md> # check the block covers every row
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`<N>` is the phase number as ROADMAP.md spells it (`3`, `2.1`). Resolution of the requirement
|
|
140
|
+
IDs: the phase's `**Requirements**:` line in `.planning/ROADMAP.md` (brackets optional); else the
|
|
141
|
+
phase's row in `_phases.md` (integer phases only); else none — the extract then says so and carries
|
|
142
|
+
no rows, exit 0.
|
|
143
|
+
|
|
144
|
+
### The extract
|
|
145
|
+
|
|
146
|
+
```markdown
|
|
147
|
+
<!-- discovery:auto -->
|
|
148
|
+
## Discovery extract — Phase 3
|
|
149
|
+
|
|
150
|
+
Requirement IDs: K-01, K-02 (source: .planning/ROADMAP.md)
|
|
151
|
+
Rendered by `pp_run query discovery.for-phase 3`. Do not edit here: amend the artifact row (`→ amended by D-P<nn>-<n>`) and re-run.
|
|
152
|
+
|
|
153
|
+
### Requirements — `.planning/discovery/_requirements.md`
|
|
154
|
+
| … six columns, rows verbatim … |
|
|
155
|
+
|
|
156
|
+
### User stories — `.planning/discovery/_stories.md`
|
|
157
|
+
### Process steps — `.planning/discovery/_processes.md`
|
|
158
|
+
#### Main processes
|
|
159
|
+
#### MP-01 — <name>
|
|
160
|
+
### Entities — `.planning/discovery/_entities.md`
|
|
161
|
+
#### <Entity> (attributes) #### Relationships #### Lifecycles
|
|
162
|
+
### Business rules — `.planning/discovery/_rules.md`
|
|
163
|
+
### Screens — `.planning/discovery/_screens.md`
|
|
164
|
+
#### No screen (still MVP)
|
|
165
|
+
### Roles — `.planning/discovery/_roles.md`
|
|
166
|
+
#### Roles #### Permissions #### Screens
|
|
167
|
+
### Integrations — `.planning/discovery/_integrations.md`
|
|
168
|
+
#### Interfaces #### Contract #### Errors
|
|
169
|
+
### Migration — … (one `####` per section of a generic register)
|
|
170
|
+
|
|
171
|
+
Not filterable by requirement: `.planning/discovery/_deviations.md § Deviations` has no requirement column — read it whole.
|
|
172
|
+
|
|
173
|
+
Artifacts read: .planning/discovery/_requirements.md, …
|
|
174
|
+
<!-- /discovery:auto -->
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Sections appear only when they carry a row. Cells are copied verbatim with pipes re-escaped. The
|
|
178
|
+
`Artifacts read` line is what a phase's canonical refs name — artifact paths, never session files.
|
|
179
|
+
The join is the ID, so a cross-cutting requirement (an audit or notification rule every flow
|
|
180
|
+
touches) pulls steps of other main processes into the phase that owns it — by design, not scope
|
|
181
|
+
creep: those steps are where the requirement is realised.
|
|
182
|
+
|
|
183
|
+
### Row keys
|
|
184
|
+
|
|
185
|
+
Every keyed row has one identity, `<artifact basename> <row>`, used by the conformance block:
|
|
186
|
+
|
|
187
|
+
| Artifact | Row key |
|
|
188
|
+
|---|---|
|
|
189
|
+
| `_requirements.md` | the requirement ID (`K-01`) |
|
|
190
|
+
| `_stories.md` | the story ID (`US-02`) |
|
|
191
|
+
| `_processes.md` | `MP-<nn> #<cell>` — main process and the matrix's `#` cell verbatim (`MP-05 #05.1`); the same spelling `_stories.md` uses in `Source step`; the § To-be rows are detail, not keys |
|
|
192
|
+
| `_entities.md` | the entity name; attribute, relationship and lifecycle rows are detail |
|
|
193
|
+
| `_rules.md` | `BR-<nn>` |
|
|
194
|
+
| `_screens.md` | `SCR-<nn>`, or `no-screen <requirement ID>` for a bucket row |
|
|
195
|
+
| `_roles.md` | the role name (§ Roles and § Permissions rows share it; § Screens rows are detail) |
|
|
196
|
+
| `_integrations.md` | `IF-<nn>` (§ Contract and § Errors rows are detail) |
|
|
197
|
+
| generic registers | the row's first cell |
|
|
198
|
+
|
|
199
|
+
### Parser contract — structure only
|
|
200
|
+
|
|
201
|
+
| Fault | Raised when |
|
|
202
|
+
|---|---|
|
|
203
|
+
| `missing_section` / `bad_table_shape` | a present artifact's owning section or header is off its template (`_requirements.md` § Requirements, `_stories.md` § Stories, `_processes.md` § To-be and every `### MP-nn — <name>` under § Steps, `_entities.md` § Entities and the attribute tables of selected entities, `_rules.md` § Rules, `_screens.md` § Screens and § No screen (still MVP), `_roles.md` § Roles / § Permissions / § Screens, `_integrations.md` § Interfaces / § Contract / § Errors) |
|
|
204
|
+
| `requirements_unparseable` | `_requirements.md` present but failing the rollup parse — run `pp_run query discovery.rollup --check` |
|
|
205
|
+
| `artifact_unreadable` | an artifact present but unreadable |
|
|
206
|
+
|
|
207
|
+
Exit identity `discovery_for_phase_failed`, on structure only. The command never judges whether a
|
|
208
|
+
row is relevant; the join is the ID.
|
|
209
|
+
|
|
210
|
+
### The Discovery conformance block (R3)
|
|
211
|
+
|
|
212
|
+
`--conformance-template` renders, for the verifier to fill:
|
|
213
|
+
|
|
214
|
+
```markdown
|
|
215
|
+
### Discovery conformance
|
|
216
|
+
|
|
217
|
+
<!-- discovery:conformance -->
|
|
218
|
+
| Artifact | Row | Status | Evidence |
|
|
219
|
+
|---|---|---|---|
|
|
220
|
+
| `_requirements.md` | K-01 | missed | |
|
|
221
|
+
| `_processes.md` | MP-01 #2 | missed | |
|
|
222
|
+
<!-- /discovery:conformance -->
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
`Status` is exactly `honoured`, `missed`, or `amended (D-P<nn>-<n>)` naming the build decision that
|
|
226
|
+
changed the row (R2). Every row starts as `missed`: an unverified row is a gap until evidence says
|
|
227
|
+
otherwise. `Evidence` is free text (`file:line`, a test name, the amended cell).
|
|
228
|
+
|
|
229
|
+
`--verify <file>` faults: `conformance_markers` (not exactly one open and one close, in order),
|
|
230
|
+
`bad_table_shape`, `bad_status`, `unknown_row` (a key the extract does not have), `duplicate_row`,
|
|
231
|
+
`missing_row` (an extract row absent from the block). It reports the counts `honoured`, `amended`,
|
|
232
|
+
`missed`; a `missed` row is never a fault of the block — it is the verifier's finding, and the
|
|
233
|
+
verifier's status rule turns it into `gaps_found`.
|
|
234
|
+
|
|
235
|
+
## R2 in build — amending a discovery fact
|
|
236
|
+
|
|
237
|
+
When a `/pp-discuss-phase` decision changes something the sprint recorded (a field, a rule, a role,
|
|
238
|
+
a flow step, a screen):
|
|
239
|
+
|
|
240
|
+
1. Edit the artifact row in place and append `→ amended by D-P<nn>-<n>` to the changed cell
|
|
241
|
+
(`<nn>` the zero-padded phase, `<n>` the decision's sequence in CONTEXT.md).
|
|
242
|
+
2. Re-run the artifact's check (`entity-check`, `process-check`, `rules-check`, `screen-check`,
|
|
243
|
+
`stories-check`, `phases-check`, `rollup --check`) — exit 0 before continuing.
|
|
244
|
+
3. Bump `version` in `docs/discovery/PROJECT-CHARTER.md` and add a § 20 Version history row naming
|
|
245
|
+
the decision; a signed charter is not silently superseded.
|
|
246
|
+
4. Re-run `for-phase` — CONTEXT.md and PLAN.md hold the extract, never an override.
|
|
247
|
+
|
|
248
|
+
## `_deviations.md` read contract for `pp-vault-review`
|
|
249
|
+
|
|
250
|
+
`pp_run check vault-review` reads `.planning/discovery/_deviations.md` when present and adds
|
|
251
|
+
`deviations[]` to its payload: every row of every table that carries, by header name, a `Standard`
|
|
252
|
+
column and a `Status` column (`ID`, `Decision` and `Approver` are copied when present). The vault
|
|
253
|
+
reviewer treats a `FAIL` whose clause an `Approved` deviation covers as `N-A` with the reason
|
|
254
|
+
`deviation on file: <ID> (<Decision>)`; a deviation in any other status leaves the `FAIL` standing
|
|
255
|
+
and is named in the row's reason. A present but unreadable file is a payload gap. The file's full
|
|
256
|
+
grammar is `references/discovery-standards.md`; the two column names are the join.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Discovery Charter — Parser Contract, Heading Keys & Language
|
|
2
|
+
|
|
3
|
+
Single home for the machine side of the Project Charter: what `pp_run query discovery.charter-check`
|
|
4
|
+
verifies in `docs/discovery/PROJECT-CHARTER.md`, the heading keys that make the shape
|
|
5
|
+
language-independent, and the heading renderings for the sprint languages. The template itself is
|
|
6
|
+
`templates/project-charter.md`; the drafting procedure is `workflows/discovery-sprint/charter.md`.
|
|
7
|
+
This file is Read lazily; it is never `@`-imported.
|
|
8
|
+
|
|
9
|
+
## When the charter appears
|
|
10
|
+
|
|
11
|
+
| Moment | What happens | Who |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Session 13 Step 0.5 | Drafted from the session record into `docs/discovery/PROJECT-CHARTER.md`, `status: Draft`, `go_no_go: Pending` | `charter.md` § Draft |
|
|
14
|
+
| Session 13 topics 2–3 | Reviewed section by section; the Go / No-Go table is recorded in `session-13.md` and copied into § 17 | Session 13 |
|
|
15
|
+
| Session 13 Closing Step | `status: For sign-off`, `charter-check` exits 0, exports written, committed | `charter.md` § Finish |
|
|
16
|
+
| Signatures collected | `status` set from the § 19 rows: `Signed`, `Signed with conditions` or `Rejected`; version history row | operator, `charter.md` § Redraft |
|
|
17
|
+
| `/pp-discovery-to-build` Step 2 | `charter-check --require-signed` hard-blocks unless `Signed` or `Signed with conditions`; `--unsigned` records the gap instead | `handoff-gates.md` |
|
|
18
|
+
| any later version | § 20 row, `version` bump, `status: Draft`, exports regenerated | `charter.md` § Redraft |
|
|
19
|
+
|
|
20
|
+
**Write targets.** The charter and its exports are written under `docs/discovery/` only — relative
|
|
21
|
+
paths, no `..`, no absolute path — the same rule `docs/architecture/` follows for the architecture
|
|
22
|
+
deliverables (T-04-03 extended). Nothing under `.planning/` is a sign-off medium.
|
|
23
|
+
|
|
24
|
+
## Heading keys
|
|
25
|
+
|
|
26
|
+
Every section heading carries a key comment: `## 7. Deviations from standards <!-- charter:deviations -->`.
|
|
27
|
+
The check identifies sections by key, so headings, labels and prose can be rendered in the sprint
|
|
28
|
+
language while the shape stays verifiable. The keys, in the only order the check accepts:
|
|
29
|
+
|
|
30
|
+
| § | Key | English heading | Dutch heading |
|
|
31
|
+
|---|---|---|---|
|
|
32
|
+
| 1 | `purpose` | Purpose and background | Doel en achtergrond |
|
|
33
|
+
| 2 | `objectives` | Objectives and success measures | Doelstellingen en succesmaten |
|
|
34
|
+
| 3 | `scope` | Scope | Scope |
|
|
35
|
+
| 4 | `stakeholders` | Stakeholders and users | Belanghebbenden en gebruikers |
|
|
36
|
+
| 5 | `approvals` | Approvals and role holders | Goedkeuringen en rolhouders |
|
|
37
|
+
| 6 | `solution` | Solution overview | Oplossing in hoofdlijnen |
|
|
38
|
+
| 7 | `deviations` | Deviations from standards | Afwijkingen van de standaarden |
|
|
39
|
+
| 8 | `data` | Data | Gegevens |
|
|
40
|
+
| 9 | `quality` | Quality and acceptance | Kwaliteit en acceptatie |
|
|
41
|
+
| 10 | `validated` | What was validated | Wat is gevalideerd |
|
|
42
|
+
| 11 | `delivery` | Delivery plan | Opleverplan |
|
|
43
|
+
| 12 | `team` | Team and governance | Team en governance |
|
|
44
|
+
| 13 | `budget` | Budget, constraints and assumptions | Budget, randvoorwaarden en aannames |
|
|
45
|
+
| 14 | `risks` | Risks | Risico's |
|
|
46
|
+
| 15 | `open-items` | Open items | Open punten |
|
|
47
|
+
| 16 | `conditions` | Conditions | Voorwaarden |
|
|
48
|
+
| 17 | `go-no-go` | Go / No-Go recommendation | Go / No-Go-advies |
|
|
49
|
+
| 18 | `decisions` | Key decisions | Kernbesluiten |
|
|
50
|
+
| 19 | `sign-off` | Sign-off | Ondertekening |
|
|
51
|
+
| 20 | `history` | Version history | Versiegeschiedenis |
|
|
52
|
+
|
|
53
|
+
One more key marks a line, not a section: `<!-- charter:counts -->` on the requirement-counts line in
|
|
54
|
+
§ 3. Any other `charter:` key is a fault.
|
|
55
|
+
|
|
56
|
+
For a language not in this table, translate the headings and labels yourself and keep the keys; the
|
|
57
|
+
check does not read the heading text. Never translate: the frontmatter field names and values, the
|
|
58
|
+
key comments, and the enum cells — `status`, `go_no_go`, `Green` / `Amber` / `Red`, `Approve` /
|
|
59
|
+
`Approve with conditions` / `Reject`, `Yes` / `No` at the start of a *Must resolve before build?* cell.
|
|
60
|
+
Column order is fixed; column headings may be translated.
|
|
61
|
+
|
|
62
|
+
## Language resolution
|
|
63
|
+
|
|
64
|
+
1. Session 1 § Sprint Logistics, row **Charter language** — a BCP-47 code (`nl`, `en`, `nl-BE`).
|
|
65
|
+
2. Else `discovery.language` in `.planning/config.json` (`pp_run query config-get discovery.language --default "" --raw`).
|
|
66
|
+
3. Else the language the sprint was facilitated in (Flow 2 Step 5's rule).
|
|
67
|
+
|
|
68
|
+
The resolved code is written to the frontmatter `language` field. `und` is the template's placeholder
|
|
69
|
+
and is replaced at draft time.
|
|
70
|
+
|
|
71
|
+
## Parser contract — `pp_run query discovery.charter-check [--require-signed]`
|
|
72
|
+
|
|
73
|
+
The check takes no positional path: `docs/discovery/PROJECT-CHARTER.md` and every source under
|
|
74
|
+
`.planning/discovery/` resolve against the working directory. Faults are located by 1-based line and
|
|
75
|
+
carry a validated ID, a section key or a field name — never charter prose. Every row below names the
|
|
76
|
+
fault code emitted; a rule that is **not** mechanically checked says so.
|
|
77
|
+
|
|
78
|
+
| Field / cell | Grammar | Fault when violated |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| the file | present and readable at `docs/discovery/PROJECT-CHARTER.md` | `charter_missing` (absent — at Session 13 Step 0 this means "proceed to Step 0.5"; at the handoff it blocks unless `--unsigned`); `artifact_unreadable` (present, unreadable) |
|
|
81
|
+
| frontmatter | opens at line 1 with `---`, closes with `---` | `frontmatter_missing` |
|
|
82
|
+
| `document`, `project`, `client`, `version`, `status`, `date`, `language`, `discovery_sessions_completed`, `go_no_go` | each present and non-empty | `field_missing` naming the field |
|
|
83
|
+
| `document` | exactly `project-charter` | `bad_document` |
|
|
84
|
+
| `status` | `Draft` \| `For sign-off` \| `Signed` \| `Signed with conditions` \| `Rejected` | `bad_status` |
|
|
85
|
+
| `go_no_go` | `Pending` \| `Go` \| `Go with conditions` \| `No-Go` | `bad_go_no_go`; `go_no_go_pending` when `Pending` while `status` is not `Draft` |
|
|
86
|
+
| `version` | `<major>.<minor>` digits | `bad_version` (also for a § 20 row) |
|
|
87
|
+
| `date` | `YYYY-MM-DD` shape (`0000-00-00` passes — the placeholder the draft step replaces) | `bad_date` — the date is **not** parsed as a calendar date |
|
|
88
|
+
| `language` | BCP-47 shape: `nl`, `en`, `en-GB`, `und` | `bad_language` |
|
|
89
|
+
| `project`, `client`, `discovery_sessions_completed` | free | **not mechanically checked** beyond presence |
|
|
90
|
+
| section headings | each of the 20 keys on exactly one `## ` heading, in table order | `section_missing` (key), `section_duplicate` (key, at the repeat), `section_order` (the first key out of place), `section_unknown` (a `charter:` key that is not one of the 20 or `counts`, or a section key off a heading line) |
|
|
91
|
+
| tables | the row before a `\|---\|` separator is a header; data rows follow until a non-pipe line | `table_missing` for § 15, 16, 17, 19, 20, which the check reads; other sections' tables are **not required to exist** — an empty table with no rows satisfies the fixed shape |
|
|
92
|
+
| any ID in a table cell | `D-<ss>-<n>` and `A-<ss>-<n>` resolve against the first column of every table in `.planning/discovery/*.md`; `OI-`, `R-`, `CON-`, `SCR-`, `E-`, `US-`, `BO-`, `ADR-`, `IF-`, `CR-`, `RS-`, `DG-`, `DEV-` the same; a registered requirement prefix resolves against the rows of `_requirements.md` | `unknown_id` naming the token — also for a two-part ID in a one-part family or the reverse. A prefix in none of these families (`ISO-27001`) is **not checked**. Requirement IDs are **not checked** while `_requirements.md` is absent; § 20 is never scanned |
|
|
93
|
+
| § 3 counts line (`<!-- charter:counts -->`) | `<PREFIX>- <n>` for every registered prefix (rows with disposition `MVP` or `Later`), then `Dropped <n>`, separated by ` · ` | `counts_missing` (no marked line while `_requirements.md` exists), `counts_mismatch` (any count off, a prefix missing or extra). **Not checked** while `_requirements.md` is absent |
|
|
94
|
+
| dropped requirements | every `Dropped (D-ss-n)` row of `_requirements.md` is cited in a § 16 cell | `dropped_missing` naming the requirement |
|
|
95
|
+
| § 17 table | eight rows in Session 13's order; `Status` is the second column | `go_no_go_mismatch` — located `(rows)` when not eight; `(overall)` when the last row's status differs from `go_no_go`; `(row-n)` when a row's status differs from `session-13.md` § Go / No-Go Assessment; `(frontmatter)` when `go_no_go` differs from the session's overall recommendation. Compared only once the session's overall cell is filled; **not checked** while `session-13.md` is absent |
|
|
96
|
+
| § 16 vs Session 13 open items | every `session-13.md` § Open Items Register row whose *Must Resolve Before Build?* cell starts with `Yes` is either closed (its Status starts with `Closed`, `Resolved` or `Done`) or cited by `OI-` ID in a § 16 cell | `must_resolve_open` naming the item |
|
|
97
|
+
| § 19 `Decision` (third column) | empty, `Approve`, `Approve with conditions` or `Reject` | `bad_signoff_decision` |
|
|
98
|
+
| § 19 vs `status` | `Signed` ⇔ every row `Approve`; `Signed with conditions` ⇔ every row approves and at least one with conditions; `Rejected` ⇒ at least one `Reject`; `Draft` / `For sign-off` unconstrained | `signoff_status_mismatch` |
|
|
99
|
+
| § 20 table | at least one row; versions in `<major>.<minor>`; the last row's version equals the frontmatter `version` | `history_missing`, `bad_version`, `history_version_mismatch` |
|
|
100
|
+
| `_requirements.md` present but unparseable | the rollup grammar is owned by `discovery rollup` | `requirements_unparseable`, once — run `discovery rollup --check` for the detail; requirement IDs and counts are then not resolved |
|
|
101
|
+
| any source under `.planning/discovery/` that exists but cannot be read | present-and-readable | `artifact_unreadable` naming the path — an unreadable source is a fault, never a silent skip |
|
|
102
|
+
| `--require-signed` | `status` is `Signed` or `Signed with conditions` | `charter_unsigned`; when it is the only fault the exit identity is `discovery_charter_unsigned`, so the handoff can tell "unsigned" from "malformed" |
|
|
103
|
+
| prose, table cells other than IDs and enums | free text in the sprint language | **not mechanically checked** — never validated, never echoed |
|
|
104
|
+
|
|
105
|
+
**Posture (D-43 / D-53).** At Session 13 the check reports: an unsigned charter is not a fault, and a
|
|
106
|
+
`Draft` with `Pending` is the expected state before topic 3. The hard block lives at
|
|
107
|
+
`/pp-discovery-to-build` and nowhere else: `--require-signed` refuses `Draft`, `For sign-off` and
|
|
108
|
+
`Rejected`; `--unsigned` on the handoff lets the build start and records the gap in PROJECT.md and
|
|
109
|
+
STATE.md so nobody later mistakes it for a signed charter.
|
|
110
|
+
|
|
111
|
+
**§ 7 and `_deviations.md` (improvement plan, Batch 3).** A `DEV-` ID resolves against
|
|
112
|
+
`.planning/discovery/_deviations.md` alone — a `DEV-` in any other table is `unknown_id` — and every
|
|
113
|
+
`DEV-` row of that register appears in the § 7 table (`deviation_missing` naming the row); § 7 holds a
|
|
114
|
+
table even when empty (`table_missing`). Grammar of the register: `references/discovery-standards.md`.
|
|
115
|
+
|
|
116
|
+
**Exit identity.** `discovery_charter_check_failed` for structural faults; `discovery_charter_unsigned`
|
|
117
|
+
when the only fault is the signature requirement. The JSON payload (`ok`, `file`, `status`, `go_no_go`,
|
|
118
|
+
`version`, `language`, `sections`, `ids_checked`) is emitted before the error on both failure paths.
|
|
119
|
+
|
|
120
|
+
## Exports
|
|
121
|
+
|
|
122
|
+
`PROJECT-CHARTER.docx` and `PROJECT-CHARTER.pdf` are written next to the markdown by the `docx` and
|
|
123
|
+
`pdf` skills with the `pareto-brand` skill applied, every time the markdown changes (draft, for
|
|
124
|
+
sign-off, every later version). The markdown is the source; an export is never edited by hand and never
|
|
125
|
+
read back. When a skill is not installed, the draft step says so once, records
|
|
126
|
+
`export: skipped (<skill> unavailable)` in the § 20 row's Change cell, and continues — a missing
|
|
127
|
+
renderer never blocks the sprint. Exports are committed with the markdown.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Discovery Data Model — `_entities.md` Template & Parser Contract
|
|
2
|
+
|
|
3
|
+
Single home for the data model a build starts from: the `_entities.md` bootstrap template, its
|
|
4
|
+
cell grammar, and the `pp_run query discovery.entity-check` parser contract (Discovery Sprint
|
|
5
|
+
improvement plan, Batch 2). The handoff's ERD (`architecture-deliverables.md` § Data Model) is
|
|
6
|
+
drawn from this file and nothing else, so a cardinality it does not state is a gap in the
|
|
7
|
+
artifact, never a default. This file is Read lazily; it is never `@`-imported.
|
|
8
|
+
|
|
9
|
+
## When the file appears
|
|
10
|
+
|
|
11
|
+
| Session | Writes | From |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| 2 | creates the file from the template; one `## Entities` row per Data Entity Map row, Source `S2`, pending cells `—` | topic 5 Data flows and information architecture |
|
|
14
|
+
| 3 | names the objects each step touches in `_processes.md` § Steps (`Task [C]`); every name must be an entity, so Step 5C adds missing rows here with Source `S3` | Step 5C |
|
|
15
|
+
| 5 | **consolidates**: identifier, attribute table, relationships with cardinality, lifecycle states for every entity; `Status lifecycle` leaves `—` | topic 3 Key architectural components, § Domain Model / Entity Register |
|
|
16
|
+
| 6 | writes `Classification` (the vault's four levels) and `Retention` for every entity | § Data Classification Matrix |
|
|
17
|
+
| 8 | `entity-check` runs in the Closing Step (reporting) | Closing Step |
|
|
18
|
+
| 13 | `entity-check` runs in the Step 0 gates (reporting) | `session-13-gates.md` |
|
|
19
|
+
| handoff | `entity-check --require-complete` hard-blocks: no `—` left, every entity has attributes | `handoff-gates.md` |
|
|
20
|
+
|
|
21
|
+
**Entities are named, never numbered** (Batch 2 decision). An entity is cited by its name, exactly
|
|
22
|
+
as the `## Entities` table spells it — in step matrices, in `_rules.md`, in the charter. Nothing is
|
|
23
|
+
deleted or renamed: an entity that turns out not to exist keeps its row with its reason in `Notes`
|
|
24
|
+
and `Retention` `—`, exactly as a dropped requirement keeps its row.
|
|
25
|
+
|
|
26
|
+
## Shared grammar
|
|
27
|
+
|
|
28
|
+
- **Closed cells and free-text cells are not the same kind of cell** (`discovery-traceability.md`
|
|
29
|
+
§ Shared grammar). The parser-contract table below says which is which; a free-text cell is never
|
|
30
|
+
validated and never echoed.
|
|
31
|
+
- **`—` is "not yet known"**, allowed in `Identifier`, `Status lifecycle`, `Classification`,
|
|
32
|
+
`Retention`, and in an attribute's `Type` and `Required`, while the sprint runs; refused by
|
|
33
|
+
`--require-complete` at the handoff. Never write a guessed `yes` where `—` is the truth: the gate
|
|
34
|
+
can only name a gap it can see. An empty cell
|
|
35
|
+
is never allowed where `—` is: write the dash.
|
|
36
|
+
- **Cardinality is Mermaid's**, so the ERD copies it: a left end `||` (exactly one), `|o` (zero or
|
|
37
|
+
one), `}o` (zero or more), `}|` (one or more); a line `--` (identifying) or `..` (non-identifying);
|
|
38
|
+
a right end `||`, `o|`, `o{`, `|{`. `||--o{` reads "one From has zero or more To". The line is
|
|
39
|
+
`--` when the relationship is carried by a foreign key and `..` when it is a reference by ID
|
|
40
|
+
without a key (an audit entry that outlives its subject). Inside a
|
|
41
|
+
markdown table cell every pipe is escaped — write `\|\|--o{` — or the row splits into the wrong
|
|
42
|
+
columns; the check unescapes before it validates.
|
|
43
|
+
- **Classification is the vault's** (`security/compliance.md` § Information handling): `Public`,
|
|
44
|
+
`Internal`, `Confidential`, `Restricted`. A data store takes the highest level of any data in it.
|
|
45
|
+
- **A data object in a step matrix is `Name [C/R/U/D]`** — the entity name, a space, and the CRUD
|
|
46
|
+
letters touched, slash-separated inside brackets: `Task [C]`, `Membership [C/R/U]`. Several are
|
|
47
|
+
comma-separated; `—` when the step touches none. Only entities of the product being built are
|
|
48
|
+
data objects: a file, a pull request, a pipeline run or a document of another system belongs in
|
|
49
|
+
the `Integration` column (with its direction) or in the step text, never in `Data objects`.
|
|
50
|
+
|
|
51
|
+
Illustration only — these rows are **not** part of the template below, and the names are invented:
|
|
52
|
+
|
|
53
|
+
| Entity | Identifier | Status lifecycle | Classification | Retention | Owner module | Source |
|
|
54
|
+
|---|---|---|---|---|---|---|
|
|
55
|
+
| Task | `id` GUID, app-generated | yes | Internal | 2 years after done (D-06-3) | Tasks | S2 |
|
|
56
|
+
| Membership | (`team_id`, `user_id`) | none | Confidential | Ends when the member leaves (F-14) | Teams | S3 |
|
|
57
|
+
|
|
58
|
+
| From | Cardinality | To | Name |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| Team | \|\|--o{ | Membership | has |
|
|
61
|
+
|
|
62
|
+
**Template verbatim-safety rule.** The fenced template carries the title, the conventions line, the
|
|
63
|
+
four section headings and the table headers with their separator rows — and **no example rows**.
|
|
64
|
+
Copying it verbatim into a new discovery package passes `entity-check` cleanly, and a test proves it
|
|
65
|
+
by executing it.
|
|
66
|
+
|
|
67
|
+
Bootstrap template — Session 2 copies it verbatim to `.planning/discovery/_entities.md`, replacing
|
|
68
|
+
`[PROJECT_NAME]`:
|
|
69
|
+
|
|
70
|
+
```markdown
|
|
71
|
+
# Data Model — [PROJECT_NAME]
|
|
72
|
+
|
|
73
|
+
**Conventions:** pp-core reference `references/discovery-data-model.md`. Entities are named, never numbered, and cited exactly as spelled below. `—` means not yet known; nothing is deleted or renamed. A change after sign-off edits the row in place and appends `→ amended by D-<ss>-<n>` (`references/discovery-id-conventions.md` § Precedence).
|
|
74
|
+
|
|
75
|
+
## Entities
|
|
76
|
+
|
|
77
|
+
| Entity | Identifier | Status lifecycle | Classification | Retention | Owner module | Source |
|
|
78
|
+
|--------|------------|------------------|----------------|-----------|--------------|--------|
|
|
79
|
+
|
|
80
|
+
## Attributes
|
|
81
|
+
|
|
82
|
+
## Relationships
|
|
83
|
+
|
|
84
|
+
| From | Cardinality | To | Name |
|
|
85
|
+
|------|-------------|----|------|
|
|
86
|
+
|
|
87
|
+
## Lifecycles
|
|
88
|
+
|
|
89
|
+
| Entity | State | Transition | Allowed by |
|
|
90
|
+
|--------|-------|------------|------------|
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Under `## Attributes`, Session 5 adds one `### <Entity>` heading per entity with this table:
|
|
94
|
+
|
|
95
|
+
```markdown
|
|
96
|
+
### Task
|
|
97
|
+
|
|
98
|
+
| Attribute | Type | Required | Bounds | Notes |
|
|
99
|
+
|-----------|------|----------|--------|-------|
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Parser contract — `pp_run query discovery.entity-check [--require-complete]`
|
|
103
|
+
|
|
104
|
+
No positional path: `.planning/discovery/_entities.md` and `_processes.md` resolve against the
|
|
105
|
+
working directory. Faults name the artifact, the 1-based line, a validated entity name, a section
|
|
106
|
+
or column name and the reason code — never cell prose. An absent `_entities.md` exits 0 with
|
|
107
|
+
`present: false` (an engagement that predates the data model).
|
|
108
|
+
|
|
109
|
+
| Cell / field | Grammar | Fault when violated |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| `## Entities`, `## Attributes`, `## Relationships`, `## Lifecycles` | each present once as a `##` heading; Entities, Relationships and Lifecycles hold one table | `missing_section` naming the section (also when the heading exists but its table is absent) |
|
|
112
|
+
| table headers | the template's columns, in order (case-insensitive) | `bad_table_shape` naming the section, or `Attributes · <Entity>` |
|
|
113
|
+
| `Entity` | `^[A-Z][A-Za-z0-9]*$` — one PascalCase token — unique in the table | `bad_entity_name` (the cell is not echoed), `duplicate_entity` |
|
|
114
|
+
| `Identifier` | non-empty; `—` while pending | `empty_cell (<Entity> · Identifier)`; `incomplete_cell` under `--require-complete` |
|
|
115
|
+
| `Status lifecycle` | `none` \| `yes` \| `—` | `bad_lifecycle_flag`; `yes` without a `## Lifecycles` row → `lifecycle_without_states`; `none` with one → `states_without_lifecycle`; `—` → `incomplete_cell` under `--require-complete` |
|
|
116
|
+
| `Classification` | `Public` \| `Internal` \| `Confidential` \| `Restricted` \| `—` | `bad_classification`; `—` → `incomplete_cell` under `--require-complete` |
|
|
117
|
+
| `Retention` | free text, non-empty; `—` while pending | `empty_cell`; `—` → `incomplete_cell` under `--require-complete`. The text is **not mechanically checked** |
|
|
118
|
+
| `Owner module`, `Source` | free text | **not mechanically checked** |
|
|
119
|
+
| `### <Entity>` under Attributes | names a row of `## Entities`; holds the attribute table | `unknown_entity`; `bad_table_shape (Attributes · <Entity>)` |
|
|
120
|
+
| an entity with no attribute row | every entity has at least one attribute by Session 5 | `attributes_missing` under `--require-complete` only |
|
|
121
|
+
| `Attribute`, `Type` | non-empty; `Type` may be `—` while pending | `empty_cell (<Entity> · Attribute)`; a `—` Type → `incomplete_cell (<Entity> · <attribute> · Type)` under `--require-complete` |
|
|
122
|
+
| `Required` | `yes` \| `no` \| `—` | `bad_required`; `—` → `incomplete_cell (<Entity> · <attribute> · Required)` under `--require-complete` |
|
|
123
|
+
| `Bounds`, `Notes` | free text | **not mechanically checked** |
|
|
124
|
+
| `From`, `To` | entity names from `## Entities` | `unknown_entity` |
|
|
125
|
+
| `Cardinality` | `^(\|\||\|o|\}o|\}\|)(--|\.\.)(\|\||o\||o\{|\|\{)$` | `bad_cardinality` |
|
|
126
|
+
| relationship `Name` | free text | **not mechanically checked** |
|
|
127
|
+
| Lifecycles `Entity` | an entity name | `unknown_entity` |
|
|
128
|
+
| Lifecycles `State` | non-empty | `empty_cell (<Entity> · State)` |
|
|
129
|
+
| Lifecycles `Transition`, `Allowed by` | free text | **not mechanically checked** |
|
|
130
|
+
| `_processes.md` § Steps `Data objects` | every well-formed `Name [C/R/U/D]` token names an entity | `unknown_entity` located in `_processes.md`; a malformed token is `process-check`'s `bad_data_object`, not reported here |
|
|
131
|
+
| `_processes.md` present but unreadable | present-and-readable | `artifact_unreadable` |
|
|
132
|
+
|
|
133
|
+
**Exit identity.** `discovery_entity_check_failed` for structural faults;
|
|
134
|
+
`discovery_entity_check_incomplete` when every fault is an `incomplete_cell` or `attributes_missing`
|
|
135
|
+
raised by `--require-complete`, so a gate can tell "not finished" from "malformed". The payload
|
|
136
|
+
(`ok`, `present`, `file`, `entities`, `attributes`, `relationships`, `lifecycles`,
|
|
137
|
+
`step_objects_checked`) is emitted before the error on the failure path.
|
|
138
|
+
|
|
139
|
+
## How the handoff draws from it
|
|
140
|
+
|
|
141
|
+
`architecture-deliverables.md` § Data Model emits one `erDiagram` entity block per `## Entities` row
|
|
142
|
+
with its attributes (`type name`), and one relationship line per `## Relationships` row with the
|
|
143
|
+
cardinality verbatim. There is no default cardinality any more: a relationship this file does not
|
|
144
|
+
state is not drawn, and the prose says `[not captured in Discovery]`. An engagement without
|
|
145
|
+
`_entities.md` falls back to Session 5's register under the same rule.
|