specpro-cli 0.1.0__py3-none-any.whl

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 (76) hide show
  1. specpro_cli/__init__.py +16 -0
  2. specpro_cli/assets/commands/specpro.analyze.md +1102 -0
  3. specpro_cli/assets/commands/specpro.checklist.md +335 -0
  4. specpro_cli/assets/commands/specpro.clarify.md +581 -0
  5. specpro_cli/assets/commands/specpro.constitution.md +488 -0
  6. specpro_cli/assets/commands/specpro.feature.md +115 -0
  7. specpro_cli/assets/commands/specpro.implement.md +1881 -0
  8. specpro_cli/assets/commands/specpro.manual-test.md +206 -0
  9. specpro_cli/assets/commands/specpro.plan.md +3284 -0
  10. specpro_cli/assets/commands/specpro.qc.md +1489 -0
  11. specpro_cli/assets/commands/specpro.scenarios.md +154 -0
  12. specpro_cli/assets/commands/specpro.specify.md +1449 -0
  13. specpro_cli/assets/commands/specpro.status.md +863 -0
  14. specpro_cli/assets/commands/specpro.tasks.md +1207 -0
  15. specpro_cli/assets/commands/specpro.test-implement.md +462 -0
  16. specpro_cli/assets/commands/specpro.test-plan.md +383 -0
  17. specpro_cli/assets/commands/specpro.user-manual.md +178 -0
  18. specpro_cli/assets/scripts/bash/check-anti-coupling.sh +293 -0
  19. specpro_cli/assets/scripts/bash/check-prerequisites.sh +176 -0
  20. specpro_cli/assets/scripts/bash/common.sh +88 -0
  21. specpro_cli/assets/scripts/bash/create-new-feature.sh +336 -0
  22. specpro_cli/assets/scripts/bash/qc-auto-fix.sh +121 -0
  23. specpro_cli/assets/scripts/bash/setup-plan.sh +60 -0
  24. specpro_cli/assets/scripts/bash/verify-cumulative-records.sh +203 -0
  25. specpro_cli/assets/scripts/bash/verify-deliverables-tracked.sh +147 -0
  26. specpro_cli/assets/scripts/bash/verify-deployment.sh +239 -0
  27. specpro_cli/assets/scripts/bash/verify-frontmatter-yaml.sh +63 -0
  28. specpro_cli/assets/scripts/bash/verify-ledger.sh +376 -0
  29. specpro_cli/assets/scripts/bash/verify-shapes.sh +1082 -0
  30. specpro_cli/assets/scripts/git-hooks/pre-commit +243 -0
  31. specpro_cli/assets/scripts/install-git-hooks.sh +67 -0
  32. specpro_cli/assets/scripts/powershell/check-anti-coupling.ps1 +249 -0
  33. specpro_cli/assets/scripts/powershell/check-prerequisites.ps1 +148 -0
  34. specpro_cli/assets/scripts/powershell/common.ps1 +95 -0
  35. specpro_cli/assets/scripts/powershell/create-new-feature.ps1 +229 -0
  36. specpro_cli/assets/scripts/powershell/qc-auto-fix.ps1 +110 -0
  37. specpro_cli/assets/scripts/powershell/setup-plan.ps1 +61 -0
  38. specpro_cli/assets/scripts/powershell/verify-cumulative-records.ps1 +133 -0
  39. specpro_cli/assets/scripts/powershell/verify-deliverables-tracked.ps1 +112 -0
  40. specpro_cli/assets/scripts/powershell/verify-deployment.ps1 +278 -0
  41. specpro_cli/assets/scripts/powershell/verify-frontmatter-yaml.ps1 +56 -0
  42. specpro_cli/assets/scripts/powershell/verify-ledger.ps1 +383 -0
  43. specpro_cli/assets/scripts/powershell/verify-shapes.ps1 +978 -0
  44. specpro_cli/assets/templates/agent-context-template.md +49 -0
  45. specpro_cli/assets/templates/assumptions-template.md +248 -0
  46. specpro_cli/assets/templates/checklist-template.md +40 -0
  47. specpro_cli/assets/templates/clarifications-template.md +155 -0
  48. specpro_cli/assets/templates/constitution-template.md +50 -0
  49. specpro_cli/assets/templates/feature-spec-template.md +66 -0
  50. specpro_cli/assets/templates/plan-overview-template.md +150 -0
  51. specpro_cli/assets/templates/plan-template.md +387 -0
  52. specpro_cli/assets/templates/protocol-golden-bytes-guide.md +195 -0
  53. specpro_cli/assets/templates/requirements-template.md +356 -0
  54. specpro_cli/assets/templates/spec-template.md +267 -0
  55. specpro_cli/assets/templates/tasks-template.md +252 -0
  56. specpro_cli/assets/templates/test-tasks-template.md +174 -0
  57. specpro_cli/cli/__init__.py +5 -0
  58. specpro_cli/cli/cmd_init.py +416 -0
  59. specpro_cli/cli/cmd_remove.py +122 -0
  60. specpro_cli/cli/entry.py +181 -0
  61. specpro_cli/integrations/__init__.py +36 -0
  62. specpro_cli/integrations/base.py +601 -0
  63. specpro_cli/integrations/claude/__init__.py +101 -0
  64. specpro_cli/integrations/copilot/__init__.py +153 -0
  65. specpro_cli/integrations/cursor_agent/__init__.py +51 -0
  66. specpro_cli/integrations/gemini/__init__.py +44 -0
  67. specpro_cli/integrations/opencode/__init__.py +48 -0
  68. specpro_cli/integrations/qodercli/__init__.py +54 -0
  69. specpro_cli/integrations/registry.py +88 -0
  70. specpro_cli/packaged/__init__.py +5 -0
  71. specpro_cli/packaged/sync.py +106 -0
  72. specpro_cli-0.1.0.dist-info/METADATA +117 -0
  73. specpro_cli-0.1.0.dist-info/RECORD +76 -0
  74. specpro_cli-0.1.0.dist-info/WHEEL +4 -0
  75. specpro_cli-0.1.0.dist-info/entry_points.txt +2 -0
  76. specpro_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,195 @@
1
+ # Protocol Golden Bytes Guide
2
+
3
+ **Purpose**: Shared reference for the protocol codec module rules used across specpro workflows — protocol-point inventory, golden-bytes spec anchoring, and verification-method semantic review.
4
+
5
+ **Applies to**: modules that implement a wire format (encode/decode), parse protocol messages, or interoperate with a protocol peer. Non-protocol modules are unaffected by this guide.
6
+
7
+ ---
8
+
9
+ ## 1. Protocol Point Inventory — field- and branch-level enumeration
10
+
11
+ Protocol-point granularity MUST drill down to **fields and branches**, not stop at message types. Message-level tests can pass while the defect sits in one parameter branch.
12
+
13
+ Inventory format (one row per protocol point):
14
+
15
+ | Protocol point | Semantics | Branches / boundaries | Anchor source | Test coverage |
16
+ |----------------|-----------|----------------------|---------------|---------------|
17
+ | Payload byte count | How many stream bytes a payload occupies | Parameter-dependent branch table (bit depth × pixel format, etc.) | Reference implementation + captured stream | Matrix cases ×N |
18
+ | Run-length extension chain | Semantics of a multi-byte continuation chain | Per-byte accumulation vs continuation marker (differs per protocol) | Specification + observed implementation behaviour | Property tests |
19
+ | ⤷ encoding of this row | Described by **byte-level example, never prose** — "skip the marker byte" and "accumulate the marker value" describe **different** streams | — | — | — |
20
+ | Control-byte bit semantics | Bit allocation for flag / index / palette size | Top-bit dispatch; index width varies with palette size | Specification | Matrix cases |
21
+ | Stream lifecycle | Continuous single stream vs per-message independent stream | Decoder reuse across rectangles / frames | Specification + reference implementation | Incremental-context cases |
22
+ | Peer diversity | Differences between peer implementations | Optional fields present or absent; compile-time options; environment-dependent behaviours | Measured inventory (guessing forbidden) | Environment annotations |
23
+
24
+ > **What the `Test coverage` column means — read this before filling it.** It states the **coverage method** the row requires: the testing *means* suited to that protocol point's shape (matrix cases for bit packing, property tests for extension chains, incremental-context cases for stream lifecycle, environment annotations for peer divergences). It is a **design specification**, fixed when the row is written — it does **not** change as tests are added.
25
+ >
26
+ > **What it is NOT — two things that look like coverage and belong elsewhere:**
27
+ > - **Coverage status** (which points are covered *right now*) belongs to the **test matrix** (`specs/test-tasks.md`), derived by scanning the **actual** test assets. An upstream stage MUST NOT record it here: its source of truth is downstream, so the upstream stage would have no way to keep it current — a status written upstream is stale the moment the next test is added, and downstream consumers would act on the stale value.
28
+ > - **Anchor reachability** (whether this row's anchor source could be reached) **is** a plan-layer fact and **does** belong here — an unreachable anchor is recorded as a **GAP** (§6.3), because only the stage that did the anchoring knows whether the source was reachable.
29
+ >
30
+ > Writing a ✅/⚠️/❌ status into this column is the failure this note prevents: it mixes a downstream fact into an upstream artifact, producing a snapshot that no one can maintain.
31
+
32
+ **Byte-level example — an extension chain (run-length encoding, run length = value + 1)**:
33
+
34
+ ```
35
+ run of 300 px → 0xFF 0x2C ... 1 + 255, then + 45 → 256 + 44 = 300
36
+ run of 511 px → 0xFF 0xFE ... 1 + 255, then + 255 → 256 + 255 = 511
37
+ run of 512 px → 0xFF 0xFF 0x00 ... 1 + 255, then + 256 → 256 + 256 = 512
38
+ ```
39
+
40
+ Two readings of the marker that produce **different streams**:
41
+
42
+ - **accumulate** (correct): each `0xFF` adds 255/256 and the chain continues while the marker repeats.
43
+ - **skip** (wrong): `0xFF` is a no-op that is skipped, and the next byte is the total. The run reads 0 for the third example and the stream desynchronises.
44
+
45
+ Neither reading is derivable from the phrase "255 extension chain" — the inventory row MUST carry the example, not the phrase. A run whose length lands exactly on the marker boundary (511, 512) is the discriminating case and MUST be in the matrix.
46
+
47
+ **Rule**: For protocol modules the inventory MUST be produced in the design section of `plan.md`, and every point MUST be mapped to test coverage in the matrix tasks of `tasks.md`. That mapping is the input for the coverage audit (§4, L3).
48
+
49
+ ---
50
+
51
+ ## 2. Golden Bytes — three-layer cross-anchoring
52
+
53
+ **Golden bytes** = a manually derived, **known-correct byte sequence**, used as a two-way spec anchor: the encoder's output must equal it, and the decoder must accept it. Every anchor MUST be annotated by source layer.
54
+
55
+ | Layer | Source | What it anchors | Known limitation |
56
+ |-------|--------|-----------------|------------------|
57
+ | **L1** Specification | RFC / protocol extension documents | Top-level structure, field order | Frequently omits bit-level detail of sub-encodings |
58
+ | **L2** Reference implementation | Source of an independent implementation | Bit-level semantics | Behaviour specific to that implementation version |
59
+ | **L3** Captured stream | Wire bytes captured from a real peer | Final arbitration (derived spec vs actual output) | Environment-dependent |
60
+
61
+ **Rules**:
62
+
63
+ - Every anchor MUST record **both** its source layer **and the protocol / peer version it was derived from**. An anchor without a version is not usable against a second version of the same protocol.
64
+ - When the three layers conflict, L3 (measured) wins; write the corrected understanding back into the L1/L2 notes.
65
+ - **Forbidden**: using the **output of the implementation under test** as a spec anchor. That is a self-confirming loop — the implementation's own bug is mirrored back as "correct".
66
+ - For continuous-stream formats, segmented verification MUST use a **reuse-style decode path** (feed each segment into a persistent decoder). Reporting `incomplete` from a one-shot full-buffer decode is a **normal artefact** of a continuous stream, not defect evidence. The verification method must match the stream semantics **before** any defect conclusion is drawn.
67
+
68
+ ---
69
+
70
+ ## 3. Test Matrix — the standard four-part shape for codec modules
71
+
72
+ 1. **Decode matrix**: message / tile type × full-frame vs incremental context × parameters — assert byte-by-byte or pixel-by-pixel.
73
+ 2. **Encode reverse matrix**: `encoder(pixels) → bytes`, compared against the golden anchor byte by byte. Catches ordering and formatting regressions.
74
+ 3. **Shared golden-bytes fixture**: all anchors are constructed in one place and shared by the encoder and decoder matrices, so the two directions lock each other.
75
+ 4. **Property-test extension**: randomized content / length / combinations, with a fixed seed and a failure output that reproduces the failing parameters (§3.2). Covers what hand-written matrices miss — extension chains, cross-tile boundaries, non-divisible sizes.
76
+
77
+ **Error paths are part of the matrix.** Truncated stream, invalid control byte, over-long run, out-of-range index — each MUST have a decided expected behaviour (reject vs tolerate). "Unspecified" is not an answer; it is the shape of the next latent defect. This item is **MUST**, not optional: an error path with no decided behaviour is an untested branch that merely has not been reached yet.
78
+
79
+ ### 3.1 Two sets of samples, both anchored
80
+
81
+ The decoder set and the encoder set are separate deliverables and **both** are anchored by §2:
82
+
83
+ - **Decoder samples**: bytes → pixels. The golden bytes are the anchor; assert the decoded pixels against the recorded expectation.
84
+ - **Encoder samples**: pixels → bytes. The anchor is the **expected byte stream**, and it comes from the same three layers as any other anchor.
85
+
86
+ The frequent mistake sits in the second set: the encoder's expectation gets filled in with **the implementation's own output**, or with a byte stream produced by a sibling component of the same implementation. That is the §2 self-confirming loop wearing a different hat — the test compares the implementation to itself, and every assertion passes by construction.
87
+
88
+ - A round-trip test (`encode → decode → compare pixels`) is a **regression guard, not a consistency proof**. Encoder and decoder are two faces of one implementation: they can share a mistaken reading of the protocol and still round-trip perfectly. Round-trip MUST NOT be counted as coverage for a protocol point that has no anchored byte-level case.
89
+
90
+ ### 3.2 Property tests carry their reproduction parameters
91
+
92
+ Randomised content / length / colour count / sub-encoding selection, with:
93
+
94
+ - a **fixed seed** recorded alongside the test;
95
+ - on failure, output of the **parameters that reproduce it** — seed, dimensions, tile content descriptor, sub-encoding.
96
+
97
+ Without the second item a failure is not attributable, and an unattributable failure in a randomised suite gets re-run until it passes. That is how a randomised suite silently stops reporting defects.
98
+
99
+ A property test is also the cheapest home for the cases a hand-written matrix is tempted to skip — extension chains, cross-tile boundaries, sizes that do not divide evenly. When the matrix sample table "avoids" a protocol point because the bytes are awkward to write by hand, that point belongs in the property suite, not in the gap.
100
+
101
+ **Implementation notes**:
102
+
103
+ - **Decide the verification path — and therefore the test host — before writing a single case.** A table-driven matrix hosted end-to-end (real socket, real handshake, real message loop) inherits timing coupling that has nothing to do with the protocol: connect races, consume-window competition, timeout tuning under load. The symptom is a suite that alternates PASS/FAIL across runs with no code change, which destroys its value as a regression guard because a failure no longer means anything. Feed the codec layer **directly** first — no network, no handshake, no threads, no timeouts — so the matrix measures protocol behaviour and nothing else. End-to-end and real-peer cases belong in the outer layers (see **Layering** above), doing conformance spot-checks.
104
+ - A mock peer's consume loop MUST **block until the target message arrives**. A silent-exit window is unreliable under load: when the client's message is slow to arrive the loop exits early, producing a **zero-frame artefact** that looks like a real defect.
105
+ - Teardown between tests MUST leave no server / client / thread residue — a lingering socket poisons later cases.
106
+ - For event-driven protocols (request → ack + asynchronous event), mind the sync/async semantics: an ack is not the event.
107
+
108
+ ---
109
+
110
+ ## 4. Lateral Audit Rules — criteria for `analyze` Pass L
111
+
112
+ - **L1 — Same-semantics branch scan**: after fixing a byte-counting / packing / stream-semantics defect in one function, scan sibling functions in the same family for the same-shaped branch. Missing one leaves the defect latent. General shape of the failure: a family carries N same-semantics branches, the fix touches N−1.
113
+ - **L2 — Verification-method semantic audit**: does the verification technique match the semantics of the stream under test? An `incomplete` / `truncated` verdict MUST first rule out a method-semantics mismatch before it is treated as defect evidence.
114
+ - **L3 — Protocol-point coverage audit**: check the protocol-point inventory (§1) point by point against test coverage. A low-frequency path (incremental small payloads, extension chains, non-divisible sizes) with no coverage is a finding.
115
+ - **L4 — Anchor-source audit**: every golden byte and expected test value MUST carry its source layer (§2). Unlabelled, or sourced from the implementation under test, is a finding.
116
+ - **L5 — Peer-behaviour assertion audit**: every expectation that asserts how a peer behaves MUST trace to a row in the **Peer Diversity Registry** (§1, last row) — the closed set of *measured* peer behaviours, held in `specs/test-tasks.md`. An assertion with no registered row is a finding: unmeasured peer behaviour MUST NOT be frozen into an expectation. "Not in the registry" and "not measured" mean the same thing, which is why the registry must stay closed and authoritative rather than being a free-form appendix.
117
+
118
+ ---
119
+
120
+ **Layering**: items 1–4 are in-memory, network-free, and MUST all pass. Real-peer tests (a real server, a real capture) sit in the integration / E2E layers and are **conformance spot-checks** — they confirm that the mock-layer protocol model matches the real world. They are not the place to find byte-level defects: a black-box peer shows a wrong picture, not a wrong byte, and the defect being hunted lives at a byte offset the black box cannot display.
121
+
122
+ ## 5. Sample Management — anchors are versioned assets
123
+
124
+ - **Every sample row carries its source layer (§2) and the protocol / peer version it was derived from.** An anchor with no version is unusable against the next version of the same protocol.
125
+ - **Sample files (binary or hex text) are version-controlled with the code.** A sample that lives only in a developer's scratch directory is not a regression guard.
126
+ - **Every golden case traces back to a requirement ID** (FR / US / protocol-point row). Without that link the coverage audit (§4, L3) and the matrix mapping (§3 items 1–4) have nothing to walk — they can only confirm that cases exist, not that the required points are covered.
127
+ - **The inventory is a living artifact.** A protocol point discovered mid-execution is written back to the inventory, and the sample table is extended in the same change; otherwise the matrix silently falls behind the protocol model. A point that has no coverage yet is **kept as an empty row** — an empty cell is the audit's input, and deleting the row is how coverage gaps become invisible.
128
+
129
+ ## 6. Activation Gate — deciding whether this module is in scope
130
+
131
+ Every workflow that carries protocol rules activates **conditionally**. The condition is the weak link: judged afresh by each workflow, in prose, it drifts — one stage decides "protocol module", another decides "not really", and the rules quietly stop applying. This section replaces prose judgement with a **decidable verdict that is itself an artifact**.
132
+
133
+ **Rule — activation is a product, not a recollection.** A stage that could plausibly be in scope MUST emit one of two things:
134
+
135
+ - the protocol artifacts required by that stage (§1 inventory, §2 anchors, §3 matrix, §5 samples), **or**
136
+ - an explicit **not-active** verdict with its trigger evidence.
137
+
138
+ Producing neither is not a third option; it is the failure this gate exists to catch.
139
+
140
+ ### 6.1 Triggers — mechanical, not interpretive
141
+
142
+ The gate opens when **any** trigger is observable in the artifacts the stage reads:
143
+
144
+ | # | Trigger | Observable at |
145
+ |---|---------|---------------|
146
+ | T1 | A requirement's text contains a byte-level protocol anchor — message layout, field widths, control-byte semantics, packing order, encoding identifiers | FR text |
147
+ | T2 | A requirement names an external protocol / wire format / extension document | FR text |
148
+ | T3 | The design encodes or decodes a byte stream (serialiser, parser, codec, tile/message framing) | design section / source tree |
149
+ | T4 | The design interoperates with a peer process or device over a wire format | design / contract |
150
+ | T5 | A test or mock emits or asserts on raw bytes | test tasks / test source |
151
+
152
+ A single trigger is sufficient. "Partially protocol" is not a category — a requirement that touches one wire field is in scope for that field.
153
+
154
+ **Do not infer the gate from the presence of a network, a socket, or a client/server split.** Those are transport concerns; a module can be network-facing and carry no wire format, and it can be wire-format-bearing with no network at all. Trigger T3/T5 are about bytes, not about I/O.
155
+
156
+ ### 6.2 Verdicts — three states, all recorded
157
+
158
+ | Verdict | Meaning | What this stage MUST output |
159
+ |---------|---------|------------------------------|
160
+ | **ACTIVE** | ≥1 trigger present, required sources reachable | The full artifact set for the stage |
161
+ | **ACTIVE-WITH-GAPS** | ≥1 trigger present, but a required anchor source is unreachable | The artifact set, with every unreachable item recorded as **GAP** (§6.3) |
162
+ | **NOT-ACTIVE** | No trigger present | A one-line verdict with the trigger scan result |
163
+
164
+ **ACTIVE-WITH-GAPS is a first-class outcome, not a failure.** It records reality. What is forbidden is presenting a gap as covered — or filling it with plausible-looking content.
165
+
166
+ **Propagation**: downstream stages **consume** the upstream verdict; they do not re-judge it. If a later stage finds a trigger the earlier stage missed, it does not silently override — it records the discrepancy, which is a finding for the coverage audit (§4).
167
+
168
+ ### 6.3 GAP — how to state an unreachable anchor
169
+
170
+ An unreachable anchor is recorded, never invented:
171
+
172
+ | Column | Content |
173
+ |--------|---------|
174
+ | Protocol point | The row from §1 |
175
+ | Missing layer | Which of L1 / L2 / L3 cannot be reached |
176
+ | Why | e.g. "L1 document does not specify sub-encoding bit layout" |
177
+ | Acquisition path | What would provide it — reference source at a named version, a capture from a named peer |
178
+
179
+ **Forbidden**: writing a byte sequence that was not derived from a named source layer, annotated as if it were. A fabricated anchor passes every format check, enters the fixture, and silently corrupts both directions of the matrix — this is §2's self-confirming loop in its most durable form, because the fabricated value then outlives the session that produced it.
180
+
181
+ ### 6.4 Verdict record
182
+
183
+ Wherever this guide is consumed, the verdict is written down in this shape:
184
+
185
+ | Stage | Verdict | Trigger | Evidence | Artifacts / Gaps |
186
+ |-------|---------|---------|----------|------------------|
187
+ | plan | ACTIVE | T3, T1 | `XxxCodec.decodeRect` dispatch; FR-012 | inventory §1 · anchors: L1 ✔ L2 ✔ L3 GAP (no capture) |
188
+
189
+ The row is what the coverage audit (§4) reads. A stage with protocol rules and no verdict row is a finding regardless of whether the artifacts happen to exist.
190
+
191
+ ## 7. Structural Defences — implementation side
192
+
193
+ - **Single source of truth for same-semantics branches.** Byte-length and packing semantics MUST NOT be duplicated across multiple functions in a when/switch family — converge them into one helper.
194
+ - **No per-tile or per-message state in decoder member variables.** It leaks across instances. State that genuinely must be shared between callers belongs in a host-side anchor, not inside the decoder.
195
+ - **Do not transfer a fix's lesson to another encoder by default.** Stream semantics may be opposite — a continuous single stream in one codec, an independent per-rectangle stream in another. Verify before generalizing.
@@ -0,0 +1,356 @@
1
+ # Specification Quality Checklist: [FEATURE NAME]
2
+
3
+ **Purpose**: Validate `spec.md`: must contain only functional specifications; implementation details are not allowed.
4
+ **Created**: [DATE]
5
+ **Spec Version**: [VERSION]
6
+ **Validation Scope**: [Full | Incremental]
7
+ **QC Command**: /specpro-qc
8
+
9
+ > ⚠️ **This template defines the CURRENT run's outcome and nothing else.** The produced
10
+ > file is replaced wholesale on every invocation, so **nothing may be accumulated in it**
11
+ > and no cross-run record may be kept there — anything this template cannot produce is
12
+ > deleted by the next run, silently. Cross-run records belong in an artifact that is not
13
+ > rebuilt (see `specs/audit/`).
14
+
15
+ ---
16
+
17
+ ## Overall Status
18
+
19
+ > ⚠️ **`/specpro-qc` OVERWRITES all four values below on every run** (`T225` / `ISS-193`) — the
20
+ > three bracketed ones **and** `**Total Items**`. So on a *produced* checklist these are
21
+ > numbers, and they are **re-derived from the per-item rows**, never copied from the counters.
22
+ > ⇒ **The literal `11` on this line is the AUTHORING-TIME criterion count** — it is what a
23
+ > reader of the *template* (e.g. `/specpro-tasks` §3.e, which points here for the count) sees.
24
+ > **Adding or retiring a criterion MUST update it in the same round**; a template that says 11
25
+ > while carrying 12 criteria would hand that reader a count nothing computes — which is the
26
+ > shape this whole block was fixed to remove.
27
+
28
+ **Status**: [PASS | BLOCK]
29
+ **Total Items**: 11
30
+ **Passed**: [X]
31
+ **Failed**: [Y]
32
+
33
+ **If BLOCK**: Cannot proceed to plan/tasks/implement until all items pass.
34
+
35
+ ### 条目状态取值 ⚠️ [四个命令的门禁读此字段]
36
+
37
+ 条目行形如 `- [ ] **Status**: <取值>`。**门禁按此处的「取值」判定完成度,不按复选框**——复选框与「跳过」在字面上完全同形(模板即 `- [ ]`),只看它会把诚实跳过读成未完成。
38
+
39
+ **取值必须是该字段的全部内容**——任何解释写在**下一行**,不要缀在取值之后:
40
+
41
+ ```markdown
42
+ - [ ] **Status**: ⊘ Skipped
43
+ (本项对本项目不适用,理由:……) ← 解释在下一行,不参与判定
44
+ ```
45
+
46
+ > **为什么要求取值独占该行**:若允许取值后跟散文,判定就只能退化为"取值是否出现"——那么 `**Status**: 未做,别当成 x` 这类文本里出现的 `x` 会被读成通过。**判定要有牙,取值就不能有歧义。**
47
+
48
+ | 取值 | 含义 | 门禁 |
49
+ |---|---|---|
50
+ | `x` | 通过 | 不阻塞 |
51
+ | `⊘ Skipped` | **诚实跳过**——按检查定义无可推导来源、或判据对本项目不适用;**不计通过也不计失败** | **不阻塞** |
52
+ | `✗ Failed` | 不通过 | **阻塞** |
53
+ | 空白,或此表之外的取值 | **未完成** | **阻塞** |
54
+
55
+ > **为什么单列一档「跳过」**:此前它写作 `[ ]` 加自由文本,与「未做」无法区分,四个命令的门禁因此把**诚实跳过**读成**未完成**并硬阻塞(工具缺陷 #10)。**跳过是一个诚实的结论,不是一笔欠账**——把两者混为一谈,等于诱导执行方用假通过去绕过门禁。
56
+
57
+ ---
58
+
59
+ ## P0: Content Quality (Blocking)
60
+
61
+ ### CQ001: No implementation details
62
+
63
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
64
+
65
+ **Validation**: Automated keyword search
66
+
67
+ **Fail Keywords**: React, Vue, Angular, SQL, PostgreSQL, MongoDB, MySQL, Redis, REST, GraphQL, HTTP, TCP, UDP, async/await, await, coroutine, class, function, def, public, private, interface, abstract, extends, implements
68
+
69
+ **Result**: [Zero / N] implementation details found
70
+
71
+ **Action**: [Auto-fix: Remove implementation details OR convert to functional description]
72
+
73
+ **Examples**:
74
+ ❌ "System uses React for UI rendering"
75
+ ✅ "System provides responsive web interface"
76
+
77
+ ---
78
+
79
+ <!-- ⚠️ **One Content-Quality criterion was RETIRED here** (2026-09-19, `T197`; the item
80
+ count went 12 → 11). Its subject was *technical performance metrics in spec.md*, and
81
+ its premise was false: **a performance metric is a REQUIREMENT, not an implementation
82
+ detail** — "how you achieve it" is the implementation detail, and that is the two
83
+ criteria around this comment's territory. It forbade the very input the downstream
84
+ chain reads (plan's Performance Goals, contracts' Performance Requirements, analyze's
85
+ Pass H, test-plan's `Performance:` fields), so a spec carrying a legitimate target
86
+ could never pass QC. It was **not** re-scoped: a narrower version would have
87
+ duplicated the criterion below, which already owns "requirements are functional,
88
+ not technical".
89
+ ⚠️ The retired criterion is NOT named or quoted here — a value written into prose is
90
+ indistinguishable from a current one to a mechanical reader (the Change Summary note
91
+ above states the rule). Its trace is git history, not this comment. -->
92
+
93
+ ### CQ003: Requirements are functional, not technical
94
+
95
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
96
+
97
+ **Validation**: Semi-automated
98
+
99
+ **Check**: Do FRs describe WHAT the system does, not HOW?
100
+
101
+ **Result**: [All / Some] FRs are functional
102
+
103
+ **Action**: [Add to clarifications.md if unclear]
104
+
105
+ **Examples**:
106
+ ✅ "System MUST support remote desktop viewing" (functional)
107
+ ✅ "System MUST provide plugin architecture" (functional)
108
+ ❌ "System MUST use async I/O for network operations" (technical - HOW)
109
+ ❌ "System MUST implement the wire protocol using coroutines" (technical - HOW)
110
+
111
+ ⚠️ **What this criterion owns, and what `Semi-automated` therefore means here** (`T201`,
112
+ 2026-09-19): **a numeric target is a requirement; naming the METHOD that attains it is the
113
+ implementation detail.** So `System MUST use async I/O to reach 60 FPS` fails this
114
+ criterion — not because of the number, but because of the method. The criterion previously
115
+ matched **none** of its frames on that sentence, and no other criterion did either, so the
116
+ shape had no checker at all.
117
+
118
+ ⚠️ **Its detector is a partial one, and that is stated rather than implied.** The frames are
119
+ **enumerations**, and an enumeration is narrower than the ways the shape gets written. The
120
+ method-bound frame is constrained by **shape** (a method carries a slash — `async I/O`,
121
+ `HTTP/2`) rather than by a list of outcome verbs, precisely because a verb list is the
122
+ narrower-and-pays-for-it shape this repository has already rejected. A method spelled
123
+ without a slash ("a thread pool") is **not** matched.
124
+
125
+ ⇒ **A `x` here means "nothing in the covered shapes fired", never "no implementation detail
126
+ exists".** The uncovered remainder is **human review** — that is what `Semi-automated`
127
+ declares, and reading a pass as clean is reading it as more than it is (`FR-036`: 声称通过
128
+ 而基线未覆盖,不构成通过).
129
+
130
+ ---
131
+
132
+ ## P0: Completeness (Blocking)
133
+
134
+ ### CP001: All mandatory sections completed
135
+
136
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
137
+
138
+ **Validation**: Automated check
139
+
140
+ **Required Sections** — the artifacts this criterion enforces carry the *same* set, written
141
+ the way the spec actually spells them. ⚠️ This list used to read `Overview` / `User Scenarios
142
+ & Testing` / **`Functional Requirements`** while `check_cp001` held a *different* array and
143
+ `templates/spec-template.md` — the file that produces `spec.md` — defined no `Overview` at
144
+ all. **A criterion with two sources has no source**; the template's own `*(mandatory)*`
145
+ markers are the one that counts, and the check derives from them (FR-041):
146
+
147
+ - ✅ `## Overview`
148
+ - ✅ `## User Scenarios & Testing`
149
+ - ✅ `## Requirements` (the container; the FR entries live under `### Functional
150
+ Requirements` inside it — the earlier `Functional Requirements` here named the
151
+ sub-heading while the check looked for a top-level one, so the two never matched)
152
+
153
+ **Result**: [All / Some] sections present
154
+
155
+ **Action**: [Manual: Add missing sections]
156
+
157
+ ---
158
+
159
+ ### CP002: Every User Story has Acceptance Scenarios
160
+
161
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
162
+
163
+ **Validation**: Automated check
164
+
165
+ **Check**: Does each User Story have Given-When-Then scenarios?
166
+
167
+ **Result**: [All / Some] US have scenarios
168
+
169
+ **Missing**: [List of US without scenarios]
170
+
171
+ **Action**: [Add to clarifications.md]
172
+
173
+ **Example**:
174
+ ```markdown
175
+ ### US1 - [Title]
176
+ **Acceptance Scenarios**:
177
+ 1. **Given** [initial state], **When** [action], **Then** [expected outcome]
178
+ 2. **Given** [initial state], **When** [action], **Then** [expected outcome]
179
+ ```
180
+
181
+ ---
182
+
183
+ ### CP003: Acceptance Scenarios are functional (not technical)
184
+
185
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
186
+
187
+ **Validation**: Semi-automated
188
+
189
+ **Check**: Do scenarios verify functionality, not performance?
190
+
191
+ **Fail Pattern**: Scenarios containing performance metrics like "within \d+ms", "\d+ FPS"
192
+
193
+ **Result**: [All / Some] scenarios are functional
194
+
195
+ **Action**: [Auto-fix: Remove performance metrics]
196
+
197
+ **Examples**:
198
+ ✅ "Given the app is running, When user enters server address, Then connection is established"
199
+ ❌ "Given a remote viewing session, When screen changes, Then updates show within 200ms"
200
+
201
+ ---
202
+
203
+ ## P1: Consistency (High Priority)
204
+
205
+ ### CS001: User Stories are internally consistent
206
+
207
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
208
+
209
+ **Validation**: Automated contradiction detection
210
+
211
+ **Check**: Any contradictions between User Stories?
212
+
213
+ **Result**: [No / Some] contradictions found
214
+
215
+ **Action**: [Manual: Requires intervention]
216
+
217
+ **Example Conflict**:
218
+ - US1: "System MUST support offline mode"
219
+ - US2: "System MUST require always-on connection"
220
+ → Contradiction detected
221
+
222
+ ---
223
+
224
+ ### CS002: Functional Requirements are internally consistent
225
+
226
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
227
+
228
+ **Validation**: Automated contradiction detection
229
+
230
+ **Check**: Any contradictions between FRs?
231
+
232
+ **Result**: [No / Some] contradictions found
233
+
234
+ **Action**: [Manual: Requires intervention]
235
+
236
+ **Example Conflict**:
237
+ - FR-xxx: "System MUST store data locally"
238
+ - FR-xxx: "System MUST NOT use local storage"
239
+ → Contradiction detected
240
+
241
+ ---
242
+
243
+ ### CS003: US → FR mapping is complete
244
+
245
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
246
+
247
+ **Validation**: Automated traceability check
248
+
249
+ **Check**: Does every User Story have associated FRs?
250
+
251
+ **Result**: [All / Some] US have associated FRs
252
+
253
+ **Orphan US**: [List of US without FRs]
254
+
255
+ **Action**: [Add to clarifications.md]
256
+
257
+ ---
258
+
259
+ ### CS004: Identifier references resolve to definitions
260
+
261
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
262
+
263
+ **Validation**: Automated reference integrity check
264
+
265
+ **Check**: Does every identifier mentioned in spec.md (FR-nnn mentions, "(per X-nnn)" attributions) resolve to a definition in this document?
266
+
267
+ **Dangling References**: [List of unresolved identifiers]
268
+
269
+ **Action**: [Add to clarifications.md]
270
+
271
+ ---
272
+
273
+ ## P1: Traceability (High Priority)
274
+
275
+ ### TR001: Constitution constraints documented
276
+
277
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
278
+
279
+ **Validation**: Semi-automated (domain detection + Constitution matching)
280
+
281
+ **Method**:
282
+ 1. Identify feature domains from spec.md (network, security, protocol, etc.)
283
+ 2. Search Constitution for matching principles
284
+ 3. Verify FRs include Constitution requirements
285
+
286
+ **Matched Domains**: [List of domains]
287
+ **Matched Principles**: [List of Constitution principles]
288
+
289
+ **Result**: [All / Some] applicable constraints documented
290
+
291
+ **Missing**: [List of missing Constitution constraints]
292
+
293
+ **Action**: [Add to clarifications.md]
294
+
295
+ ---
296
+
297
+ ### TR002: External dependencies identified
298
+
299
+ - [ ] **Status**: [x | ⊘ Skipped | ✗ Failed]
300
+
301
+ **Validation**: Automated keyword search — ⚠️ **over a labelled vocabulary only**
302
+
303
+ **Check**: Are external dependencies documented?
304
+
305
+ **Result**: [All / Some] dependencies documented
306
+
307
+ **Missing**: [List of missing dependencies]
308
+
309
+ **Action**: [Add to clarifications.md]
310
+
311
+ ⚠️ **The scan recognises a dependency only when the spec LABELS it** (`外部` / `第三方` /
312
+ `external <noun>` / `third-party`). **An unlabelled functional name is not recognised** —
313
+ including the examples above, which carry no such label. When nothing is recognised the
314
+ criterion reports `⊘ not decidable by this scan`, **not** "no external dependencies": the two
315
+ are different statements and only the first is true (ISS-150). ⇒ **Unlabelled names are
316
+ covered by human review, not by this criterion** — do not read a `⊘` here as a clean result.
317
+
318
+ **Examples** — ⚠️ **these MUST name the functional layer**, not the implementation stack.
319
+ The entries here used to name a **protocol**, a **library** and a **cipher suite** — i.e.
320
+ exactly the layer `FR-040` forbids this criterion from judging, and the opposite of where the
321
+ source was moved. ⇒ **each was rewritten to name the outside thing, not the mechanism.**
322
+ ⚠️ **The removed values are deliberately NOT quoted here** — a value sitting in prose is
323
+ indistinguishable from a current one to any mechanical reader, and to a human scanning the
324
+ file it reads as present (the rule stated in `spec-template.md`'s Change Summary note).
325
+ **A dependency is the outside thing the product talks to, not the mechanism it talks with** —
326
+ the mechanism may be replaced without the dependency changing:
327
+
328
+ - "the payment gateway the checkout flow calls"
329
+ - "the identity provider users sign in through"
330
+ - "the object store exports are written to"
331
+
332
+ **Where it is written**: the spec's `## External Dependencies` section
333
+ (`templates/spec-template.md`), which is `*(if applicable)*` — a feature with no outside
334
+ system simply omits it.
335
+
336
+ ---
337
+
338
+ **Validator**: specpro-qc
339
+
340
+ ---
341
+
342
+ <!-- End-of-file sentinel: everything above belongs to a section, and a row added
343
+ after the `-->` line below belongs to none — which is the condition this
344
+ makes visible ("position decides ownership" with no boundary marker fails
345
+ silently: the misfiled row still looks filed).
346
+
347
+ ⚠️ **Nothing is inserted before it any more.** Until 2026-09-19 a per-run row was
348
+ written here; that row is gone with the rest of the cross-run content (`FR-060`),
349
+ and with it the only writer that ever used this sentinel. **The sentinel itself
350
+ stays, and it is still correct** — it marks "the tagged content ends here", which
351
+ is exactly what a boundary marker is for. `plan.md` → Constraint 7 cites it as a
352
+ working example of one, and deleting it would invalidate that row.
353
+
354
+ NOTE: the closer of this comment is deliberately NOT alone on its line — a bare
355
+ `-->` line here would itself read as a second sentinel. -->
356
+ -->