provenance-cli 0.1.0__tar.gz → 0.2.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.
Files changed (87) hide show
  1. provenance_cli-0.2.0/.agents/skills/spec-capture-expectations/SKILL.md +140 -0
  2. provenance_cli-0.2.0/.agents/skills/spec-drift-sync/SKILL.md +152 -0
  3. provenance_cli-0.2.0/.agents/skills/spec-entry-format/SKILL.md +302 -0
  4. provenance_cli-0.2.0/.agents/skills/spec-request-flow/SKILL.md +174 -0
  5. provenance_cli-0.2.0/.claude/skills/spec-capture-expectations/SKILL.md +140 -0
  6. provenance_cli-0.2.0/.claude/skills/spec-drift-sync/SKILL.md +152 -0
  7. provenance_cli-0.2.0/.claude/skills/spec-entry-format/SKILL.md +302 -0
  8. provenance_cli-0.2.0/.claude/skills/spec-request-flow/SKILL.md +174 -0
  9. provenance_cli-0.2.0/.editorconfig +22 -0
  10. provenance_cli-0.2.0/.gitattributes +19 -0
  11. provenance_cli-0.2.0/.github/workflows/ci.yml +31 -0
  12. provenance_cli-0.2.0/.github/workflows/publish-pypi.yml +27 -0
  13. provenance_cli-0.2.0/.gitignore +71 -0
  14. provenance_cli-0.2.0/.python-version +1 -0
  15. provenance_cli-0.2.0/AGENTS.md +43 -0
  16. provenance_cli-0.2.0/CLAUDE.md +43 -0
  17. provenance_cli-0.2.0/PKG-INFO +133 -0
  18. provenance_cli-0.2.0/README.md +107 -0
  19. provenance_cli-0.2.0/docs/README.md +13 -0
  20. provenance_cli-0.2.0/docs/agent-setup.md +110 -0
  21. provenance_cli-0.2.0/docs/architecture.md +2002 -0
  22. provenance_cli-0.2.0/docs/cli.md +238 -0
  23. provenance_cli-0.2.0/docs/development.md +62 -0
  24. provenance_cli-0.2.0/docs/publishing.md +65 -0
  25. provenance_cli-0.2.0/docs/spec-format.md +219 -0
  26. provenance_cli-0.2.0/install.sh +83 -0
  27. provenance_cli-0.2.0/prov/.spec/code-index.json +184 -0
  28. provenance_cli-0.2.0/prov/.spec/graph.json +1977 -0
  29. provenance_cli-0.2.0/prov/CONTEXT.md +40 -0
  30. provenance_cli-0.2.0/prov/agent.md +119 -0
  31. provenance_cli-0.2.0/prov/cli.md +96 -0
  32. provenance_cli-0.2.0/prov/core.md +48 -0
  33. provenance_cli-0.2.0/prov/format.md +83 -0
  34. provenance_cli-0.2.0/prov/install.md +96 -0
  35. provenance_cli-0.2.0/prov/storage.md +66 -0
  36. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/pyproject.toml +11 -6
  37. provenance_cli-0.2.0/scripts/build.sh +17 -0
  38. provenance_cli-0.2.0/scripts/dev-install.sh +21 -0
  39. provenance_cli-0.2.0/scripts/install-spec-pre-commit.sh +237 -0
  40. provenance_cli-0.2.0/scripts/publish.sh +25 -0
  41. provenance_cli-0.2.0/src/prov/__init__.py +11 -0
  42. provenance_cli-0.2.0/src/prov/__main__.py +7 -0
  43. provenance_cli-0.2.0/src/prov/cli.py +258 -0
  44. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/check_slug.py +1 -0
  45. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/context.py +1 -0
  46. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/diff.py +1 -0
  47. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/domain.py +1 -0
  48. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/find.py +1 -0
  49. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/impact.py +5 -4
  50. provenance_cli-0.2.0/src/prov/commands/init.py +111 -0
  51. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/orient.py +36 -16
  52. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/rebuild.py +1 -0
  53. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/reconcile.py +1 -0
  54. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/scope.py +5 -4
  55. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/sync.py +1 -0
  56. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/validate.py +2 -1
  57. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/write.py +1 -0
  58. provenance_cli-0.2.0/src/prov/format.py +100 -0
  59. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/indexing.py +54 -11
  60. provenance_cli-0.2.0/src/prov/installer.py +170 -0
  61. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/model.py +1 -0
  62. provenance_cli-0.2.0/src/prov/prompts/spec-agent.md +581 -0
  63. provenance_cli-0.2.0/src/prov/rules/project-rules.md +41 -0
  64. provenance_cli-0.2.0/src/prov/rules/spec-agent-protocol.md +116 -0
  65. provenance_cli-0.2.0/src/prov/rules/spec-skill-router.md +88 -0
  66. provenance_cli-0.2.0/src/prov/skills/spec-capture-expectations/SKILL.md +140 -0
  67. provenance_cli-0.2.0/src/prov/skills/spec-drift-sync/SKILL.md +152 -0
  68. provenance_cli-0.2.0/src/prov/skills/spec-entry-format/SKILL.md +302 -0
  69. provenance_cli-0.2.0/src/prov/skills/spec-request-flow/SKILL.md +174 -0
  70. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/spec_io.py +5 -3
  71. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/writer.py +1 -0
  72. provenance_cli-0.2.0/tests/test_backlinks.py +79 -0
  73. provenance_cli-0.2.0/tests/test_installer.py +170 -0
  74. provenance_cli-0.2.0/uv.lock +324 -0
  75. provenance_cli-0.1.0/PKG-INFO +0 -423
  76. provenance_cli-0.1.0/README.md +0 -397
  77. provenance_cli-0.1.0/setup.cfg +0 -4
  78. provenance_cli-0.1.0/src/prov/__init__.py +0 -4
  79. provenance_cli-0.1.0/src/prov/cli.py +0 -105
  80. provenance_cli-0.1.0/src/prov/commands/init.py +0 -41
  81. provenance_cli-0.1.0/src/provenance_cli.egg-info/PKG-INFO +0 -423
  82. provenance_cli-0.1.0/src/provenance_cli.egg-info/SOURCES.txt +0 -29
  83. provenance_cli-0.1.0/src/provenance_cli.egg-info/dependency_links.txt +0 -1
  84. provenance_cli-0.1.0/src/provenance_cli.egg-info/entry_points.txt +0 -2
  85. provenance_cli-0.1.0/src/provenance_cli.egg-info/top_level.txt +0 -1
  86. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/LICENSE +0 -0
  87. {provenance_cli-0.1.0 → provenance_cli-0.2.0}/src/prov/commands/__init__.py +0 -0
