The live forward-planning surface. docs/v1_plan.md and docs/implementation_plan.md are the historical v1 plan (phases 0–4, all complete); this file is what's true now and what's next.
How work proceeds: phases are over. Work is small, tracked increments. Each picks one or two items from "Next" or "Deferred", ships them, updates this file, and replaces docs/next_session.md with the following handoff.
Last updated: 2026-07-06 (v1.18 — confirmation gate (HITL) shipped as a pattern; the "operate my app" story is now complete).
- 19 npm packages in the workspace + 1 PyPI package (
acture— graduated this increment from name-reservation placeholder to real Python MCP client). Pending changeset:acture(patchto drive the version-sync to PyPI). - 489 package tests + 41 example tests (npm) green; +23 Python tests covering the
ActureClientfacade, error unwrapping, transport helpers. All packages and examples build + typecheck; the Python distribution builds + passestwine check. - Canonical positioning is now written down (
docs/positioning.md) and wired into the skills. Rule-of-three rescoped (docs/redesign_takeaways.md§6): the soft heuristic applies to acture users deciding when to formalize a command, not to acture maintainers deciding what to ship. - 27 skills (+1 this increment): consumer-surface skills — palette / hotkeys (now incl. end-user customization) / MCP / AI /
acture-ai-assistant(app-operating assistant) / macros / e2e / telemetry / undo / test-property / python — plus dev / foundation / greenfield / dotnet / php / extensionsacture-*skills and 5migration-*. - Ten reproducibility / recipe docs:
hand-written-registry.md,hand-written-command-sequence.md,hand-written-telemetry.md,hand-written-undo.md,hand-written-test-property.md,hand-written-python-client.md,hand-written-keymap-override.md,hand-written-view-registry.md,hand-written-assistant-runtime.md, andai-codemod-recipe.md.
Core, state adapters, all consumer adapter packages, the migration package + migration skill track, the tier system, CLI, devtools. See docs/phase-*-reflection.md.
DOM interception, RTK example, build-tier AST mode, deep schema diffs, the full research-4 §B.5 codemod set (5 codemods), eslint-plugin-acture-migration (acture/no-stale-wrap-mutation), and the deferred fresh-agent release-gate test. See docs/v1_{1..4}-reflection.md and docs/fresh-agent-test-results.md.
docs/positioning.mdwritten — canonical: acture is a development tool first, packages are an optional accelerator, the two flexibility dimensions (core vs strangler-fig; agent-written vs package-reuse), and the dev-tool-first principle (zeroacture-*dependency unless explicitly chosen).acture-consumer-integrationskill created — the foundational pattern for building a consumer in a target project. Dev skills (acture-architecture-primer,acture-hard-donts,acture-palette-design) updated to load it whenever a task touches a consumer surface;acture-hard-dontsgained a positioning check (merge-ritual item #6).- Namespace migration — all 13
@acture/*packages renamed to unscopedacture-*(the@acturenpm scope was unavailable; flat naming also fits the "optional à-la-carte tools" positioning better). All imports, workspace deps, configs, examples, docs, and skills updated; lockfile regenerated; full workspace re-validated. - READMEs — root,
packages/core, and all 14 sub-package READMEs carry the dev-tool-first framing.AGENTS.mdupdated.
All 15 packages are live on npm (2026-05-14). The @acture org could not be created (namespace taken) → went unscoped acture-*. One further collision surfaced at publish time: the unscoped name acture-mcp was already taken by an unrelated project, so the MCP adapter was renamed to acture-mcp-server.
Audit of packages/core against docs/positioning.md. Findings and outcome (full write-up: docs/core-review-reflection.md):
- Import boundary: clean. Core depends only on
zod(peer). Zero React, zero state libraries — verified across all source files (hard-don'ts #6 holds). - Promise A (core is the minimal primitive): one extraction. Seven of eight source files are genuinely primitive (registry/dispatcher, schema bridge, state-adapter interface; the
whenDSL is defensibly primitive — the dispatcher must evaluate the closedwhenfield). The outlier wastier-warnings.ts—enableTierWarningsis dispatch instrumentation (it monkey-patchesregistry.dispatchtoconsole.warn), structurally identical toacture-devtools'sinstrumentRegistry. Moved toacture-devtools.acturecore ↔acture-devtoolsbothminor. - Promise B (the agent-written path is reproducible): the central gap, now closed. The skills taught acture's design and
acture-consumer-integrationcovered the hand-written path for consumers, but nothing made the core primitive itself reproducible without reverse-engineering ~1000 lines of source. New artifacts:docs/hand-written-registry.md(a legible, ~80-line, zero-dependency registry+dispatcher reference) and theacture-greenfieldskill (walks an agent through standing up the core primitive in a new project — hand-write vs. installacturecore as a deliberate per-project choice).acture-architecture-primerupdated to loadacture-greenfieldfor greenfield tasks. CommandRecordunchanged — stays closed at 15 fields.
The two least-tooled consumer surfaces — macros and e2e — built per the positioning. Full write-up: docs/v1_7-reflection.md.
- Step 1 design decision (settled with the user via
AskUserQuestion): the shared command-sequence concept is not a package. The fork was (A) a sharedacture-sequencesubstrate, (B) two independent packages, (C) a hand-written reference doc + only the tool-bound package. Chose C. Rule of three (no third concrete code caller of a substrate yet), hard-don't #2 (a substrate package layering macros + e2e + assertions courts god-packaging), and the journal's own "the macro layer is a thin consumer, not a new primitive" (§3.7) all pointed the same way — and it matches the v1.6docs/hand-written-registry.mdprecedent exactly. Macros: pattern + skill, no package (also user-confirmed). docs/hand-written-command-sequence.md— the reproducible reference:recordSequence/replaySequence/replayTestover{commandId, params}sequences, ~60 lines a project owns outright. The sibling ofdocs/hand-written-registry.md.acture-e2e-playwright— the one new package (the tool-bound piece). Two layers kept separate: a pure, Playwright-free sequence engine that mirrors the reference doc line-for-line, and the Playwright glue (dispatchInPage,clickCommand,commandSelector,replaySequenceInPage,replayTestInPage, plus atestfixture atacture-e2e-playwright/fixture). Playwright is type-only in the main entry; the runtime import is isolated in./fixture. 23 tests.minorchangeset.acture-macros+acture-e2econsumer skills — both build onacture-consumer-integration.acture-macrosdocuments the no-package, hand-write-from-the-doc path;acture-e2ecovers the test-pyramid compilation strategy, the Playwright package, and that Cypress / Vitest browser mode / other runners are equally valid (agent-written) choices.acture-architecture-primerandacture-consumer-integrationupdated: the eight-consumer-surface list and the per-tool table now reference the shipped macros/e2e artifacts instead of marking them "post-v1" / "planned".
Three per-surface consumer skills, for the three remaining consumer surfaces that already have shipping packages. Full write-up: docs/v1_8-reflection.md.
- Step 1 decision (settled with the user via
AskUserQuestion): picked per-surface consumer skills over codemods polish / greenfield agent-track skills, scoped to hotkeys + MCP + AI — the three surfaces with shipping packages (acture-hotkeys,acture-mcp-server,acture-ai-vercel). telemetry / undo / extensions were deferred: no shipping packages yet (telemetry & undo are post-v1), so their skills would be agent-written-path-only and less consistent — a later increment. acture-hotkeysskill — keyboard shortcuts as a registry projection. The tool-library choice (tinykeys / react-hotkeys-hook / custom), agent-written vs theacture-hotkeyspackage, first-registered-wins conflict resolution, fire-timewhen-clause evaluation, the input-aware default, modal scoping.acture-mcpskill — the registry as an MCP server. The two-layer split (pure projection vs transport glue), the SDK/transport choice, tier semantics, the deterministic@deprecatedbanner, function-whenexclusion, errors-as-data, and the prompt-injection guardrails (hard-don'ts #5/#10).acture-aiskill — the registry as LLM tool definitions. The SDK choice and the schema-projection fork (pass Zod through vs project to JSON Schema), errors-as-data, function-whenexclusion, the prompt-injection guardrails, and the "an AI tool-call sequence is a macro" cross-reference.- All three build on
acture-consumer-integration, follow theacture-macros/acture-e2etemplate for shape and tone, and document both the agent-written and package-reuse paths with the tool-library choice framed as the user's. - Consistency updates:
acture-architecture-primer's consumer-surface list andacture-consumer-integration's "See also" now point at the new skills. - Skills + docs only — no package code changed, no changeset. Full workspace build / typecheck / test re-verified green.
Two backlog increments shipped in one session (the user delegated the scope call: "fix what's fixable autonomously"). Full write-up: docs/v1_9-reflection.md.
Part A — codemods README/CLI polish + AI-codemod-recipe doc (closes the docs/backlog/codemods-polish-and-tier-mirror.md file):
acture-codemodsCLI — the ambiguous "No files matched" error (v1.4 fresh-agent finding #4) is now three distinct messages: no--target/--files-fromgiven, a path that does not exist (likely a typo), a path with no.ts/.tsx/.jsxfiles.--helpgained Modes (--list/--manifest) and Exit codes sections. +3 CLI tests (52 → 55).minorchangeset.acture-codemodsREADME — rewritten: documents every--optionkey for all five codemods,--manifestvs--list,--files-from, exit codes, and the from-a-clone invocation. (Finding #1 — thenpx404 — was resolved by reality:acture-codemodsis published on npm; the README now states that and adds the contributor invocation.)docs/ai-codemod-recipe.md— research-4 recommendation #8: theCodemodcontract, the four-point conservative-codemod discipline, a ts-morphrunskeleton, a prompt recipe, and how to run a one-off codemod (throwaway script vs. drop into the package)..d.tstier mirror — deliberately NOT built. Deferred v1.2 → v1.8 with no concrete consumer; tier filtering is runtime-only (registry.list({ tiers })), nothing consumes tier at the type level. Building it would be speculative infrastructure without a named need. Instead, theacture-build-tierREADME caveat was rewritten to make the deferral explicit-with-rationale..changeset/README.md— fixed: it still described the droppedfixedgroup and the stale "0.x quirk". Now describes independent versioning and post-1.0 semver.
Part B — greenfield agent-track skills (the per-step skills below the acture-greenfield foundation):
acture-greenfield-state-model— Step 1 in detail: the four hard constraints on the state shape (JSON-serializable, typed slices, normalized, stored-vs-derived), the deterministic counter-in-state id-generation pattern, theStateAdapterseam, what does NOT belong in state.acture-greenfield-bootstrap— the concrete file-by-file walk-through of the foundation's four-step sequence, grounded in theexamples/greenfield/graph-editorworked app: the three core files (state.ts→registry.ts→commands/index.ts), the "every mutation through dispatch" acceptance criterion + itsrgaudit, the ordering discipline, the recurring hand-write-vs-install decision points.- Consistency update:
acture-greenfieldnow points at both sub-skills (intro + Step 1 + See also).
Two small, autonomous backlog items surfaced by research-6 (the user picked "smaller backlog items" over pulling a post-v1 item forward). Full write-up: docs/v1_10-reflection.md.
acture/require-param-describe(new ESLint rule ineslint-plugin-acture-migration) — flags top-level fields in adefineCommand({ params: z.object({...}) })schema whose value expression has no.describe(...)in its method chain. Zod → JSON Schema is lossy; without.describe()every downstream consumer (MCP tool inputs, AI function-calling tool args, autoform / rjsf form adapters) is left with a parameter that has no semantic hint. Conservative detection (tracks thedefineCommandandzbindings, only fires when both are recognised andparamsis structurallyz.object({...})). +19 tests.minorchangeset. The plugin now hosts both migration-specific and schema-quality rules; the historical-migrationpackage suffix was kept to avoid a breaking rename (a god-package-of-one new plugin would have been speculative infrastructure — hard-don't #2).- MCP spec-version pin (
packages/mcp/src/spec-version.test.ts) — pinsEXPECTED_PROTOCOL_VERSION = '2025-11-25'and asserts the SDK'sLATEST_PROTOCOL_VERSIONmatches andSUPPORTED_PROTOCOL_VERSIONSstill contains the older dates we interoperate with. When the SDK ships a new spec date the test fails, surfacing the upgrade as the deliberate, semver-major decision the roadmap calls for rather than an accidental transitive-dep pickup. README documents the policy + the test's upgrade checklist. +2 tests.patchchangeset onacture-mcp-server.
Two new packages pulled forward from Post-v1 by explicit user direction. Full write-up: docs/v1_11-reflection.md.
acture-telemetry(new package,1.0.0) — observe every dispatch via a configurable sink. Optional pass-throughredactandsamplercallbacks (single-function shapes, no mini-DSL). One built-inconsoleSinkfor reference; multi-destination is user-side composition (sink: (r) => { a(r); b(r); }). Errors-as-data preserved end-to-end. Telemetry never breaks dispatch (sampler/redact/sink each in defensivetry/catch). +18 tests.minorchangeset. Reference:docs/hand-written-telemetry.md. Consumer skill:acture-telemetry.acture-undo(new package,1.0.0) — patch-based undo/redo over aPatchCapableAdapter.createUndoHistory(adapter, registry, options?)returns{ undo, redo, canUndo, canRedo, clear, transaction, entries, dispose }. Observes the adapter'ssetStateWithPatchescalls and groups them by dispatch boundary;transaction(fn)groups N dispatches. Partial-failure semantics: mid-transaction failure leaves prior mutations applied; the entry is still pushed; caller canundo()to rewind. Effects flow through optionalonEffect(effect, { isUndo, isRedo })host callback at apply/undo/redo lifecycle points — acture-undo never enacts effects itself. +19 tests.minorchangeset. Reference:docs/hand-written-undo.md. Consumer skill:acture-undo.- Step 1 shape decisions (settled with the user via
AskUserQuestion): telemetryredact= pass-through callback (not declarative key-list); telemetrysampler= function (not fraction); undo effects = host callbackonEffect(effect, { isUndo, isRedo })(not typed enum); transaction failure = partial stays applied (not auto-rewind). All four landed on the simpler, more flexible options. - Composition: both packages wrap
registry.dispatchvia the same monkey-patch pattern asacture-devtools'sinstrumentRegistryandenableTierWarnings. Install order = install order; dispose in reverse install order. No core change was needed. - Consistency updates:
acture-architecture-primer's consumer-surface list (#5 telemetry, #6 undo/redo) now references the shipped artifacts;acture-consumer-integration's per-tool table gained telemetry and undo rows and its "See also" enumerates the new skills;acture-state-adapterno longer marks undo as "post-v1".
New package pulled forward from Post-v1 as part of the autonomous v1.12 + v1.13 chain. Full write-up: docs/v1_12-reflection.md.
acture-test-property(new package,1.0.0) — fast-check arbitraries over the command registry; randomCommandSequences replayed viaacture-e2e-playwright'sreplaySequence; invariants asserted end-of-sequence. On a counter-example, the thrownPropertyTestFailurecarries the shrunk failing sequence (replayable verbatim throughreplaySequence) and the invariant name. +29 tests.minorchangeset. Reference:docs/hand-written-test-property.md. Consumer skill:acture-test-property.- Shape decisions (settled autonomously per next_session.md): tool-library = fast-check (the dominant JS property-testing library; jsverify unmaintained; hand-roll loses shrinking). Zod-to-arbitrary mapping = in-package mapper (the spec-listed
@fast-check/zodpackage does not exist on npm; verified withnpm view @fast-check/zod). Mapper subset = the JSON-Schema-representable subset acture'stoJsonSchemaalready serializes:string / number / boolean / literal / enum / array / object / union / optional / nullable. Unsupported types throwUnsupportedZodTypeErrorloudly — silent skipping would mean a "valid" failing sequence the user couldn't reproduce. Invariants run end-of-sequence, matchingreplayTest's shape. - Builds on, doesn't re-derive, the v1.7 sequence engine: imports
replaySequence,CommandSequence,SequenceStepfromacture-e2e-playwright(the package depends on the pure sequence module, not on Playwright runtime). Tested against bothacture-state-zustandandacture-state-reduxadapters in the same suite. - No god-package. One fast-check binding only. No Vitest/Jest matchers, no HTML report, no CI integration, no per-step invariants, no
fc.commandsstateful-model surface — each is its own future package if real demand surfaces (hard-don't #2). - Consistency updates: roadmap status snapshot updated; this section added;
acture-test-propertyskill registered as the eighth-and-a-half consumer surface variant (it does not add a 9th surface — it is the e2e surface's property-test variant).
New PyPI distribution (graduated from name-reservation placeholder) pulled forward from Post-v1 as the second half of the autonomous v1.12 + v1.13 chain. Full write-up: docs/v1_13-reflection.md.
actureon PyPI — graduated from the placeholder that reserved the name to a real, thin MCP-client facade perdocs/research/acture_research_6. Surface:ActureClient(aMapping[str, Command]),Command(callable;__call__returnsstructuredContent,call_rawreturns the fullCallToolResult),ActureError(errors-as-data across the language boundary — code, message, command_id, details),stdio_transport/http_transporthelpers. ~300 LoC, dict-like in thedol/py2mcpidiom. No Pydantic dependency — agents read JSON Schema anddescriptiondirectly; Pydantic-codegen is optional, out-of-package, deliberately post-v1. No OpenAPI emitter — MCP already speaks JSON Schema. One dependency: the officialmcpSDK (≥ 1.10). +23 tests using the SDK's in-memory transport. Hand-written equivalent:docs/hand-written-python-client.md(~50 lines). Consumer skill:acture-python.- Cross-language semver = lockstep, today.
scripts/sync-python-version.mjswas already in place; the v1.13 release rides the existingpatch-bump-of-npm-acturemechanism to drive the PyPI version + publish. Decoupling is a deliberate future decision, not made in this increment. - Server side unchanged.
acture-mcp-serveralready shipped; the Python client consumes itstools/list+tools/callshape verbatim, including theformatToolResponseerror envelope (isError: truewith a JSON-stringifiedCommandErrorin a text content block). - Shape decisions (settled autonomously per next_session.md): package name =
acture(already PyPI-reserved by the existing placeholder; verified by inspection ofpython/'s state). API =ActureClientasMapping[str, Command]per research-6 §"v1 scope" sketch. Pydantic = optional, NOT a hard dep. OpenAPI = out of scope. Test substrate = the SDK's in-memory transport (create_connected_server_and_client_session), not a Node subprocess — same wire, no flakiness, no JS-build dependency in pytest. Errors-as-data = typed exceptionActureError(the convenient form) +call_rawreturning the rawCallToolResult(the dict form), so callers can pick whichever ergonomics they prefer. - One escalation that didn't fire: the version-lockstep question (should PyPI
acturedecouple from npmacture?) was flagged in advance as a possible escalation; investigation showed the existingsync-python-version.mjsinfrastructure handles the cross-language semver cleanly for v1, and decoupling is reversible later. Kept the lockstep, documented the choice in the changeset andacture-pythonskill.
v1.14 — consumer-gap research + skills (keybinding customization, app-operating AI assistant) — complete (this increment)
User-driven gap-fill: assess and close the specialized-support gaps for three consumer surfaces the user is about to implement (command palette, keyboard-shortcut customization, an app-operating AI assistant) before implementation. Palette was already fully covered (research-1/2, acture-palette-design, acture-palette-react + form adapters); the two real gaps were customization and the assistant. Pattern-first — no package code this increment (user-confirmed); the deliverables are research + skills + reproducible references, per dev-tool-first. The concrete consumer is reelee-web (its src/ai/acture-tools.ts already bridges the registry to Anthropic tools and classifies destructive commands), which grounds both gaps in a real named need.
- research-10 — End-user keyboard-shortcut customization (
docs/research/acture_research_10 -- End-User Keyboard-Shortcut Customization.md). Product survey (VS Code / JetBrains / Sublime / Zed / Obsidian / Atom / Emacs / games), VS Code's last-defined-wins resolution, the physical-vs-logical key decision (event.keyfor mnemonic,event.codefor positional;getLayoutMap()for display), conflict-warning UX, WCAG 2.1.4, and the finding that no JS hotkey library ships a persisted user-rebindable keymap — so acture's layer is differentiating. Design: a sparseUserKeymapoverride map outside the closedCommandRecord, resolved by pure composition over the existingcollectBindings. - research-11 — AI assistant operating a command-dispatch app (
docs/research/acture_research_11 -- AI Assistant Operating a Command-Dispatch App.md). Companion toai_assistants 03(write-side). Framework survey (CopilotKit / assistant-ui / Vercel AI SDK / AG-UI / LangGraph / OpenAI / Anthropic / MCP). Findings: the read side is an industry-wide gap acture is placed to close (viaPatchCapableAdapter's RFC-6902 patches); MCP tools-vs-resources → ship both a resource projection and agetStatetool; HITL converged on a dispatch-boundary confirmation gate; capture the deterministic dispatch chain as a macro, not the LLM trace. - Skills.
acture-hotkeysextended with a full end-user-customization section (data model, resolution, capture UX, conflict detection, WCAG) and customization removed from its "What NOT to build" list. Newacture-ai-assistantskill — the app-operating-assistant consumer that composesacture-ai/acture-mcp(write) with the read side + HITL + macro capture, and bridges to the generalai-assistant-*skill family for the runtime/chat-UI/prompts (kept the app's choice).acture-architecture-primerandacture-consumer-integrationupdated to surface both. - Reproducible references (3 new
hand-written-*).docs/hand-written-keymap-override.md(~50-line user-keymap layer),docs/hand-written-view-registry.md(the read-side dual ofhand-written-registry.md: views → MCP resources +getStatetool),docs/hand-written-assistant-runtime.md(confirmation gate + dispatch-chain capture + backend/frontend loop wiring). - Deferred to a named implementation need (the user's call, per hard-don't #2 / dev-tool-first): the package accelerators — a
ViewRegistry+ MCPresourcesprojection inacture-mcp, and a keymap-customization helper inacture-hotkeys— plus the closed-surface question of whethersideEffect/requiresConfirmationbecomeCommandRecordfields (currently middleware+convention). Research-10 §7 and research-11 §12 record the exact decision each unblocks. Note: issue #34 (MCP tool-name contract) sits in the file the resources projection would extend — verify/close before that work.
The first of the v1.14-deferred package accelerators, pulled forward: the AI read side. Full context: research-11 §3 (the read side is the industry-wide gap; acture is placed to close it). Kept to acture's precedent — extend the already-published acture-mcp-server (additive minor), no new npm package, no core-surface change; the ViewRegistry primitive stays the hand-written pattern (docs/hand-written-view-registry.md) until a second projection target justifies extracting it (exactly how macros stayed a pattern while only the tool-bound acture-e2e-playwright earned a package).
acture-mcp-servergains a resources projection. Pure layer (resources.ts, SDK-free):buildResourcesList(views, opts)/readResource(views, uri)/viewIdToUri+ theViewSourceinterface (thelist/read/onStateChangedsubset of the hand-writtenViewRegistry). Server glue:createMcpServer(registry, { views, resourceUriPrefix? })wiresresources/list+resources/read+resources/subscribe, advertises theresourcescapability, and firesnotifications/resources/updatedfrom the source'sonStateChanged. Tier-filtered like tools (internalnever projected — enforced by theViewSource, mirroring how core'sdispatchenforces the write side). Omitviews→ tools-only, fully backward-compatible. +8 tests (resources.test.ts); typecheck + build green.minorchangeset onacture-mcp-server.- The pure/glue two-layer discipline held:
resources.tshas zero SDK dependency (the SDK'sReadResourceResultupcast happens only inserver.ts), so non-stdio transports consume the projection unchanged (hard-don't #3,acture-mcpskill). - Docs/skills:
acture-mcpskill gained a "The read side" section and dropped resources from its "What NOT to build" list; README gained a resources section;docs/hand-written-view-registry.mdandacture-ai-assistantnow note the shipped package path. Issue #34 was verified stale (names sanitized onmainvia #24) and closed before this work. - Still deferred: the
getState-tool hedge for tools-only hosts (companion to resources), the keymap-customization helper, and thesideEffect/requiresConfirmationclosed-surface question — each awaits its own named need.
Completes the read side started in v1.15. MCP resources are the correct read side but the least-supported MCP primitive (some hosts — e.g. Cursor — are tools-only); a getState tool is the portable hedge that works on any tools-capable host, including a direct Anthropic/Vercel tool projection (research-11 §3.2, "ship both"). This directly serves the named consumer reelee-web, which consumes buildToolsList to feed Anthropic tools (not MCP) — so a pure getState tool descriptor slots straight into its flow.
- Pure (
resources.ts):buildGetStateTool(views, opts)→ a wire-safe (app_getStatedefault,^[a-zA-Z0-9_-]{1,64}$),readOnlyHinttool descriptor whoseviewparam enumerates the listed view ids;callGetState(views, args)reads the requested view as errors-as-data (invalidview→isError; unknown/internal view →null). Feed the descriptor into atools/listalongsidebuildToolsList, or straight into a non-MCP tool array. - Server:
createMcpServer(registry, { views, getStateTool: true })merges the tool intotools/listand routes it intools/call. Default off; requiresviews. Fully backward-compatible. McpToolDescriptorgained an optionalannotationsfield (readOnlyHint/destructiveHint/idempotentHint/openWorldHint) — the getState tool sets it. Additive; the command-tool projection is unchanged (deriving annotations from a command side-effect class stays deferred with the confirmation-gate work). +5 tests (28 total in the package); typecheck + build + workspace green.minorchangeset (acture-mcp-server1.2.0 → 1.3.0).- Still deferred: the keymap-customization helper (the second v1.14 accelerator) and the
sideEffect/requiresConfirmationclosed-surface question.
The second v1.14-deferred accelerator. Lets a user (not just the developer) remap shortcuts and have the choice persist (research-10) — pure composition over the record defaults, no change to the closed CommandRecord. The reproducible zero-dependency equivalent already shipped as docs/hand-written-keymap-override.md (v1.14); this is the tested acture-hotkeys accelerator.
bindHotkeys(registry, { keymap })— an optionalUserKeymap(sparsecommandId → { replace | add | remove }) layered over each record's defaultkeybindingat bind time. Default empty → existing callers unaffected.useHotkeys(React) forwards it and re-binds on keymap identity change, so a live remap UI takes effect.- Pure layer (
keymap.ts):resolveKeys(cmd, keymap)(override resolution);collectBindingsgained a keymap param and orders user-touched bindings first on a shared key (VS Code's "user override wins, scope still respected");detectConflicts(registry, keymap?)(definite/possiblesame-key clashes — the highest-value remap affordance). - Capture / display primitives:
tokenFromEvent(press-to-record),isReservedCombo/RESERVED_COMBOS(reject browser-owned combos),formatKeybinding(⌘/Ctrl labels),layoutLabel(getLayoutMapfor physical keys, with fallback). McpToolDescriptor-style discipline held: the purekeymap.tsis tinykeys-free;bind.tscomposes it. +14 tests (23 in the package; the 9 pre-existing bind tests still pass — backward-compatible).minorchangeset (acture-hotkeys1.0.1 → 1.1.0).- Left to the app (the primitives cover it): the full remap-UI React component, preset packs, cloud sync, WCAG "disable character-key shortcuts" toggle — documented, YAGNI-gated (research-10 §5 "deliberately omits").
- Still deferred: the
sideEffect/requiresConfirmationclosed-surface question (the confirmation-gate work).
The last "operate my app" piece: a human-in-the-loop gate for destructive/irreversible AI dispatch (research-11 §6). Design settled with the user: middleware + convention, NOT CommandRecord fields — getRisk(id) is an external map, so the closed record stays closed (the fields alternative was declined to avoid opening the guarded surface). And like macros / recordSequence, the ~40-line gate ships as a pattern, not a package (hard-don't #2 — no god-package-of-one, no natural existing package home); the delivery surface is the reference doc + skill.
docs/hand-written-assistant-runtime.mdPiece 1 rewritten from a sketch to a complete, secure implementation:createApprovalStore(one-use tokens bound to the exact{command, params}),confirmationGate(a dispatch wrapper that returns aconfirmation_requirederrors-as-data proposal for risky assistant calls), and the runtime re-dispatch flow.- The security fix that motivated hardening it: the token is minted by the runtime after a human approves, and never returned to the model — the prior sketch's
!ctx?.approvedTokentruthiness check (any token passes) plus a hinted token-in-proposal would let the model self-approve by lifting the token from the tool result. The proposal now carries only{command, params, preview}; tokens are one-use and call-bound. acture-ai-assistantskill §2 updated: the trust-boundary rule (token minted post-human-approval, never to the model), the one-use call-bound tokens, and the settled convention-not-fields / pattern-not-package decision.- Docs/skill only — no package, no changeset, no version bump (pattern delivery).
With this, the "operate my app" story is complete: write side (tools/MCP) + read side (resources + getState) + HITL confirmation + macro capture + the runtime bridge — all shipped, as packages where a package earned it and as patterns/skills elsewhere.
The autonomous v1.12 + v1.13 chain is complete. The remaining post-v1 items need user direction; the rewritten docs/next_session.md surfaces them. The candidates are: acture-state-jotai (atom-tree ↔ flat-state bridge is non-trivial per research-3; the adapter may not implement PatchCapableAdapter cleanly), acture-state-valtio (proxy-to-patch translation is non-trivial). (acture-sandbox is no longer a candidate — its isolation-only seam shipped in the extension-system increment; see below.) Pull-forward decisions are the user's; surface options with honest trade-offs when scheduled.
Valid, not scheduled. Pick up when prioritized.
.d.tsmirror of resolved tier values — ⏸️ deliberately deferred, not just unscheduled. Considered in v1.9 and explicitly not built: zero concrete callers, tier filtering is runtime-only, nothing consumes tier at the type level. Rule-of-three gated — waits for a concrete type-level tier consumer. Theacture-build-tierREADME documents the deferral and its rationale.- Per-surface consumer skills —
acture-consumer-integrationis the foundation; per-surface skills now exist for the palette (acture-palette-design), macros (acture-macros), e2e (acture-e2e), hotkeys (acture-hotkeys), MCP (acture-mcp), and AI tool calling (acture-ai). Still missing: telemetry, undo, extensions — but these have no shipping packages (telemetry & undo are post-v1; v1.11 pulls those forward), so their skills are best written after the packages exist. Revisit once v1.11 ships. - Deeper greenfield agent-track skills — the foundation (
acture-greenfield) plus the two agent-track sub-skills (acture-greenfield-state-model,acture-greenfield-bootstrap, added v1.9) now cover the greenfield sequence end-to-end. No specific gap is scheduled; add further sub-skills only if practice surfaces one.
Per docs/v1_plan.md §"Post-v1" — none ship without explicit user direction. (Earlier drafts of this section gated post-v1 promotion on a "three concrete callers" rule of three; that was a misapplication — see docs/redesign_takeaways.md §6. Post-v1 items pull forward on user direction plus the standard maintainer principles: hard-don't #2, dev-tool-first, single accelerators.)
✅ Shipped v1.11.acture-undo— patch-based undo, transactions, effect queue.✅ Shipped v1.11.acture-telemetry— middleware logging every dispatch.✅ Isolation-only seam shipped (the extension-system increment). Gating research filed asacture-sandbox— third-party extension sandboxing.docs/research/acture_research_9 -- Extensions and Plugin Systems.md(the §7 brief): the host/loader is a core-only pattern (docs/hand-written-sandbox.md+ theacture-extensionsskill), andacture-sandboxships only theExtensionRunnerport + an in-process transport. The real isolating transports (Worker / iframe / QuickJS-WASM /isolated-vm), the capability/manifest/entitlement layers, and a marketplace remain deferred until a real untrusted-author user (research-9 §0 — the maintainer overrode the no-named-user NO-GO to build the seam).✅ Shipped v1.12.acture-test-property— fast-check arbitraries derived from command param schemas; random command sequences asserting state invariants.acture-state-jotai,acture-state-valtio— additional referenceStateAdapter<S>implementations.Python companion — thin MCP-client facade.✅ Shipped v1.13 as theacturePyPI package, graduating from the name-reservation placeholder. Seedocs/v1_13-reflection.md. Out of scope and explicitly post-v1.13: Pydantic-codegen SDK, OpenAPI emitter, inverse-direction skill kit (Python authors registering commands that acture surfaces back through MCP).
Both items below were picked up in v1.10:
.describe()discipline as a lint rule — ✅ Shipped asacture/require-param-describeineslint-plugin-acture-migration. The plugin's name kept its historical-migrationsuffix (renaming an already-published package is breaking; creating a new one-rule plugin would have been a god-package-of-one — hard-don't #2).- Pin the MCP spec version in CI — ✅ Shipped as a
vitesttest inpackages/mcp/src/spec-version.test.tsthat asserts the SDK'sLATEST_PROTOCOL_VERSIONmatchesEXPECTED_PROTOCOL_VERSION = '2025-11-25'. An SDK upgrade that bumps the spec date now surfaces as a deliberate, semver-major decision.
Explicit done/not-done for everything raised in conversation, so nothing is lost:
| Thread | Status |
|---|---|
eslint-plugin-acture-migration |
✅ Done (v1.4), published |
| Fresh-agent release-gate test | ✅ Done (v1.4) — docs/fresh-agent-test-results.md |
| Publish acture suite to npm | ✅ Done — all 15 live (2026-05-14); acture-mcp collided, shipped as acture-mcp-server |
@acture npm org unavailable |
✅ Resolved — went unscoped acture-* (v1.5) |
| Canonical positioning written down | ✅ Done (v1.5) — docs/positioning.md |
acture-consumer-integration skill + dev-skill wiring |
✅ Done (v1.5) |
@acture/* → acture-* rename |
✅ Done (v1.5) |
| READMEs reflect dev-tool-first positioning | ✅ Done (v1.5) |
acture core positioning-alignment review |
✅ Done (v1.6) — tier-warnings extracted to acture-devtools; docs/hand-written-registry.md + acture-greenfield skill added; see docs/core-review-reflection.md |
| Macros tooling | ✅ Done (v1.7) — pattern + skill (acture-macros), no package; docs/hand-written-command-sequence.md |
e2e testing tooling (acture-e2e-playwright) |
✅ Done (v1.7) — package shipped; acture-e2e consumer skill; see docs/v1_7-reflection.md |
| Shared command-sequence substrate question | ✅ Resolved (v1.7) — settled with user: hand-written reference doc + one tool-bound package, no acture-sequence |
Changeset spurious 2.0.0 major bump |
✅ Resolved (v1.7) — peer-dep ranges loosened to ^1.0.0 + onlyUpdatePeerDependentsWhenOutOfRange + fixed group dropped; see docs/escalations.md |
| Codemods README/CLI polish | ✅ Done (v1.9) — CLI error disambiguation + full README rewrite; minor changeset on acture-codemods; see docs/v1_9-reflection.md |
| AI-codemod-recipe doc | ✅ Done (v1.9) — docs/ai-codemod-recipe.md |
.d.ts tier mirror |
⏸️ Deferred (v1.9 decision) — explicitly not built: no type-level tier consumer; rationale in the acture-build-tier README |
.changeset/README.md stale (fixed group, 0.x quirk) |
✅ Fixed (v1.9) — now describes independent versioning + post-1.0 semver |
| Per-surface consumer skills — hotkeys / MCP / AI | ✅ Done (v1.8) — acture-hotkeys, acture-mcp, acture-ai; see docs/v1_8-reflection.md |
| Per-surface consumer skills — telemetry / undo | ✅ Done (v1.11) — shipped alongside the packages; see docs/v1_11-reflection.md |
| Per-surface consumer skills — extensions | ✅ Done — acture-extensions skill + docs/hand-written-sandbox.md + acture-sandbox (isolation-only seam); see research-9 |
| Greenfield agent-track skills | ✅ Done (v1.9) — acture-greenfield-state-model + acture-greenfield-bootstrap below the foundation; see docs/v1_9-reflection.md |
.describe() schema-lint rule |
✅ Done (v1.10) — acture/require-param-describe in eslint-plugin-acture-migration; minor changeset; see docs/v1_10-reflection.md |
| Pin MCP spec version | ✅ Done (v1.10) — packages/mcp/src/spec-version.test.ts pins 2025-11-25; patch changeset on acture-mcp-server; see docs/v1_10-reflection.md |
acture-test-property |
✅ Shipped v1.12 — see docs/v1_12-reflection.md |
state-jotai, state-valtio |
🔒 Post-v1 |
acture-undo, acture-telemetry |
✅ Shipped v1.11 — see docs/v1_11-reflection.md |
acture-sandbox |
✅ Isolation-only seam shipped — ExtensionRunner port + in-process transport; design in research-9; isolating transports deferred until an untrusted-author user |
| Research-6 (cross-language story) | ✅ Done — filed at docs/research/acture_research_6 … |
| Python companion | ✅ Shipped v1.13 — acture on PyPI, graduated from placeholder; thin MCP-client facade per research-6; see docs/v1_13-reflection.md |