Skip to content

Releases: gonimar/claude-web-studio

v0.14.0

Choose a tag to compare

@gonimar gonimar released this 27 Sep 16:31
Immutable release. Only release title and notes can be modified.
2de618e

Nothing new to run: this release verifies and slims what 0.13 shipped, and adds the four technology groups the audit
found missing. Audit of 2026-09-26 (plugin-validator, skill-reviewer on the eleven heaviest skills, the
skill-development checklist on the other thirty-nine, claude-md-improver, automation-recommender): 7 blocking defects,
10 false semantics, all closed here; the full report and the reviewers' notes stayed in the maintainer's dev/.

  • Behavioural evals (evals/, claude plugin eval). 21 cases for dev-story, code-review, story-done, init,
    adopt, refactor, hotfix, update, help and impact, each derived from a spec case in testing/skills/, graded
    deterministically (the skill's verdict or gate phrase in the final message, a tool that must or must not run, no file before the
    gate); scaffold helpers build the testing/e2e fixtures in the run's workspace. CI gains an evals job
    (workflow_dispatch with a case glob, nightly, cost ceiling, results as an artifact); claude plugin validate .claude-plugin/plugin.json joins the marketplace validation in CI, tests/run-all.sh and the kit's CLAUDE.md —
    . alone validated only marketplace.json. testing/README.md § Evals says how an eval differs from a spec;
    catalog.yaml carries last_eval / last_eval_result. A deliberately broken grader was shown red (exit 1) before
    it was removed. Local finding: the eval sandbox does not start Bash as root (seccomp), so the green run is CI's.
  • agent: was never doing anything. Twenty-nine skills declared agent:; a live probe with a sentinel in the
    agent showed no subagent was started and the agent's prompt never applied — the field acts only with
    context: fork, which no skill uses (and cannot: a forked skill has no AskUserQuestion, so no gate). The field is
    gone; the linter rejects agent without context: fork and requires the web-studio: namespace on it. model:
    does act — on the whole turn, the closing hand-off included — so 43 sonnet/haiku pins are gone too; help keeps
    haiku, the six opus skills keep opus, and the linter refuses a model pin on a skill that edits files. help's
    undocumented context: | block is deleted. CONTRIBUTING § 3 states the field semantics as Claude Code applies them.
  • The eleven heaviest skills read shorter and carry every rule. Shared fragments (language, <hooks>,
    namespaces, gates, the documents-lane commit gate, the Skill tool, CI wait, verdict and next step) are defined
    once in coordination-rules § Skill conventions and named by one line; per-stack and per-mode detail moved verbatim
    to skills/<name>/references/ (checks-go/php, baseline-go/php, apply, routing, interviews, close edits, DoD
    recipes, signals…), read on the step that needs it. On-invoke per claude plugin details: refactor 7.8k → 4.3k,
    dev-story 6.9k → 5.0k, code-review 5.3k → 3.2k, adopt 5.1k → 4.0k, update 4.5k → 3.7k, hotfix 4.4k → 3.8k, help 4.4k →
    3.2k, story-done 4.3k → 3.7k, impact 3.7k → 3.2k, init 3.6k → 2.9k, setup-stack 3.6k → 2.7k — 53.6k → 39.7k tokens
    (−26 %); the same graders old-vs-new on every case: no case lost, three gained. /skill-test static all: 50 COMPLIANT.
    Defects closed on the way: session state now records the namespaced /web-studio:code-review (a resumed plugin-mode
    session ran Claude Code's built-in review); story-done's studio-review check recognised only leads and engineers
    (a technical-director or accessibility-specialist review read as "no studio review"), a Done story with an open PR
    re-ran the close, a pull_request-only CI with no PR deadlocked DONE; setup-stack cited a layout ADR nothing wrote and
    could lower a brownfield stage; init had no <root> in copy mode and let an installed plugin turn a copy-mode
    project into plugin mode; update's restart check came after the seed gate; hotfix's chore lane had no verdict;
    impact's solo/lean modes had no defined outcome; adopt copied rule 7 verbatim.
  • One collaboration protocol, not thirty copies. The 380-word block every agent carried (55 % of the agents'
    text) is the preloaded skill collaboration-protocol (user-invocable: false); each agent keeps a one-paragraph
    pointer and skills: [collaboration-protocol, …]; a forked agent was shown to receive it. The agent-development
    pass: directors drop the inert Task/AskUserQuestion pre-grants and return questions to the caller; the four
    leads that "routed work" name the specialist the session dispatches and say they do not spawn; ## Never for
    seo-specialist, appsec-engineer, network-security-engineer; a color per tier; protocol item 10 says what agent
    memory holds and that MEMORY.md is read first; the plugin-mode memory directory is named.
  • templates/CLAUDE.md.template cut to what its imports do not already say (audit of 2026-09-26: 80 lines, about 45 of
    them restating the @-imported coordination-rules). Principles keep their numbers and names and point to the rule or
    section that owns them; directory-structure.md and security-baseline.md are referenced by path, not imported (principle 4 keeps the
    four baseline items in one line); merge-policy line under principle 5, /help commands / /help guide pointer, "managed by /update"
    on the two studio sections. Principle 3's package-health checks move to rules/dependencies.md (manifests and lockfiles);
    principle 9's "neighbouring code stays as it is" reaches the TypeScript, Vue and Angular rules as it already did Go and PHP.
    Principle 7 loses its incident: catalog artifacts authored in the chat, and product code written right after /init
    because the goal "looked trivial", skipped the steps' gates and templates — that is why the first code goes through /start.
  • Kit CLAUDE.md names the commit gate (tests/run-all.sh), the kit ↔ project path mapping, tests/ vs testing/ vs
    evals/, the hook contract and the rule that the template's principle numbers are never renumbered.
  • Observability and Kubernetes references (observability.md, kubernetes.md): JSON logs, Prometheus /metrics,
    OpenTelemetry over OTLP, /healthz + /readyz; the kubernetes deploy target gets its shape (one chart per service,
    values per environment, Gateway API, probes on those endpoints, requests/limits, PDB, HPA, external-secrets, images
    by digest, rollout and rollback). Wired through technical-preferences, setup-stack, stack-update, rules/kubernetes.md
    and the Go/PHP/TS rules, devops-lead/devops-engineer and the backend engineers, /adopt detection, /deploy.
  • Supply chain (supply-chain.md): syft SBOM, cosign keyless signing verified by digest before deploy, GitHub
    provenance attestations, Renovate with a release age, lockfile and registry hygiene, Actions pinned by SHA; templates
    (renovate.json, release-attest.yml, verify-image.sh); /harden gets a supply-chain check group, /release-checklist
    three items with commands, /deploy verifies the signature, /dependency-audit scans the SBOM, /adopt detects it.
  • LLM in the product and MCP for the studio (llm-integration.md): the Anthropic SDKs and Messages API
    essentials, MCP as a product feature, evals, cost, and the security table mapped to the OWASP GenAI LLM Top 10;
    /threat-model adds the prompt-injection surface (trust boundaries, tool side effects, RAG, MCP) when a project
    declares or imports an LLM SDK; rules/security-sensitive.md and impact-guard cover prompts/, llm/, mcp/.
    .mcp.json declares one optional server, Playwright (a11y-audit, perf-audit and pentest drive the live page through
    it when present; the CLI path stays the default; the playbook says what it costs and how to switch it off). The
    GitHub MCP server is not declared — a plugin server starts for every user and this one fails without Docker or a
    token — the playbook says how to add it (remote OAuth or Docker, toolsets pull_requests,actions); story-done and
    hotfix may use it instead of gh with the gates unchanged. Two hooks watch it whatever its toolsets: the new
    github-mcp-guard blocks its file-writing tools (commits go through git and its hooks) and secret-guard blocks a
    token or key in any of its inputs — a PR body or an issue as much as a file.
  • Symfony and Laravel are full references (107 and 118 lines, from the frameworks' documentation repositories):
    versions and support, the studio's defaults, idioms per layer with the FRAMEWORK_NAMESPACES keys, testing,
    performance, security, upgrade paths, review checklists; corrections to the stubs (Symfony 8.1 shipped 2026-05-29,
    Laravel 13 on 2026-03-17). php-engineer reads the framework file first; code-review and refactor gain framework checks.
  • Descriptions say what and when. Twenty-eight rewritten from the audit (refactor 678 → 349 chars; fourteen gain
    the "use when …" sentence with the phrases a user types; story-done names the PR open and merge, init is "the
    studio's init, not Claude Code's", hotfix names --chore, code-review is "the studio's review, not the built-in").
    The description optimizer (skill-creator, 20 queries × 3 runs × 4 iterations) on help, backlog and impact: precision
    100 %, recall 11–33 % whatever the text — the model answers "what now" itself in a bare project; the descriptions that
    scored best on the held-out set are the ones shipped. Seven descriptions shrink and twenty-two grow. What that
    costs is not tokens: Claude Code caps the skill listing at about 1 % of the context window (≈ 8,000 characters at 200k;
    SLASH_COMMAND_TOOL_CHAR_BUDGET raises it) and drops the least-used descriptions to name-only beyond it — the 50
    descriptions total 18.8k characters (16.8k on 0.13), so with no usage history 18 of 50 keep theirs in the listing
    (23 before), the rest until they are used. README § 1 documents the cap; on-invoke is where the budget went.
  • Roadmap "Toward 1.0": condition 5 gains its C...
Read more

v0.13.0

Choose a tag to compare

@gonimar gonimar released this 27 Sep 16:31
Immutable release. Only release title and notes can be modified.
6613ceb

Two sources: the lab's traces of two real projects (the sprint cycle, comments, agent memory — WS-131, WS-136…139), and
the skill pass with its follow-ups (#62, #64–#67).

  • Agent memory is committed with the work that produced it. Thirty agents write .claude/agent-memory/<agent>/**
    on every run and no lane owned those files: a Haiku /story-done hid 16 of them from ten stories in git stash push -u,
    where they sat for 28 hours until the owner asked what was hanging (WS-136). git-workflow gains the Agent memory
    lane; /dev-story, /refactor --apply, /code-review, the audits and /team-* stage .claude/agent-memory/ with their commits;
    /story-done requires git status --short and git stash list empty and offers one more commit, never a stash;
    the hooks treat .claude/agent-memory/ as the documents lane (a memory-only docs: commit of an audit on the
    default branch passes); coordination-rules § Subagents says it in one sentence.
  • The retrospective closes the sprint — and nothing else does. A sprint had no act of closing: /retrospective wrote
    its section, /sprint-plan folded the previous block only as a side effect and only when every story was [x], so a
    sprint with one carried-over story never closed, sprints closed with no retrospective at all, and one block was folded by
    hand. Now /retrospective Phase 4 moves unfinished stories back to the Backlog with their markers, folds the block
    (closed · N stories · K carried over), writes Status: closed YYYY-MM-DD into the sprint file and reconciles its
    ## Stories table from the roadmap; /sprint-plan is BLOCKED (sprint NN open — run /retrospective NN first);
    /story-done recommends the retrospective after the last story; /sprint-status prints the sprint's status and
    OVER (not closed); /help prints an Attention: line. Template sprint-plan.md gains the Status: header;
    /migrate sprints adds it to older files.
  • The sprint file's Stories table is kept in step. /sprint-status read story states from a table that only
    /sprint-plan ever wrote (six closed stories still read Ready on one project, the owner synced it by hand). /dev-story
    and /refactor --apply set the row to In Progress, /story-done to Done · ⏱ Nh · PR #N (third place in its proof
    step), /sprint-status reads states from the roadmap and counts a differing row as sprint file ≠ roadmap.
  • Actual time in one clock. Started: carries its offset (date +%FT%H:%M%z), /refactor --apply writes it too
    (four refactor stories had their times read off git reflog), and /story-done never takes "now" from a CI or GitHub
    UTC stamp — 10.5 h became 8 h and 2 h became 8 h that way, and the calibration ratio ran on those numbers.
  • Comments are the contract and the reason, not the story's history (rules/comments.md). Agents knew the godoc
    form (228 of 229 doc comments start with the name) and nobody had said what goes inside: on two projects the rendered
    go doc -all carried 426 and 315 lines of story ids, "pre-S-050", "used to" and review rounds, one file was 35 % comments,
    and the projects had 0 and 1 TODOs — the gaps lived in prose ("left as a follow-up if a future story wants"). The rule
    names two kinds (doc comment = contract, body = reason), what never goes in code, the tests-only exception for ids, and
    TODO(S-NNN):/TODO(I-NNN): as the only TODO. /code-review checks the added lines (TODO-NOID, COMMENT-HISTORY,
    COMMENT-LONG), /story-done checks every new TODO's id exists, /tech-debt lists TODOs with closed or unknown ids and
    comment history per package. Templates: revive (exported, package-comments) + godot in golangci.yml, Slevomat
    comment sniffs in ecs.php (slevomat/coding-standard added by /test-setup), an ESLint snippet in typescript.md.
    New code only — existing files are a chore story per package, never a drive-by.

Skill pass and follow-ups (#62, #64–#67)

A pass over all 50 skills: bodies rewritten as numbered steps in the order they run, and the defects that hid in
the long paragraphs fixed. No rule was dropped; every spec case was re-checked against the new text. The style the
pass followed is now written down in CONTRIBUTING § 3 ("How the body reads").

  • Consent is collected by the parent. Eight skills told delegated agents to "follow the same protocol" or to
    "show code before writing (the user approves)" — a Task subagent cannot ask the user, so the rule either stalled
    or was silently skipped. The plan / Proceed answer now names the agents and the files each will write and covers
    those files; a specialist that needs more stops and reports, and the parent asks. On a /dev-story fixture run
    this cut the happy path from five questions to three with the same result.
  • Steps that ran before their inputs existed. /dev-story waited for CI in Phase 5, before the Phase 6 push;
    /code-review re-reviewed a fix commit it had not made yet; /test-setup generated configs before asking to
    write them; /sprint-status ran agent-stats --since before it knew the sprint's start date; /story-done asked
    "CI is green, merge?" before the PR that starts a pull_request workflow existed.
  • /story-done pushes its close commit before the merge (gh pr merge merges the remote head, so the
    docs: close commit was lost with the local branch), waits for CI on the PR's latest commit, and marks a draft PR
    from /dev-story ready before gh pr merge, which refuses drafts. The PR number is read (or the PR created) before
    the close edits that cite it; "close without the PR" skips the merge phase; red CI on the close commit leaves the
    close in place and says "closed, not merged".
  • git pull --ff-only origin <default> in /dev-story, /story-done, /release-checklist and git-workflow:
    a local default branch without an upstream refused the bare pull in both fixture runs.
  • Gates and modes the specs expected but the skills lacked: /release-checklist's first-release
    observability gate, a docs: release commit before the tag so the tag contains the release document, and the
    tag as a separate question on READY with -m (no editor), pushed to origin; /deploy rollback
    (the playbook and the delegate contract already relied on it); REJECTED in /architecture-decision; BLOCKED
    stops in /feature-spec, /data-model, /create-stories, /sprint-plan, /api-contract, /stack-update,
    /docs, /migrate, /hotfix, /test-setup that the verdict lines named but no step produced; write gates for
    /impact's findings and backlog rows, /perf-audit, /a11y-audit, /security-audit, /harden's in-repo
    config edits, /setup-stack's stage change and compose-ssh files.
  • Commands that did not do what they said: /migrate's ID check used ERE syntax with grep -o and matched
    nothing; /update --dry-run ran claude plugin update in plugin mode; /skill-improve's revert could discard
    kept iterations and the user's uncommitted edits; /changelog failed in a repository without tags;
    /team-release's "any FAIL stops" never matched /perf-audit's OVER BUDGET or /dependency-audit's
    ACTION REQUIRED.
  • Plan-level consent is in the rules, not only in the skills: coordination-rules rule 7 says the caller's plan
    answer approves the files the plan names (with .write-consent touched before each Task batch), and the agents'
    protocol item 4 says the brief's files carry the "yes".
  • The run-evidence numbers that explained individual rules ("35 %", "126 vs 5", "966 k", …) left the skill bodies under
    the new CONTRIBUTING rule; the rules stay, the numbers remain in the 0.12 section of this changelog.
  • Namespaces: /team-feature, /team-game, /hotfix hand off to /web-studio:code-review, /start to
    /web-studio:init in plugin mode (the bare names are Claude Code built-ins).
  • /refactor: the go doc ./pkg/... API baseline never worked (go doc takes no package patterns) and was never
    captured before Phase 6 compared against it — now saved in Phase 2 with go list | xargs go doc -all; --apply
    has one start question before the branch and a push question; PHP gets its own check column and engineer.
  • /architecture-review could not do what it asked: it runs go list, make arch-check and records findings, yet
    had neither Bash nor Write/Edit — allowed-tools gains them, with the findings row behind a gate.
  • /help applies the findings and game-gate overrides while choosing NEXT, not after printing it; /adopt moves the
    Go items that sat under PHP, names unrecorded HIGH items in the verdict and gates its Phase 3–4 writes.
  • /game-concept no longer carries stack versions (they live in docs/stack-reference/); /skill-test takes spec
    paths from the catalog and accepts PLANNED like the linter.
  • install.sh without rsync copied the excluded hooks.json into a fresh install (the fallback protected the file
    only when it already existed); tests/installer.sh failed on every machine without rsync. /update in copy mode
    compared the kit's version with the skill directory's name, which carries none — it now compares with the version the
    gate named and re-asks when the kit moved on. /story-done's "the studio's review ran" grep missed reviewers with two
    hyphens (web-game-engineer). /setup-stack no longer carries stack versions in its interview; the numbers come from
    stack-reference/index.md at question time, as the rule for version facts says. tests/run-all.sh lints
    testing/e2e/*.sh and testing/e2e/fixtures/*.sh too.
  • Testing: testing/e2e/fixtures/make-story-fixture.sh builds a story-ready synthetic project (happy,
    no-strategy, merged-spike) for comparing two versions of a pipeline skill; dev-story spec gains two cases;
    validate-structure checks hooks called as <hooks>session-state.sh … too.

#...

Read more

v0.12.0

Choose a tag to compare

@gonimar gonimar released this 26 Sep 13:12
Immutable release. Only release title and notes can be modified.

Findings of a week-long manual run on a real project (Web Studio 0.11.1, ten sessions, 250 agent runs) and of an
external PHP project. Nothing new to learn: the same commands, the same agents — cheaper, and harder to bypass.

  • One story per session (coordination-rules rule 13). 80 % of the week's spend was the parent's context, not the
    agents' work: sessions ran to 966 k tokens with two compactions in ten sessions, and 85 % of requests re-read more than
    200 k. /story-done now hands off to /clear before the next story (continuing in the same conversation is no longer
    an offered option), /dev-story refuses to start a story past 50 % context without offering /clear first, and
    /code-review sends a re-review after fixes to a fresh session past that mark. Playbook § 10.25 says the same in two languages.
  • Commands carry their namespace. A bare /code-review in a hand-off ran Claude Code's built-in review skill of the
    same name — nine general-purpose agents, no routing table, no appsec — and its findings travelled under the studio's name;
    once a security-sensitive story was closed on its word. Every hand-off in dev-story, refactor, code-review,
    story-done and every line /help prints now names /web-studio:<command> in plugin mode; coordination-rules § Subagents
    says why, next to the same rule for subagent_type.
  • /help no longer starts the next command. It runs on Haiku, and a skill started from its closing question inherited
    that model: a /code-review and a /story-done ran on Haiku and closed a story with invented numbers. After the answer
    /help prints Run: /web-studio:<command> and ends the turn.
  • The studio's review has to be in the log. /story-done DoD: a reviewer's SubagentStop after the branch's first
    commit, appsec-engineer among them for a security-sensitive story — otherwise NOT DONE (no studio review).
  • A verdict is the reviewer's. After fixes /code-review sends the fix diff to the reviewer that raised each finding
    and moves NEEDS CHANGES to APPROVED only on its answer — never on a green CI (five of five verdicts had been flipped by
    the parent). A BLOCKING is downgraded only by the reviewer that raised it or by technical-director through /impact.
    Reviewers get the diff as one file and open every verdict with Read: N/M files; N < M is PARTIAL and never
    counts towards APPROVED (35 % of lead reviews had been cut off mid-diff).
  • Engineers write the code, in every mode. The rule lived in dev-story and refactor; on an external PHP project
    the session drifted into "faster to fix it myself" from the third review round. It is now in coordination-rules
    § Subagents, principle 8 of the CLAUDE.md template, code-review Phase 5 and hotfix — and it has an observer:
    hooks/parent-write.sh (PreToolUse Write|Edit, warn-only) names the engineer the roster has for a code file the
    session writes itself and leaves a ParentWrite line in agent-audit.log; agent-stats.sh and /sprint-status print the count.
  • Turn budgets and briefs. maxTurns 30 → 60 for the implementing Tier-3 engineers, 25 → 40 for the leads and
    appsec-engineer (go-engineer hit its limit on 55 % of runs, test-engineer on 50 %, backend-lead as a reviewer on 35 %).
    The dev-story brief has six fixed lines (Story · Read with line ranges · Write · Check · Skip · Report) because
    half of an engineer's turns went into grep/sed navigation of files the parent had already read; every agent's
    protocol gains point 8 — Read/Grep on the brief's paths, shell search only when the path is unknown, and a
    Checkpoint: line kept in the result so a cut-off hands the caller the point to resume from. After a cut-off the parent
    sends one resume line and runs no checks of its own until the SubagentStop (50 of 64 cut-offs had been answered with
    the parent's own git status and builds).
  • The roster says what the tiers do. Leads review, design and name the specialist; the session dispatches. The Task
    tool and "routes work to …" leave the seven leads — measured on real projects, no lead ever spawned an agent.
  • Hooks, four false positives closed and one gap: validate-commit blocks provider-shaped credentials everywhere but only
    warns on password = "…" shapes in test code and agent memory (three test files had been rewritten to please it);
    validate-push reads the commit from a git commit … && git push call instead of an empty rev-list (docs commits
    on the default branch cried wolf three times a day); written-paths resolves p='…'; open(p,'w') and
    Path(p).write_text(…) (27 document writes in one session had passed every guard); consent-guard stays silent on a
    one-line Status:/Started:/Actual: edit, on a command that sets the marker before writing, and on
    docs/ops/measurements/ (rule 12 asks for those). hooks/session-state.sh is executable — skills call it as a
    command and one call failed with Permission denied; the structure linter checks the bit for every hook a skill calls.

v0.11.1

Choose a tag to compare

@gonimar gonimar released this 17 Sep 08:50
  • Review follow-ups of 0.11.0. /refactor without an argument is a full interview: every architecture and tooling choice is asked with the current value first, a kept value produces no step and a changed one becomes an ADR-first plan step — this is how the owner changes the approach of a running project; with an argument only that mode's questions are asked. The go_layers/php_layers fields are gone: the use-case shape is the tree the layout ADR shows, and /architecture-review code already compares the tree with the ADR. /code-review lints a layered Go diff with --new-from-rev=<default-branch> only; the whole-module run belongs to make ci. stack-reference/index.md has a Verified column carrying each file's own updated: date, so a partial refresh no longer has to lie with one header date; /stack-update fills the row. rules/*.md follow CONTRIBUTING §5 again — short imperative bullets with a link — and the Go, PHP and test rules stop restating the stack-reference tables (the cmd/ contract and the numbers a story reports now live in rules/go-code.md, which every *.go edit loads; go-engineer and php-engineer keep the role, the mechanics only they add, the Never list and the Reference line). post-edit-check has one smell helper for Go, PHP and Vitest (setTimeout waits, toThrow("string")) so the patterns cannot drift apart. coverage-gate.php streams the clover report with XMLReader, so a large project's report fits the default memory_limit. The refactor row sits with the pipeline rows in testing/catalog.yaml.

v0.11.0

Choose a tag to compare

@gonimar gonimar released this 17 Sep 07:55
  • PHP is separated from its framework. stack-reference/php.md (new) holds the language (8.5 the target, 8.4 the floor for property hooks and asymmetric visibility — the fixture and every tool ran on both 8.5.10 and 8.4.25), the two architecture styles, tests by layer and the tooling; yii3.md (renamed from php-yii3.md — technology files carry no language prefix, like angular.md) keeps only what is Yii3; symfony.md and laravel.md are stubs (versions, where the layers live) to be filled by /stack-update and the first project on them. php_framework (yii3 · symfony · laravel · slim · none) is asked in /setup-stack and detected by /adopt from composer.json; where the reference is a stub, php-engineer works from the official documentation and says so in every result — the framework is an Infrastructure detail, never the shape of the code. security-lead, performance-engineer and backend-lead read php.md first.
  • php_architecture: layered (src/Domain → src/Application → src/Infrastructure, php_layers per-context or flat) is enforced by docs/templates/php/deptrac.yaml, whose Framework layer holds the framework's namespaces (the exact value is in each framework file) and is allowed only from Infrastructure — so /refactor framework --dry-run can inventory what a framework change would touch; the Vendor layer is Psr\ plus the php_domain_allow list, nothing pre-approved. Rich models use PHP 8.4 asymmetric visibility (public private(set)), verified to block writes from outside. graphql-php's BuildSchema takes an entity named Subscription as the root subscription type exactly as gqlgen does, so the root-name rule and the GQL-ROOT hint cover both.
  • Recorded tool choices replace hard-coded ones: php_static_analysis (PHPStan level 9 · Psalm level 1), php_cs_tool (ECS with perCs: true · php-cs-fixer @PER-CS) with a template for each, PER Coding Style 3.1 named as the current edition, PHPUnit 13 as the baseline (Pest 5 on top of it when the project prefers it), scripts/coverage-gate.php reading the clover report per layer (--root= for an app/ tree), and composer ci (validate → lint → stan → arch-check → tests with coverage → coverage-gate; composer ci-full adds composer audit, the network step). Verified on a php:8.4-cli fixture: deptrac fails on a Domain → Infrastructure dependency, PHPStan 9 and ECS run clean after --fix, the gate prints Domain 100.0% >= 90% OK and fails at Application=100, the template chain runs end to end. post-edit-check hints TEST-SLEEP/TEST-ERRSTR on *Test.php and formats through ECS when it is installed; /code-review, /architecture-review code, /test-setup, /dev-story, /tech-debt and /refactor (modes <namespace>, layout, tests, framework) carry the PHP twins of the Go rules.
  • Migrations are named explicitly: schema changes are migration files, never DDL in a class or a story (rules/database.md says so; rules/php-code.md and php-engineer repeat it for PHP).
  • Go has two architecture styles and the studio can tell them apart. stack-reference/go.md gains "Architecture style" and "Layered architecture": go_architecture: layered (internal/domain → internal/usecase → internal/infrastructure, dependencies inwards only, ports declared in the domain, one struct per use case with Execute, rich models with unexported fields and a validating constructor, DTOs or bound domain types per graphql_models) next to modular (internal/<domain>/). The rule is a linter rule: docs/templates/go/golangci.yml (v2 — a v1 linters-settings: file is rejected by golangci-lint 2.x) carries depguard lists for the two inner layers, and the arch-check target in docs/templates/go/Makefile.snippet adds the transitive check over the package graph (go list -deps -test) that per-file depguard cannot do; the two are complementary, not the same test. Verified before shipping: a domain file importing an infrastructure package fails both; the usecase list runs in list-mode: lax because depguard's default mode denied github.com/google/uuid in a use case. /setup-stack asks the style, the directory shape (go_layers, go_composition_root), the router (go_router: chi or ServeMux), the GraphQL model mode, the value libraries the domain may import (go_domain_allow) and the coverage thresholds; /adopt records the style from the tree and offers /refactor layout instead of restructuring; technical-preferences.md has the fields. go-engineer, graphql-engineer, backend-lead, /code-review (LAYER, RICH-MODEL, COVERAGE, TEST-LAYER findings by command output) and /architecture-review code (dependency direction from the graph) read them.
  • Tests have a layer and a gate. go.md "Tests by layer": domain tests without doubles, use-case tests with func-field fakes (≤ 3 methods) or moq and no I/O, infrastructure against containers; docs/templates/go/coverage-gate.sh (installed as scripts/coverage-gate.sh by /test-setup, called by make coverage-gate on the profile make test already wrote) fails the build below go_coverage_domain (90 %) / go_coverage_usecase (80 %) — two explicit technical-preferences fields that /test-setup writes into the Makefile variables, the one place the build reads them — and prints one line per layer; make layout-check covers every binary under cmd/; make ci is the local gate and make ci-full adds govulncheck. Rules every Go test now follows, in rules/tests.md and rules/go-code.md: errors.Is/errors.As against a sentinel — never err.Error() == "…", which breaks on the first %w wrap; no time.Sleep to wait for a result — testing/synctest or a polling helper with a deadline; case names in English. post-edit-check hints on a _test.go with a sleep (except inside testing/synctest, where sleeping on the fake clock is the recommended form) or an error compared to a string, and GQL-ROOT on a .graphqls whose type Subscription carries an id field and no schema {} block; /code-review reports them as TEST-SLEEP/TEST-ERRSTR from grep output.
  • /refactor — the studio can change the shape of the code it maintains without changing what it does. Dry-run by default: a baseline by numbers (build, vet, lint, tests, coverage per layer, layout numbers, dependency direction, package sizes, test smells) before any question, the architecture choices as in /setup-stack when the mode is layout, a step plan whose first step is always characterisation tests and whose second is the tooling that will fail on purpose, then a plan document in docs/ops/refactor-<date>-<scope>.md and stories through /create-stories. Code moves only with --apply S-NNN on refactor/S-NNN-<slug>: every step through go-engineer, go build && go test -race after each, one green step per refactor(S-NNN): … commit, a red step fixed or reverted and never committed, and a before/after table that must not regress (tests, coverage, depguard, layout, the public API of pkg/). Modes <package>, layout, tests; no argument runs every applicable mode after asking all questions up front. Go in this version. Catalog step, spec testing/skills/pipeline/refactor.md, playbook § 5.5.
  • The GraphQL SDL of a Go module lives at api/schema.graphqls and is read in place. api_contract_path in technical-preferences names the one schema file (docs/architecture/api/schema.graphql for PHP/Node projects); /api-contract, graphql-engineer, rules/api-contracts.md and docs/templates/go/gqlgen.yml point at it, and docs/architecture/api/api-contract.md links to it instead of holding a copy. A schema type named Query, Mutation or Subscription that is not the root is a BLOCKING finding before generation: gqlgen treats those names as the root operation types, and an entity called Subscription came out as a set of channel-returning subscription resolvers when the example from a widely shared guide was generated.

v0.10.6

Choose a tag to compare

@gonimar gonimar released this 16 Sep 19:52
  • The agent summary counts agents, not events. 0.10.5 paired starts and stops by aid and printed "K starts without a stop"; a project session recounted by name, got 126 where the tool said 5, and reported it. Both numbers were answering different questions and one of them is not a question worth asking: SubagentStart fires on every resume of the same agent — one aid in a real log carries eight starts and no stop — so starts minus stops counts resumes, not losses. What the log does support is the agent: an aid started and never closed (five on that project, seven on another) means an agent cut off at its turn limit or still running, and the story it was given is where to look. The summary now says that, and says when it cannot: lines written before the id fields existed are named as unpairable, so a silent zero no longer reads as "clean" when it means "blind" — 139 of that project's runs are in that state. (WS-117)

v0.10.5

Choose a tag to compare

@gonimar gonimar released this 16 Sep 19:39
  • /sprint-status says who did the work. hooks/agent-stats.sh summarises the trail log-agent already keeps: runs all-time and within the sprint, the top five agents (the plugin's web-studio:go-engineer and copy mode's go-engineer counted as one agent, not two), and two lines that were previously invisible without opening the log — starts with no matching stop (an agent cut off at its turn limit, or still running) and runs of non-studio agents (general-purpose, Explore), which mean routing went around the roster. Both go under Risk to the goal when they are not zero. On real projects the second line reads 106 of 260 runs and 22 of 255 — the oldest open defect in the register turns from an observation into a number the project sees itself. Costs nothing: one pass over a few hundred local lines.

v0.10.4

Choose a tag to compare

@gonimar gonimar released this 16 Sep 19:25
  • hooks/session-state.sh never destroys a state file again, and converts one on request. Shipped in 0.10.3, it rebuilt active.md from its own seven fields and silently dropped everything else: on the first project that used it, a 148-line working state — sprint status, fifteen lessons, tech debt, a cleanup plan with an open item — became nine lines, in a gitignored file with no archive behind it; the content came back only because the session had read it earlier. The writer now refuses any file it cannot round-trip, says how many lines it does not understand and what to do instead, and backs the file up before every write it does make (last five kept). session-state.sh migrate does the conversion once and deliberately: the whole previous file is archived to production/session-state/archive/active-<timestamp>-premigration.md, the fields it recognises — including the bold **Task**: spelling — are carried over, and the output says where the rest belongs (sprint file, agent memory, findings, backlog). The template says what lives in this file and what does not. The post-edit-check hint no longer points at the call that did the damage. (WS-115)
  • /impact no longer writes Next:. Next: is where the session was heading and a triage is usually a detour from it, so the skill's own instruction contradicted coordination rule 7 — a project session hit exactly that, with Next: /sprint-plan 04 pending while /impact was told to overwrite it. The verdict's commands go into the dated note and the closing question; Next: changes only when the user picks one there, because that choice is what makes it the task. (WS-116)
  • /dev-story states that the parent does not write the story's code. The skill said "implementation via Task to the right engineers" and named them, but nothing said what happens when an agent is cut off at its turn limit — and across four stories in a row the implementing agent was spawned once, wrote nothing, and the parent wrote 687 lines itself while the stories passed. The rule is now explicit: every file through Task with an explicit studio subagent_type, a truncated agent is resumed rather than replaced, twice-truncated work is split into smaller calls, and a parent-written fallback is recorded in the story result in one line. Phase 3 plans in agent-sized steps and names the agent per step; Phase 5 compares the agents that actually started in agent-audit.log against the ones the plan named. (WS-087)
  • CI no longer cancels runs on the default branch: cancel-in-progress is now conditional, after three PR merges went in while the run that was checking them was cancelled by the next push. (CWS-07)
  • The settings templates stop auto-approving pnpm dlx <any package>: Bash(pnpm *) is replaced by the same narrow verbs npm already had (install, run, test, audit, outdated). A permission rule that runs arbitrary code from the network is not a convenience. (CWS-12)

v0.10.3

Choose a tag to compare

@gonimar gonimar released this 16 Sep 18:10
  • /brainstorm writes its concept brief from a template that now exists. The skill created docs/specs/concept-brief.md and /product-spec Phase 1 read it as input, but docs/templates/ had no brief — so each run invented a shape and the next skill looked for facts where they were not. Template, a row in rules/docs-format.md and a post-edit-check branch; an empty section is written n/a — reason rather than dropped. (WS-100)
  • /architecture-decision has an outcome for "no ADR needed". A discussion that ended in rejection had nowhere to be recorded, and one ended instead with a production Dockerfile edited from a document session — bypassing the review, the branch and the DoD of the story that owns the file. The rejection is now a D-NN line in production/decisions.md (or an ADR marked Rejected), and a change to code is handed to /impact, /hotfix or a story. (WS-106)
  • A finding ID is never minted without the finding. /impact verdicts cited ARCH-004 for a deviation that existed in no file: the next session greps the ID and finds nothing. The row is now written into production/findings.md in the same turn under the same write gate, and /story-done checks that every ARCH-NNN/SEC-NNN named in a story card exists there. (WS-084)
  • /dev-story no longer waits for a CI run that was never queued. With on: pull_request and no push trigger, a bare push starts nothing; the skill reads the triggers and opens a draft PR (gh pr create --draft --fill) when the PR is what starts the checks, so they run while the review happens and /story-done turns the draft ready. (WS-083)
  • A spike has a place to live: tools/spike-<slug>/, gitignored and deleted when the story closes. The plugin called a spike a way to verify a decision three times over without saying where one goes, so it landed in the repository root; Phase 6 now stages the story's files by name — never git add -A — and names any unplanned ?? entry before committing. (WS-096)
  • /code-review prints its routing. Reviewers were chosen by eye and the report showed only findings, so a diff touching three layers could be reviewed by one specialist with nothing to show it. Phase 2 prints the table (path → required reviewer → spawned yes/no) before the reviewers run, a skipped role costs a line saying why, and Phase 5 repeats the table with each verdict. (WS-091)
  • Work outside a story has a lane. CI, linters, dependencies and developer tooling fell through the pipeline entirely: not a story, not a document, so an urgent "fix the runner" either rode a story branch or landed straight on the default branch, and what was learned was recorded nowhere. git-workflow.md gains the chore/infra lane (chore/<slug>, ci(…)/chore(…) commits, a PR with /code-review --diff, experimental commits squashed before the merge, the outcome recorded as a finding or a backlog entry), /hotfix --chore follows it without the release machinery, and the catalog has the step. (WS-093)
  • A subagent running out of turns is treated as normal, not as failure. For a mid-sized story in a typed language the default limit is reached routinely; the caller used to spawn a second agent on the same task, which starts from an empty head and redoes the work. Coordination rule 7 now describes the turn budget — the signs of a truncated result, resuming the same agent rather than replacing it, and handing out work in pieces a budget holds: one layer per call, a result carrying decisions and numbers instead of a copy of the diff. log-agent marks a second SubagentStart for an agent whose Stop never came as resume=1, so the pairs stay countable. (WS-088)
  • CI minutes are a budget the studio now plans against. A generated pipeline ran seven parallel jobs on every push, each with its own checkout and install and each rounded up to a minute — seven minutes per push on a 2 000-minute monthly tier, which a project burns through mid-month and then starts merging around. tooling-devops.md § CI states the rules (one job per toolchain, paths: filters, e2e and security on pull requests to the default branch, concurrency: cancel-in-progress, runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }} so a self-hosted runner is a variable rather than an edit of every workflow) and /test-setup reports the estimated minutes per run and per month. (WS-015)
  • production/session-state/active.md has a writer instead of improvised one-liners. Skills updated it with sed -i and python3 -c inside double quotes, and nothing read the result back: a broken quote left the file unchanged and the session carried on believing it had saved its state. hooks/session-state.sh set|note|show|clear keeps every field of the template in order, fills untouched ones with —, dates each note, keeps the last ten and archives the rest to production/session-state/archive/, and prints the file so a failed write is visible. /dev-story, /story-done and /impact call it; post-edit-check warns when the file is missing one of its seven fields. (WS-095)
  • Measurements have a home: docs/ops/measurements/YYYY-MM-DD-<topic>.md with the command, the environment, the raw output and the number, linked from whatever document quotes it. Coordination rule 12 says a number in a document cites an artefact, never session-state, which is gitignored working memory the next session may not have — until now Notes: was the only place measurements were written down, so a decision's evidence disappeared with the session. /architecture-decision and /impact name the file; after a compaction session-start prints the state's decision fields and a bounded tail of notes instead of the whole file. (WS-094)
  • The startup banner stops telling configured projects that their stack is not configured. session-start.sh kept the whole-file grep for TO BE CONFIGURED that 0.10.2 replaced in the installer, so every session of a fully configured project opened with "Stack not configured — run /setup-stack or /adopt" because the template's header comment mentions the placeholder. That is not cosmetic: /help routes a project with code and an unconfigured stack to /adopt full, which would rewrite the very file WS-082 was about. "Configured" now has one definition, hooks/prefs.sh, shared by the banner and the installer, and /help names the **Type** field instead of the placeholder. (WS-113)
  • validate-commit reads the message of a git commit -F too. For -F the hook set the message to an empty string, so the documents lane was invisible — a commit staging nothing but .claude/docs/coordination-rules.md with the subject docs: … was warned about "committing directly to 'master'" — and the Conventional Commits check was skipped altogether: blind rather than lenient. -F is not an exotic corner: git commit -m runs command substitution on backticks, so every multi-line message with inline code, which is what a documents commit looks like, goes through it. The hook now reads the file, or the heredoc body of -F -, and validate-push (which always read the subject from git) stops disagreeing with it. (WS-112)
  • install.sh --seed-only no longer writes .claude/.web-studio-version. 0.10.2 put the rule in the skill ("the stamp is written only in copy mode") and left the installer stamping unconditionally, so a normal plugin-mode /update re-created the file a project had deliberately removed — naming a version whose agents and skills are not in the project, and pointing the next run at the copy-mode branch. Found on a real project in the first run after the release. (WS-111)
  • The published 0.10.2 changelog section carried a stray # Changelog / ## Unreleased pair from a merge resolution, so the release read as unassembled. Cleaned, and the GitHub release notes rewritten from the corrected section.
  • /update reads the plugin listing per project. claude plugin list --json covers every project on the machine, and the skill took the first web-studio row it saw — with four projects side by side on three different versions, a project on 0.10.0 read a neighbour's 0.10.1 and reported itself up to date. Phase 1 now selects the row by projectPath, Phase 2 takes the scope from that row, Phase 3 re-reads it the same way, and a listing with no row for this project is reported as "not installed here" instead of being substituted. The form without --json is documented as unusable for this: its blocks carry Version, Scope and Status and no project path. Spec case update 12. (WS-110)

v0.10.2

Choose a tag to compare

@gonimar gonimar released this 16 Sep 17:38
  • /update no longer overwrites a configured technical-preferences.md. In plugin mode the skill had no seeding command, so a session copied docs/ wholesale (cp -r <cache>/docs/* .claude/docs/) and replaced a filled stack — type, pinned versions, the rationale for rejected upgrades, the ADR log — with the template; the run then reported "project data unchanged". Seeding is now a single command, install.sh <project> --seed-only (docs/ and rules/ only, agents/skills/hooks come from the plugin update), and Phase 3 verifies the result with git diff --quiet before it may claim the file was untouched, restoring it when it was not. The installer's own guard was broken as well: it looked for TO BE CONFIGURED anywhere in the file, while the template's header comment mentions the placeholder — so every configured file looked unconfigured and was overwritten in copy mode too. "Configured" now means the **Type** field is filled, the same predicate workflow-catalog.yaml uses, and the installer prints technical-preferences.md: kept (configured). Without rsync the exclusion is real instead of a warning after the fact. Installer tests cover a fixture that keeps the header comment, the no-rsync path and --seed-only; spec case update 9. (WS-082)
  • /update Phase 2 updates the plugin in the scope where it is installed: claude plugin update web-studio --scope <scope>, taken from the claude plugin list --json output Phase 1 already reads (-y in a non-interactive run). The bare command assumes user scope and stops the run with Plugin "web-studio" is not installed at scope user in every project installed with --scope local. Spec case update 10. (WS-108)
  • /update recognises a third mode: a copy-mode install left in place under the plugin. Plugin and copy mode were described as exclusive, so a project could run last month's skills from .claude/skills/ for weeks — project copies shadow the plugin by name, and only the web-studio: prefix reached the current version. Phase 1 now reports HYBRID INSTALL, establishes the copy's real version by comparing it with the cached plugin versions instead of believing .claude/.web-studio-version, and lists the files that match no version — those are local edits and the project's own kit, everything else is removable without loss. Phase 3 offers the removal as its own gate, moves agent memory from <agent> to web-studio-<agent> (appending MEMORY.md pointers), checks whether .claude/settings.json wires the copied hooks at all, and ends with "restart the session" — removing .claude/skills empties the skill registry of the running session. The stamp is written only in copy mode: in plugin mode claude plugin list --json is the source of truth, and a stamp naming a version whose files are not in the project is worse than none. /help prints one line when project copies shadow the plugin. Observed on a real project: a stamp reading 0.5.8 over files from 0.4.3, then 0.10.1 while only docs/ and rules/ had been reseeded. Spec case update 11. (WS-109)
  • validate-commit no longer passes everything in silence when the staging happens in the same Bash call. The hook read the index, and git add secrets.env && git commit -m "…" — the form the studio's own skills use — leaves the index empty at the moment the hook runs, so the secret-file block, the secret-string block, the lockfile and TODO warnings and the branch checks all did nothing. The hook now resolves what the command's git add segments would stage (git add --dry-run) and reads the content from the working tree, so a staged-in-the-same-call .env or a leaked token is blocked exactly as before. (WS-101)
  • validate-commit accepts a story ID as the Conventional Commits scope: the class [a-z0-9/_-] rejected capitals, so feat(S-019): … — the message /dev-story itself generates — always warned, which is how a warning becomes noise. A capitalised type (Feat: …) is still flagged. (WS-102)
  • validate-push knows about the documents lane. Pipeline documents live on the default branch by design and validate-commit lets them through, but every push then warned "pushing directly to 'master'", including the push that carried exactly those documents. The push hook now checks the commits that would travel: all of them docs: and touching documents only → no warning; anything else, or a range it cannot establish → the warning stands. The lane is defined once, in hooks/docs-lane.sh, so the two hooks cannot drift apart. (WS-103)
  • log-agent stops calling built-in tooling a lost agent: a Stop event with no agent type is logged as builtin rather than unknown, so Start/Stop pairs in agent-audit.log stay countable and an unpaired studio agent is visible again. (WS-089)
  • /help stops inventing commands. The hand-off named /dev-story complete S-007, which does not exist — a story is closed by /story-done — and a command shape invented by the studio's own orientation skill sends the user to a dead end with the studio's authority behind it. Every command in the answer now comes from the catalog or from a skill's argument-hint, and the session-start context (merged branch, template placeholder, stale stack reference, an open Gate:) is repeated as one line each instead of being left in the startup block the user already scrolled past. (WS-052)
  • Calibration is one sample with one name. /sprint-plan scaled the next sprint by a ratio over "every closed story" while /retrospective computed its own over one sprint, and the plan's text claimed the two were the same number. Both now read the last six closed stories of the roadmap that carry ~Nh and ⏱ Nh; the retrospective additionally prints the sprint's own ratio, labelled, so the two are never confused. (WS-086)
  • /sprint-plan moves the selected stories out of the Backlog block instead of copying them into the sprint: a story listed in both places made every <summary> count on the roadmap wrong from then on. The write step recalculates both counts and states them (Backlog: N → M, Sprint: 0 → K, overlap none). (WS-107)
  • A reviewer now gets something it can actually read. /architecture-decision required that "each reviewer receives the full draft text", which does not fit a Task prompt and was never once done: the draft goes to a session file and the reviewer receives its path plus the requirement to quote the ADR title and the two Decision lines back — the quote being the evidence of reading. A verdict with no quote is returned once, then reported as unread rather than counted. The same rule is in coordination-rules § Subagents for every skill that reviews a draft. (WS-097)
  • subagent_type is always a studio agent. A three-round "final assessment" of an ADR draft was performed by a generic agent with a model override: no project rules, no agent memory, no role in the audit log. Wanting a stronger opinion changes the model of a roster agent, never the agent itself. (WS-104)
  • A FAIL that was edited is reviewed again. A product spec went out as FAIL with four blocking factual errors, was rewritten "according to all eight comments" and recorded as done — checked by nobody. The same verifier now gets a short second pass, the document's verdict is the last review's, and a skipped re-review is written down as FAIL (edits unverified) instead of quietly becoming a pass. Same rule in /feature-spec. (WS-098)
  • An idea that leaves the backlog sideways is closed anyway. /impact run directly on a backlog entry left I-003 open for weeks while the work was already done, because only /backlog promote marked entries. /impact now writes its verdict back into the entry under the same write gate, and backlog review recognises an entry whose text matches a spec, ADR or verdict written later. (WS-099)
  • /story-done proves the roadmap carries the numbers. For three closed stories in a row the ⏱ time and the 🔗 PR link travelled only as far as the chat answer: neither the sprint line nor the ## Docs row received them. The skill now re-reads both places after the edit and reports a mismatch as an open DoD item. (WS-092)
  • go-engineer leaves a trace of the stack reference. "Read stack-reference/go.md first" was followed in about half of the runs, and nothing could tell the difference. The result now starts with Reference: stack-reference/go.md (updated: YYYY-MM-DD), carrying the date from the file that was opened; no line means the reference was not read. (WS-105)
  • Spec cases for all of the above: help, sprint-plan (2), retrospective, architecture-decision, product-spec, impact, story-done, and the go-engineer agent spec.
  • The hooks see what the skills actually do. consent-guard, secret-guard, impact-guard and the document-format part of post-edit-check were registered on Write|Edit only, while the skills author documents with cat > file <<EOF and python3 - <<PY — so the entire guard lane watched a tool nobody used. Measured on one real day in a project: 588 Bash calls, 15 Writes (all into a scratchpad), 0 Edits, 0 guard lines of any kind, and touch .claude/.write-consent executed 176 times with nothing left to check it. The four hooks now also run on Bash, and hooks/written-paths.sh is the single place that answers "what would this command write" — redirections, tee, cp/mv/install, sed -i, and a heredoc body that writes a file itself (open('f','w'), writeFileSync). A configured .env written through a heredoc is blocked, a token pasted into a heredoc body is blocked, a roadmap written without a fresh consent marker warns, and a document written that way gets its format check. Code formatters stay on the Write/Edit path, where the call names one file and means it. coordination-rules rule 7 now says documents are written with Write/Edit: the Bash lane is a safety net for literal paths, not a licence — a path built from a variable is still invisible. Nine hook tests, six...
Read more