code-factory-1-spec 0.3.0__tar.gz
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.
- code_factory_1_spec-0.3.0/LICENSE +21 -0
- code_factory_1_spec-0.3.0/PKG-INFO +199 -0
- code_factory_1_spec-0.3.0/README.md +186 -0
- code_factory_1_spec-0.3.0/code_factory_1_spec.egg-info/PKG-INFO +199 -0
- code_factory_1_spec-0.3.0/code_factory_1_spec.egg-info/SOURCES.txt +38 -0
- code_factory_1_spec-0.3.0/code_factory_1_spec.egg-info/dependency_links.txt +1 -0
- code_factory_1_spec-0.3.0/code_factory_1_spec.egg-info/entry_points.txt +2 -0
- code_factory_1_spec-0.3.0/code_factory_1_spec.egg-info/requires.txt +4 -0
- code_factory_1_spec-0.3.0/code_factory_1_spec.egg-info/top_level.txt +1 -0
- code_factory_1_spec-0.3.0/pyproject.toml +27 -0
- code_factory_1_spec-0.3.0/setup.cfg +4 -0
- code_factory_1_spec-0.3.0/specline/__init__.py +16 -0
- code_factory_1_spec-0.3.0/specline/adapters.py +32 -0
- code_factory_1_spec-0.3.0/specline/attribution.py +60 -0
- code_factory_1_spec-0.3.0/specline/cli.py +136 -0
- code_factory_1_spec-0.3.0/specline/drift_audit.py +150 -0
- code_factory_1_spec-0.3.0/specline/gates.py +40 -0
- code_factory_1_spec-0.3.0/specline/handoff.py +44 -0
- code_factory_1_spec-0.3.0/specline/ledger.py +40 -0
- code_factory_1_spec-0.3.0/specline/loop.py +66 -0
- code_factory_1_spec-0.3.0/specline/packets.py +107 -0
- code_factory_1_spec-0.3.0/specline/paths.py +10 -0
- code_factory_1_spec-0.3.0/specline/plan_lint.py +38 -0
- code_factory_1_spec-0.3.0/specline/scaffold.py +40 -0
- code_factory_1_spec-0.3.0/specline/spec_lint.py +49 -0
- code_factory_1_spec-0.3.0/specline/specfactor.py +21 -0
- code_factory_1_spec-0.3.0/specline/strict_lint.py +308 -0
- code_factory_1_spec-0.3.0/templates/AGENTS.md +22 -0
- code_factory_1_spec-0.3.0/templates/PLAN_TEMPLATE.md +11 -0
- code_factory_1_spec-0.3.0/templates/SPEC_TEMPLATE.md +38 -0
- code_factory_1_spec-0.3.0/templates/context/AI_WORKFLOW_RULES.md +6 -0
- code_factory_1_spec-0.3.0/templates/context/ARCHITECTURE.md +12 -0
- code_factory_1_spec-0.3.0/templates/context/CODE_STANDARDS.md +6 -0
- code_factory_1_spec-0.3.0/templates/context/PROGRESS.md +7 -0
- code_factory_1_spec-0.3.0/templates/context/PROJECT_OVERVIEW.md +10 -0
- code_factory_1_spec-0.3.0/templates/context/UI_CONTEXT.md +4 -0
- code_factory_1_spec-0.3.0/templates/personas/reviewer.md +6 -0
- code_factory_1_spec-0.3.0/templates/personas/security_auditor.md +5 -0
- code_factory_1_spec-0.3.0/tests/test_specline.py +125 -0
- code_factory_1_spec-0.3.0/tests/test_strict.py +180 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 WizeMe.APP
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: code-factory-1-spec
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: SpecLine — a spec-driven production line for AI-assisted engineering: PRD -> spec -> plan -> atomic task packets -> gated code, with token-lean context hygiene and a compiled-decision handoff to Harness Software Factory (HSF).
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: PyYAML>=6.0
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# SpecLine 🏭
|
|
15
|
+
|
|
16
|
+
**A spec-driven production line for AI coding agents.** PRD → spec → plan →
|
|
17
|
+
atomic task packets → gated code → production, with token-lean context
|
|
18
|
+
hygiene enforced by tooling instead of discipline, and a compiled-decision
|
|
19
|
+
handoff to [Harness Software Factory](../harness-factory) for the logic that
|
|
20
|
+
should never be improvised twice.
|
|
21
|
+
|
|
22
|
+
Works with **Claude Code, Codex, and any agent harness** — one command wires it in.
|
|
23
|
+
|
|
24
|
+
## Workflow at a glance
|
|
25
|
+
|
|
26
|
+
```mermaid
|
|
27
|
+
flowchart LR
|
|
28
|
+
A["PRD or rough idea"] --> B["Draft spec"]
|
|
29
|
+
B --> C["Strict contract check"]
|
|
30
|
+
C -->|"blocks ambiguity"| B
|
|
31
|
+
C --> D["Gate spec and seal hash"]
|
|
32
|
+
D --> E["Create atomic plan"]
|
|
33
|
+
E --> F["Emit one task packet"]
|
|
34
|
+
F --> G["Agent builds exactly one slice"]
|
|
35
|
+
G --> H["Audit code against packet"]
|
|
36
|
+
H -->|"drift found"| F
|
|
37
|
+
H --> I["Gate code and update receipts"]
|
|
38
|
+
I --> J{"Decision table?"}
|
|
39
|
+
J -->|"yes"| K["Handoff to HSF"]
|
|
40
|
+
J -->|"no"| L["Ready for ForgeLine or PR"]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
PRD ──> Spec (EARS+Gherkin) ──> Gate ──> Plan (atomic tasks) ──> Gate
|
|
45
|
+
│
|
|
46
|
+
┌─────────────────────────────────────────┘
|
|
47
|
+
▼
|
|
48
|
+
┌── Ralph Wiggum Loop ──┐ Decision tables in the spec
|
|
49
|
+
│ specline loop next │ ──> specline handoff
|
|
50
|
+
│ → token-budgeted │ ──> HSF compiles them ONCE into
|
|
51
|
+
│ TASK PACKET │ gated, deterministic code
|
|
52
|
+
│ agent does ONE task │ (zero tokens per decision, forever)
|
|
53
|
+
│ specline loop done │
|
|
54
|
+
│ → verify + seal │
|
|
55
|
+
└──── context reset ────┘ ──> Gate ──> ship
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Why
|
|
59
|
+
|
|
60
|
+
Vibe coding hits the wall around four files: context pollution, intent
|
|
61
|
+
drift, API hallucinations. The fixes are known — specs as source of truth,
|
|
62
|
+
constitutions, vertical slices, context resets — but they live in blog
|
|
63
|
+
posts as *discipline*. SpecLine turns them into *tooling*: linted, gated,
|
|
64
|
+
hash-sealed, and receipt-audited, so the discipline holds at 2am too.
|
|
65
|
+
|
|
66
|
+
## Quickstart (5 minutes, no API keys)
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install -e ".[dev]"
|
|
70
|
+
specline init # constitution + six-file context system
|
|
71
|
+
specline new refunds # spec + plan skeletons
|
|
72
|
+
# ... you + your agent fill the spec ...
|
|
73
|
+
specline validate refunds # EARS/Gherkin/leak lint — ambiguity dies here
|
|
74
|
+
specline gate spec refunds # hash-sealed human signoff
|
|
75
|
+
specline tasks refunds # atomicity lint: ≤4 files, one slice, verify cmd
|
|
76
|
+
specline gate plan refunds # locks the spec hash (drift guard arms)
|
|
77
|
+
specline loop next refunds # emits a token-budgeted TASK PACKET
|
|
78
|
+
# ... agent session does exactly one packet ...
|
|
79
|
+
specline loop done refunds T1 # runs verify command, seals receipt, advances
|
|
80
|
+
specline handoff refunds # decision table -> HSF workflow spec
|
|
81
|
+
specline agent claude # wires CLAUDE.md + /next-task command
|
|
82
|
+
specline status # token-savings receipt
|
|
83
|
+
pytest -q # 25 tests
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## The mechanisms (what's actually enforced)
|
|
87
|
+
|
|
88
|
+
| Blog-post advice | SpecLine enforcement |
|
|
89
|
+
|---|---|
|
|
90
|
+
| "Write clear specs" | EARS keyword lint, Gherkin required, implementation-leak detection (`E_IMPL_LEAK`) |
|
|
91
|
+
| "Keep tasks small" | Atomicity linter: ≤4 files, one vertical slice, explicit verify command, no skeleton edits |
|
|
92
|
+
| "Reset agent context" | The loop emits self-contained **task packets** under a hard ~2.2k-token budget; one packet = one session |
|
|
93
|
+
| "Minimize context (C_t=γ·R_f·T_d)" | Packets list the exact R_f file set; excerpt only spec lines relevant to the task; deterministic prune over budget |
|
|
94
|
+
| "Prevent intent drift" | Plan gate seals the spec hash; if the spec changes, the loop **refuses** (`E_INTENT_DRIFT`) until re-gated |
|
|
95
|
+
| "Human review gates" | `specline gate spec|plan|code` writes hash-sealed signoff receipts to the progress tracker |
|
|
96
|
+
| "Don't let agents improvise business rules" | Decision tables compile through HSF: one-time generation, four gates, zero tokens per decision |
|
|
97
|
+
| "Measure the process" | SpecFactor gauge (Goldilocks 0.75–2.5) + a **context ledger**: packet tokens vs naive baseline, % saved |
|
|
98
|
+
|
|
99
|
+
## Agent integration
|
|
100
|
+
|
|
101
|
+
- **Claude Code:** `specline agent claude` → writes `CLAUDE.md` (constitution +
|
|
102
|
+
protocol) and `.claude/commands/next-task.md`. The whole loop is one slash command.
|
|
103
|
+
- **Codex:** `specline agent codex` → appends the protocol to `AGENTS.md`
|
|
104
|
+
(Codex reads it natively).
|
|
105
|
+
- **Anything else:** `specline agent <name>` → portable constitution file.
|
|
106
|
+
The protocol is plain text; any harness that can read a file can follow it.
|
|
107
|
+
|
|
108
|
+
## The factory calibration (the part that saves real money)
|
|
109
|
+
|
|
110
|
+
Most business logic in AI-built apps is *decision-shaped*: ordered rules over
|
|
111
|
+
extracted facts. Letting agents re-implement those rules inline is how you get
|
|
112
|
+
inconsistent behavior and burned tokens. SpecLine specs carry a
|
|
113
|
+
`## Decision logic` table; `specline handoff` converts it to a Harness
|
|
114
|
+
Software Factory spec, and HSF compiles it once into deterministic, gated,
|
|
115
|
+
signed code — verified end-to-end in this repo's test suite against a real
|
|
116
|
+
HSF install. App code flows through the line; decisions flow through the
|
|
117
|
+
factory; nothing is improvised twice.
|
|
118
|
+
|
|
119
|
+
## Receipts culture
|
|
120
|
+
|
|
121
|
+
Every gate signoff, packet emission, and task completion writes a hash-sealed
|
|
122
|
+
line to `context/PROGRESS.md`, and the context ledger accumulates the token
|
|
123
|
+
economics (`specline status` — the walkthrough example shows ~75% saved vs
|
|
124
|
+
naive full-context sessions, and the gap widens as the repo grows). Claims
|
|
125
|
+
trace to receipts, never to vibes. That's the whole point.
|
|
126
|
+
|
|
127
|
+
MIT licensed.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## v0.2 — Strict Input Contract & Drift Audit
|
|
132
|
+
|
|
133
|
+
The base linter checks that a spec *looks* right (EARS keywords present, valid task
|
|
134
|
+
format). That's necessary but not sufficient: it lets **ambiguity** through, and the
|
|
135
|
+
AI coder then *invents* the missing parameters — which is drift. v0.2 closes that gap
|
|
136
|
+
with two new stages that bracket the coder.
|
|
137
|
+
|
|
138
|
+
### `specline strict <feature>` — reject ambiguity *before* the coder runs
|
|
139
|
+
|
|
140
|
+
Treats the spec as a **contract the coder must execute with zero invention**. Every
|
|
141
|
+
finding is a BLOCK with an exact line and fix. It catches the five drift sources:
|
|
142
|
+
|
|
143
|
+
1. **Incomplete requirements** — an EARS keyword isn't enough. Each requirement must
|
|
144
|
+
have a concrete outcome verb (`return`/`reject`/`store`/…), not `handle`/`support`/
|
|
145
|
+
`manage`. `The system shall handle it appropriately` is rejected.
|
|
146
|
+
2. **Surviving placeholders** — `<trigger>`, `<N>`, `TBD` can't reach an approved spec.
|
|
147
|
+
3. **Unquantified bounds** — a requirement that implies a timeout/limit/retry/size must
|
|
148
|
+
state a number+unit.
|
|
149
|
+
4. **Untraceable acceptance** — every value in a Given/When/Then must be defined in a
|
|
150
|
+
requirement or the data model. A Gherkin step can't introduce a fact the coder would
|
|
151
|
+
have to invent.
|
|
152
|
+
5. **Non-deterministic decisions** — each rule's `if` references a declared fact and its
|
|
153
|
+
`then` is exactly one outcome. No `maybe`/`or`/`etc`; no duplicate conditions.
|
|
154
|
+
(`else`/`default` catch-all rows are allowed.)
|
|
155
|
+
|
|
156
|
+
An `approved` spec that still fails strict raises `S_APPROVED_BUT_AMBIGUOUS` — approval
|
|
157
|
+
is a lie until the blocks are resolved.
|
|
158
|
+
|
|
159
|
+
Strict is **on by default** in `specline gate spec|plan`. Pass `strict=False` to the
|
|
160
|
+
gate API only for legacy specs.
|
|
161
|
+
|
|
162
|
+
### `specline audit <feature> --files … --slice …` — catch drift *after* the coder runs
|
|
163
|
+
|
|
164
|
+
Compares what shipped against what the contract authorized:
|
|
165
|
+
|
|
166
|
+
- **`A_INVENTED_PARAM`** — a config value (`TIMEOUT = 45`) whose number the spec never
|
|
167
|
+
authorized. The coder guessed; the audit fails the build.
|
|
168
|
+
- **`A_SCOPE_ESCAPE`** — a file outside the task's authorized slice.
|
|
169
|
+
- **`A_UNAUTHORIZED_FILE`** — a file not in the packet's list.
|
|
170
|
+
- **`A_STUB_LEFT`** — a `TODO`/`NotImplementedError` left behind.
|
|
171
|
+
|
|
172
|
+
### Requirement-scoped packets
|
|
173
|
+
|
|
174
|
+
The packet excerpt no longer bag-of-words-matches individual lines (which could hand the
|
|
175
|
+
agent half a requirement). It now ships **whole requirement blocks** and the **complete
|
|
176
|
+
acceptance scenario intact** — the agent never receives a partial rule to improvise around.
|
|
177
|
+
|
|
178
|
+
### Flow
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
new → write spec → validate → strict → gate spec → write plan → tasks → gate plan
|
|
182
|
+
→ loop (build) → audit → gate code → handoff
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Deterministic by design: same spec text → same findings, every run. No LLM, no clock.
|
|
186
|
+
## Failure attribution
|
|
187
|
+
|
|
188
|
+
SpecLine 0.3 reports strict-lint results per requirement and drift-audit results
|
|
189
|
+
per Python function. Failed units include a stable class such as
|
|
190
|
+
`ambiguous_requirement`, `untyped_input`, `invented_param`, or `scope_escape`,
|
|
191
|
+
plus the offending source phrase or code location. Existing pass/fail rules do
|
|
192
|
+
not change.
|
|
193
|
+
|
|
194
|
+
For machine-readable output:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
specline strict my_feature --json
|
|
198
|
+
specline audit my_feature --files slices/my_feature/logic.py --json
|
|
199
|
+
```
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# SpecLine 🏭
|
|
2
|
+
|
|
3
|
+
**A spec-driven production line for AI coding agents.** PRD → spec → plan →
|
|
4
|
+
atomic task packets → gated code → production, with token-lean context
|
|
5
|
+
hygiene enforced by tooling instead of discipline, and a compiled-decision
|
|
6
|
+
handoff to [Harness Software Factory](../harness-factory) for the logic that
|
|
7
|
+
should never be improvised twice.
|
|
8
|
+
|
|
9
|
+
Works with **Claude Code, Codex, and any agent harness** — one command wires it in.
|
|
10
|
+
|
|
11
|
+
## Workflow at a glance
|
|
12
|
+
|
|
13
|
+
```mermaid
|
|
14
|
+
flowchart LR
|
|
15
|
+
A["PRD or rough idea"] --> B["Draft spec"]
|
|
16
|
+
B --> C["Strict contract check"]
|
|
17
|
+
C -->|"blocks ambiguity"| B
|
|
18
|
+
C --> D["Gate spec and seal hash"]
|
|
19
|
+
D --> E["Create atomic plan"]
|
|
20
|
+
E --> F["Emit one task packet"]
|
|
21
|
+
F --> G["Agent builds exactly one slice"]
|
|
22
|
+
G --> H["Audit code against packet"]
|
|
23
|
+
H -->|"drift found"| F
|
|
24
|
+
H --> I["Gate code and update receipts"]
|
|
25
|
+
I --> J{"Decision table?"}
|
|
26
|
+
J -->|"yes"| K["Handoff to HSF"]
|
|
27
|
+
J -->|"no"| L["Ready for ForgeLine or PR"]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
PRD ──> Spec (EARS+Gherkin) ──> Gate ──> Plan (atomic tasks) ──> Gate
|
|
32
|
+
│
|
|
33
|
+
┌─────────────────────────────────────────┘
|
|
34
|
+
▼
|
|
35
|
+
┌── Ralph Wiggum Loop ──┐ Decision tables in the spec
|
|
36
|
+
│ specline loop next │ ──> specline handoff
|
|
37
|
+
│ → token-budgeted │ ──> HSF compiles them ONCE into
|
|
38
|
+
│ TASK PACKET │ gated, deterministic code
|
|
39
|
+
│ agent does ONE task │ (zero tokens per decision, forever)
|
|
40
|
+
│ specline loop done │
|
|
41
|
+
│ → verify + seal │
|
|
42
|
+
└──── context reset ────┘ ──> Gate ──> ship
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Why
|
|
46
|
+
|
|
47
|
+
Vibe coding hits the wall around four files: context pollution, intent
|
|
48
|
+
drift, API hallucinations. The fixes are known — specs as source of truth,
|
|
49
|
+
constitutions, vertical slices, context resets — but they live in blog
|
|
50
|
+
posts as *discipline*. SpecLine turns them into *tooling*: linted, gated,
|
|
51
|
+
hash-sealed, and receipt-audited, so the discipline holds at 2am too.
|
|
52
|
+
|
|
53
|
+
## Quickstart (5 minutes, no API keys)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install -e ".[dev]"
|
|
57
|
+
specline init # constitution + six-file context system
|
|
58
|
+
specline new refunds # spec + plan skeletons
|
|
59
|
+
# ... you + your agent fill the spec ...
|
|
60
|
+
specline validate refunds # EARS/Gherkin/leak lint — ambiguity dies here
|
|
61
|
+
specline gate spec refunds # hash-sealed human signoff
|
|
62
|
+
specline tasks refunds # atomicity lint: ≤4 files, one slice, verify cmd
|
|
63
|
+
specline gate plan refunds # locks the spec hash (drift guard arms)
|
|
64
|
+
specline loop next refunds # emits a token-budgeted TASK PACKET
|
|
65
|
+
# ... agent session does exactly one packet ...
|
|
66
|
+
specline loop done refunds T1 # runs verify command, seals receipt, advances
|
|
67
|
+
specline handoff refunds # decision table -> HSF workflow spec
|
|
68
|
+
specline agent claude # wires CLAUDE.md + /next-task command
|
|
69
|
+
specline status # token-savings receipt
|
|
70
|
+
pytest -q # 25 tests
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## The mechanisms (what's actually enforced)
|
|
74
|
+
|
|
75
|
+
| Blog-post advice | SpecLine enforcement |
|
|
76
|
+
|---|---|
|
|
77
|
+
| "Write clear specs" | EARS keyword lint, Gherkin required, implementation-leak detection (`E_IMPL_LEAK`) |
|
|
78
|
+
| "Keep tasks small" | Atomicity linter: ≤4 files, one vertical slice, explicit verify command, no skeleton edits |
|
|
79
|
+
| "Reset agent context" | The loop emits self-contained **task packets** under a hard ~2.2k-token budget; one packet = one session |
|
|
80
|
+
| "Minimize context (C_t=γ·R_f·T_d)" | Packets list the exact R_f file set; excerpt only spec lines relevant to the task; deterministic prune over budget |
|
|
81
|
+
| "Prevent intent drift" | Plan gate seals the spec hash; if the spec changes, the loop **refuses** (`E_INTENT_DRIFT`) until re-gated |
|
|
82
|
+
| "Human review gates" | `specline gate spec|plan|code` writes hash-sealed signoff receipts to the progress tracker |
|
|
83
|
+
| "Don't let agents improvise business rules" | Decision tables compile through HSF: one-time generation, four gates, zero tokens per decision |
|
|
84
|
+
| "Measure the process" | SpecFactor gauge (Goldilocks 0.75–2.5) + a **context ledger**: packet tokens vs naive baseline, % saved |
|
|
85
|
+
|
|
86
|
+
## Agent integration
|
|
87
|
+
|
|
88
|
+
- **Claude Code:** `specline agent claude` → writes `CLAUDE.md` (constitution +
|
|
89
|
+
protocol) and `.claude/commands/next-task.md`. The whole loop is one slash command.
|
|
90
|
+
- **Codex:** `specline agent codex` → appends the protocol to `AGENTS.md`
|
|
91
|
+
(Codex reads it natively).
|
|
92
|
+
- **Anything else:** `specline agent <name>` → portable constitution file.
|
|
93
|
+
The protocol is plain text; any harness that can read a file can follow it.
|
|
94
|
+
|
|
95
|
+
## The factory calibration (the part that saves real money)
|
|
96
|
+
|
|
97
|
+
Most business logic in AI-built apps is *decision-shaped*: ordered rules over
|
|
98
|
+
extracted facts. Letting agents re-implement those rules inline is how you get
|
|
99
|
+
inconsistent behavior and burned tokens. SpecLine specs carry a
|
|
100
|
+
`## Decision logic` table; `specline handoff` converts it to a Harness
|
|
101
|
+
Software Factory spec, and HSF compiles it once into deterministic, gated,
|
|
102
|
+
signed code — verified end-to-end in this repo's test suite against a real
|
|
103
|
+
HSF install. App code flows through the line; decisions flow through the
|
|
104
|
+
factory; nothing is improvised twice.
|
|
105
|
+
|
|
106
|
+
## Receipts culture
|
|
107
|
+
|
|
108
|
+
Every gate signoff, packet emission, and task completion writes a hash-sealed
|
|
109
|
+
line to `context/PROGRESS.md`, and the context ledger accumulates the token
|
|
110
|
+
economics (`specline status` — the walkthrough example shows ~75% saved vs
|
|
111
|
+
naive full-context sessions, and the gap widens as the repo grows). Claims
|
|
112
|
+
trace to receipts, never to vibes. That's the whole point.
|
|
113
|
+
|
|
114
|
+
MIT licensed.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## v0.2 — Strict Input Contract & Drift Audit
|
|
119
|
+
|
|
120
|
+
The base linter checks that a spec *looks* right (EARS keywords present, valid task
|
|
121
|
+
format). That's necessary but not sufficient: it lets **ambiguity** through, and the
|
|
122
|
+
AI coder then *invents* the missing parameters — which is drift. v0.2 closes that gap
|
|
123
|
+
with two new stages that bracket the coder.
|
|
124
|
+
|
|
125
|
+
### `specline strict <feature>` — reject ambiguity *before* the coder runs
|
|
126
|
+
|
|
127
|
+
Treats the spec as a **contract the coder must execute with zero invention**. Every
|
|
128
|
+
finding is a BLOCK with an exact line and fix. It catches the five drift sources:
|
|
129
|
+
|
|
130
|
+
1. **Incomplete requirements** — an EARS keyword isn't enough. Each requirement must
|
|
131
|
+
have a concrete outcome verb (`return`/`reject`/`store`/…), not `handle`/`support`/
|
|
132
|
+
`manage`. `The system shall handle it appropriately` is rejected.
|
|
133
|
+
2. **Surviving placeholders** — `<trigger>`, `<N>`, `TBD` can't reach an approved spec.
|
|
134
|
+
3. **Unquantified bounds** — a requirement that implies a timeout/limit/retry/size must
|
|
135
|
+
state a number+unit.
|
|
136
|
+
4. **Untraceable acceptance** — every value in a Given/When/Then must be defined in a
|
|
137
|
+
requirement or the data model. A Gherkin step can't introduce a fact the coder would
|
|
138
|
+
have to invent.
|
|
139
|
+
5. **Non-deterministic decisions** — each rule's `if` references a declared fact and its
|
|
140
|
+
`then` is exactly one outcome. No `maybe`/`or`/`etc`; no duplicate conditions.
|
|
141
|
+
(`else`/`default` catch-all rows are allowed.)
|
|
142
|
+
|
|
143
|
+
An `approved` spec that still fails strict raises `S_APPROVED_BUT_AMBIGUOUS` — approval
|
|
144
|
+
is a lie until the blocks are resolved.
|
|
145
|
+
|
|
146
|
+
Strict is **on by default** in `specline gate spec|plan`. Pass `strict=False` to the
|
|
147
|
+
gate API only for legacy specs.
|
|
148
|
+
|
|
149
|
+
### `specline audit <feature> --files … --slice …` — catch drift *after* the coder runs
|
|
150
|
+
|
|
151
|
+
Compares what shipped against what the contract authorized:
|
|
152
|
+
|
|
153
|
+
- **`A_INVENTED_PARAM`** — a config value (`TIMEOUT = 45`) whose number the spec never
|
|
154
|
+
authorized. The coder guessed; the audit fails the build.
|
|
155
|
+
- **`A_SCOPE_ESCAPE`** — a file outside the task's authorized slice.
|
|
156
|
+
- **`A_UNAUTHORIZED_FILE`** — a file not in the packet's list.
|
|
157
|
+
- **`A_STUB_LEFT`** — a `TODO`/`NotImplementedError` left behind.
|
|
158
|
+
|
|
159
|
+
### Requirement-scoped packets
|
|
160
|
+
|
|
161
|
+
The packet excerpt no longer bag-of-words-matches individual lines (which could hand the
|
|
162
|
+
agent half a requirement). It now ships **whole requirement blocks** and the **complete
|
|
163
|
+
acceptance scenario intact** — the agent never receives a partial rule to improvise around.
|
|
164
|
+
|
|
165
|
+
### Flow
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
new → write spec → validate → strict → gate spec → write plan → tasks → gate plan
|
|
169
|
+
→ loop (build) → audit → gate code → handoff
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Deterministic by design: same spec text → same findings, every run. No LLM, no clock.
|
|
173
|
+
## Failure attribution
|
|
174
|
+
|
|
175
|
+
SpecLine 0.3 reports strict-lint results per requirement and drift-audit results
|
|
176
|
+
per Python function. Failed units include a stable class such as
|
|
177
|
+
`ambiguous_requirement`, `untyped_input`, `invented_param`, or `scope_escape`,
|
|
178
|
+
plus the offending source phrase or code location. Existing pass/fail rules do
|
|
179
|
+
not change.
|
|
180
|
+
|
|
181
|
+
For machine-readable output:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
specline strict my_feature --json
|
|
185
|
+
specline audit my_feature --files slices/my_feature/logic.py --json
|
|
186
|
+
```
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: code-factory-1-spec
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: SpecLine — a spec-driven production line for AI-assisted engineering: PRD -> spec -> plan -> atomic task packets -> gated code, with token-lean context hygiene and a compiled-decision handoff to Harness Software Factory (HSF).
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: PyYAML>=6.0
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# SpecLine 🏭
|
|
15
|
+
|
|
16
|
+
**A spec-driven production line for AI coding agents.** PRD → spec → plan →
|
|
17
|
+
atomic task packets → gated code → production, with token-lean context
|
|
18
|
+
hygiene enforced by tooling instead of discipline, and a compiled-decision
|
|
19
|
+
handoff to [Harness Software Factory](../harness-factory) for the logic that
|
|
20
|
+
should never be improvised twice.
|
|
21
|
+
|
|
22
|
+
Works with **Claude Code, Codex, and any agent harness** — one command wires it in.
|
|
23
|
+
|
|
24
|
+
## Workflow at a glance
|
|
25
|
+
|
|
26
|
+
```mermaid
|
|
27
|
+
flowchart LR
|
|
28
|
+
A["PRD or rough idea"] --> B["Draft spec"]
|
|
29
|
+
B --> C["Strict contract check"]
|
|
30
|
+
C -->|"blocks ambiguity"| B
|
|
31
|
+
C --> D["Gate spec and seal hash"]
|
|
32
|
+
D --> E["Create atomic plan"]
|
|
33
|
+
E --> F["Emit one task packet"]
|
|
34
|
+
F --> G["Agent builds exactly one slice"]
|
|
35
|
+
G --> H["Audit code against packet"]
|
|
36
|
+
H -->|"drift found"| F
|
|
37
|
+
H --> I["Gate code and update receipts"]
|
|
38
|
+
I --> J{"Decision table?"}
|
|
39
|
+
J -->|"yes"| K["Handoff to HSF"]
|
|
40
|
+
J -->|"no"| L["Ready for ForgeLine or PR"]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
PRD ──> Spec (EARS+Gherkin) ──> Gate ──> Plan (atomic tasks) ──> Gate
|
|
45
|
+
│
|
|
46
|
+
┌─────────────────────────────────────────┘
|
|
47
|
+
▼
|
|
48
|
+
┌── Ralph Wiggum Loop ──┐ Decision tables in the spec
|
|
49
|
+
│ specline loop next │ ──> specline handoff
|
|
50
|
+
│ → token-budgeted │ ──> HSF compiles them ONCE into
|
|
51
|
+
│ TASK PACKET │ gated, deterministic code
|
|
52
|
+
│ agent does ONE task │ (zero tokens per decision, forever)
|
|
53
|
+
│ specline loop done │
|
|
54
|
+
│ → verify + seal │
|
|
55
|
+
└──── context reset ────┘ ──> Gate ──> ship
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Why
|
|
59
|
+
|
|
60
|
+
Vibe coding hits the wall around four files: context pollution, intent
|
|
61
|
+
drift, API hallucinations. The fixes are known — specs as source of truth,
|
|
62
|
+
constitutions, vertical slices, context resets — but they live in blog
|
|
63
|
+
posts as *discipline*. SpecLine turns them into *tooling*: linted, gated,
|
|
64
|
+
hash-sealed, and receipt-audited, so the discipline holds at 2am too.
|
|
65
|
+
|
|
66
|
+
## Quickstart (5 minutes, no API keys)
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install -e ".[dev]"
|
|
70
|
+
specline init # constitution + six-file context system
|
|
71
|
+
specline new refunds # spec + plan skeletons
|
|
72
|
+
# ... you + your agent fill the spec ...
|
|
73
|
+
specline validate refunds # EARS/Gherkin/leak lint — ambiguity dies here
|
|
74
|
+
specline gate spec refunds # hash-sealed human signoff
|
|
75
|
+
specline tasks refunds # atomicity lint: ≤4 files, one slice, verify cmd
|
|
76
|
+
specline gate plan refunds # locks the spec hash (drift guard arms)
|
|
77
|
+
specline loop next refunds # emits a token-budgeted TASK PACKET
|
|
78
|
+
# ... agent session does exactly one packet ...
|
|
79
|
+
specline loop done refunds T1 # runs verify command, seals receipt, advances
|
|
80
|
+
specline handoff refunds # decision table -> HSF workflow spec
|
|
81
|
+
specline agent claude # wires CLAUDE.md + /next-task command
|
|
82
|
+
specline status # token-savings receipt
|
|
83
|
+
pytest -q # 25 tests
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## The mechanisms (what's actually enforced)
|
|
87
|
+
|
|
88
|
+
| Blog-post advice | SpecLine enforcement |
|
|
89
|
+
|---|---|
|
|
90
|
+
| "Write clear specs" | EARS keyword lint, Gherkin required, implementation-leak detection (`E_IMPL_LEAK`) |
|
|
91
|
+
| "Keep tasks small" | Atomicity linter: ≤4 files, one vertical slice, explicit verify command, no skeleton edits |
|
|
92
|
+
| "Reset agent context" | The loop emits self-contained **task packets** under a hard ~2.2k-token budget; one packet = one session |
|
|
93
|
+
| "Minimize context (C_t=γ·R_f·T_d)" | Packets list the exact R_f file set; excerpt only spec lines relevant to the task; deterministic prune over budget |
|
|
94
|
+
| "Prevent intent drift" | Plan gate seals the spec hash; if the spec changes, the loop **refuses** (`E_INTENT_DRIFT`) until re-gated |
|
|
95
|
+
| "Human review gates" | `specline gate spec|plan|code` writes hash-sealed signoff receipts to the progress tracker |
|
|
96
|
+
| "Don't let agents improvise business rules" | Decision tables compile through HSF: one-time generation, four gates, zero tokens per decision |
|
|
97
|
+
| "Measure the process" | SpecFactor gauge (Goldilocks 0.75–2.5) + a **context ledger**: packet tokens vs naive baseline, % saved |
|
|
98
|
+
|
|
99
|
+
## Agent integration
|
|
100
|
+
|
|
101
|
+
- **Claude Code:** `specline agent claude` → writes `CLAUDE.md` (constitution +
|
|
102
|
+
protocol) and `.claude/commands/next-task.md`. The whole loop is one slash command.
|
|
103
|
+
- **Codex:** `specline agent codex` → appends the protocol to `AGENTS.md`
|
|
104
|
+
(Codex reads it natively).
|
|
105
|
+
- **Anything else:** `specline agent <name>` → portable constitution file.
|
|
106
|
+
The protocol is plain text; any harness that can read a file can follow it.
|
|
107
|
+
|
|
108
|
+
## The factory calibration (the part that saves real money)
|
|
109
|
+
|
|
110
|
+
Most business logic in AI-built apps is *decision-shaped*: ordered rules over
|
|
111
|
+
extracted facts. Letting agents re-implement those rules inline is how you get
|
|
112
|
+
inconsistent behavior and burned tokens. SpecLine specs carry a
|
|
113
|
+
`## Decision logic` table; `specline handoff` converts it to a Harness
|
|
114
|
+
Software Factory spec, and HSF compiles it once into deterministic, gated,
|
|
115
|
+
signed code — verified end-to-end in this repo's test suite against a real
|
|
116
|
+
HSF install. App code flows through the line; decisions flow through the
|
|
117
|
+
factory; nothing is improvised twice.
|
|
118
|
+
|
|
119
|
+
## Receipts culture
|
|
120
|
+
|
|
121
|
+
Every gate signoff, packet emission, and task completion writes a hash-sealed
|
|
122
|
+
line to `context/PROGRESS.md`, and the context ledger accumulates the token
|
|
123
|
+
economics (`specline status` — the walkthrough example shows ~75% saved vs
|
|
124
|
+
naive full-context sessions, and the gap widens as the repo grows). Claims
|
|
125
|
+
trace to receipts, never to vibes. That's the whole point.
|
|
126
|
+
|
|
127
|
+
MIT licensed.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## v0.2 — Strict Input Contract & Drift Audit
|
|
132
|
+
|
|
133
|
+
The base linter checks that a spec *looks* right (EARS keywords present, valid task
|
|
134
|
+
format). That's necessary but not sufficient: it lets **ambiguity** through, and the
|
|
135
|
+
AI coder then *invents* the missing parameters — which is drift. v0.2 closes that gap
|
|
136
|
+
with two new stages that bracket the coder.
|
|
137
|
+
|
|
138
|
+
### `specline strict <feature>` — reject ambiguity *before* the coder runs
|
|
139
|
+
|
|
140
|
+
Treats the spec as a **contract the coder must execute with zero invention**. Every
|
|
141
|
+
finding is a BLOCK with an exact line and fix. It catches the five drift sources:
|
|
142
|
+
|
|
143
|
+
1. **Incomplete requirements** — an EARS keyword isn't enough. Each requirement must
|
|
144
|
+
have a concrete outcome verb (`return`/`reject`/`store`/…), not `handle`/`support`/
|
|
145
|
+
`manage`. `The system shall handle it appropriately` is rejected.
|
|
146
|
+
2. **Surviving placeholders** — `<trigger>`, `<N>`, `TBD` can't reach an approved spec.
|
|
147
|
+
3. **Unquantified bounds** — a requirement that implies a timeout/limit/retry/size must
|
|
148
|
+
state a number+unit.
|
|
149
|
+
4. **Untraceable acceptance** — every value in a Given/When/Then must be defined in a
|
|
150
|
+
requirement or the data model. A Gherkin step can't introduce a fact the coder would
|
|
151
|
+
have to invent.
|
|
152
|
+
5. **Non-deterministic decisions** — each rule's `if` references a declared fact and its
|
|
153
|
+
`then` is exactly one outcome. No `maybe`/`or`/`etc`; no duplicate conditions.
|
|
154
|
+
(`else`/`default` catch-all rows are allowed.)
|
|
155
|
+
|
|
156
|
+
An `approved` spec that still fails strict raises `S_APPROVED_BUT_AMBIGUOUS` — approval
|
|
157
|
+
is a lie until the blocks are resolved.
|
|
158
|
+
|
|
159
|
+
Strict is **on by default** in `specline gate spec|plan`. Pass `strict=False` to the
|
|
160
|
+
gate API only for legacy specs.
|
|
161
|
+
|
|
162
|
+
### `specline audit <feature> --files … --slice …` — catch drift *after* the coder runs
|
|
163
|
+
|
|
164
|
+
Compares what shipped against what the contract authorized:
|
|
165
|
+
|
|
166
|
+
- **`A_INVENTED_PARAM`** — a config value (`TIMEOUT = 45`) whose number the spec never
|
|
167
|
+
authorized. The coder guessed; the audit fails the build.
|
|
168
|
+
- **`A_SCOPE_ESCAPE`** — a file outside the task's authorized slice.
|
|
169
|
+
- **`A_UNAUTHORIZED_FILE`** — a file not in the packet's list.
|
|
170
|
+
- **`A_STUB_LEFT`** — a `TODO`/`NotImplementedError` left behind.
|
|
171
|
+
|
|
172
|
+
### Requirement-scoped packets
|
|
173
|
+
|
|
174
|
+
The packet excerpt no longer bag-of-words-matches individual lines (which could hand the
|
|
175
|
+
agent half a requirement). It now ships **whole requirement blocks** and the **complete
|
|
176
|
+
acceptance scenario intact** — the agent never receives a partial rule to improvise around.
|
|
177
|
+
|
|
178
|
+
### Flow
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
new → write spec → validate → strict → gate spec → write plan → tasks → gate plan
|
|
182
|
+
→ loop (build) → audit → gate code → handoff
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Deterministic by design: same spec text → same findings, every run. No LLM, no clock.
|
|
186
|
+
## Failure attribution
|
|
187
|
+
|
|
188
|
+
SpecLine 0.3 reports strict-lint results per requirement and drift-audit results
|
|
189
|
+
per Python function. Failed units include a stable class such as
|
|
190
|
+
`ambiguous_requirement`, `untyped_input`, `invented_param`, or `scope_escape`,
|
|
191
|
+
plus the offending source phrase or code location. Existing pass/fail rules do
|
|
192
|
+
not change.
|
|
193
|
+
|
|
194
|
+
For machine-readable output:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
specline strict my_feature --json
|
|
198
|
+
specline audit my_feature --files slices/my_feature/logic.py --json
|
|
199
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
code_factory_1_spec.egg-info/PKG-INFO
|
|
5
|
+
code_factory_1_spec.egg-info/SOURCES.txt
|
|
6
|
+
code_factory_1_spec.egg-info/dependency_links.txt
|
|
7
|
+
code_factory_1_spec.egg-info/entry_points.txt
|
|
8
|
+
code_factory_1_spec.egg-info/requires.txt
|
|
9
|
+
code_factory_1_spec.egg-info/top_level.txt
|
|
10
|
+
specline/__init__.py
|
|
11
|
+
specline/adapters.py
|
|
12
|
+
specline/attribution.py
|
|
13
|
+
specline/cli.py
|
|
14
|
+
specline/drift_audit.py
|
|
15
|
+
specline/gates.py
|
|
16
|
+
specline/handoff.py
|
|
17
|
+
specline/ledger.py
|
|
18
|
+
specline/loop.py
|
|
19
|
+
specline/packets.py
|
|
20
|
+
specline/paths.py
|
|
21
|
+
specline/plan_lint.py
|
|
22
|
+
specline/scaffold.py
|
|
23
|
+
specline/spec_lint.py
|
|
24
|
+
specline/specfactor.py
|
|
25
|
+
specline/strict_lint.py
|
|
26
|
+
specline/../templates/AGENTS.md
|
|
27
|
+
specline/../templates/PLAN_TEMPLATE.md
|
|
28
|
+
specline/../templates/SPEC_TEMPLATE.md
|
|
29
|
+
specline/../templates/context/AI_WORKFLOW_RULES.md
|
|
30
|
+
specline/../templates/context/ARCHITECTURE.md
|
|
31
|
+
specline/../templates/context/CODE_STANDARDS.md
|
|
32
|
+
specline/../templates/context/PROGRESS.md
|
|
33
|
+
specline/../templates/context/PROJECT_OVERVIEW.md
|
|
34
|
+
specline/../templates/context/UI_CONTEXT.md
|
|
35
|
+
specline/../templates/personas/reviewer.md
|
|
36
|
+
specline/../templates/personas/security_auditor.md
|
|
37
|
+
tests/test_specline.py
|
|
38
|
+
tests/test_strict.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
specline
|