feat: add side-effect taxonomy, data models, and file discovery - #8
Conversation
Constitution (v1.0.0 → v1.1.0): - Declare parent_constitution: unbound-force/unbound-force v1.2.0 - Add Principle V: Analysis Safety (untrusted input, static-only, dependency necessity, SHA-pinned CI actions) - Add determinism MUST rules under Principle I - Upgrade Upstream Alignment: pin protocol v1.1.0, require conformance suite, alignment-issue-within-one-release-cycle obligation - Add org supremacy clause and Conflict Resolution clause - Add SYNC IMPACT REPORT version history block AGENTS.md: - Add Constitution bridge section (5 principle summaries) - Fix Shell Commands to mirror ci.yml (--locked, --check, --cov-fail-under=85) - Expand Convention Packs from 5 to 9 (add python, ci packs) - Add Spec Organization guidance (Speckit/OpenSpec two-tier table) - Add Workflow Gates (Constitution Check, Review Council, CI Parity)
- Add 48-value SideEffectType StrEnum lifting gaze-py's 38 types plus 10 new Python-specific types (analysis/effects.py) - Add Effect and FunctionRecord protocol-shaped data models with None-omitting serialization (analysis/models.py) - Implement file discovery engine using os.walk with symlink safety, fixed exclusion set, and deterministic output (discovery.py) - Wire discover JSON-RPC method with parameter validation and FileNotFoundError-to-RpcError mapping (server.py) - Flip capabilities.discover to true in initialize handshake - Add sort_keys=True for deterministic JSON serialization - Add Path.resolve() for path traversal safety - Update README.md and AGENTS.md to reflect new modules - Scope CI cancel-in-progress to non-default branches - Add coverage.json to .gitignore - Add OpenSpec change artifacts for taxonomy-and-discovery - 108 tests, 100% coverage across all modules Assisted-by: claude-opus Generated with AI assistance (claude-opus)
jflowers
left a comment
There was a problem hiding this comment.
Council Verdict: APPROVE
Note: Could not post as APPROVE due to self-review prohibition. Posted as COMMENT instead. Original verdict: APPROVE.
Reviewers: Adversary, Architect, Curator, Envoy, Guard, Herald, Scribe, SRE, Testing
Iterations: 0 (all approved on first pass)
Pre-flight: All 5 CI gates passed (ruff check, ruff format, mypy, pytest 108 tests/100% coverage, uv sync --locked)
Adversary (APPROVE)
1 LOW finding omitted.
Architect (APPROVE)
4 LOW findings omitted.
Guard (APPROVE)
No findings. Perfect spec-to-implementation alignment across all 4 capability specs. All 5 constitution principles PASS. Zero waste.
Testing (APPROVE)
- [MEDIUM] Missing Tier enum shape tests — spec scenarios "Five tiers exist" (
len(Tier) == 5) and "Tier values match names" (Tier.P0.value == "P0") have no corresponding tests. - [MEDIUM] Missing gaze-py-only fields absent test — spec scenario "gaze-py-only fields are absent" from
models/spec.mdhas no test verifyingFunctionRecordexcludesvisibility,is_test,is_generator,complexity,id. - [MEDIUM] Missing multi-effect serialization test — spec scenario "side_effects serializes as a list" with 2+ effects is untested (only 0 and 1 effect tested).
- [MEDIUM]
_writehelper duplicated intest_discovery.pyandtest_discover_method.py— consider moving toconftest.py.
4 LOW findings omitted.
SRE (APPROVE)
5 LOW findings omitted.
Curator (APPROVE)
No findings. README and AGENTS.md accurate and current.
Envoy (APPROVE)
6 LOW findings omitted.
Herald (APPROVE)
5 LOW findings omitted.
Scribe (APPROVE)
5 LOW findings omitted.
This review was generated by /review-council (AI-assisted).
PR Cost Report: #8Session: Review council command templateID:
Timeline: 2026-08-28 12:08:52 — 2026-08-28 14:01:28 Child sessions: 10 — additional cost: $11.94 Child session breakdown
Session: New session - 2026-08-28T18:02:18.698ZID:
Timeline: 2026-08-28 14:02:18 — 2026-08-28 16:45:11 Child sessions: 9 — additional cost: $9.02 Child session breakdown
Grand Total: $38.75 across 2 session tree(s) (21 sessions) |
Summary
Adds the foundational analysis vocabulary and file discovery capability to Snake Eyes, implementing the second OpenSpec change (
taxonomy-and-discovery).This change introduces:
SideEffectTypeStrEnum — lifts gaze-py's 38 types and adds 10 new Python-specific types (e.g.,AsyncGeneratorYield,MetaprogrammingMutation,ImportSideEffect)EffectandFunctionRecordfrozen dataclasses withNone-omitting serialization, shaped to the Gaze v1.1.0 protocol (not gaze-py internals)discover()usingos.walkwith symlink safety, fixed exclusion set (16 dirs), test/source classification, and deterministic sorted outputdiscoverJSON-RPC method — wired into the server with parameter validation,FileNotFoundError-to-RpcErrormapping, andcapabilities.discover = trueAlso includes review-council fixes:
sort_keys=Truefor deterministic JSON,Path.resolve()for traversal safety, CIcancel-in-progressscoped to non-default branches, and updated README/AGENTS.md documentation.How to Test
How to Demo
uv run snake-eyes --stdioand send aninitializerequest — observe"discover": truein the capabilitiesdiscoverrequest with"root_path": "src"— observesource_fileslisting all 7.pyfiles andtest_filesas empty (no test files undersrc/)discoverrequest with"root_path": "."— observe bothsource_filesandtest_filespopulated, with test files correctly classifiedKey Files Changed
src/snake_eyes/analysis/effects.pySideEffectTypeStrEnum,Tierenum,TIER_MAPsrc/snake_eyes/analysis/models.pyEffect,FunctionRecordfrozen dataclasses,function_record_to_dictsrc/snake_eyes/analysis/__init__.pySideEffectType,TIER_MAPsrc/snake_eyes/discovery.pydiscover(),DiscoveryResult, file walking and classificationsrc/snake_eyes/server.py_discoverhandler wired intoDEFAULT_DISPATCHsrc/snake_eyes/protocol.pycapabilities.discover = True,sort_keys=Trueinto_json.github/workflows/ci.ymlcancel-in-progressscoped to non-default branchesREADME.mdAGENTS.mdopenspec/changes/taxonomy-and-discovery/tests/test_effects.pytests/test_models.pytests/test_discovery.pytests/test_discover_method.pyKnown Issues
The following findings from the review council were acknowledged but not resolved:
os.walkfile discovery — a pathological project could cause unbounded memory/time consumption (deferred to follow-up issue)to_dictin protocol.py vsfunction_record_to_dictin models.py) — intentional per design decision D4_write,_runacross test files) — candidate for conftest.py extraction_extract_idand_truncateprivate helpers lack docstrings_is_testmay miss root-levelconftest.pyThis PR was generated by /uf.finale (AI-assisted).