Skip to content

feat(ops): Phase 2 of ops-specs-features — status-flip write API#239

Merged
silversurfer562 merged 1 commit into
mainfrom
feat/ops-specs-phase2-write-api
May 11, 2026
Merged

feat(ops): Phase 2 of ops-specs-features — status-flip write API#239
silversurfer562 merged 1 commit into
mainfrom
feat/ops-specs-phase2-write-api

Conversation

@silversurfer562
Copy link
Copy Markdown
Member

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

  • Rewrites the **Status:** line in a phase file (decisions.md, requirements.md, design.md, tasks.md).
  • Recognizes BOTH **Status:** (attune-ai) and **Status**: (attune-gui) conventions; normalizes output to the attune-ai form.
  • Inserts a status line if none exists (no-op-safe for malformed files).
  • Atomic write via tempfile.mkstemp + os.replace — concurrent readers see old-or-new, never partial.
  • Gated by config.allow_run — returns 403 in --read-only mode.
  • Validates slug (regex), phase name (allowlist), and status value (draft, in-review, approved, complete, completed, done).

Test coverage: 16 new tests, all passing.

Class Coverage
Success path Both **Status:** and **Status**: conventions, insertion when missing, alias values, multi-root collision
Validation Unknown spec (404), unknown phase (400), invalid status (400), missing body field (422), invalid slug shape (400)
Security Read-only mode (403), path-traversal slugs rejected

Test plan

  • uv run pytest tests/unit/ops/ --no-cov — 60 passed
  • uv run ruff check src/attune/ops/routes/specs.py tests/unit/ops/test_specs_routes.py — clean
  • pre-commit run black — clean
  • CI matrix green
  • Manual smoke: launch attune ops --specs-root docs/specs/ --allow-run, PUT a status, verify file rewrite

Next

Phase 3 — Specs tab frontend (nav + template + drill-in UI). Will reference attune-gui's templates/specs.html as the pattern.

🤖 Generated with Claude Code

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>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
attune-ai Error Error May 11, 2026 4:49pm
website Ready Ready Preview, Comment May 11, 2026 4:49pm

@codecov
Copy link
Copy Markdown

codecov Bot commented May 11, 2026

Codecov Report

❌ Patch coverage is 88.23529% with 8 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/attune/ops/routes/specs.py 88.23% 7 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@silversurfer562 silversurfer562 merged commit c24ecf7 into main May 11, 2026
30 of 38 checks passed
@silversurfer562 silversurfer562 deleted the feat/ops-specs-phase2-write-api branch May 11, 2026 17:19
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.
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core documentation Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant