Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .claude/skills/migration-graduate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ For each graduated command:
- The legacy handler is either deleted (most common) or kept as a tiny adapter the command's execute calls.
- All tests still pass.

## Finding graduation candidates with ESLint

`eslint-plugin-acture-migration` ships the `acture/no-stale-wrap-mutation` rule, which flags `wrapMutation(...)` calls whose result is never used — a strong single-file signal that the wrapper has graduated. Enable it during a migration and the lint warnings become your graduation backlog:

```js
// eslint.config.js
import acture from 'eslint-plugin-acture-migration';
export default [{ plugins: { acture }, rules: { 'acture/no-stale-wrap-mutation': 'warn' } }];
```

The rule is conservative (it stays quiet on exported or still-referenced bindings), so a clean lint run does not prove every wrapper has graduated — but every warning is a real candidate. Step 1 below is the cross-file verification the rule cannot do.

## Steps

### 1. Pick a wrapped command to graduate
Expand Down
11 changes: 7 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,22 @@ Full discussion is in `docs/redesign_takeaways.md` §3 and the `acture-hard-dont
- Generalizing beyond what `v1_plan.md` commits to. Rule of three.
- Modifying the central paper (`docs/command_dispatch_journal_article.md`). It is canonical.

## Current state (v1.3, Phase 4 + v1.1 + v1.2 + v1.3 increments DONE, 2026-05-13)
## Current state (v1.4, Phase 4 + v1.1 → v1.4 increments DONE, 2026-05-14)

Fourteen packages ship in the workspace at versions ranging from v1.0.0 to v1.2.0:
Fifteen packages ship in the workspace at versions ranging from v1.0.0 to v1.2.0:

- Core: `acture@1.1.0` — `enableTierWarnings`, `deprecationReason`, `internalToken`, `DispatchOptions`.
- State: `@acture/state-zustand@1.0.0`, `@acture/state-redux@1.0.0`.
- UI: `@acture/palette-react@1.0.0`, `@acture/hotkeys@1.0.0`, `@acture/forms-autoform@1.0.0`, `@acture/forms-rjsf@1.0.0`.
- Surfaces: `@acture/mcp@1.0.0`, `@acture/ai-vercel@1.0.0` — honour the tier filter and prepend `[DEPRECATED — <reason>]`.
- Migration: `@acture/migration@1.1.0` — `createDomInterceptor` for DOM-event interception.
- Tooling: `@acture/build-tier@1.1.0` (regex + AST mode), `@acture/cli@1.2.0` (deep nested compare-schemas diffs), `@acture/devtools@1.0.0`.
- Codemods: `@acture/codemods@1.1.0` — **research-4 §B.5 codemod set is complete in v1.3** (5 codemods: `wrap-handler-with-mutation`, `extract-onclick-to-command`, `redux-action-to-command`, `usestate-mutation-to-command`, `rtk-thunk-to-command`).
- Codemods: `@acture/codemods@1.1.0` — **research-4 §B.5 codemod set is complete** (5 codemods: `wrap-handler-with-mutation`, `extract-onclick-to-command`, `redux-action-to-command`, `usestate-mutation-to-command`, `rtk-thunk-to-command`).
- Lint: `eslint-plugin-acture-migration@1.0.0` — **new in v1.4.** One rule, `acture/no-stale-wrap-mutation`: flags `wrapMutation(...)` calls whose result is never used (the migration has graduated; author with `defineCommand`).

Four worked examples: `examples/greenfield/graph-editor/`, `examples/drop-in/`, `examples/migration/zustand-wrap/{before,after}/`, `examples/migration/redux-wrap/` (RTK + `actureMiddleware` end-to-end). See `docs/next_session.md` for the v1.4 backlog.
Four worked examples: `examples/greenfield/graph-editor/`, `examples/drop-in/`, `examples/migration/zustand-wrap/{before,after}/`, `examples/migration/redux-wrap/` (RTK + `actureMiddleware` end-to-end).

v1.4 also ran the deferred fresh-agent release-gate test against `@acture/codemods` — see `docs/fresh-agent-test-results.md`. The codemod engine passed; README-accuracy fixes are carried to v1.5. See `docs/next_session.md` for the v1.5 backlog.

## Phase progression

Expand Down
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ pnpm add @acture/migration # strangler-fig adoption primitives
# …plus @acture/forms-autoform and @acture/forms-rjsf for parameterized commands.

# Dev / CI tooling (post-v1.0):
pnpm add -D @acture/build-tier # build-step @stable/@experimental/@internal/@deprecated mirror
pnpm add -D @acture/cli # `acture compare-schemas` / `acture snapshot` CLI
pnpm add -D @acture/devtools # embeddable <Inspector /> for dev builds
pnpm add -D @acture/build-tier # build-step @stable/@experimental/@internal/@deprecated mirror
pnpm add -D @acture/cli # `acture compare-schemas` / `acture snapshot` CLI
pnpm add -D @acture/devtools # embeddable <Inspector /> for dev builds
pnpm add -D eslint-plugin-acture-migration # ESLint rule that flags stale wrapMutation wrappers
```

> The `acture` name is also reserved on PyPI as a placeholder; a real Python companion is post-v1. `pip install acture` gives you a no-op package whose only purpose is to keep the name ours.

## Status

**v1.3.0 (Phase 4 DONE + v1.1 + v1.2 + v1.3 increments, 2026-05-13).** Fourteen packages ship in the workspace:
**v1.4.0 (Phase 4 DONE + v1.1 → v1.4 increments, 2026-05-14).** Fifteen packages ship in the workspace:

| Package | Role |
| --- | --- |
Expand All @@ -44,6 +45,7 @@ pnpm add -D @acture/devtools # embeddable <Inspector /> for dev builds
| [`@acture/cli`](packages/cli) | `acture compare-schemas` (CI gating, deep nested diffs) + `acture snapshot` (registry → JSON) |
| [`@acture/devtools`](packages/devtools) | embeddable `<Inspector />` and `instrumentRegistry` dispatch log |
| [`@acture/codemods`](packages/codemods) | Codemod CLI: all five research-4 §B.5 codemods now shipped (`wrap-handler-with-mutation`, `extract-onclick-to-command`, `redux-action-to-command`, `usestate-mutation-to-command`, `rtk-thunk-to-command`). `--dry-run` + `--json` for agents |
| [`eslint-plugin-acture-migration`](packages/eslint-plugin-acture-migration) | ESLint rule `acture/no-stale-wrap-mutation` — flags `wrapMutation(...)` wrappers whose result is never used (the migration has graduated; author with `defineCommand`) |

Worked examples:

Expand All @@ -54,6 +56,11 @@ Worked examples:

Agent skills live under [`.claude/skills/`](.claude/skills/): five migration-track skills (`migration-diagnose`, `migration-plan`, `migration-scaffold`, `migration-wrap`, `migration-graduate`) plus the architecture / tier / schema / hard-don'ts primer skills.

What's new in v1.4 (release-readiness theme):

- **`eslint-plugin-acture-migration`.** One rule, `acture/no-stale-wrap-mutation`: flags `wrapMutation(...)` calls whose result is never used — the strangler-fig wrapper has graduated and should become a `defineCommand`. Single-file, conservative detection. +16 tests. Closes a research-4 backlog item carried since v1.1.
- **Fresh-agent release-gate test.** A fresh agent drove `@acture/codemods` from its README alone. The codemod engine + CLI passed; the README's pre-publish `npx` invocation and undocumented `--option` keys did not. Full assessment in [`docs/fresh-agent-test-results.md`](docs/fresh-agent-test-results.md); fixes carried to v1.5.

What's new in v1.3:

- **Codemod set complete.** Three new codemods finish research-4 §B.5: `redux-action-to-command` (RTK action calls → registry.dispatch), `usestate-mutation-to-command` (setX-only handlers → wrapMutation), `rtk-thunk-to-command` (`createAsyncThunk` → `defineCommand`). +30 tests; manifest now has zero `status: 'planned'` entries.
Expand All @@ -74,7 +81,7 @@ Previously in v1.0 / v1.1:
- **`<Inspector registry={...} />`.** Embeddable React dev-tool with a command list (tier-filterable), dispatch log, and live when-clause evaluator. Mount it behind a toggle in any greenfield app.
- **`enableTierWarnings(registry)`.** Once-per-process `console.warn` on first dispatch of each `@experimental` command. Suppress with `ACTURE_SUPPRESS_EXPERIMENTAL_WARNINGS=1`.

What's next: see [`docs/next_session.md`](docs/next_session.md) for the v1.4 backlog.
What's next: see [`docs/next_session.md`](docs/next_session.md) for the v1.5 backlog.

## Three paths

Expand Down
51 changes: 51 additions & 0 deletions docs/fresh-agent-test-results.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Fresh-agent release-gate test — results

**Run:** 2026-05-14, as part of v1.4 (release-readiness theme).
**Gate origin:** Phase-4 reflection §5 deferred this through v1.0 → v1.3. v1.3's reflection §"Pre-v1.4 reflection answers" §4 named the next session as the right place to run it, with the `@acture/codemods` README as the densest agent-facing surface in the repo.

## What was tested

A fresh agent — no prior context about acture — was given only:

- the location of `packages/codemods/README.md`,
- the fact that `@acture/codemods` is an unpublished workspace package whose CLI is built at `packages/codemods/dist/cli.js`.

It was instructed to read **only the README** (not source, not other docs, not skills), pick one codemod, build a realistic sample file, drive the CLI end-to-end (`--list`, `--help`, `--dry-run --json`, real apply), and deliberately mis-use the CLI to test error messages. The deliverable was a written assessment of where the README + CLI fall short — **no code change in v1.4** (per `docs/next_session.md` §"Strong candidates" #2).

## Outcome

**The codemod mechanics passed; the README's accuracy did not.** The agent got `wrap-handler-with-mutation` working end-to-end (handler wrapped, import added, output functionally correct) and rated the CLI surface — `--list`, `--help`, `--dry-run`, `--json`, the per-file `before`/`after`/`changed` JSON, the readable plain-text diff — as solid. But it returned a **"not ready to ship as-is"** verdict, driven entirely by README gaps and one error-message ambiguity.

### Findings (verbatim priority order from the fresh agent)

1. **The headline invocation does not work.** Every Quick-start and CLI example uses `npx @acture/codemods …` or the `acture-codemods` bin. The package is unpublished, so the *first command a copy-pasting user runs* fails with an npm 404. The README never mentions `node dist/cli.js`, a workspace bin alias, a build step, or publish status. Single biggest blocker.

2. **Per-codemod `--option` keys are undiscoverable.** The README mentions `--option key=value` generically and the codemod table alludes to "configurable setter pattern" / "optional slash→dot id rewrite", but no option *names* are listed anywhere a CLI user can see them. `--help` shows one example (`id-prefix=app.button`) but no enumeration. The programmatic example leaks `events: 'onClick,onSubmit'` — so the options exist, just unlisted.

3. **`--manifest` and `--files-from` are under/undocumented.** `--manifest` appears in the CLI usage block with no explanation (vs. `--list`?). `--files-from` appears in `--help` but is **absent from the README entirely**.

4. **"No files matched" error is ambiguous.** A missing `--target` and a *nonexistent* `--target` path produce the identical message ("No files matched. Use --target…"). A user who typo'd a real path is told to "use --target" when they already did.

5. **Cosmetic:** rewritten handler bodies are over-indented in the output diff. Harmless, but a reviewing user may distrust the transform.

6. **Undocumented exit codes** (errors → 2, no-args → 0). Minor.

Positives worth keeping: `--help` is actually *more* complete than the README; the JSON dry-run shape is "exactly what an agent needs"; the bad-codemod-name error helpfully lists all valid names.

## Assessment

The v1.x codemod *engine* is release-ready — the abstraction shape, the dry-run/JSON contract, and the error handling for the common "wrong codemod name" case are all sound. The release risk is **documentation drift**, not code: the README was written assuming a published package and never revisited for the pre-publish reality, and it under-documents the CLI's own surface (`--option` keys, `--manifest`, `--files-from`).

None of the findings indicate a design problem or a hard-don't violation. They are all README edits plus one ~3-line error-message disambiguation. Because `docs/next_session.md` explicitly scoped #2 as a no-code-change written assessment, **the fixes are deferred to v1.5** and carried forward as the top candidate in the v1.5 planning prompt.

## Recommended v1.5 follow-up (codemods README + CLI polish)

In priority order:

1. **Fix the invocation story.** Either document the monorepo invocation (`node dist/cli.js …` or a `pnpm` workspace bin) alongside the `npx` form, or add an explicit "published?" status line. The Quick start must contain at least one command that actually runs today.
2. **Document per-codemod `--option` keys** — a column in the codemod table, or a short sub-section per codemod. They must be discoverable without reading source.
3. **Document `--manifest` and `--files-from`** in the README; explain `--manifest` vs `--list`.
4. **Disambiguate the "No files matched" error** — distinguish "no `--target` given" from "`--target` path does not exist".
5. (Optional) Fix the output over-indentation; document exit codes.

Estimated effort: README pass + one small CLI error-message edit + ~3 tests. A natural quick-win pairing for v1.5.
Loading
Loading