feat(ops): Phase 2 of ops-specs-features — status-flip write API#239
Merged
Conversation
Adds PUT /api/specs/{slug}/{phase}/status to flip the **Status** line
in a phase file. Mirrors attune-gui semantics; rejected in --read-only
mode. Atomic write via tempfile+os.replace. 16 new tests, all passing.
Closes Phase 2 of #230 (ops-specs-features). Frontend in Phase 3.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This was referenced May 12, 2026
silversurfer562
added a commit
that referenced
this pull request
May 12, 2026
Patches a DNS-rebinding vulnerability in the local ops dashboard that allowed any visited website to invoke ops endpoints (including workflow execution) on the local machine. Fix landed in #254. Also bundles UI/UX changes shipped between v6.7.0 and now: Tier 1 rich rendering (#247), full-page run view (#251), specs tab (#236/#239/#240), humanized 409s + tab cleanup (#228/#231), run-enabled-by-default ops mode (#227). Bumps version in pyproject.toml, plugin manifests, root marketplace.json, .claude/CLAUDE.md, API_REFERENCE.md, and uv.lock. CHANGELOG entry leads on the security fix.
silversurfer562
added a commit
that referenced
this pull request
May 12, 2026
* release: v6.7.1 — DNS-rebinding fix for ops dashboard Patches a DNS-rebinding vulnerability in the local ops dashboard that allowed any visited website to invoke ops endpoints (including workflow execution) on the local machine. Fix landed in #254. Also bundles UI/UX changes shipped between v6.7.0 and now: Tier 1 rich rendering (#247), full-page run view (#251), specs tab (#236/#239/#240), humanized 409s + tab cleanup (#228/#231), run-enabled-by-default ops mode (#227). Bumps version in pyproject.toml, plugin manifests, root marketplace.json, .claude/CLAUDE.md, API_REFERENCE.md, and uv.lock. CHANGELOG entry leads on the security fix. * chore(audit): CLAUDE.md — remove superseded and stale lessons Audit pass 1 (supersession) + pass 3 (stale references). Removed 4 lessons: - Session hooks may be vestigial — referenced session_end.py which no longer exists. - Read source before writing tests for tricky logic — used is_in_docstring_or_comment() as the concrete example, which has since been removed. - Skill frontmatter has a strict allowlist — contradicted by the March 2026 allowlist lesson; the original listed the wrong fields as valid. - Verify optional dep boundaries with a MetaPathFinder — recommended the deprecated find_module/load_module hooks that stopped firing in Python 3.12+. The replacement (sys.modules[name] = None sentinel) is the surviving lesson, which has been retitled to lead with the recommendation instead of opening on a now-deleted lesson. Also dropped the trailing "the old lesson about a strict 8-field allowlist was outdated" sentence from the March 2026 skill frontmatter lesson, since the old lesson no longer exists in the file. 267 -> 263 lessons. * chore(audit): CLAUDE.md — consolidate duplicate lessons Pass 2 of the audit. Merges 11 clusters of duplicate or near-duplicate lessons into single consolidated entries. Each merge preserves the substantive content of every original; only the duplication is collapsed. Mergers (each is N originals → 1 consolidated lesson): - GPG signing in non-interactive terminals (2 → 1) Combines pinentry-mac setup and "first match wins" gotcha. - Path.glob / PurePosixPath.match (2 → 1) Combines the dir-vs-file gotcha and the 3.10 single-segment gotcha. - Stop hook configuration (4 → 1) Combines stderr-not-stdout, ordering, sentinel-files, cd-prefix. - Path validation completeness (3 → 1) Combines reads-need-it-too, validate-before-import, copy-from-neighbor. - Dataclass field completeness (3 → 1) Combines parser updates, getattr-vs-.get, named-not-positional. - Version bump checklist (3 → 1) Combines 7+ files, dist rebuild, README rebuild. - Dead code detection (3 → 1) Combines silent-pass-blocks, embeddings-look-alive, hot_reload-look-alive. - GitHub branch protection (4 → 1) Combines exact-check-names, in-progress-checks, enforce_admins, auto-merge-vs-restore. - PyPI publishing (4 → 1) Combines trusted-publishing, env-approval-gate, twine-token-env, never-paste-tokens. - Pre-commit stash conflicts (5 → 1) Combines auto-fix-with-unstaged, black-restage-after-failure, any-unstaged-triggers, manual-preempt, stash-unrelated-files. - Patchable lazy imports (5 → 1) Combines availability-guard, module-scope-hoist, patch-source-module, patch.dict-sys.modules, ImportError simulation. 263 -> 236 lessons. Net file size down ~80 lines despite the consolidated entries being individually larger — each merge removed redundant prose more than it added new prose. No information lost: every distinct rule, mechanism, and example from the originals is preserved in the merged entry. * chore(audit): CLAUDE.md — tighten four overlong lessons Pass 4 of the audit. Trims four lessons that ran 27-50 lines apiece down to 17-24, removing redundant narrative and inline transcripts while preserving the rule, the mechanism, and the scope of applicability. - Two CodeQL setups can coexist and deadlock merges (50 -> 19 lines). Dropped the full SARIF error transcript and the duplicated "Resolution in attune-ai" paragraph; kept the diagnostic commands and the pick-ONE structural fix. - `import X` in try block + `except X.SomeError` (43 -> 24). Dropped the duplicated code block illustrating the bug; kept the failing example, the fix pattern, and the scope of where it applies. - Direct pushes to main blocked by required_pull_request_reviews presence, not count (27 -> 17). Dropped the API call transcripts; kept the surprising-derivation rule and the practical recommendation (always open a PR). - GitHub Copilot Autofix pushes commits to PR branches (30 -> 17). Dropped the specific commit SHA and PR number; kept the recognition signal, the recovery recipe, and the rebase-replay warning. Final state: 236 lessons / 2889 lines, from 267 / 3081 at the start of the audit. Net: -31 lessons, -192 lines, no information lost. * chore(audit): CLAUDE.md — tighten three more lessons Continuation of pass 4. Three lessons that ran 23-27 lines trimmed to 14-17 by dropping repeated narrative and specific artifact references (commit SHAs, file paths) while keeping the rule, the diagnostic signal, and the fix. - HAS_API_KEY-gated integration tests poison the matrix (27 -> 14 lines). Dropped the duplicated explanation of the failure mode and the specific PR number. - Research subagents can confabulate SDK signatures (26 -> 17). Dropped the full failed-claim example; kept the introspection pattern and rule. - Past-due deprecations are deletion targets (23 -> 16). Dropped the artifact-specific paragraph; kept the rule and the generalization. Final state: 236 lessons / 2863 lines, from 267 / 3081 at the start of the audit. Net: -31 lessons, -218 lines. Stopping tightening here. The remaining long entries (30 lines) are either intentional merge consolidations or RAG content with specific empirical numbers (P@1 percentages, faithfulness scores) where compression would risk losing precision.
4 tasks
silversurfer562
added a commit
that referenced
this pull request
May 13, 2026
…#290) Phase 0 gate verification done. Both 0.1b and 0.5 satisfied. Key finding: the spec is far more done than tasks.md showed. Phases 1, 2, 3 were all shipped via PRs #236, #239, #249 — but only Phase 2/3 checkboxes got flipped at the time. Phase 1's checkboxes sat as [ ] todo while the code lived on main for days. Verification: - All Phase 1 capabilities exist (GET /api/specs, GET /api/specs/{slug}, --specs-root CLI flag, multi-root support). - 54 tests in tests/unit/ops/test_specs_*.py — all green. - All "What we explicitly do NOT port" items confirmed absent. - CI on main: 2 consecutive successful runs, one earlier flaky timeout failure (not a new mode). Spec status flipped to "Phases 1–3 complete; Phase 4 reflection cycle awaiting 2 weeks of usage (target: 2026-05-25)." Phase 4 is time-gated by design, not work-gated. Files: - phase0-audit.md (new) — verification of both gate conditions plus the per-task confirmation that Phase 1 shipped - tasks.md — 0.1b, 0.5, 1.1, 1.2, 1.3 all flipped to [x] with PR references; spec status updated to reflect reality Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 2 of #230 (ops-specs-features) — adds the status-flip write API on top of Phase 1's read-only foundation.
New endpoint:
PUT /api/specs/{slug}/{phase}/status**Status:**line in a phase file (decisions.md,requirements.md,design.md,tasks.md).**Status:**(attune-ai) and**Status**:(attune-gui) conventions; normalizes output to the attune-ai form.tempfile.mkstemp+os.replace— concurrent readers see old-or-new, never partial.config.allow_run— returns 403 in--read-onlymode.draft,in-review,approved,complete,completed,done).Test coverage: 16 new tests, all passing.
**Status:**and**Status**:conventions, insertion when missing, alias values, multi-root collisionTest plan
uv run pytest tests/unit/ops/ --no-cov— 60 passeduv run ruff check src/attune/ops/routes/specs.py tests/unit/ops/test_specs_routes.py— cleanpre-commit run black— cleanattune ops --specs-root docs/specs/ --allow-run, PUT a status, verify file rewriteNext
Phase 3 — Specs tab frontend (nav + template + drill-in UI). Will reference attune-gui's
templates/specs.htmlas the pattern.🤖 Generated with Claude Code