@prodshape/integration-openspec 0.5.2 → 0.6.0-alpha.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/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # @prodshape/integration-openspec
2
+
3
+ OpenSpec integration for Product Definition as Code (PDaC), in two lanes: a citation lane that grounds OpenSpec's spec-driven delivery workflow in the accepted product model, and a product lane that hosts the PDaC product workflow inside OpenSpec itself.
4
+
5
+ Both lanes write only official OpenSpec surfaces (`openspec/config.yaml`, `openspec/schemas/product/`) plus ProductShape's own integration metadata (`.product/integrations/openspec.json`). The integration never patches OpenSpec-generated commands or skills, never modifies OpenSpec's built-in schemas, and never writes into a native spec-driven change's documents. Every write is byte-gated and ownership-proven per file: metadata paths are validated and confined to `openspec/schemas/product/`; `prodshape integration add openspec` collides on every pre-existing unrecorded target, even when byte-identical; `update` replaces or removes only content whose recorded digest still proves ownership, including obsolete assets; and `remove` deletes only recorded, proven-managed files while preserving and reporting unrecorded or hand-edited ones. With no recorded product schema it touches nothing under `openspec/schemas/`. Dry runs report exactly what the real operation would do.
6
+
7
+ ## The citation lane (delivery)
8
+
9
+ The integration merges PDaC authority context and citation rules into `openspec/config.yaml` and installs a CI-ready verification example. Spec-driven OpenSpec documents cite canonical product artifacts by id and sha256 digest; `prodshape citations verify --provider openspec` resolves every citation against the model and enforces the scope-declaration population contract. A spec-driven delivery change never edits `docs/product/model`.
10
+
11
+ ## The product lane (the hosted product workflow)
12
+
13
+ The integration installs a project-local OpenSpec schema named `product` at `openspec/schemas/product/`. An OpenSpec change created with that schema hosts a PDaC Product Change: the normative semantic delta (`product/change.md` plus `product/proposed/**`) against the accepted model in `docs/product/model`, which stays the only source of product truth.
14
+
15
+ The schema pin is a load-bearing, enforced invariant: the rail accepts only one folder-safe OpenSpec 1.11 change name and validates the complete OpenSpec 1.11 metadata shape in `.openspec.yaml`, not merely the presence of a schema string. It treats a change as a product change only when that valid metadata pins `schema: product`. A change pinned to another schema never lists, validates, applies or enters concurrency, however product-shaped its contents look. A product-shaped container with missing or malformed metadata stops listing and concurrency with a clear error instead of disappearing from the live-change set.
16
+
17
+ The primary workflow is OpenSpec's own:
18
+
19
+ ```text
20
+ /opsx:new <change> --schema product
21
+ |
22
+ /opsx:continue (or /opsx:ff) authors proposal.md, then product/change.md + product/proposed/**
23
+ |
24
+ /opsx:apply <change> follows the schema's apply instruction
25
+ |
26
+ /opsx:archive <change> a separate action after successful apply and verification
27
+ ```
28
+
29
+ Apply and archive are separate lifecycle operations. The schema's apply instruction delegates the deterministic write to this package's apply rail through the installed bridge script:
30
+
31
+ ```text
32
+ node openspec/schemas/product/scripts/product-apply.mjs --change <name> [--dry-run]
33
+ ```
34
+
35
+ The bridge resolves the locally installed `@prodshape/integration-openspec` and calls `applyOpenSpecProductChange`, which re-reads the accepted model and revalidates everything at apply time: the configuration, the baseline itself (including per-document load diagnostics of artifacts the change never touches) and the hosted delta as an overlay; a prior validate call is never trusted. Any blocking diagnostic refuses before any write, with the model and the change container byte-identical. It enforces base-revision drift (PRODUCT027) and the apply-authorised state (PRODUCT028, whose hosted message states the protocol requirement without pretending to verify the actor), writes the delta into the model named by lowercase id, reports the product diff computed from the result, and flips the hosted change.md status to applied in place. It never commits and never archives; `openspec archive` moves the change container afterwards and never touches the model. A preflight bridge exists beside it (`product-validate.mjs`) for explicit overlay validation at any point.
36
+
37
+ Validation is mandatory; authorisation policy is outside the deterministic rail. `status: approved` in the hosted change.md is the apply-authorised protocol state. ProductShape's accepted policy requires human product approval before that state is recorded; the integration verifies the state but cannot identify or judge the actor, and it never performs the transition. Merging the resulting baseline also remains a human decision.
38
+
39
+ Product-semantic clarification happens before the delta. While authoring the intent, the schema asks the agent to identify wording that admits materially different observable outcomes, present those alternatives to the user and stop. An unresolved decision must remain visible under `Open Questions for the Product Owner`; the agent must not choose an outcome, author the delta or seek approval merely to advance the artifact graph. The deterministic rail validates structure and semantics it can prove, but it cannot infer that a human-facing request was ambiguous. `proposal.md` cites the accepted model it consumes; `product/change.md` and `product/proposed/**` carry no citations or scope declarations, and only the proposed artifacts can be materialized into the accepted model.
40
+
41
+ ### Requirements
42
+
43
+ - OpenSpec >= 1.7.0 for the product workflow (`skip_specs` change metadata, declaration-order artifacts, schema-agnostic skill instructions). The schema files install under any supported OpenSpec (>= 1.0.0) and are inert data below the floor: `prodshape doctor` then reports the product workflow UNAVAILABLE while the citation lane keeps working.
44
+ - `@prodshape/integration-openspec` installed locally (`npm install --save-dev @prodshape/integration-openspec`). The ProductShape CLI bundles this package for its own commands, so a CLI-only installation does not put it in `node_modules`; the bridge scripts need the package resolvable from the repository and say so when it is not. This documented installation is proven end to end by the packed-consumer suite, which installs the packed tarballs into a fresh repository and runs the bridge scripts by bare specifier with no override.
45
+ - `@prodshape/cli` available locally for the authoring capabilities the schema instructions name (`prodshape inspect`, `prodshape impact`, `prodshape template <kind>`, `prodshape validate`).
46
+
47
+ ## Library API
48
+
49
+ The deterministic rails are exported for wrappers, tests and custom callers; the bridge scripts are thin argument parsers over them.
50
+
51
+ ```ts
52
+ import {
53
+ inspectProductModel, // accepted model + in-memory graph + diagnostics
54
+ listOpenSpecProductChanges, // OpenSpec changes hosting product/change.md
55
+ loadOpenSpecProductChange,
56
+ validateOpenSpecProductChange, // overlay validation; concurrency spans both containers
57
+ applyOpenSpecProductChange, // revalidates at apply time; fail closed; never archives
58
+ deriveDeliveryContext, // fresh post-apply context for a future delivery workflow
59
+ } from '@prodshape/integration-openspec';
60
+ ```
61
+
62
+ Concurrency (PRODUCT025) spans both change containers: a hosted OpenSpec product change and a native change under `docs/product/changes/active` touching the same artifact report against each other.
63
+
64
+ The citation-lane surface (`addOpenSpecIntegration`, `updateOpenSpecIntegration`, `checkOpenSpecIntegration`, `removeOpenSpecIntegration`, `bootstrapOpenSpecWorkspace`, the population provider) is unchanged and documented in the module source.
@@ -0,0 +1,120 @@
1
+ # MANAGED FILE. Installed by `prodshape integration add openspec` and regenerated by
2
+ # `prodshape integration update`. Hand edits are reported by `prodshape doctor` and replaced
3
+ # on the next update; remove the integration to take the schema out.
4
+ name: product
5
+ version: 1
6
+ description: >-
7
+ PDaC product workflow hosted in OpenSpec: requested product intent becomes a Product Change delta against the accepted model in docs/product/model, deterministically validated as an overlay, then applied by the PDaC integration only for a change in the apply-authorised state. Requires OpenSpec >= 1.7.0. This schema changes product meaning only; implementation work belongs to a separate spec-driven change.
8
+ artifacts:
9
+ - id: intent
10
+ generates: proposal.md
11
+ description: Requested product intent, grounded in the accepted product model
12
+ template: proposal.md
13
+ instruction: |
14
+ Capture WHY the product definition should change, before any delta exists.
15
+
16
+ Ground the intent in the accepted model:
17
+ 1. Read the accepted Product Definition (docs/product/model unless .product/config.yaml moves product-root).
18
+ Never treat proposals, archived changes or OpenSpec documents as product truth.
19
+ 2. Compare the request with the whole definition, then widen through the product graph:
20
+ for every artifact the request depends on, alters or contradicts, inspect its neighbours and impact.
21
+ The repository's ProductShape tooling provides this deterministically: `prodshape inspect <ID>` and
22
+ `prodshape impact <ID>` resolve the locally installed @prodshape/cli. Install the CLI locally
23
+ (a devDependency counts) rather than relying on network resolution.
24
+ 3. List every impacted artifact in the proposal and name any neighbour you checked and left out.
25
+ 4. Cite the artifacts the intent stands on: read the digest with `prodshape inspect <ID>`, emit the
26
+ payload with `prodshape cite --id <ID> --digest <digest>`, and wrap it in an HTML comment on its
27
+ own line. Declare the document scope: `pdac-scope: cited` when the proposal carries citations, or
28
+ `pdac-scope: none` with a non-empty human reason when no product text is involved.
29
+
30
+ Before declaring the intent ready, actively look for wording that permits materially different
31
+ product outcomes. Compare those alternatives in product-observable terms. When the accepted model
32
+ and the request do not select one outcome, put the alternatives under "Open Questions for the
33
+ Product Owner", ask the user for the missing decision, and STOP before authoring the delta. Never
34
+ silently select, combine or narrow product meaning on the user's behalf. `None.` is appropriate only
35
+ after this ambiguity pass finds no unresolved decision that would change product behaviour, scope,
36
+ policy or acceptance.
37
+
38
+ Decide the outcome honestly. When the request changes no product meaning (tooling, refactoring,
39
+ delivery-only work), record that verdict under the "No product delta" heading and STOP: do not
40
+ author a delta artifact and do not invent product change to satisfy the workflow. Otherwise state
41
+ the intended product outcome in product language, not implementation language.
42
+ requires: []
43
+
44
+ - id: delta
45
+ generates: 'product/**/*.md'
46
+ description: The PDaC Product Change delta, change.md plus the complete proposed future state
47
+ template: change.md
48
+ instruction: |
49
+ Author the PDaC Product Change under product/ in this change directory: product/change.md plus
50
+ product/proposed/** holding the COMPLETE future state of every artifact the change adds or
51
+ modifies, laid out exactly as it will live in the model (actors/, journeys/, use-cases/,
52
+ business-rules/, behaviours/, domain/terms/, domain/bounded-contexts/, requirements/functional/,
53
+ requirements/quality/, requirements/constraints/), each file named <lowercase-id>.md.
54
+
55
+ Rules that make the delta valid:
56
+ - Re-read the intent's "Open Questions for the Product Owner" before writing. Do not author or
57
+ complete the delta while any product-semantic question remains unresolved: ask the user and stop.
58
+ Never choose a product outcome on the user's behalf. Carry the user's answer into one unambiguous
59
+ intended outcome; do not merely delete the question.
60
+ - change.md frontmatter carries id (CHG-...), type: product-change, title, status: draft,
61
+ base-revision (the commit the change was authored against, `git rev-parse --short HEAD`, quoted),
62
+ and operations with all three keys add, modify and remove. The body carries seven sections in
63
+ order: Problem, Intended Product Outcome, Rationale, Affected Product Areas, Open Questions,
64
+ Product Acceptance, Out of Scope.
65
+ - product/change.md is a change manifest, not a consumer document. Never add PDaC citations or a
66
+ pdac-scope declaration to it or to product/proposed/**. Citations belong in proposal.md and other
67
+ documents that consume the accepted model; proposed artifacts use typed PDaC relationships.
68
+ - Preserve stable IDs: evolve an existing artifact by listing its EXISTING id under
69
+ operations.modify, never by adding a near duplicate under a new id. Create only the artifacts
70
+ the intent requires.
71
+ - Every id in operations.add and operations.modify has a complete proposed artifact under
72
+ product/proposed/; nothing else appears there. Removals list existing ids and ship no files.
73
+ - Use the exact current PDaC formats. `prodshape template <kind>` prints the authoring template
74
+ for every kind (actor, journey, use-case, business-rule, domain-term, bounded-context,
75
+ functional-requirement, quality-requirement, constraint, structured-behaviour); it resolves the
76
+ locally installed @prodshape/cli.
77
+ - Keep typed relationships resolvable: primary-actor, steps[].use-case, bounded-context,
78
+ governed-by, uses-terms, applies-to, defined-in, derived-from, illustrates and
79
+ verification[].scenario-ref must point at ids that exist in the baseline or in this delta.
80
+ - Stay in product semantics: no file paths, package names or implementation detail inside product
81
+ artifacts. Add a structured-behaviour only where it clarifies observable product behaviour
82
+ (given/when/then in frontmatter, Intent and Boundaries body sections).
83
+ - Leave status: draft while authoring. Status approved records human product approval under
84
+ ProductShape's accepted policy; that decision happens outside this artifact, and neither
85
+ this workflow nor the integration grants it.
86
+ - Never edit docs/product/model directly; the accepted model changes only through the
87
+ deterministic apply of this change.
88
+
89
+ Preflight is available at any time:
90
+ `node openspec/schemas/product/scripts/product-validate.mjs --change <change-name>` validates the
91
+ accepted baseline plus this delta as an overlay without touching either.
92
+ requires:
93
+ - intent
94
+
95
+ apply:
96
+ requires:
97
+ - delta
98
+ instruction: |
99
+ Apply materializes the approved delta into docs/product/model. It is never implicit, never a
100
+ commit and never an archive.
101
+
102
+ 1. Confirm the change is in the apply-authorised state: product/change.md carries
103
+ status: approved. That protocol state is required for apply (PRODUCT028 otherwise); the
104
+ integration checks only that protocol state. ProductShape's accepted policy requires human
105
+ product approval; neither this workflow nor the integration grants, infers or judges it.
106
+ Before asking for or recording that state, confirm there are no unresolved product-semantic questions
107
+ in either the intent or the delta. `status: approved` must not be recorded merely to make apply proceed.
108
+ 2. Run the deterministic apply through the PDaC integration, dry run first:
109
+ `node openspec/schemas/product/scripts/product-apply.mjs --change <change-name> --dry-run`
110
+ then without --dry-run. The script resolves the locally installed
111
+ @prodshape/integration-openspec and calls its apply rail, which re-reads the accepted model,
112
+ revalidates this delta as an overlay at apply time, refuses on any blocking diagnostic with
113
+ docs/product/model untouched, enforces base-revision drift (PRODUCT027) and the
114
+ apply-authorised state (PRODUCT028), writes the delta into the model, reports the product diff
115
+ computed from the result and flips this change's status to applied in place.
116
+ 3. Re-read docs/product/model and validate the resulting accepted model: `prodshape validate` must
117
+ report zero errors. Refresh any citations the reported diff made stale.
118
+ 4. STOP. Do not archive this change as part of apply: archiving is a separate OpenSpec action
119
+ performed after successful Product apply and verification. Do not implement delivery work, do
120
+ not modify implementation code and never edit docs/product/model by hand.
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+ // MANAGED FILE. Installed by `prodshape integration add openspec` as part of the OpenSpec product
3
+ // schema. The executable bridge from the schema's apply instruction to the deterministic apply
4
+ // rail: the apply logic lives in @prodshape/integration-openspec (applyOpenSpecProductChange);
5
+ // this script only resolves the local installation, invokes it and reports. It revalidates the
6
+ // overlay at apply time, refuses with the model untouched on any blocking diagnostic, requires
7
+ // the apply-authorised state (status: approved) and never archives the change.
8
+ import { dirname, resolve } from 'node:path';
9
+ import { fileURLToPath, pathToFileURL } from 'node:url';
10
+ import process from 'node:process';
11
+
12
+ const scriptDir = dirname(fileURLToPath(import.meta.url));
13
+ // openspec/schemas/product/scripts sits four levels below the repository root.
14
+ const defaultRoot = resolve(scriptDir, '..', '..', '..', '..');
15
+
16
+ function usage(message) {
17
+ console.error(message);
18
+ console.error(
19
+ 'Usage: node openspec/schemas/product/scripts/product-apply.mjs --change <name> [--dry-run] [--root <dir>]',
20
+ );
21
+ process.exit(2);
22
+ }
23
+
24
+ function parseArgs(argv) {
25
+ const args = { change: undefined, root: undefined, dryRun: false };
26
+ for (let i = 0; i < argv.length; i += 1) {
27
+ const arg = argv[i];
28
+ if (arg === '--change') {
29
+ args.change = argv[(i += 1)];
30
+ } else if (arg === '--root') {
31
+ args.root = argv[(i += 1)];
32
+ } else if (arg === '--dry-run') {
33
+ args.dryRun = true;
34
+ } else {
35
+ usage(`Unknown argument: ${arg}`);
36
+ }
37
+ }
38
+ if (!args.change) usage('Missing --change <name>.');
39
+ return args;
40
+ }
41
+
42
+ async function loadIntegration() {
43
+ const override = process.env.PRODSHAPE_INTEGRATION_OPENSPEC_ENTRY;
44
+ if (override) {
45
+ const url = override.startsWith('file:') ? override : pathToFileURL(resolve(override)).href;
46
+ return import(url);
47
+ }
48
+ try {
49
+ return await import('@prodshape/integration-openspec');
50
+ } catch (error) {
51
+ console.error('Could not resolve @prodshape/integration-openspec from this repository.');
52
+ console.error('The product workflow bridge needs the integration package installed locally:');
53
+ console.error(' npm install --save-dev @prodshape/integration-openspec');
54
+ console.error(error instanceof Error ? error.message : String(error));
55
+ process.exit(2);
56
+ }
57
+ }
58
+
59
+ function printDiagnostics(diagnostics) {
60
+ for (const diagnostic of diagnostics) {
61
+ const attrs = ['artifact', 'change', 'field', 'target', 'line', 'entry']
62
+ .filter((key) => diagnostic[key] !== undefined)
63
+ .map((key) => `${key}=${diagnostic[key]}`)
64
+ .join(' ');
65
+ console.log(
66
+ `${diagnostic.severity} ${diagnostic.code} ${diagnostic.file}${attrs ? ` ${attrs}` : ''}: ${diagnostic.message}`,
67
+ );
68
+ }
69
+ }
70
+
71
+ const args = parseArgs(process.argv.slice(2));
72
+ const repoRoot = args.root ? resolve(args.root) : defaultRoot;
73
+ const integration = await loadIntegration();
74
+ const result = await integration.applyOpenSpecProductChange(repoRoot, args.change, {
75
+ dryRun: args.dryRun,
76
+ });
77
+ printDiagnostics(result.plan.diagnostics);
78
+ if (result.outcome === 'refused') {
79
+ console.log('Apply refused; docs/product/model untouched.');
80
+ process.exit(1);
81
+ }
82
+ for (const action of result.plan.actions) {
83
+ console.log(`${action.kind}: ${action.description}`);
84
+ }
85
+ const { added, modified, removed } = result.plan.diff;
86
+ console.log(
87
+ `Product diff: ${added.length} added, ${modified.length} modified, ${removed.length} removed.`,
88
+ );
89
+ if (result.outcome === 'dry-run') {
90
+ console.log('Dry run; nothing was written.');
91
+ process.exit(0);
92
+ }
93
+ const resultingErrors = (result.resultingModel?.diagnostics ?? []).filter(
94
+ (diagnostic) => diagnostic.severity === 'error',
95
+ );
96
+ if (resultingErrors.length > 0) {
97
+ printDiagnostics(resultingErrors);
98
+ console.log(
99
+ 'Applied, but the resulting accepted model reports errors. Investigate before archiving.',
100
+ );
101
+ process.exit(1);
102
+ }
103
+ console.log(
104
+ 'Applied. Nothing was committed and the change was not archived: verify the model, then archive separately.',
105
+ );
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ // MANAGED FILE. Installed by `prodshape integration add openspec` as part of the OpenSpec product
3
+ // schema. Deterministic overlay preflight for a hosted Product Change: the validation logic lives
4
+ // in @prodshape/integration-openspec; this script only resolves the local installation, invokes it
5
+ // and reports. It writes nothing.
6
+ import { dirname, resolve } from 'node:path';
7
+ import { fileURLToPath, pathToFileURL } from 'node:url';
8
+ import process from 'node:process';
9
+
10
+ const scriptDir = dirname(fileURLToPath(import.meta.url));
11
+ // openspec/schemas/product/scripts sits four levels below the repository root.
12
+ const defaultRoot = resolve(scriptDir, '..', '..', '..', '..');
13
+
14
+ function usage(message) {
15
+ console.error(message);
16
+ console.error(
17
+ 'Usage: node openspec/schemas/product/scripts/product-validate.mjs --change <name> [--root <dir>]',
18
+ );
19
+ process.exit(2);
20
+ }
21
+
22
+ function parseArgs(argv) {
23
+ const args = { change: undefined, root: undefined };
24
+ for (let i = 0; i < argv.length; i += 1) {
25
+ const arg = argv[i];
26
+ if (arg === '--change') {
27
+ args.change = argv[(i += 1)];
28
+ } else if (arg === '--root') {
29
+ args.root = argv[(i += 1)];
30
+ } else {
31
+ usage(`Unknown argument: ${arg}`);
32
+ }
33
+ }
34
+ if (!args.change) usage('Missing --change <name>.');
35
+ return args;
36
+ }
37
+
38
+ async function loadIntegration() {
39
+ const override = process.env.PRODSHAPE_INTEGRATION_OPENSPEC_ENTRY;
40
+ if (override) {
41
+ const url = override.startsWith('file:') ? override : pathToFileURL(resolve(override)).href;
42
+ return import(url);
43
+ }
44
+ try {
45
+ return await import('@prodshape/integration-openspec');
46
+ } catch (error) {
47
+ console.error('Could not resolve @prodshape/integration-openspec from this repository.');
48
+ console.error('The product workflow bridge needs the integration package installed locally:');
49
+ console.error(' npm install --save-dev @prodshape/integration-openspec');
50
+ console.error(error instanceof Error ? error.message : String(error));
51
+ process.exit(2);
52
+ }
53
+ }
54
+
55
+ function printDiagnostics(diagnostics) {
56
+ for (const diagnostic of diagnostics) {
57
+ const attrs = ['artifact', 'change', 'field', 'target', 'line', 'entry']
58
+ .filter((key) => diagnostic[key] !== undefined)
59
+ .map((key) => `${key}=${diagnostic[key]}`)
60
+ .join(' ');
61
+ console.log(
62
+ `${diagnostic.severity} ${diagnostic.code} ${diagnostic.file}${attrs ? ` ${attrs}` : ''}: ${diagnostic.message}`,
63
+ );
64
+ }
65
+ }
66
+
67
+ const args = parseArgs(process.argv.slice(2));
68
+ const repoRoot = args.root ? resolve(args.root) : defaultRoot;
69
+ const integration = await loadIntegration();
70
+ const result = await integration.validateOpenSpecProductChange(repoRoot, args.change);
71
+ printDiagnostics(result.diagnostics);
72
+ if (result.blocking.length > 0) {
73
+ const count = result.blocking.length;
74
+ console.log(`Overlay validation: FAIL (${count} blocking diagnostic${count === 1 ? '' : 's'}).`);
75
+ process.exit(1);
76
+ }
77
+ console.log('Overlay validation: PASS.');
@@ -0,0 +1,49 @@
1
+ ---
2
+ id: CHG-EXAMPLE-001
3
+ type: product-change
4
+ title: Example product change
5
+ status: draft
6
+ base-revision: '3f2a91c'
7
+ operations:
8
+ add:
9
+ - FR-EXAMPLE-001
10
+ modify:
11
+ - UC-EXAMPLE-001
12
+ remove: []
13
+ ---
14
+
15
+ This file lives at `product/change.md` inside the OpenSpec change directory, and the proposed future state lives beside it under `product/proposed/**`, laid out exactly as it will live in `docs/product/model` with files named by lowercase id.
16
+
17
+ This manifest and every artifact under `product/proposed/**` are Product Definition content, not consumer documents. Do not add `pdac-scope` declarations or PDaC citations here. Proposed artifacts express their internal connections through typed PDaC relationships; citations remain in `proposal.md` and other documents that consume the accepted model.
18
+
19
+ Every ID under `operations.add` and `operations.modify` needs a complete proposed artifact under `product/proposed/`. Author each artifact from its current PDaC template (`prodshape template <kind>`). Set `base-revision` to the baseline commit this change was authored against, quoted so YAML reads an all-digit revision as a string.
20
+
21
+ Leave `status: draft` while authoring; `status: approved` is the apply-authorised protocol state and setting it is the caller's authorisation act, outside this workflow. Apply materializes the proposal into the accepted model on a working branch; it never archives this change, and a pull-request merge accepts the resulting baseline. Product Change status never records implementation, verification, release or deployment.
22
+
23
+ ## Problem
24
+
25
+ What is wrong or missing in the current Product Definition? State the problem, not the solution.
26
+
27
+ ## Intended Product Outcome
28
+
29
+ What the Product Definition says once this change is accepted. Describe the destination, not the steps.
30
+
31
+ ## Rationale
32
+
33
+ Why this outcome, and why now. Record the reasoning a future reader would otherwise have to reconstruct.
34
+
35
+ ## Affected Product Areas
36
+
37
+ Which parts of the product this change touches, in product language rather than file paths.
38
+
39
+ ## Open Questions
40
+
41
+ Unresolved questions that need a decision before the change can be authorised. If answering a question could produce materially different product behaviour, scope, policy or acceptance, ask the product owner and stop: do not complete this delta or select an answer on the user's behalf. Write `None.` only after every product-semantic question in both the intent and this manifest has been resolved.
42
+
43
+ ## Product Acceptance
44
+
45
+ How a reviewer recognises that the accepted definition expresses the intended outcome.
46
+
47
+ ## Out of Scope
48
+
49
+ What this change explicitly does not touch, including delivery, technical design and implementation.
@@ -0,0 +1,29 @@
1
+ <!-- pdac-scope: cited -->
2
+
3
+ # <Requested product change title>
4
+
5
+ Declare the document scope on the first line: keep `pdac-scope: cited` when this proposal carries citations (the normal case), or replace it with `<!-- pdac-scope: none reason="<why no product text is involved>" -->`.
6
+
7
+ ## Why
8
+
9
+ The request as it arrived: the Issue, ask or observation that started this change, in one or two sentences.
10
+
11
+ ## Requested Product Intent
12
+
13
+ What the product should mean once this change is accepted, in product language. Destination, not steps; no implementation detail.
14
+
15
+ ## Impacted Product Areas
16
+
17
+ Every accepted artifact this intent depends on, alters or contradicts. One line per artifact: the id, why it is impacted, and a citation payload on its own line directly under it (emit with `prodshape cite --id <ID> --digest <digest>`, never write one by hand).
18
+
19
+ ## Neighbours Checked and Left Out
20
+
21
+ Artifacts inspected through the graph (impact, relationships) and judged out of scope, each with the one-line reason. Write `None.` when the impact list already covers everything inspected.
22
+
23
+ ## No Product Delta
24
+
25
+ Only when the honest verdict is that this request changes no product meaning: state that verdict and the reason, and stop the workflow here (no delta artifact follows). Delete this section otherwise.
26
+
27
+ ## Open Questions for the Product Owner
28
+
29
+ Questions that must be answered before the delta can be authored or authorised. First identify any wording that permits materially different observable product outcomes and list the alternatives here. Ask the product owner and stop before the delta until each such decision is answered. Never choose an outcome on the user's behalf. Write `None.` only after this ambiguity pass finds no unresolved decision that would change product behaviour, scope, policy or acceptance.