Skip to content

feat: add side-effect taxonomy, data models, and file discovery - #8

Merged
jflowers merged 3 commits into
mainfrom
opsx/taxonomy-and-discovery
Aug 28, 2026
Merged

feat: add side-effect taxonomy, data models, and file discovery#8
jflowers merged 3 commits into
mainfrom
opsx/taxonomy-and-discovery

Conversation

@jflowers

Copy link
Copy Markdown
Contributor

Summary

Adds the foundational analysis vocabulary and file discovery capability to Snake Eyes, implementing the second OpenSpec change (taxonomy-and-discovery).

This change introduces:

  • 48-value SideEffectType StrEnum — lifts gaze-py's 38 types and adds 10 new Python-specific types (e.g., AsyncGeneratorYield, MetaprogrammingMutation, ImportSideEffect)
  • Protocol-shaped data modelsEffect and FunctionRecord frozen dataclasses with None-omitting serialization, shaped to the Gaze v1.1.0 protocol (not gaze-py internals)
  • File discovery enginediscover() using os.walk with symlink safety, fixed exclusion set (16 dirs), test/source classification, and deterministic sorted output
  • discover JSON-RPC method — wired into the server with parameter validation, FileNotFoundError-to-RpcError mapping, and capabilities.discover = true

Also includes review-council fixes: sort_keys=True for deterministic JSON, Path.resolve() for traversal safety, CI cancel-in-progress scoped to non-default branches, and updated README/AGENTS.md documentation.

How to Test

# Install dependencies
uv sync --locked

# Run the full CI gate (85% coverage required, actual: 100%)
uv run pytest --cov=snake_eyes --cov-report=term-missing --cov-fail-under=85

# Lint and type check
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
uv run mypy src/

# Manual verification: initialize reports discover capability
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"analyzer_version":"0.1.0","protocol_version":"1.1.0"}}
{"jsonrpc":"2.0","id":2,"method":"shutdown"}' | uv run snake-eyes --stdio

# Manual verification: discover against this repo
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"analyzer_version":"0.1.0","protocol_version":"1.1.0"}}
{"jsonrpc":"2.0","id":2,"method":"discover","params":{"root_path":"src"}}
{"jsonrpc":"2.0","id":3,"method":"shutdown"}' | uv run snake-eyes --stdio

How to Demo

  1. Run uv run snake-eyes --stdio and send an initialize request — observe "discover": true in the capabilities
  2. Send a discover request with "root_path": "src" — observe source_files listing all 7 .py files and test_files as empty (no test files under src/)
  3. Send a discover request with "root_path": "." — observe both source_files and test_files populated, with test files correctly classified

Key Files Changed

File Change
src/snake_eyes/analysis/effects.py 48-member SideEffectType StrEnum, Tier enum, TIER_MAP
src/snake_eyes/analysis/models.py Effect, FunctionRecord frozen dataclasses, function_record_to_dict
src/snake_eyes/analysis/__init__.py Re-exports SideEffectType, TIER_MAP
src/snake_eyes/discovery.py discover(), DiscoveryResult, file walking and classification
src/snake_eyes/server.py _discover handler wired into DEFAULT_DISPATCH
src/snake_eyes/protocol.py capabilities.discover = True, sort_keys=True in to_json
.github/workflows/ci.yml CI workflow, cancel-in-progress scoped to non-default branches
README.md Updated status table, capability flags, project structure
AGENTS.md Updated project structure, technology stack qualifiers
openspec/changes/taxonomy-and-discovery/ Full OpenSpec change artifacts (proposal, design, specs, tasks)
tests/test_effects.py Taxonomy completeness and tier mapping tests
tests/test_models.py Serialization, frozenness, None-omission tests
tests/test_discovery.py File walking, classification, edge case tests
tests/test_discover_method.py JSON-RPC roundtrip integration tests

Known Issues

The following findings from the review council were acknowledged but not resolved:

  • MEDIUM: No resource limits on os.walk file discovery — a pathological project could cause unbounded memory/time consumption (deferred to follow-up issue)
  • MEDIUM: Dual serialization approaches (to_dict in protocol.py vs function_record_to_dict in models.py) — intentional per design decision D4
  • LOW: Test helper duplication (_write, _run across test files) — candidate for conftest.py extraction
  • LOW: Go-specific taxonomy names without Python-applicability commentary
  • LOW: Missing spec scenario tests (DiscoveryResult frozen, gaze-py-only fields absent, multiple effects serialize, Tier enum count)
  • LOW: _extract_id and _truncate private helpers lack docstrings
  • LOW: _is_test may miss root-level conftest.py

This PR was generated by /uf.finale (AI-assisted).

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 jflowers left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.md has no test verifying FunctionRecord excludes visibility, 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] _write helper duplicated in test_discovery.py and test_discover_method.py — consider moving to conftest.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).

@jflowers
jflowers merged commit 3e8d216 into main Aug 28, 2026
2 checks passed
@jflowers

jflowers commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

PR Cost Report: #8

Session: Review council command template

ID: ses_fb6de6b5effe5OxqyJJbhHm9Oo

Metric Value
Cost (parent only) $11.99
Input tokens 87,182
Output tokens 41,961
Reasoning tokens 2,747
Cache read tokens 8,381,892
Cache write tokens 1,051,330

Timeline: 2026-08-28 12:08:52 — 2026-08-28 14:01:28

Child sessions: 10 — additional cost: $11.94
Session tree total: $23.92

Child session breakdown
Session Cost Output Tokens
Gaze quality analysis (@gaze-reporter subagent) $1.79 7,254
Adversary security review (@divisor-adversary subagent) $1.00 5,161
Architect structure review (@divisor-architect subagent) $1.23 5,723
Guard intent drift review (@divisor-guard subagent) $1.08 5,738
Testing quality review (@divisor-testing subagent) $0.97 4,732
SRE operations review (@divisor-sre subagent) $1.11 5,321
Curator documentation review (@divisor-curator subagent) $1.48 6,275
Herald announcement review (@divisor-herald subagent) $1.34 5,081
Envoy communications review (@divisor-envoy subagent) $0.95 4,263
Scribe documentation review (@divisor-scribe subagent) $0.99 4,479

Session: New session - 2026-08-28T18:02:18.698Z

ID: ses_fb6769135ffewV2V6vaCJCUZQK

Metric Value
Cost (parent only) $5.80
Input tokens 76
Output tokens 26,501
Cache read tokens 4,996,972
Cache write tokens 422,975

Timeline: 2026-08-28 14:02:18 — 2026-08-28 16:45:11

Child sessions: 9 — additional cost: $9.02
Session tree total: $14.83

Child session breakdown
Session Cost Output Tokens
Adversary code review (@divisor-adversary subagent) $0.88 4,420
Architect code review (@divisor-architect subagent) $0.98 5,599
Guard code review (@divisor-guard subagent) $0.96 5,044
Testing code review (@divisor-testing subagent) $1.11 7,067
SRE code review (@divisor-sre subagent) $0.98 4,595
Curator code review (@divisor-curator subagent) $0.79 4,121
Envoy code review (@divisor-envoy subagent) $1.38 4,571
Herald code review (@divisor-herald subagent) $0.96 3,447
Scribe code review (@divisor-scribe subagent) $0.98 3,648

Grand Total: $38.75 across 2 session tree(s) (21 sessions)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant