codexspec 0.7.11__tar.gz → 0.7.12__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.
- {codexspec-0.7.11 → codexspec-0.7.12}/PKG-INFO +1 -1
- {codexspec-0.7.11 → codexspec-0.7.12}/pyproject.toml +1 -1
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/__init__.py +1 -1
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/profile.py +30 -11
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/distill.md +72 -2
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/evolve.md +2 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/onboard.md +4 -4
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/specify.md +1 -1
- {codexspec-0.7.11 → codexspec-0.7.12}/.gitignore +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/LICENSE +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/README.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/codexspec-icon.svg +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/codexspec-logo-dark.svg +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/codexspec-logo-light.svg +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/scripts/bash/check-i18n-completeness.sh +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/scripts/bash/check-i18n-structure.sh +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/scripts/bash/check-prerequisites.sh +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/scripts/bash/common.sh +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/scripts/bash/create-new-feature.sh +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/scripts/bash/review-context.sh +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/scripts/powershell/check-prerequisites.ps1 +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/scripts/powershell/common.ps1 +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/scripts/powershell/create-new-feature.ps1 +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/scripts/powershell/review-context.ps1 +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/commands/__init__.py +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/commands/installer.py +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/i18n.py +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/idea.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/integrations/__init__.py +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/integrations/base.py +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/integrations/claude.py +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/integrations/codex.py +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/src/codexspec/translator.py +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/analyze.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/checklist.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/clarify.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/commit-staged.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/config.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/constitution.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/debug.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/generate-spec.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/implement-tasks.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/plan-to-tasks.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/pr.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/quick.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/release-notes.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/review-code.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/review-design.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/review-plan.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/review-spec.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/review-tasks.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/spec-to-design.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/spec-to-plan.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/commands/tasks-to-issues.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/docs/checklist-template.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/docs/constitution-template.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/docs/design-template.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/docs/plan-template-detailed.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/docs/plan-template-simple.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/docs/requirements-template.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/docs/spec-template-detailed.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/docs/spec-template-simple.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/docs/tasks-template-detailed.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/docs/tasks-template-simple.md +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/translations/de.json +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/translations/en.json +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/translations/es.json +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/translations/fr.json +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/translations/ja.json +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/translations/ko.json +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/translations/pt-BR.json +0 -0
- {codexspec-0.7.11 → codexspec-0.7.12}/templates/translations/zh-CN.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: codexspec
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.12
|
|
4
4
|
Summary: CodexSpec - A Requirements-First SDD toolkit for Claude Code
|
|
5
5
|
Project-URL: Homepage, https://github.com/Zts0hg/codexspec
|
|
6
6
|
Project-URL: Repository, https://github.com/Zts0hg/codexspec
|
|
@@ -44,7 +44,7 @@ from .profile import ensure_profile_scaffold, inject_profile_block
|
|
|
44
44
|
from .translator import SUPPORTED_LANGUAGES, translate
|
|
45
45
|
|
|
46
46
|
# Version info
|
|
47
|
-
__version__ = "0.7.
|
|
47
|
+
__version__ = "0.7.12"
|
|
48
48
|
__author__ = "CodexSpec Team"
|
|
49
49
|
|
|
50
50
|
# Constitution file path constants
|
|
@@ -4,13 +4,13 @@ Wires a user project's ``.codexspec/profile/`` into the AI context files so that
|
|
|
4
4
|
knowledge distilled by ``/codexspec:distill`` is consulted in later work.
|
|
5
5
|
|
|
6
6
|
Store layout: **one record per file** under a per-category directory
|
|
7
|
-
(``constraints/`` ``conventions/`` ``pitfalls/`` ``decisions/``
|
|
8
|
-
feature branches each add differently-named
|
|
9
|
-
knowledge merges without conflict.
|
|
7
|
+
(``constraints/`` ``conventions/`` ``pitfalls/`` ``decisions/`` ``strategies/``
|
|
8
|
+
``runbooks/``). Because parallel feature branches each add differently-named
|
|
9
|
+
record files, their distilled knowledge merges without conflict.
|
|
10
10
|
|
|
11
11
|
Two concerns live here:
|
|
12
12
|
|
|
13
|
-
- ``ensure_profile_scaffold`` — create the
|
|
13
|
+
- ``ensure_profile_scaffold`` — create the six category directories (each kept
|
|
14
14
|
by a ``.gitkeep``) so every injected reference resolves, independent of whether
|
|
15
15
|
any knowledge has been distilled yet.
|
|
16
16
|
- ``render_profile_block`` / ``inject_profile_block`` — render a bounded,
|
|
@@ -27,7 +27,14 @@ from pathlib import Path
|
|
|
27
27
|
|
|
28
28
|
# Ordered: constraints first (highest weight, honored first). Each is a directory
|
|
29
29
|
# holding one record per file.
|
|
30
|
-
PROFILE_CATEGORIES = (
|
|
30
|
+
PROFILE_CATEGORIES = (
|
|
31
|
+
"constraints",
|
|
32
|
+
"conventions",
|
|
33
|
+
"pitfalls",
|
|
34
|
+
"decisions",
|
|
35
|
+
"strategies",
|
|
36
|
+
"runbooks",
|
|
37
|
+
)
|
|
31
38
|
|
|
32
39
|
PROFILE_BLOCK_START = "<!-- CODEXSPEC PROFILE START -->"
|
|
33
40
|
PROFILE_BLOCK_END = "<!-- CODEXSPEC PROFILE END -->"
|
|
@@ -43,24 +50,33 @@ _PROFILE_BLOCK = "".join(
|
|
|
43
50
|
"**Project constraints (highest priority — read these FIRST):** before any non-trivial work you MUST ",
|
|
44
51
|
"read every record under `.codexspec/profile/constraints/` — the project's hard prohibitions ",
|
|
45
52
|
"(严禁 / 仅允许). Honor them before anything else.\n\n",
|
|
46
|
-
"**
|
|
53
|
+
"**Actively recall relevant knowledge before non-trivial work.** Do not wait to stumble on it: ",
|
|
54
|
+
"scan the record headings and their `scope/when` (and, for strategies, `trigger`) lines across the ",
|
|
55
|
+
"categories below, and read every record whose condition matches the task you are about to start ",
|
|
47
56
|
"(each directory holds one record per file):\n\n",
|
|
48
57
|
"- `.codexspec/profile/conventions/` — cross-feature conventions / steering; ",
|
|
49
58
|
"read before adopting a pattern, structure, or naming choice.\n",
|
|
50
59
|
"- `.codexspec/profile/pitfalls/` — known traps and their workarounds; ",
|
|
51
60
|
"read before implementing or debugging in an area that may have bitten before.\n",
|
|
52
61
|
"- `.codexspec/profile/decisions/` — past cross-feature / architectural decisions; ",
|
|
53
|
-
"read before deciding in the same area, to reuse prior rationale rather than re-litigate it.\n
|
|
62
|
+
"read before deciding in the same area, to reuse prior rationale rather than re-litigate it.\n",
|
|
63
|
+
"- `.codexspec/profile/strategies/` — metacognitive trigger→action rules (and `scope: self` notes on ",
|
|
64
|
+
"the agent's own recurring slips); read before choosing an approach or when a fix is not converging.\n",
|
|
65
|
+
"- `.codexspec/profile/runbooks/` — ordered multi-step procedures with failure recovery; ",
|
|
66
|
+
"read before carrying out a known multi-step task.\n\n",
|
|
54
67
|
"Read the full record — each carries a `status` of `candidate` or `vetted`; ",
|
|
55
68
|
"weight `candidate` items with appropriate caution. A directory may be empty ",
|
|
56
|
-
"until `/codexspec:distill` has captured knowledge.\n",
|
|
69
|
+
"until `/codexspec:distill` has captured knowledge.\n\n",
|
|
70
|
+
"**Capture knowledge as you go.** When this session produces reusable cross-feature knowledge — even ",
|
|
71
|
+
"in plain chat or a non-SDD fix — run `/codexspec:distill` near that moment rather than only at ",
|
|
72
|
+
"wrap-up. It is non-blocking and early-exits when there is nothing new.\n",
|
|
57
73
|
f"{PROFILE_BLOCK_END}\n",
|
|
58
74
|
]
|
|
59
75
|
)
|
|
60
76
|
|
|
61
77
|
|
|
62
78
|
def ensure_profile_scaffold(target_dir: Path) -> Path:
|
|
63
|
-
"""Create ``.codexspec/profile/`` and its
|
|
79
|
+
"""Create ``.codexspec/profile/`` and its six category directories if absent.
|
|
64
80
|
|
|
65
81
|
Each category is a directory of one-record-per-file entries; a ``.gitkeep``
|
|
66
82
|
keeps an empty category tracked so every pointer resolves. Idempotent and
|
|
@@ -79,10 +95,13 @@ def ensure_profile_scaffold(target_dir: Path) -> Path:
|
|
|
79
95
|
def render_profile_block() -> str:
|
|
80
96
|
"""Render the bounded managed profile block.
|
|
81
97
|
|
|
82
|
-
Identical for CLAUDE.md and AGENTS.md: constraints and the
|
|
98
|
+
Identical for CLAUDE.md and AGENTS.md: constraints and the five on-demand
|
|
83
99
|
categories are all delivered as pointers to their directories — no ``@import``
|
|
84
100
|
anywhere — so the block is channel-neutral and the store can be
|
|
85
|
-
one-file-per-record directories that merge without conflict.
|
|
101
|
+
one-file-per-record directories that merge without conflict. The block also
|
|
102
|
+
directs active recall (scan record ``scope/when``/``trigger`` and read matches
|
|
103
|
+
before non-trivial work) and near-moment ``distill`` capture; it is a fixed
|
|
104
|
+
directive whose size is independent of how many records the profile holds.
|
|
86
105
|
"""
|
|
87
106
|
return _PROFILE_BLOCK
|
|
88
107
|
|
|
@@ -23,6 +23,8 @@ Converse in the interaction language and author artifacts in the document langua
|
|
|
23
23
|
`distill` extracts the reusable, cross-feature knowledge produced during work and persists it to the project-level store `.codexspec/profile/`. It runs two ways:
|
|
24
24
|
|
|
25
25
|
- **Auto (primary)**: embedded in wrap-up commands (`implement-tasks` on completion, `commit-staged`, `pr`), gated by `workflow.auto_distill` in `.codexspec/config.yml` (**default enabled**; disabled only when explicitly set to the literal `false`).
|
|
26
|
+
- **Near-moment (ambient)**: driven by the profile block's "capture knowledge as you go" rule, distill may be invoked **near the moment** reusable cross-feature knowledge is produced — in **any session**, including plain chat or a **non-SDD fix** that never reaches a wrap-up command. This is the primary way knowledge from ad-hoc work is captured at all.
|
|
27
|
+
- **Long-run**: in a long-running `implement-tasks`, distill **along the way** near each knowledge-producing event rather than only at the very end, so mid-task evidence is not lost to context compaction; the end-of-task `auto_distill` still runs as a **backstop**.
|
|
26
28
|
- **Manual (fallback)**: invoked directly on the supplied or most-recent interaction segment.
|
|
27
29
|
|
|
28
30
|
distill is **non-blocking and non-interactive**: it never prompts, never gates another command, and **early-exits without writing** when the delta contains nothing reusable.
|
|
@@ -42,12 +44,16 @@ Apply this boundary test to every candidate: **"Would a single feature's `requir
|
|
|
42
44
|
|
|
43
45
|
## The profile store: `.codexspec/profile/`
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
Six **category directories**, each holding **one record per file** (`<id>.md`) with **only current-effective** knowledge — dense, with no "retired" section (git history is the ledger). One-file-per-record is deliberate: parallel feature branches each add differently-named files, so distilled knowledge merges without conflict. Create the directory and record file on first write.
|
|
46
48
|
|
|
47
49
|
- `constraints/` — negative constraints (`严禁 / 仅允许`). These carry the **highest** weight and MUST be honored first.
|
|
48
50
|
- `conventions/` — positive cross-feature conventions / steering.
|
|
49
51
|
- `pitfalls/` — cross-feature traps and their workarounds.
|
|
50
52
|
- `decisions/` — cross-feature / architectural decisions only (ADR-lite). **Never** single-feature requirement rationale.
|
|
53
|
+
- `strategies/` — metacognitive `trigger → action` rules: when you recognize signal X, switch to approach Y. A **self-model** (knowledge about the agent's own recurring slips in this project) lives here too, marked `scope: self`. A strategy is the layer **above** a pitfall — the transferable "what to do when" generalized across many specific traps.
|
|
54
|
+
- `runbooks/` — ordered multi-step procedures with failure recovery: how to carry out a known multi-step task (e.g. a release), step by step, including what to do when a step fails.
|
|
55
|
+
|
|
56
|
+
There is **no** `facts/` category — a bare fact with no "therefore do X" is either feature-scoped (leave it in `requirements.md`) or belongs as a `convention`/`constraint` with an evidence anchor.
|
|
51
57
|
|
|
52
58
|
### Record format — `claim` and `evidence` physically separated
|
|
53
59
|
|
|
@@ -55,7 +61,7 @@ Every record MUST separate the distilled claim from the evidence it rests on:
|
|
|
55
61
|
|
|
56
62
|
- `id` — **type letter + full source-feature id + local sequence**, e.g. `P-2026-0812-14054p-1` or `Con-2026-0812-14054p-1`. It is **both** the record's `### <id>: <title>` heading **and its filename** (`pitfalls/P-2026-0812-14054p-1.md`). The **source-feature id** is the distilling feature's full spec-dir id `{YYYY-MMDD-HHMM}{rr}` (e.g. `2026-0812-14054p`); it is globally unique by the timestamp+random scheme spec directories use, so records distilled on parallel feature branches never collide on id **or filename** (they merge with no conflict). Keep the **full** id (not a short tail) so the record is self-describing: the date supports recency/staleness reading, and the feature id ties the record to its originating change for decision context and scope. When distilling with no feature context, generate a fresh `{YYYY-MMDD-HHMM}{rr}` id now (same convention as create-new-feature). **Never** use a bare sequential id such as `P-001` — those collide across parallel branches.
|
|
57
63
|
- `claim` — one-sentence reusable **summary** (a title line, not the actionable body — for a `pitfall` the usable content lives in the three body parts below, not in this sentence).
|
|
58
|
-
- `type` — `convention` | `constraint` | `pitfall` | `decision` (`constraint` = highest priority).
|
|
64
|
+
- `type` — `convention` | `constraint` | `pitfall` | `decision` | `strategy` | `runbook` (`constraint` = highest priority).
|
|
59
65
|
- `scope/when` — natural-language applicability condition (e.g. "when editing Python code"); omit for global. **No formal syntax.**
|
|
60
66
|
- `evidence.facts` — the concrete observations behind it; **quote the user's original words, do not paraphrase**.
|
|
61
67
|
- `evidence.state` — the context/validity when true (feature / commit / config; still valid?).
|
|
@@ -70,6 +76,20 @@ Every record MUST separate the distilled claim from the evidence it rests on:
|
|
|
70
76
|
|
|
71
77
|
If you cannot state all three, the pitfall is not yet understood well enough to record. `convention` / `constraint` / `decision` records usually need only `claim` + `evidence`; this three-part body is required specifically for traps.
|
|
72
78
|
|
|
79
|
+
**Strategy records carry a `trigger → action` body.** A `strategy` MUST, beyond `claim` and `evidence`, spell out two parts:
|
|
80
|
+
|
|
81
|
+
- `trigger` — the **signature** by which you recognize you are in this situation (e.g. "a substring contract test fails", "a fix is not converging after several attempts"). This is what lets the strategy be recalled by the situation, not by remembering the one incident that produced it.
|
|
82
|
+
- `action` — what to do when the trigger fires.
|
|
83
|
+
|
|
84
|
+
A **self-model** — a strategy about your *own* recurring slip (e.g. "I keep forgetting to regenerate derived forms") — is a strategy marked `scope: self`; its `trigger` is self-referential but the body is identical.
|
|
85
|
+
|
|
86
|
+
**Runbook records carry an ordered body.** A `runbook` MUST, beyond `claim` and `evidence`, spell out:
|
|
87
|
+
|
|
88
|
+
- `steps` — the ordered steps to carry out the task.
|
|
89
|
+
- `failure-recovery` — for the steps that can fail, what to do to recover (the branch that a flat one-line record loses).
|
|
90
|
+
|
|
91
|
+
If you cannot state these parts, the strategy or runbook is not yet worth recording — the same anti-hollow bar as pitfalls.
|
|
92
|
+
|
|
73
93
|
> **onboard variant**: `/codexspec:onboard` writes to this same store and format, with one difference — its records are inferred from code, so `evidence.facts` holds a verbatim **code observation** (path + snippet) instead of a user quote, `provenance` marks the onboard scan, and `derivation` is always `inferred`. onboard therefore writes `status: candidate` **at write time** (it never writes `vetted` itself); such a record can still be promoted to `vetted` later once it is outcome-verified and approved in `/distill review` — its `inferred` origin is not a barrier (per the `status` rule above).
|
|
74
94
|
|
|
75
95
|
This separation is what makes a later error locatable as **misread** (facts wrong) vs **overreach** (claim over-generalized) vs **stale** (state no longer holds).
|
|
@@ -103,12 +123,50 @@ Example — a `pitfall` (note the required `root-cause` / `workaround` / `lesson
|
|
|
103
123
|
- status: candidate
|
|
104
124
|
```
|
|
105
125
|
|
|
126
|
+
Example — a `strategy` (note the `trigger` / `action` body), file `strategies/S-2026-0813-1606fz-1.md`:
|
|
127
|
+
|
|
128
|
+
```markdown
|
|
129
|
+
### S-2026-0813-1606fz-1: When a substring contract test fails, suspect markdown emphasis first
|
|
130
|
+
- claim: A failing substring assertion over a prose template is usually a wrong assertion, not a wrong template.
|
|
131
|
+
- type: strategy
|
|
132
|
+
- scope/when: writing or debugging substring contract tests over `templates/commands/*.md`
|
|
133
|
+
- trigger: a `test_*_template.py` substring assertion fails on a phrase you believe the template contains.
|
|
134
|
+
- action: check whether the template wrote inline `**`/`*`/backticks inside the asserted span before touching the template; re-target the assertion at an emphasis-free span.
|
|
135
|
+
- evidence.facts: "断言 span 里含 `**not**` 导致子串匹配失败"
|
|
136
|
+
- evidence.state: confirmed at feature 2026-0813-1606fz; still valid.
|
|
137
|
+
- provenance: distill @implement-tasks, 2026-08-13, derivation: inferred, confidence: high
|
|
138
|
+
- status: candidate
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Example — a `runbook` (note the ordered `steps` + `failure-recovery` body), file `runbooks/R-2026-0813-1143el-1.md`:
|
|
142
|
+
|
|
143
|
+
```markdown
|
|
144
|
+
### R-2026-0813-1143el-1: Release a new CodexSpec version
|
|
145
|
+
- claim: The end-to-end steps (and failure recovery) to cut a release.
|
|
146
|
+
- type: runbook
|
|
147
|
+
- scope/when: publishing a new version of this repo
|
|
148
|
+
- steps: 1) bump the version manually in `pyproject.toml`, `__version__`, and `uv.lock`; 2) run `publish.sh`; 3) push the tag; 4) commit the marketplace update.
|
|
149
|
+
- failure-recovery: if the `pip-audit` pre-commit hook aborts on a transient SSL error, reset the half-applied bump and re-run with `SKIP=pip-audit`.
|
|
150
|
+
- evidence.facts: "publish.sh 不自动 bump __version__;pip-audit 偶发 SSL 失败中止发布"
|
|
151
|
+
- evidence.state: confirmed at feature 2026-0813-1143el; still valid.
|
|
152
|
+
- provenance: distill @implement-tasks, 2026-08-13, derivation: inferred, confidence: high
|
|
153
|
+
- status: candidate
|
|
154
|
+
```
|
|
155
|
+
|
|
106
156
|
## Extraction
|
|
107
157
|
|
|
108
158
|
Read the interaction segment and extract, per the dimensions above, only **verified** knowledge — prefer facts confirmed by outcomes over speculation; speculation MUST NOT become `vetted`.
|
|
109
159
|
|
|
110
160
|
Before writing, **read the current profile** (the record files under each category directory) and skip anything already covered; update anything changed via `replace`. **This is how deduplication is done — by judgment, not an algorithm.**
|
|
111
161
|
|
|
162
|
+
## Debounce across the trigger surface
|
|
163
|
+
|
|
164
|
+
distill can now fire from several points close together — the near-moment ambient rule, the long-run along-the-way calls, and the wrap-up hooks (`implement-tasks` → `commit-staged` → `pr`) — often over largely the **same** work. To avoid re-distilling and near-duplicate records, apply a lightweight debounce:
|
|
165
|
+
|
|
166
|
+
- **Session-local boundary.** Keep a **session-local already-distilled boundary** — your own memory, in this conversation's context, of what you have already distilled this session and up to which point of the interaction. This is held **in conversation context**; introduce **no persistent runtime state** (no marker file, no counter on disk).
|
|
167
|
+
- **Delta-only.** On a later trigger, distill only the **substantive new delta** since that boundary. If nothing substantive was produced since, **early-exit** (report "nothing to distill") without deep-reading the whole profile.
|
|
168
|
+
- **Cross-session fallback.** When the boundary is unavailable — a new session, or context was compacted — there is no session memory to lean on, so distill **falls back to reading the profile and skipping covered records** (the judgment dedup above). Worst case is one extra early-exiting scan, never a duplicate.
|
|
169
|
+
|
|
112
170
|
## Conflict adjudication
|
|
113
171
|
|
|
114
172
|
When a new item conflicts with an existing rule, resolve in this order:
|
|
@@ -128,12 +186,24 @@ Change the profile **only** through three conceptual operations (you edit the fi
|
|
|
128
186
|
|
|
129
187
|
git history is the audit ledger. Do **NOT** keep a retired file or a retired section.
|
|
130
188
|
|
|
189
|
+
## Consolidation (compress narrow records into general rules)
|
|
190
|
+
|
|
191
|
+
Growth is not just accumulation: many narrow records on one theme should compress into **one general rule plus its exceptions** (the way experience compacts into judgment). distill performs the **detect-and-mark** half automatically; a human performs the **merge** half in `/distill review`.
|
|
192
|
+
|
|
193
|
+
- **Mark, don't merge.** When you notice a cluster of narrow records sharing a generalization (e.g. several derived-artifact pitfalls, or several lockstep conventions), **mark** them as **consolidation candidates** by writing a **per-record field** into each member's own file — `consolidation: candidate; cluster: <short-theme-key>` — using the same shared `<short-theme-key>` on every member. This is judgment, not an algorithm. It is **non-destructive**: marking **does not auto-rewrite or delete** any record.
|
|
194
|
+
- **No central index.** The cluster lives only as that shared key across the members' own files — there is **no central index** or manifest file (which would be a merge-conflict magnet and break the conflict-free store). `/distill review` discovers a cluster by scanning for records that share a `cluster:` key.
|
|
195
|
+
- **Cross-category promotion.** A consolidation may cross categories — e.g. **promoting several** `pitfalls` **into one** `strategy` (the transferable "what to do when" above the individual traps). The general record is written in whichever category fits the generalized claim.
|
|
196
|
+
|
|
197
|
+
The merge itself is confirmed by a human in `/distill review` (below); distill never merges unattended.
|
|
198
|
+
|
|
131
199
|
## Vetting candidates (manual, interactive)
|
|
132
200
|
|
|
133
201
|
Auto-distill writes `candidate` records non-interactively and **never prompts**. Promote them through the **manual review mode** — `/distill review` (or `/distill` with no new segment to distill): list every pending `candidate` compactly (claim + evidence + provenance) and let the user approve inline — "vet all", "vet 1,3", "edit 2", "drop 4". Apply the choices by editing each record's `status` (a `replace`). **The user never hand-edits the profile files.**
|
|
134
202
|
|
|
135
203
|
The user's approval here **is** the human endorsement half of the `vetted` gate: an approved `candidate` that is already outcome-verified becomes `vetted` **regardless of its original `derivation`** (an `inferred` record is not blocked from vetting). If a candidate has not yet been outcome-verified, approval keeps it `candidate` (or the user may attest the outcome to complete the gate). This is the path by which `inferred` knowledge — including everything `/codexspec:onboard` writes — reaches `vetted` and becomes `evolve`-eligible.
|
|
136
204
|
|
|
205
|
+
**Consolidation review.** In the same review mode, also surface any **consolidation candidate** clusters (records sharing a `cluster:` key, from the Consolidation section above): show the cluster's members compactly and let the user confirm the merge inline — "merge 1", "merge all", "keep separate". On confirmation, write the single general record (a **general rule plus its exceptions**), `remove` the superseded members, and clear the `cluster:`/`consolidation:` marker from anything that survives so no stale flag lingers. If the user declines, leave every member untouched. distill only ever **marked** the cluster; the merge happens **only** here, on explicit confirmation.
|
|
206
|
+
|
|
137
207
|
## Self-check before finishing
|
|
138
208
|
|
|
139
209
|
A lightweight judgment pass (not an engineered lint) over what you just wrote:
|
|
@@ -31,6 +31,8 @@ Promote only records that are **both**:
|
|
|
31
31
|
|
|
32
32
|
Project-specific knowledge **stays** in the profile. Only generally-useful capability is promoted upstream. When nothing qualifies, stop and report — do not force a promotion.
|
|
33
33
|
|
|
34
|
+
This selection spans **all six** profile categories. `strategies/` (metacognitive `trigger → action` rules) and `runbooks/` (ordered multi-step procedures) are often the **most** promotable material — a vetted, general strategy or runbook compiles cleanly into a reusable skill/command — but they clear the **same** `vetted` gate as every other category; the gate is unchanged.
|
|
35
|
+
|
|
34
36
|
## Compiling the draft
|
|
35
37
|
|
|
36
38
|
Compile the selected sediment into a SKILL.md / command-template draft that conforms to both:
|
|
@@ -30,7 +30,7 @@ Converse in the interaction language and author artifacts in the document langua
|
|
|
30
30
|
Before scanning:
|
|
31
31
|
|
|
32
32
|
- If `.codexspec/` is **absent**, the project is not codexspec-initialized. **Stop** and direct the user to run `codexspec init`. Do not scaffold a whole project.
|
|
33
|
-
- If `.codexspec/` is present but the profile store is missing, **ensure the canonical scaffold** — the
|
|
33
|
+
- If `.codexspec/` is present but the profile store is missing, **ensure the canonical scaffold** — the six category directories `.codexspec/profile/{constraints,conventions,pitfalls,decisions,strategies,runbooks}/` (matching what `codexspec init` produces) — before writing.
|
|
34
34
|
- git is **not required**. onboard runs on a plain directory.
|
|
35
35
|
|
|
36
36
|
## Codebase Scan
|
|
@@ -45,12 +45,12 @@ Scan strategy is **high-signal-first over the whole repository in a single pass*
|
|
|
45
45
|
|
|
46
46
|
## What onboard Extracts — and What It Must NOT
|
|
47
47
|
|
|
48
|
-
Extraction uses your **flexible judgment over what the code actually shows** — not a fixed checklist of filenames or markers. onboard actively extracts **only two** of the
|
|
48
|
+
Extraction uses your **flexible judgment over what the code actually shows** — not a fixed checklist of filenames or markers. onboard actively extracts **only two** of the six profile categories:
|
|
49
49
|
|
|
50
50
|
- **`conventions`** (the primary yield) — the code's observable regularities: directory/module structure, naming schemes, import style, the tech stack and toolchain (read from manifests), lint/format/type configuration, test framework and layout, and patterns repeated across the codebase. **Observable architecture / tech-stack facts** are captured here as fact-plus-steering, not as ADR-style decisions.
|
|
51
51
|
- **`constraints`** (narrow, high-risk) — **only** config-level **explicit hard prohibitions**: lint/type rules set to *error* that ban imports or APIs, `do not edit` / generated-file / managed-block markers, and CODEOWNERS / protected-path conventions. Every constraint candidate carries a **precise evidence anchor** (`file:line` or a config snippet). **Absent an explicit prohibition signal, propose no constraint** — silence, never a guess.
|
|
52
52
|
|
|
53
|
-
onboard **never** extracts `decisions` or `
|
|
53
|
+
onboard **never** extracts `decisions`, `pitfalls`, `strategies`, or `runbooks`. A documented decision or pitfall is already readable in the repo (redundant to copy); an undocumented one is unreliable to infer from a cold scan (pitfalls are experiential; decision rationale would be fabricated). `strategies` (metacognitive trigger→action rules) and `runbooks` (lived multi-step procedures) are likewise experiential — a cold scan cannot reliably infer either. All four remain `distill`'s channels, where the rationale and lived experience are available.
|
|
54
54
|
|
|
55
55
|
## Record Format
|
|
56
56
|
|
|
@@ -85,5 +85,5 @@ Report concisely in the interaction language: the records added / updated per ca
|
|
|
85
85
|
|
|
86
86
|
- Read-only on code; write-only to `.codexspec/profile/`; no source / test / git / constitution mutation.
|
|
87
87
|
- Standalone: no auto-next, no automatic hook, and **no Automatic Distillation step** (onboard is not a wrap-up command).
|
|
88
|
-
- Writes only `conventions` and `constraints`; never `decisions` or `
|
|
88
|
+
- Writes only `conventions` and `constraints`; never `decisions`, `pitfalls`, `strategies`, or `runbooks`.
|
|
89
89
|
- Produces no persistent document beyond profile records.
|
|
@@ -55,7 +55,7 @@ When the argument identifies an existing feature:
|
|
|
55
55
|
Before discussing and finalizing requirements, read the project profile under `.codexspec/profile/` when it exists so the confirmed `requirements.md` is a synthesis that already accounts for accumulated project knowledge. Each category is a directory holding one record per file:
|
|
56
56
|
|
|
57
57
|
- `constraints/` first — the project's hard prohibitions (highest weight); requirements MUST NOT contradict them.
|
|
58
|
-
- `pitfalls/`, `conventions/`, `decisions/` — read the records relevant to this feature's area, to avoid re-hitting known traps, to follow established conventions,
|
|
58
|
+
- `pitfalls/`, `conventions/`, `decisions/`, `strategies/`, `runbooks/` — read the records relevant to this feature's area, to avoid re-hitting known traps, to follow established conventions, to reuse past cross-feature/architectural decisions rather than re-litigating them, and to apply proven strategies and procedures.
|
|
59
59
|
|
|
60
60
|
Each record carries a `status` (`candidate` or `vetted`); weight `candidate` entries with appropriate caution. Fold what is relevant into the discussion and the resulting entries; cite a profile record as evidence when it materially shapes a decision. This is the single point where the profile enters the SDD pipeline — downstream stages keep `requirements.md` as authority and do not re-read the profile. Degrade silently when the profile is absent or empty (nothing to apply); never block on it.
|
|
61
61
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|