@@ -0,0 +1,140 @@
1
+ ---
2
+ name: spec-capture-expectations
3
+ version: "1.0"
4
+ description: "Extract implicit user expectations and compile them into the spec. Use when starting a session or picking up a new task, when user words imply a behavior, constraint, or rule not yet in the spec, when a request reveals an assumption, edge case, or threshold to write down, or when deciding whether to add or update a spec entry."
5
+ triggers:
6
+ - session start or picking up a new task
7
+ - user words imply a behavior, constraint, or rule not yet in the spec
8
+ - request reveals an assumption, edge case, or threshold to write down
9
+ - deciding whether to add or update a spec entry
10
+ ---
11
+
12
+ ## Mission
13
+
14
+ On every task, extract implicit user expectations and compile them into the spec so the spec remains the single, correct record of what the user expects — not what was guessed or left in conversation.
15
+
16
+ ---
17
+
18
+ ## Pre-requisites
19
+
20
+ - **Spec directory** present: `prov/`, `spec/`, or `specs/`.
21
+ - **Read access** to existing spec files (to check what is already captured).
22
+ - **Write access** to spec files when adding or updating entries (only after user confirms in Phase 3 of the request flow).
23
+
24
+ ---
25
+
26
+ ## Instructions
27
+
28
+ ### Step 1 — Before acting, run the five questions
29
+
30
+ For the current request, answer (see Reference for detail):
31
+
32
+ 1. Is there a behavior implied here that is not yet in the spec?
33
+ 2. Would a future reader of the spec infer the same thing the user expects?
34
+ 3. Is there a number, threshold, limit, or edge case the user assumed?
35
+ 4. Does this reveal a domain-wide constraint ("always", "never")?
36
+ 5. Is an existing entry now wrong or incomplete?
37
+
38
+ ### Step 2 — Decide: add, update, or skip
39
+
40
+ Use the tables in Reference: **When to add a new entry** and **When NOT to add**. Add when user states or implies a behavior, specifies a constraint, an edge case is missing, or a bug fix reveals correct behavior never specified. Do not add for competent-developer defaults, implementation-only details, or duplicates.
41
+
42
+ ### Step 3 — Record implicit expectations in the right form
43
+
44
+ - User’s words reveal unstated behavior → add requirement with `> user: "exact quote"` and `~` when implemented (see Reference example).
45
+ - You infer a value they didn’t give (e.g. "keep it fast") → add entry with `> inferred: reasoning` and ` ! assumed <value> — <reason unconfirmed>`. Surface the `!` in Phase 3; user confirms, corrects, or defers (see Reference example).
46
+
47
+ ### Step 4 — Apply assumption discipline
48
+
49
+ Every gap you fill on the user’s behalf gets a `!` line. When surfacing `!`: **Confirm** → remove `!`; **Correct** → rewrite statement, remove `!`; **Defer** → keep `!` (it will appear in every future diff until confirmed). See Reference → Assumption discipline.
50
+
51
+ ### Step 5 — Feed into the request flow
52
+
53
+ All new or changed entries are proposed in Phase 3 and written in Phase 4 of the request flow. Do not add entries without going through the flow (propose → confirm → write).
54
+
55
+ ---
56
+
57
+ ## Reference
58
+
59
+ ### The principle
60
+
61
+ Every task is a chance to compile user intent into the spec. A well-maintained spec is one where a fresh agent, given only the spec and no prior context, would produce a system that matches everything the user actually expects. Never leave expectations only in code or only in conversation — compile them.
62
+
63
+ ### Five questions (detail)
64
+
65
+ 1. **Is there a behavior implied here that is not yet written in the spec?** If the user's request assumes something works a certain way and the spec doesn't say so, that's a missing entry.
66
+ 2. **Would a future reader of the spec infer the same thing the user expects?** If not, update the entry — wrong statement, missing constraint, wrong scope.
67
+ 3. **Is there a number, threshold, limit, or edge case the user assumed?** Record in the spec with a `!` line if unconfirmed, or as a confirmed statement if they said it.
68
+ 4. **Does this reveal a domain-wide constraint?** If the user says "always", "never", or "under no circumstances", that's a `C:slug:` constraint entry, not just a requirement.
69
+ 5. **Is an existing entry now wrong or incomplete?** The new request may reveal that an old entry was imprecise; update it in the same task.
70
+
71
+ ### When to add a new entry
72
+
73
+ | Signal | Action |
74
+ |--------|--------|
75
+ | User states a behavior explicitly | Add requirement entry with `> user: "their words"` |
76
+ | User implies a behavior ("obviously it should...") | Add entry with `> inferred: <reasoning>` and `!` line |
77
+ | User specifies a constraint ("always", "never", "required") | Add `C:slug:` constraint entry |
78
+ | User's request would fail in an edge case not yet covered | Add entry for that edge case |
79
+ | Fixing a bug reveals the correct behavior was never specified | Add entry for the correct behavior |
80
+ | User corrects the agent's assumption | Remove `!`, update the statement to match the correction |
81
+
82
+ ### When NOT to add a new entry
83
+
84
+ - Competent-developer defaults (error handling, logging patterns, standard HTTP responses) — skip.
85
+ - Implementation details the user never mentioned and that don't affect user-observable behavior — skip.
86
+ - Anything already correctly covered by an existing entry — skip; don't duplicate.
87
+
88
+ ### How to record an implicit expectation — examples
89
+
90
+ **User's words reveal unstated behavior:**
91
+
92
+ ```
93
+ user: "make sure the export always includes the full history"
94
+ ```
95
+
96
+ → Add:
97
+
98
+ ```
99
+ export-full-history: Exports always include the complete history of the record.
100
+ > user: "make sure the export always includes the full history"
101
+ ~ src/exports/history.py
102
+ ```
103
+
104
+ **You infer a value they didn't give:**
105
+
106
+ ```
107
+ user: "keep it fast"
108
+ ```
109
+
110
+ → "Fast" is unspecified. Add:
111
+
112
+ ```
113
+ export-performance: Export completes within 5 seconds for records up to 10,000 entries. [planned]
114
+ > inferred: user said "keep it fast" — interpreted as 5s / 10k entries
115
+ ! assumed 5s / 10k entries — "fast" is unconfirmed
116
+ ```
117
+
118
+ Surface the `!` in Phase 3. The user either confirms, corrects, or defers.
119
+
120
+ ### Assumption discipline
121
+
122
+ - `!` = "I decided this; the user has not confirmed it."
123
+ - No `!` = "The user said this, or it's an unambiguous default."
124
+ - When you surface a `!` to the user: **Confirm** → remove `!` (becomes user-specified). **Correct** → rewrite statement, remove `!`. **Defer** → keep `!`; do not remove it; it will appear in every future diff until the user explicitly confirms. The `!` is the record that this was not their explicit choice.
125
+
126
+ ### The compounding spec
127
+
128
+ Over time, with every task handled this way, the spec converges on a complete, accurate picture of user intent. Each task adds signal. The spec becomes the memory of the system — not what the agent guessed, not what was obvious in the moment, but what the user actually wants. Never leave an expectation only in code. Never leave it only in conversation. Compile it.
129
+
130
+ ---
131
+
132
+ ## Error Handling
133
+
134
+ | If this happens | Do this |
135
+ |-----------------|--------|
136
+ | You're unsure whether something is user expectation or implementation detail | Prefer capturing it with a `!` line so the user can confirm or remove. Do not leave it only in code. |
137
+ | User said something vague ("fast", "simple") and you chose a concrete value | Add a `!` line stating the assumed value and that the original was unconfirmed. Surface in Phase 3; do not remove `!` without user action. |
138
+ | You find an existing entry that's wrong but the user didn't ask to change it | Include the correction in your Phase 3 proposal ("I'm also updating X because the current spec says Y and the code/behavior is Z"). Get explicit confirmation. |
139
+ | You already added an entry and the user says "that's not what I meant" | Treat as correction: update the statement and provenance, remove or adjust `!`. Do not leave the wrong entry in place. |
140
+ | Multiple possible interpretations of the user's words | Propose one interpretation with a `!` line; in Phase 3 list the alternatives and ask which one they want. Do not implement until they choose. |
@@ -0,0 +1,152 @@
1
+ ---
2
+ name: spec-drift-sync
3
+ version: "1.0"
4
+ description: "Resolve drift between spec and code with the sync protocol, applying only user-confirmed fixes. Use when running prov sync or prov reconcile, after bulk refactors, large merges, or importing existing code, when the user asks to reconcile spec and code, or after autonomous code changes that may have left the spec out of date."
5
+ triggers:
6
+ - running prov sync or prov reconcile
7
+ - after bulk refactors, large merges, or importing existing code
8
+ - user asks to reconcile spec and code
9
+ - after autonomous code changes that may have left spec out of date
10
+ ---
11
+
12
+ ## Mission
13
+
14
+ Resolve drift between spec and code by running the sync protocol, presenting each drift item to the user with context, and applying only user-confirmed fixes so that spec and code match.
15
+
16
+ ---
17
+
18
+ ## Pre-requisites
19
+
20
+ - **prov CLI** with `prov sync` and `prov reconcile` (and patch subcommands: `mark-implemented`, `remove-ref`, `update-ref`, `remove-backlink`). If prov is not available, document that drift resolution was skipped.
21
+ - **Spec directory** and **codebase** in the same repo (or paths known).
22
+ - **Read access** to spec files and code; **write access** to spec files (and optionally code for removing backlinks) after user confirms.
23
+
24
+ ---
25
+
26
+ ## Instructions
27
+
28
+ ### Step 1 — Run the drift report
29
+
30
+ Run `prov sync <path>` (e.g. `prov sync src/`) or `prov reconcile <path>` for read-only. Read the full output. Identify each reported item by type (silent implementation, phantom slug, dead ref). See Reference → What drift is.
31
+
32
+ ### Step 2 — Present each item to the user
33
+
34
+ For each drift item: state type, slug, and location (file, line or path). State what the spec currently says vs what the code currently does. Offer the resolution options from Reference → Resolution by type. Ask: "What should I do?" Do not apply any fix until the user answers. Use the example presentation format in Reference if helpful.
35
+
36
+ ### Step 3 — Apply only confirmed fixes
37
+
38
+ Use the exact commands in Reference → Patch commands. For silent implementation: `mark-implemented` or `remove-backlink`. For phantom slug: add entry via request flow or `remove-backlink`. For dead ref: `update-ref` or `remove-ref` (and consider `[planned]` or removing the entry). Only after user confirms each item.
39
+
40
+ ### Step 4 — Validate and commit
41
+
42
+ Run `prov validate` (zero errors). Run `prov diff`. Commit spec (and any code changes) with a message such as `spec: reconcile src/<path>`.
43
+
44
+ ### Step 5 — After autonomous code changes
45
+
46
+ When the agent made code changes without the normal request flow (e.g. bulk refactor, automated migration), run `prov sync src/` before committing and include a short drift summary in the PR description. See Reference → After autonomous code changes.
47
+
48
+ ---
49
+
50
+ ## Reference
51
+
52
+ ### What drift is
53
+
54
+ Drift is a gap between what the spec says and what the code does. Three types:
55
+
56
+ | Type | Description | Detected by |
57
+ |------|-------------|-------------|
58
+ | **Silent implementation** | `[planned]` entry but code already has `spec:` backlink | `prov sync` |
59
+ | **Phantom slug** | `spec:` in code references a slug with no spec entry | `prov sync` |
60
+ | **Dead ref** | `~` path in spec no longer exists as a file or directory | `prov sync` |
61
+
62
+ ### Example presentation to the user
63
+
64
+ ```
65
+ SILENT IMPLEMENTATION: session-expiry
66
+ Spec says: [planned]
67
+ Code has: # spec: session-expiry in src/middleware/session.py:44
68
+
69
+ Options:
70
+ A. Mark as implemented — remove [planned], the code ref counts
71
+ B. Remove the backlink — code shouldn't claim to implement this yet
72
+ C. Skip — leave it as-is for now
73
+
74
+ What should I do?
75
+ ```
76
+
77
+ ### Patch commands (apply only after user confirms)
78
+
79
+ ```bash
80
+ # Silent implementation → mark as implemented
81
+ prov sync mark-implemented <slug>
82
+
83
+ # Phantom slug → remove the backlink (if the slug shouldn't exist)
84
+ prov sync remove-backlink <file> <line> <slug>
85
+ # or → add the missing spec entry via request flow (if the code is correct)
86
+
87
+ # Dead ref → remove the stale path
88
+ prov sync remove-ref <slug> <ref>
89
+ # or → update to the new path
90
+ prov sync update-ref <slug> <old-path> <new-path>
91
+ ```
92
+
93
+ ### Resolution decisions by drift type
94
+
95
+ **Silent implementation** — Spec says `[planned]` but the code already implements it.
96
+
97
+ - **Mark implemented** (`prov sync mark-implemented <slug>`): The implementation is correct and complete. Remove `[planned]`, add `~` ref.
98
+ - **Remove backlink** (`prov sync remove-backlink ...`): The code should not claim to implement this yet. The spec's `[planned]` is correct.
99
+
100
+ **Phantom slug** — Code has `# spec: some-slug` but `some-slug` doesn't exist in the spec.
101
+
102
+ - **Add the spec entry**: The code is right; the spec is missing the entry. Go through request flow Phase 3 → 4. Use provenance `> code: <file:line> — phantom slug, prov sync; user confirmed spec entry` and `! statement inferred from implementation — user confirmed after sync`. See spec-entry-format for provenance source types.
103
+ - **Remove the backlink**: The `spec:` comment is wrong or outdated.
104
+
105
+ **Dead ref** — A `~` path in the spec no longer exists.
106
+
107
+ - **Update the ref** (`prov sync update-ref ...`): The file moved or was renamed. Update to the new path.
108
+ - **Remove the ref** (`prov sync remove-ref ...`): The code was deleted. The implementation is gone; the entry may need `[planned]` restored or be removed entirely.
109
+
110
+ ### After autonomous code changes
111
+
112
+ When the agent has made code changes without going through the normal request flow (e.g. bulk refactor, automated migration), always run reconcile before committing:
113
+
114
+ ```bash
115
+ prov sync src/ # full drift report
116
+ prov validate # confirm zero errors
117
+ prov diff # review spec changes
118
+ ```
119
+
120
+ Include the drift summary in the PR description so the human reviewer can see what changed in the spec alongside the code.
121
+
122
+ ### Read-only drift check
123
+
124
+ To see drift without applying any fixes:
125
+
126
+ ```bash
127
+ prov reconcile src/ # full read-only report
128
+ prov reconcile src/ --since HEAD # since last commit (if supported)
129
+ ```
130
+
131
+ Output sections: PHANTOM SLUGS, SILENT IMPLEMENTATIONS, DEAD REFS, CLEAN (if none).
132
+
133
+ ### Provenance for entries added from code
134
+
135
+ When adding a spec entry for a phantom slug (code has `spec:` but no entry), the entry is code-derived:
136
+
137
+ - **Provenance**: `> code: <file:line> — phantom slug, prov sync; user confirmed spec entry`
138
+ - **Assumption**: `! statement inferred from implementation — user confirmed after sync`
139
+ - Always pair `code:` provenance with `!` until the user explicitly confirms the statement reflects their intent.
140
+
141
+ ---
142
+
143
+ ## Error Handling
144
+
145
+ | If this happens | Do this |
146
+ |-----------------|--------|
147
+ | **Silent implementation** — spec has `[planned]` but code has `spec:` | Present options: A. Mark implemented (update spec, add `~`). B. Remove backlink (code shouldn't claim it yet). C. Skip. Do not choose for the user. |
148
+ | **Phantom slug** — `spec:` in code but no spec entry | Present options: A. Add the spec entry (via request flow). B. Remove the backlink. Do not add an entry without user confirmation. |
149
+ | **Dead ref** — `~` path in spec does not exist | Present options: A. Update ref to new path. B. Remove ref (and possibly set entry back to `[planned]` or remove entry). Do not leave a `~` pointing at a missing file. |
150
+ | User says "skip" or "leave it for now" for an item | Do not apply any fix for that item. Move to the next item. You may note in the commit message that some drift was left unresolved. |
151
+ | `prov sync` or `prov reconcile` is not available | Do not invent patch commands. Tell the user that drift was detected but prov sync is required to fix it; list the drift items you can infer from grep/code inspection if possible. |
152
+ | After applying fixes, `prov validate` still reports errors | Fix the new errors (e.g. duplicate slug, missing `>`, dangling ref). Do not commit until validate passes. |
@@ -0,0 +1,302 @@
1
+ ---
2
+ name: spec-entry-format
3
+ version: "1.0"
4
+ description: "Apply the correct spec entry format: node types, sigils, provenance, backlinks, and commit messages. Use when writing or editing spec files, adding or updating ~ code refs or spec: backlinks, reading an unfamiliar spec entry, or checking commit or entry format."
5
+ triggers:
6
+ - writing or editing spec files
7
+ - adding or updating ~ code refs or spec: backlinks
8
+ - reading an unfamiliar spec entry
9
+ - checking commit or entry format
10
+ ---
11
+
12
+ ## Mission
13
+
14
+ Apply the correct spec entry format (node types, sigils, invariants, backlinks, commit messages) so the parser and grep-based retrieval work and the spec stays valid.
15
+
16
+ ---
17
+
18
+ ## Pre-requisites
19
+
20
+ - **Spec directory** present: `prov/`, `spec/`, or `specs/`.
21
+ - **grep** (or equivalent) for slug checks and pattern search.
22
+ - **prov CLI** (optional): `prov check-slug`, `prov validate`. If absent, use `grep -r "^<slug>:" spec/` for slug availability.
23
+
24
+ ---
25
+
26
+ ## Instructions
27
+
28
+ ### Step 1 — Before writing any entry: check slug
29
+
30
+ Run `prov check-slug <proposed-slug>` or `grep -r "^<proposed-slug>:" spec/`. If the slug exists, pick a different one or edit the existing entry. Slugs: kebab-case, 2–4 words, describe **behavior** not domain (see Reference → Slug rules).
31
+
32
+ ### Step 2 — Use the correct node type and structure
33
+
34
+ Use **Requirement**, **Constraint**, or **Question** format from Reference. Each has a statement line and sub-lines with ` >`, ` !`, ` @`, ` ?`, ` ~` (each on its own line, exactly 2-space indent).
35
+
36
+ ### Step 3 — Enforce file invariants
37
+
38
+ Every primary entry at **column 0**. Every sub-line **exactly 2 spaces** (not 4, not tab). Sigils only on their own sub-lines; never inline in the statement. One statement line per entry. See Reference → File format invariants.
39
+
40
+ ### Step 4 — Add code backlinks when implementing
41
+
42
+ In code, at the top of each function/class/block that implements a spec entry: `# spec: slug` (or `// spec: slug`). Multiple slugs: `# spec: slug-a, C:slug-b`. One comment per logical block. See Reference → Code backlinks.
43
+
44
+ ### Step 5 — Use the correct commit format
45
+
46
+ See Reference → Commit format. Spec-only vs code+spec; always include the `spec: ...` line when code and spec change together.
47
+
48
+ ---
49
+
50
+ ## Reference
51
+
52
+ ### Reading an entry — anatomy
53
+
54
+ ```
55
+ session-expiry: Sessions expire after 30 days of inactivity.
56
+ > inferred: user said "standard session timeout, nothing crazy" — interpreted as 30 days
57
+ ! assumed 30 days — "nothing crazy" is unconfirmed
58
+ @ C:jwt-stateless
59
+ ~ src/middleware/session.py:44
60
+ ~ src/middleware/session.py:101
61
+ ```
62
+
63
+ | Part | Meaning |
64
+ |------|---------|
65
+ | `session-expiry` | Slug — permanent, globally unique. Used in `spec:` backlinks in code. |
66
+ | Statement | What the system does. Current state only. |
67
+ | `>` | Provenance — use source prefix: user, inferred, code, regulatory, derived. See Provenance source types below. |
68
+ | `!` | Agent filled this in; user has not confirmed it. |
69
+ | `@` | This entry depends on another slug. |
70
+ | `~` | Code implementing this entry. One line per ref. |
71
+ | `[planned]` | Not yet implemented. No `~` lines. Remove when implemented. |
72
+
73
+ ### Provenance source types
74
+
75
+ Every `>` line must identify where the entry came from. Use exactly one of these — do not invent new types.
76
+
77
+ | Type | Format | When used | `!` required? |
78
+ |------|--------|-----------|---------------|
79
+ | user | `> user: "exact words"` | Direct quote from user | No |
80
+ | inferred | `> inferred: reasoning` | Agent interpretation of user intent | Yes |
81
+ | code | `> code: path — context` | Discovered during sync, drift, reverse-engineering | Yes |
82
+ | regulatory | `> regulatory: source — citation` | Legal, compliance, platform requirement | No |
83
+ | derived | `> derived: slug — reasoning` | Logical consequence of another entry | No |
84
+
85
+ For Q nodes: `> blocks: slug` remains valid.
86
+
87
+ Examples:
88
+
89
+ ```
90
+ > user: "we'll just do Google login for now"
91
+
92
+ > inferred: user said "nothing crazy" for timeout — interpreted as 30 days
93
+ ! assumed 30 days — not confirmed
94
+
95
+ > code: src/auth/google.py — phantom slug, prov sync 2026-03-10
96
+ ! statement inferred from implementation — user confirmed after sync
97
+
98
+ > regulatory: GDPR Article 17 — right to erasure within 30 days
99
+
100
+ > derived: C:jwt-stateless — stateless tokens can't maintain server-side revocation list
101
+ ```
102
+
103
+ ### Node types at column 0
104
+
105
+ ```
106
+ slug: requirement — user-observable behavior
107
+ C:slug: constraint — non-negotiable rule governing a domain
108
+ Q:slug: question — unresolved decision blocking implementation
109
+ ```
110
+
111
+ Sub-lines always 2-space indent. Never 4 or tab.
112
+
113
+ ### Slug rules
114
+
115
+ - kebab-case, 2–4 words, describe **behavior** not domain.
116
+ - Good: `session-expiry`, `guest-access`. Bad: `auth-session` (domain prefix), `limit` (too vague).
117
+
118
+ ### Requirement format
119
+
120
+ ```
121
+ slug: Statement describing user-observable behavior. [planned if not yet coded]
122
+ > user: "exact quote" | inferred: reasoning | code: path — context | regulatory: source — citation | derived: slug — reasoning
123
+ ! assumption (required for inferred and code; only when agent filled a gap)
124
+ @ dependency-slug (if this entry depends on another slug)
125
+ ? Q:blocking-question (if blocked by an open question)
126
+ ~ src/path/to/file.py:line (one per line, only when implemented)
127
+ ```
128
+
129
+ ### Constraint format
130
+
131
+ ```
132
+ C:slug: Non-negotiable rule statement.
133
+ > user: "exact quote" or regulatory: source — citation
134
+ ```
135
+
136
+ ### Open question format
137
+
138
+ ```
139
+ Q:slug: Question that must be resolved before implementation?
140
+ > blocks: slug-of-the-requirement-it-blocks
141
+ ```
142
+
143
+ ### File format invariants — never violate
144
+
145
+ 1. Every primary entry starts at **column 0**. No leading spaces.
146
+ 2. Every sub-line is indented **exactly 2 spaces**. Not 4. Not a tab.
147
+ 3. The `~` sigil appears only on its own sub-line. Never inline in the statement.
148
+ 4. Each entry has one statement line (the line with `slug: statement`). Multi-sentence statements on that one line are fine.
149
+
150
+ Violating these breaks the parser and grep-based retrieval.
151
+
152
+ ### Complete domain file example
153
+
154
+ ```markdown
155
+ # Auth
156
+
157
+ > OAuth-based auth and stateless JWT sessions. Two roles: admin/member.
158
+
159
+ ## Constraints
160
+
161
+ C:oauth-only: OAuth only — no email/password.
162
+ > user: "I don't want to deal with password resets"
163
+
164
+ C:jwt-stateless: Sessions are stateless JWT — no server-side session store.
165
+ > user: "I don't want to manage session infrastructure"
166
+
167
+ ## Requirements
168
+
169
+ google-login: Users authenticate via Google OAuth.
170
+ > user: "we'll just do Google login for now"
171
+ @ C:oauth-only
172
+ ~ src/api/auth/google.py
173
+ ~ src/api/auth/callback.py
174
+
175
+ session-expiry: Sessions expire after 30 days of inactivity.
176
+ > inferred: user said "standard session timeout, nothing crazy" — interpreted as 30 days
177
+ ! assumed 30 days — "nothing crazy" is unconfirmed
178
+ @ C:jwt-stateless
179
+ ~ src/middleware/session.py:44
180
+
181
+ admin-revoke: Admins can revoke any user session immediately. [planned]
182
+ > user: "need a kill switch for bad actors"
183
+ ! assumed token blocklist approach — not stated by user
184
+ @ session-expiry
185
+ ? Q:admin-revoke-scope
186
+
187
+ ## Open Questions
188
+
189
+ Q:admin-revoke-scope: Does admin-revoke apply to one session or all sessions?
190
+ > blocks: admin-revoke
191
+
192
+ ## Out of scope
193
+
194
+ MFA, SSO/SAML.
195
+
196
+ ## Refs
197
+
198
+ ~ src/api/auth/
199
+ ~ src/middleware/session.py
200
+ ~ src/models/user.py
201
+ ```
202
+
203
+ ### Code backlinks
204
+
205
+ Every function or class that implements a spec entry carries a `spec:` comment. One per logical block; multiple slugs comma-separated. Place at top of block.
206
+
207
+ ```python
208
+ # spec: session-expiry
209
+ def refresh_session(token: str) -> Session:
210
+
211
+ # spec: billing-session-sync, C:usage-cap
212
+ class PlanLimitMiddleware:
213
+ ```
214
+
215
+ ```typescript
216
+ // spec: admin-revoke
217
+ async function revokeSession(userId: string): Promise<void>;
218
+ ```
219
+
220
+ ### What the spec never contains
221
+
222
+ Do not write: "Previously this was X", "Changed from X to Y", "Deprecated — use other-slug", "We chose JWT because...", or any description of how the system got to its current state. No entry without a `>` line. No implementation detail the user did not specify without a `!` line. The spec is always current state only.
223
+
224
+ ### Commit format
225
+
226
+ ```bash
227
+ # Spec-only changes
228
+ spec(auth): add session-expiry, C:jwt-stateless
229
+ spec(auth): implement admin-revoke
230
+ spec(auth): close Q:admin-revoke-scope
231
+ spec(billing): update plan-limits statement
232
+ spec: reconcile src/api/
233
+
234
+ # Code + spec in same commit
235
+ feat(auth): implement session expiry
236
+ spec: implement session-expiry, add ! assumption for 30-day value
237
+ ```
238
+
239
+ ### Grep quick reference
240
+
241
+ Replace `spec/` with `prov/` or `specs/` if that is your spec root.
242
+
243
+ ```bash
244
+ # Orient
245
+ grep -rh "^>" spec/*.md spec/*/*.md 2>/dev/null
246
+ grep -r "^Q:" spec/
247
+ grep -r "\[planned\]" spec/
248
+ grep -r "^ !" spec/
249
+ grep -r "^C:" spec/
250
+
251
+ # What governs this path?
252
+ grep -r "~src/path/to/file" spec/
253
+ grep -r "~src/path/" spec/
254
+
255
+ # Find by slug
256
+ grep -r "^session-expiry:" spec/
257
+ grep -A 25 "^session-expiry:" spec/
258
+
259
+ # Dependents and implementers
260
+ grep -r "^ @ session-expiry" spec/
261
+ grep -rn "spec: session-expiry" src/
262
+
263
+ # Keyword search
264
+ grep -rEi "session|auth|timeout" spec/
265
+
266
+ # Slug availability (before writing)
267
+ grep -r "^my-new-slug:" spec/
268
+
269
+ # Duplicate check
270
+ grep -rhE "^[a-z][a-z0-9-]*:|^C:|^Q:" spec/ | cut -d: -f1,2 | sort | uniq -d
271
+ ```
272
+
273
+ ### prov CLI — quick reference
274
+
275
+ ```bash
276
+ prov orient # session start
277
+ prov scope <path> # what governs this file/dir
278
+ prov context <slug> # full entry + deps
279
+ prov impact <slug> # blast radius
280
+ prov find <keywords> # search entries
281
+ prov domain <name> # full domain
282
+ prov check-slug <slug> # slug availability
283
+ prov validate # before every commit
284
+ prov diff [ref] # semantic change manifest
285
+ prov reconcile <path> # drift detection (read-only)
286
+ prov sync [path] # interactive drift resolution
287
+ prov rebuild # regenerate optional .spec/ cache
288
+ prov init # scaffold CONTEXT.md
289
+ ```
290
+
291
+ ---
292
+
293
+ ## Error Handling
294
+
295
+ | If this happens | Do this |
296
+ |-----------------|--------|
297
+ | `prov validate` reports "ghost-scope" or "no > line" | Add a ` > ` line with appropriate source prefix (user, inferred, code, regulatory, derived). Do not commit without it. |
298
+ | `prov validate` reports "dead-ref" | Remove the `~` line or update the path to the real file. Do not leave a `~` pointing to a missing path. |
299
+ | `prov validate` reports "phantom-slug" | Either add the missing spec entry for that slug or remove the `spec: slug` backlink from code. Do not leave a backlink with no entry. |
300
+ | You accidentally used 4 spaces or tab for sub-lines | Change to exactly 2 spaces. Parser and grep rely on 2-space indent. |
301
+ | You put `~` or `@` inline in the statement | Move them to separate sub-lines with 2-space indent. One ref per line. |
302
+ | Slug already exists elsewhere | Choose a different slug or update the existing entry; do not create a duplicate. Use `prov check-slug` or grep before writing. |