specwarden 0.1.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 (104) hide show
  1. specwarden-0.1.0/.claude/skills/specwarden/SKILL.md +106 -0
  2. specwarden-0.1.0/.claude/skills/specwarden/scripts/activate_spec.py +18 -0
  3. specwarden-0.1.0/.claude/skills/specwarden/scripts/coverage.py +15 -0
  4. specwarden-0.1.0/.claude/skills/specwarden/scripts/new_spec.py +19 -0
  5. specwarden-0.1.0/.claude/skills/specwarden/scripts/trace.py +16 -0
  6. specwarden-0.1.0/.claude/skills/specwarden/templates/decision_entry.md.template +5 -0
  7. specwarden-0.1.0/.claude/skills/specwarden/templates/spec.md.template +25 -0
  8. specwarden-0.1.0/.claude/specs/2026-05-28_v1-audit-nits-cli-wrapper-tests-and-caveman-cleanup.md +91 -0
  9. specwarden-0.1.0/.env.eval.example +11 -0
  10. specwarden-0.1.0/.github/workflows/ci.yml +32 -0
  11. specwarden-0.1.0/.github/workflows/release.yml +61 -0
  12. specwarden-0.1.0/.gitignore +70 -0
  13. specwarden-0.1.0/CLAUDE.md +103 -0
  14. specwarden-0.1.0/LICENSE +21 -0
  15. specwarden-0.1.0/Makefile +18 -0
  16. specwarden-0.1.0/PKG-INFO +204 -0
  17. specwarden-0.1.0/README.md +189 -0
  18. specwarden-0.1.0/SPEC_specwarden.md +357 -0
  19. specwarden-0.1.0/docs/ARCHITECTURE.md +243 -0
  20. specwarden-0.1.0/docs/COMPARISONS.md +174 -0
  21. specwarden-0.1.0/docs/HOOKS.md +257 -0
  22. specwarden-0.1.0/docs/PHILOSOPHY.md +65 -0
  23. specwarden-0.1.0/docs/RELEASING.md +51 -0
  24. specwarden-0.1.0/docs/TROUBLESHOOTING.md +395 -0
  25. specwarden-0.1.0/docs/superpowers/plans/2026-05-07-specwarden-v1.md +2159 -0
  26. specwarden-0.1.0/evals/README.md +75 -0
  27. specwarden-0.1.0/evals/fixtures/task_001_add_auth/expected.md +22 -0
  28. specwarden-0.1.0/evals/fixtures/task_001_add_auth/prompt.md +5 -0
  29. specwarden-0.1.0/evals/fixtures/task_001_add_auth/starting_state/README.md +4 -0
  30. specwarden-0.1.0/evals/fixtures/task_001_add_auth/starting_state/app.py +21 -0
  31. specwarden-0.1.0/evals/fixtures/task_001_add_auth/starting_state/requirements.txt +1 -0
  32. specwarden-0.1.0/evals/fixtures/task_001_add_auth/starting_state.tar.gz +0 -0
  33. specwarden-0.1.0/evals/fixtures/task_002_refactor_logger/expected.md +26 -0
  34. specwarden-0.1.0/evals/fixtures/task_002_refactor_logger/prompt.md +4 -0
  35. specwarden-0.1.0/evals/fixtures/task_002_refactor_logger/starting_state/README.md +7 -0
  36. specwarden-0.1.0/evals/fixtures/task_002_refactor_logger/starting_state/logger.py +48 -0
  37. specwarden-0.1.0/evals/fixtures/task_002_refactor_logger/starting_state/usage.py +42 -0
  38. specwarden-0.1.0/evals/fixtures/task_002_refactor_logger/starting_state.tar.gz +0 -0
  39. specwarden-0.1.0/evals/fixtures/task_003_add_test_suite/expected.md +29 -0
  40. specwarden-0.1.0/evals/fixtures/task_003_add_test_suite/prompt.md +3 -0
  41. specwarden-0.1.0/evals/fixtures/task_003_add_test_suite/starting_state/README.md +17 -0
  42. specwarden-0.1.0/evals/fixtures/task_003_add_test_suite/starting_state/cli.py +80 -0
  43. specwarden-0.1.0/evals/fixtures/task_003_add_test_suite/starting_state.tar.gz +0 -0
  44. specwarden-0.1.0/evals/fixtures/task_004_fix_race/expected.md +25 -0
  45. specwarden-0.1.0/evals/fixtures/task_004_fix_race/prompt.md +4 -0
  46. specwarden-0.1.0/evals/fixtures/task_004_fix_race/starting_state/README.md +14 -0
  47. specwarden-0.1.0/evals/fixtures/task_004_fix_race/starting_state/counter.py +37 -0
  48. specwarden-0.1.0/evals/fixtures/task_004_fix_race/starting_state.tar.gz +0 -0
  49. specwarden-0.1.0/evals/fixtures/task_005_add_endpoint/expected.md +27 -0
  50. specwarden-0.1.0/evals/fixtures/task_005_add_endpoint/prompt.md +4 -0
  51. specwarden-0.1.0/evals/fixtures/task_005_add_endpoint/starting_state/README.md +9 -0
  52. specwarden-0.1.0/evals/fixtures/task_005_add_endpoint/starting_state/db.py +20 -0
  53. specwarden-0.1.0/evals/fixtures/task_005_add_endpoint/starting_state/models.py +11 -0
  54. specwarden-0.1.0/evals/fixtures/task_005_add_endpoint/starting_state/requirements.txt +1 -0
  55. specwarden-0.1.0/evals/fixtures/task_005_add_endpoint/starting_state/routes.py +21 -0
  56. specwarden-0.1.0/evals/fixtures/task_005_add_endpoint/starting_state.tar.gz +0 -0
  57. specwarden-0.1.0/evals/measure.py +199 -0
  58. specwarden-0.1.0/evals/results/2026-05-11.md +191 -0
  59. specwarden-0.1.0/evals/run_eval.py +251 -0
  60. specwarden-0.1.0/examples/go-microservice/.claude/decisions/2026-05-08_add-version-endpoint.md +22 -0
  61. specwarden-0.1.0/examples/go-microservice/.claude/specs/2026-05-08_add-version-endpoint.md +27 -0
  62. specwarden-0.1.0/examples/go-microservice/README.md +31 -0
  63. specwarden-0.1.0/examples/go-microservice/go.mod +5 -0
  64. specwarden-0.1.0/examples/go-microservice/main.go +54 -0
  65. specwarden-0.1.0/examples/minimal-python-cli/.claude/decisions/2026-05-08_add-utc-flag.md +22 -0
  66. specwarden-0.1.0/examples/minimal-python-cli/.claude/specs/2026-05-08_add-utc-flag.md +26 -0
  67. specwarden-0.1.0/examples/minimal-python-cli/README.md +30 -0
  68. specwarden-0.1.0/examples/minimal-python-cli/cli.py +37 -0
  69. specwarden-0.1.0/examples/react-component/.claude/decisions/2026-05-08_add-reset-button.md +22 -0
  70. specwarden-0.1.0/examples/react-component/.claude/specs/2026-05-08_add-reset-button.md +26 -0
  71. specwarden-0.1.0/examples/react-component/Counter.test.tsx +11 -0
  72. specwarden-0.1.0/examples/react-component/Counter.tsx +22 -0
  73. specwarden-0.1.0/examples/react-component/README.md +28 -0
  74. specwarden-0.1.0/examples/react-component/package.json +22 -0
  75. specwarden-0.1.0/install.ps1 +47 -0
  76. specwarden-0.1.0/install.sh +58 -0
  77. specwarden-0.1.0/pyproject.toml +46 -0
  78. specwarden-0.1.0/src/specwarden/__init__.py +3 -0
  79. specwarden-0.1.0/src/specwarden/cli.py +179 -0
  80. specwarden-0.1.0/src/specwarden/coverage.py +55 -0
  81. specwarden-0.1.0/src/specwarden/decisions.py +43 -0
  82. specwarden-0.1.0/src/specwarden/git_hook.py +52 -0
  83. specwarden-0.1.0/src/specwarden/hooks/__init__.py +0 -0
  84. specwarden-0.1.0/src/specwarden/hooks/post_tool_use.py +66 -0
  85. specwarden-0.1.0/src/specwarden/hooks/pre_tool_use.py +52 -0
  86. specwarden-0.1.0/src/specwarden/hooks/session_start.py +27 -0
  87. specwarden-0.1.0/src/specwarden/paths.py +37 -0
  88. specwarden-0.1.0/src/specwarden/spec.py +117 -0
  89. specwarden-0.1.0/src/specwarden/trace.py +38 -0
  90. specwarden-0.1.0/src/specwarden/trailers.py +17 -0
  91. specwarden-0.1.0/tests/__init__.py +0 -0
  92. specwarden-0.1.0/tests/test_cli.py +177 -0
  93. specwarden-0.1.0/tests/test_coverage.py +52 -0
  94. specwarden-0.1.0/tests/test_decisions.py +47 -0
  95. specwarden-0.1.0/tests/test_git_hook.py +102 -0
  96. specwarden-0.1.0/tests/test_measure.py +134 -0
  97. specwarden-0.1.0/tests/test_paths.py +37 -0
  98. specwarden-0.1.0/tests/test_post_tool_use.py +57 -0
  99. specwarden-0.1.0/tests/test_pre_tool_use.py +50 -0
  100. specwarden-0.1.0/tests/test_session_start.py +32 -0
  101. specwarden-0.1.0/tests/test_skill_shims.py +50 -0
  102. specwarden-0.1.0/tests/test_smoke.py +8 -0
  103. specwarden-0.1.0/tests/test_spec.py +129 -0
  104. specwarden-0.1.0/tests/test_trace.py +67 -0
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: specwarden
3
+ description: Use when starting any non-trivial code change in this repo — refuses Edit/Write until a one-page spec is written; logs every accepted edit with a backlink. Activates on `/spec`, `/trace`, `/coverage`, `/spec-help`.
4
+ ---
5
+
6
+ # specwarden
7
+
8
+ > Every code change traces back to a written spec. Enforced by hooks, not vibes.
9
+
10
+ ## What this does
11
+
12
+ specwarden enforces a spec-first discipline: before any Edit or Write tool call lands, a structured one-page spec must exist and be marked ready. The PreToolUse hook reads `.claude/specs/active` on every tool call; if no spec is active, the hook blocks the call and tells you why. This makes the discipline mechanical rather than voluntary.
13
+
14
+ Once a spec is active, every edit is logged to `.claude/decisions/<spec-id>.md` with a timestamp and a reference back to the spec. When you commit, a `Spec: <id>` trailer is appended automatically (requires `specwarden git-hook install`). The result is a chain you can walk in either direction: from a commit to its spec, or from a spec to every file it touched.
15
+
16
+ ## Slash commands
17
+
18
+ ### `/spec <slug>`
19
+
20
+ Creates a new spec file at `.claude/specs/<slug>.md` from the four-section template and writes the slug to `.claude/specs/active`. Until all four sections are filled in and you type `ready`, the PreToolUse hook blocks any Edit or Write call with a message indicating which sections are still empty.
21
+
22
+ ### `/trace [<commit>]`
23
+
24
+ Prints the full chain for a given commit: commit SHA, the `Spec:` trailer, the spec file, and the corresponding decisions log. Defaults to HEAD when no commit is specified.
25
+
26
+ ### `/coverage [--last N]`
27
+
28
+ Scans recent commits (all commits, or the last N if `--last N` is given) and reports how many carry a `Spec:` trailer. Output format: `covered/total commits have spec coverage (pct%)`, followed by a list of uncovered SHAs.
29
+
30
+ ### `/spec-help`
31
+
32
+ Prints a one-page quick-reference card: the four slash commands, the spec template, the quick-fix escape hatch, and the path layout.
33
+
34
+ ## The four-section spec template
35
+
36
+ ```markdown
37
+ # <Spec ID>: <Short Title>
38
+
39
+ **Created:** <ISO timestamp>
40
+ **Status:** active | completed | abandoned
41
+ **Author:** <human name>
42
+
43
+ ## Assumptions
44
+ What we are taking as given. If any of these turns out to be false, the spec is
45
+ invalid and must be revised before more code lands.
46
+
47
+ - Assumption 1
48
+ - Assumption 2
49
+
50
+ ## Scope
51
+ What this change is. Concrete, files-and-functions level if possible.
52
+
53
+ - We will modify X
54
+ - We will add Y
55
+ - We will not touch Z
56
+
57
+ ## Non-goals
58
+ What this change is explicitly not. The point of this section is to prevent
59
+ scope creep mid-implementation.
60
+
61
+ - We will not refactor adjacent module M
62
+ - We will not change the public API of P
63
+
64
+ ## Success criteria
65
+ How we will know we are done. Must be checkable.
66
+
67
+ - [ ] Test T passes
68
+ - [ ] Manual scenario S works
69
+ - [ ] Documentation D is updated
70
+ ```
71
+
72
+ ## The discipline
73
+
74
+ 1. User describes a feature or fix.
75
+ 2. You invoke `/spec <slug>` and fill in all four sections in conversation. Push back on vague assumptions, surface trade-offs, propose non-goals to prevent scope creep.
76
+ 3. User reviews the spec and types `ready`.
77
+ 4. You proceed to edit. Each edit is appended to `.claude/decisions/<spec-id>.md` with a timestamp.
78
+ 5. When the work is done, run `specwarden done` from the terminal (or call the `mark_done` helper) to flip the spec status to `completed`.
79
+ 6. Commits made while the spec is active automatically carry a `Spec: <id>` trailer if `specwarden git-hook install` was run beforehand.
80
+
81
+ The spec is not a bureaucratic artifact — it is the conversation record that prevents you and the human from talking past each other mid-implementation. Write it as if someone will read it six months from now to understand why a particular decision was made.
82
+
83
+ ## Quick-fix mode
84
+
85
+ For edits where a full spec is genuine overhead — typo fixes, dependency version bumps, comment rewording — set `SPECWARDEN_QUICKFIX=1` in the environment before invoking Claude Code. The PreToolUse hook will allow Edit and Write calls without an active spec. The decisions log will not capture the edit. Use sparingly; the coverage report will mark these commits as uncovered.
86
+
87
+ ## Hook contract version
88
+
89
+ This skill targets the Claude Code hook contract published in 2026-Q1:
90
+
91
+ - `PreToolUse` returns `{"permissionDecision": "allow" | "deny" | "ask", "message": "..."}` over stdout.
92
+ - `PostToolUse` returns nothing (exit 0); side effects happen on disk.
93
+ - `SessionStart` writes a banner to stdout.
94
+
95
+ If the hook contract changes in a later Claude Code release, this skill must be updated to match. The CI workflow at `.github/workflows/ci.yml` runs a weekly job that exercises the hook contract against the latest published Claude Code release to catch drift early.
96
+
97
+ ## Files this skill writes
98
+
99
+ - `.claude/specs/<spec-id>.md` — the spec document, created by `/spec` or `specwarden new`.
100
+ - `.claude/specs/active` — single line containing the currently active spec ID; read by the PreToolUse hook on every tool call.
101
+ - `.claude/decisions/<spec-id>.md` — append-only log of every edit authorized under the spec.
102
+ - `.claude/settings.json` — hook wiring; created once by `specwarden init` and not modified again by the skill.
103
+
104
+ ## Out of scope for v1
105
+
106
+ The skill does not generate specs on behalf of the user. The human writes the spec; that is the forcing function. Auto-generated specs would remove the discipline the tool is designed to create. This is recorded in the project's own SPEC under "Non-goals" for v1.
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env python3
2
+ """Slash command shim for activating a spec — delegates to `specwarden activate`."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import subprocess
7
+ import sys
8
+
9
+
10
+ def main(argv: list[str]) -> int:
11
+ if len(argv) < 1:
12
+ print("usage: activate_spec <spec-id>", file=sys.stderr)
13
+ return 2
14
+ return subprocess.call(["specwarden", "activate", argv[0]])
15
+
16
+
17
+ if __name__ == "__main__":
18
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env python3
2
+ """Slash command shim for /coverage — delegates to `specwarden coverage`."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import subprocess
7
+ import sys
8
+
9
+
10
+ def main(argv: list[str]) -> int:
11
+ return subprocess.call(["specwarden", "coverage", *argv])
12
+
13
+
14
+ if __name__ == "__main__":
15
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env python3
2
+ """Slash command shim for /spec — delegates to `specwarden new`."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import subprocess
7
+ import sys
8
+
9
+
10
+ def main(argv: list[str]) -> int:
11
+ if len(argv) < 1:
12
+ print("usage: /spec <slug>", file=sys.stderr)
13
+ return 2
14
+ title = " ".join(argv)
15
+ return subprocess.call(["specwarden", "new", title, "--author", "claude"])
16
+
17
+
18
+ if __name__ == "__main__":
19
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env python3
2
+ """Slash command shim for /trace — delegates to `specwarden trace`."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import subprocess
7
+ import sys
8
+
9
+
10
+ def main(argv: list[str]) -> int:
11
+ args = argv if argv else ["HEAD"]
12
+ return subprocess.call(["specwarden", "trace", *args])
13
+
14
+
15
+ if __name__ == "__main__":
16
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,5 @@
1
+ ## {iso_timestamp}
2
+ - File: {file_path}
3
+ - Lines: {line_range}
4
+ - Summary: {summary}
5
+ - Tool: {tool}
@@ -0,0 +1,25 @@
1
+ # {spec_id}: {title}
2
+
3
+ **Created:** {created}
4
+ **Status:** active
5
+ **Author:** {author}
6
+
7
+ ## Assumptions
8
+ What we are taking as given. If any of these turns out to be false, the spec is invalid and must be revised before more code lands.
9
+
10
+ - TODO
11
+
12
+ ## Scope
13
+ What this change is. Concrete, files-and-functions level if possible.
14
+
15
+ - TODO
16
+
17
+ ## Non-goals
18
+ What this change is explicitly not. The point of this section is to prevent scope creep mid-implementation.
19
+
20
+ - TODO
21
+
22
+ ## Success criteria
23
+ How we will know we are done. Must be checkable.
24
+
25
+ - [ ] TODO
@@ -0,0 +1,91 @@
1
+ # 2026-05-28_v1-audit-nits-cli-wrapper-tests-and-caveman-cleanup: v1 audit nits CLI wrapper tests and Caveman cleanup
2
+
3
+ **Created:** 2026-05-28T18:44:06+00:00
4
+ **Status:** completed
5
+ **Author:** Amey Ambade
6
+
7
+ ## Assumptions
8
+
9
+ - `.claude/internal/V1_AUDIT.md` is still the authoritative pre-launch
10
+ audit. It flags exactly two non-blocking nits:
11
+ (a) `coverage` and `trace` CLI wrappers in `src/specwarden/cli.py`
12
+ lack direct CLI-layer tests (existing coverage is module-level);
13
+ (b) the Caveman section in `docs/COMPARISONS.md` was written from
14
+ the SPEC's secondhand reference, not from the Caveman repo.
15
+ - The current test suite is 63 passing under
16
+ `PYTHONPATH=src .venv/bin/python -m pytest -q`. Adding tests must
17
+ keep that count monotonic and the ruff check clean.
18
+ - The Python 3.14 / hatchling editable-install `.pth` quirk is a
19
+ separate, pre-existing issue (documented in WORKLOG and
20
+ NEXT_SESSION). Not in scope here; CLI invocation uses the
21
+ documented `PYTHONPATH=src python -m specwarden.cli` fallback.
22
+
23
+ ## Scope
24
+
25
+ - `tests/test_cli.py`: add two new tests at the bottom of the file,
26
+ next to the existing CliRunner tests.
27
+ - `test_coverage_reports_against_real_commits` — initializes a
28
+ real git repo under `tmp_path`, makes two commits (one with a
29
+ `Spec: <id>` trailer, one without), invokes
30
+ `app, ["coverage", "--last", "10", "--root", str(tmp_path)]`,
31
+ asserts exit code 0 and that stdout contains the
32
+ `"N/M commits have spec coverage"` line plus the uncovered SHA
33
+ prefix.
34
+ - `test_trace_with_active_spec_succeeds` — initializes a real git
35
+ repo, runs `specwarden init` + `new` + `activate` via the CLI to
36
+ produce a real spec file, writes a decisions-log entry for that
37
+ spec, makes a commit whose message body carries
38
+ `Spec: <spec-id>`, invokes
39
+ `app, ["trace", "HEAD", "--root", str(tmp_path)]`, asserts exit
40
+ code 0 and that stdout contains the spec id and the `---`
41
+ separators emitted by `trace_commit`.
42
+ - `docs/COMPARISONS.md`: rewrite only the Caveman section
43
+ (`## Caveman` through the section break before
44
+ `## Summary table`). Replace specific reception claims ("5K+ stars
45
+ quickly", "10K upvotes on r/ClaudeAI") with neutral structural
46
+ language. Keep the "what shares" / "what differs" / "when to use
47
+ both" subsection structure. Update the Summary-table row for
48
+ Caveman only if a column claim no longer holds; if it still holds
49
+ structurally, leave the row alone.
50
+ - `.claude/internal/V1_AUDIT.md`: tick both nits closed in the
51
+ "Remaining work" column for DoD #1 row and in the post-launch
52
+ notes if present.
53
+ - `.claude/internal/WORKLOG.md`: append a single new entry
54
+ documenting the change and the spec ID.
55
+ - One commit, conventional-commit format
56
+ (`test(cli): ...` or `chore: close v1 audit nits ...`), with a
57
+ `Spec: 2026-05-28_v1-audit-nits-cli-wrapper-tests-and-caveman-cleanup`
58
+ trailer in the body.
59
+
60
+ ## Non-goals
61
+
62
+ - Not fixing the Python 3.14 / hatchling editable-install `.pth`
63
+ quirk. That is a separate issue and deserves its own spec.
64
+ - Not adding tests for any command other than `coverage` and
65
+ `trace`. The audit named exactly those two.
66
+ - Not running the Caveman repo through a fact-finding fetch.
67
+ The user explicitly chose "Replace the secondhand claims with
68
+ neutral language" over the verify-and-correct option.
69
+ - Not changing the comparison structure or summary table for
70
+ GitHub Spec Kit, CLAUDE.md, Cursor, or MCP. Only the Caveman
71
+ section is in scope.
72
+ - Not bumping the package version. This is launch-prep polish, not
73
+ a release.
74
+
75
+ ## Success criteria
76
+
77
+ - [ ] `PYTHONPATH=src .venv/bin/python -m pytest -q` reports
78
+ 65 passed (was 63).
79
+ - [ ] `uv run ruff check .` is clean.
80
+ - [ ] `uv run ruff format --check .` is clean.
81
+ - [ ] `docs/COMPARISONS.md` Caveman section contains no specific
82
+ star count or upvote claim. The "what shares" / "what
83
+ differs" framing remains intact.
84
+ - [ ] `.claude/internal/V1_AUDIT.md` shows both nits resolved.
85
+ - [ ] One git commit lands with the `Spec:` trailer pointing at
86
+ this spec id. `git log -1 --format=%B | grep -F 'Spec: 2026-05-28_v1-audit-nits-cli-wrapper-tests-and-caveman-cleanup'`
87
+ returns a match.
88
+ - [ ] Spec marked done via
89
+ `python -m specwarden.cli done --root .` after the commit
90
+ lands. `.claude/specs/active` removed; the spec file's
91
+ status frontmatter reads `completed`.
@@ -0,0 +1,11 @@
1
+ # Copy this file to .env.eval and fill in your key.
2
+ # .env.eval is gitignored via the .env.* rule in .gitignore.
3
+ #
4
+ # Required for `python evals/run_eval.py` when invoking `claude --bare`,
5
+ # which strips OAuth/keychain auth and reads only ANTHROPIC_API_KEY.
6
+ #
7
+ # Get a key at https://console.anthropic.com/settings/keys.
8
+ # Billing for the eval run hits your Anthropic API account, not your
9
+ # Claude Code subscription.
10
+
11
+ ANTHROPIC_API_KEY=sk-ant-your-key-here
@@ -0,0 +1,32 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: ${{ github.workflow }}-${{ github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ test:
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ os: [ubuntu-latest, macos-latest]
21
+ python-version: ["3.10", "3.11", "3.12"]
22
+ runs-on: ${{ matrix.os }}
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - uses: actions/setup-python@v5
26
+ with:
27
+ python-version: ${{ matrix.python-version }}
28
+ cache: "pip"
29
+ - run: pip install -e '.[dev]'
30
+ - run: ruff check .
31
+ - run: ruff format --check .
32
+ - run: pytest --cov=specwarden --cov-report=term-missing
@@ -0,0 +1,61 @@
1
+ name: release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "[0-9]+.[0-9]+.[0-9]+"
7
+ - "[0-9]+.[0-9]+.[0-9]+rc[0-9]+"
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: release-${{ github.ref }}
14
+ cancel-in-progress: false
15
+
16
+ jobs:
17
+ test:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: "3.12"
24
+ cache: "pip"
25
+ - run: pip install -e '.[dev]'
26
+ - run: ruff check .
27
+ - run: ruff format --check .
28
+ - run: pytest --cov=specwarden --cov-report=term-missing
29
+
30
+ build:
31
+ needs: test
32
+ runs-on: ubuntu-latest
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+ - uses: actions/setup-python@v5
36
+ with:
37
+ python-version: "3.12"
38
+ - run: pip install build
39
+ - run: python -m build
40
+ - uses: actions/upload-artifact@v4
41
+ with:
42
+ name: dist
43
+ path: dist/
44
+
45
+ publish:
46
+ needs: build
47
+ runs-on: ubuntu-latest
48
+ environment: pypi
49
+ permissions:
50
+ id-token: write
51
+ steps:
52
+ - uses: actions/download-artifact@v4
53
+ with:
54
+ name: dist
55
+ path: dist/
56
+ - uses: pypa/gh-action-pypi-publish@release/v1
57
+ with:
58
+ packages-dir: dist/
59
+ # Trusted Publisher: no `password` field needed.
60
+ # PyPI verifies the OIDC token from GitHub against the
61
+ # publisher config at https://pypi.org/manage/account/publishing/
@@ -0,0 +1,70 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # Virtualenvs
25
+ .venv/
26
+ venv/
27
+ env/
28
+ ENV/
29
+
30
+ # Tooling
31
+ .pytest_cache/
32
+ .ruff_cache/
33
+ .coverage
34
+ htmlcov/
35
+ .mypy_cache/
36
+ .tox/
37
+
38
+ # Editor / OS
39
+ .DS_Store
40
+ .idea/
41
+ .vscode/
42
+ *.swp
43
+ *~
44
+
45
+ # Internal tracking — not part of the published artifact
46
+ .claude/internal/
47
+
48
+ # OMC state
49
+ .omc/
50
+
51
+ # Claude Code local settings (per-machine permission cache)
52
+ .claude/settings.local.json
53
+
54
+ # uv lockfile (project uses pip via pyproject.toml; uv lockfile is generated by side-tooling)
55
+ uv.lock
56
+
57
+ # Eval artifacts that should not be committed wholesale
58
+ evals/results/_local/
59
+ evals/.cache/
60
+
61
+ # Local secrets
62
+ .env
63
+ .env.*
64
+ !.env.example
65
+ !.env.*.example
66
+
67
+ # Launch-prep notes (personal; not part of public repo)
68
+ .claude/GIF_RECORDING.md
69
+ .claude/launch.md
70
+ .claude/medium-post.md
@@ -0,0 +1,103 @@
1
+ # specwarden — working notes
2
+
3
+ This file is the standing context for anyone (human or agent) working on this repo.
4
+ Read it before touching code. Update it when conventions change.
5
+
6
+ ## What we are building
7
+
8
+ `specwarden` is a Claude Code skill plus a set of lifecycle hooks that gate
9
+ filesystem edits behind a written spec. It also ships a Python CLI and an
10
+ eval suite. The full requirements live in `SPEC_specwarden.md` at the repo
11
+ root — that file is the single source of truth for v1 scope.
12
+
13
+ If anything here drifts from `SPEC_specwarden.md`, the SPEC wins.
14
+
15
+ ## Working directories
16
+
17
+ | Path | Purpose |
18
+ | --- | --- |
19
+ | `SPEC_specwarden.md` | Authoritative spec for v1. Treat as read-only unless the user changes scope. |
20
+ | `docs/superpowers/plans/` | Implementation plan(s). The active one is `2026-05-07-specwarden-v1.md`. |
21
+ | `.claude/skills/specwarden/` | The published skill artifact (SKILL.md, scripts, templates). Ships with the package. |
22
+ | `.claude/internal/` | Tracking notes for this build. Gitignored. Worklog, project context, feature specs go here. |
23
+ | `src/specwarden/` | Python CLI package. `pipx install specwarden` installs the entry point. |
24
+ | `hooks/` | Standalone hook scripts copied into the user repo by `specwarden init`. |
25
+ | `evals/` | Three-arm benchmark. Fixtures, runner, results. |
26
+ | `examples/` | Reference projects that show specwarden in use. |
27
+ | `docs/` | Public-facing markdown docs. |
28
+
29
+ ## Conventions
30
+
31
+ - Python 3.10+. Use `from __future__ import annotations` and standard library
32
+ where possible. Third-party deps: `typer`, `pytest`. Add more only with a
33
+ reason recorded in the plan.
34
+ - Tests live next to code under `tests/<module>/test_<thing>.py`. Use `pytest`,
35
+ not `unittest`. Aim for one assertion per test where practical.
36
+ - Format with `ruff format`. Lint with `ruff check`. Both run in CI.
37
+ - Markdown is written for engineers reading on a laptop. No marketing tone,
38
+ no superlatives, no AI tells. Headings are sentence case.
39
+ - Commits follow Conventional Commits (`feat:`, `fix:`, `docs:`, `test:`,
40
+ `chore:`, `refactor:`). Subject under 72 chars. No emoji in commits or docs.
41
+ Do not tag releases with a `v` prefix.
42
+ - Every commit that lands real code should carry a `Spec: <spec-id>` trailer.
43
+ The CLI is responsible for keeping that easy.
44
+ - Keep files small and focused. Split when one file owns more than one job.
45
+
46
+ ## Spec → decisions → commit chain
47
+
48
+ This is the discipline the project itself tries to enforce, so we eat our own
49
+ dog food while building it:
50
+
51
+ 1. Before touching code for a new chunk of work, write a spec under
52
+ `.claude/specs/` (use the four-section template once it exists).
53
+ 2. Set the active spec in `.claude/specs/active`.
54
+ 3. Make changes. Each edit gets logged to `.claude/decisions/<spec-id>.md`.
55
+ 4. Commit with a `Spec: <spec-id>` trailer.
56
+
57
+ For the bootstrap phase we may write specs by hand because the tooling does
58
+ not exist yet. Once the CLI lands (Phase 1 complete), switch to the tooling.
59
+
60
+ ## How to run things
61
+
62
+ ```bash
63
+ # Install the package in editable mode for local work
64
+ pipx install -e .
65
+
66
+ # Run tests
67
+ pytest
68
+
69
+ # Lint and format
70
+ ruff check .
71
+ ruff format .
72
+
73
+ # Run the eval (slow, costs API tokens)
74
+ make eval
75
+ ```
76
+
77
+ Until `pyproject.toml` is in place, only the planning files exist. See the
78
+ implementation plan for the bootstrap order.
79
+
80
+ ## Things to watch out for
81
+
82
+ - The Claude Code hook contract (JSON shape, `permissionDecision` values) is
83
+ the integration surface with the host tool. Pin the hook version we target
84
+ in `SKILL.md` and add a CI test that exercises it.
85
+ - The `.claude/specs/active` file is the synchronization point between hooks
86
+ and the CLI. Treat it as a single line, no trailing whitespace, no BOM.
87
+ - The eval suite uses `claude` headless mode. Document the exact CLI flags
88
+ used so the benchmark is reproducible.
89
+ - Do not auto-generate specs. The whole product loses its meaning if specs
90
+ are produced by the same agent the spec is supposed to constrain.
91
+
92
+ ## Out of scope (do not build)
93
+
94
+ See the SPEC's "Non-goals" section. Short list: no web UI, no Jira-style
95
+ project management, no team features, no AI-generated specs, no external
96
+ tracker integrations, no per-language templates.
97
+
98
+ ## Where to write progress
99
+
100
+ - Plan progress: tick boxes in `docs/superpowers/plans/2026-05-07-specwarden-v1.md`.
101
+ - Session log: `.claude/internal/WORKLOG.md` (append at end of each session).
102
+ - Cross-session state: `.claude/internal/PROJECT_CONTEXT.md`.
103
+ - Per-feature notes: `.claude/internal/FEATURE_SPECS.md`.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amey Ambade
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,18 @@
1
+ .PHONY: test lint fmt eval install-dev
2
+
3
+ install-dev:
4
+ pip install -e '.[dev]'
5
+
6
+ test:
7
+ pytest
8
+
9
+ lint:
10
+ ruff check .
11
+ ruff format --check .
12
+
13
+ fmt:
14
+ ruff check --fix .
15
+ ruff format .
16
+
17
+ eval:
18
+ python evals/run_eval.py