Repository navigation
feat(app-control): discover-and-interview setup that generates and maintains a control skill #9507
Description
Problem
/app-control:drive consumes a project's control-<app> skill, but nothing in the marketplace generates one, interviews for one, maintains one, or keeps one current during ticket work. Two consumer repositories (a .NET Blazor Server web app and its separate identity server, in two repositories, several deployed environments, used from Claude Code and Cursor local and cloud multi-repo agents) built their control skills by hand over one long session. Most of what they learned is transferable and belongs in the plugins: as things a setup skill discovers, questions it asks, rules the generated skill carries, and warnings an agent keeps in mind.
The plugins must adapt to any repository, stack, organization, team and user. Ship none of the consumer's own choices (folder names, steps format, CLI language, environment names). The consumer's specifics below appear only as the example that exposed each point.
Gaps on current main (5a1fd8a76, 2026-10-23):
- No generator or maintainer for a control skill.
plugins/app-control/has one skill,skills/drive/SKILL.md.skills/drive/reference/control-skill.mddescribes the shape a control skill must have but nothing writes it.testing:map-featuresandtesting:refresh-feature-mapwrite and refresh only the testing plugin's own map. - Two map formats for the same knowledge.
plugins/app-control/skills/drive/reference/control-skill.md:85-93:features/<feature>.mdwith## Reset,## States,## Entry points(and Drive); hub index one line per feature (:24).plugins/testing/reference/feature-map.md:79-133: a separatefeature-mapskill (default.claude/skills/feature-map,plugins/testing/skills/run-e2e/SKILL.md:139) with## Parts,## Entry points,## Drive,## Traps, its own index and a Doctor line (:51).- A repository serving both
/app-control:driveand/testing:run-e2ekeeps two maps, or breaks one.
- Nothing keeps the map current during ticket work. When a change touches a mapped feature or adds one, no step says to update the map in the same pull request.
/verification:confirmalready reasons about which feature-map entry points a change touches (plugins/verification/skills/confirm/SKILL.md:166-169) and/testing:run-e2ereads the map (plugins/testing/skills/run-e2e/SKILL.md:221-224), but neither updates it. - Nothing says where a lesson goes. A lesson learned while driving could belong in a feature's Gotchas, the map contract, the repository's agent instructions, a path-scoped rule, or a personal file.
instruction-placementanddocs-hygiene:write-for-agentsown that decision and the writing, but the verification flow never calls them (no mention inconfirm/SKILL.mdorrun-e2e/SKILL.md).
Evidence
Verified this pass against origin/main at 5a1fd8a76:
git ls-treeofplugins/app-control: onlyskills/drive/SKILL.md; no map or setup skill.- Section headings of both map formats as cited above.
grepofverification/skills/confirm/SKILL.mdandtesting/skills/run-e2e/SKILL.mdforinstruction-placementandwrite-for-agents: no hits.- Issue search: no open or closed issue for a control-skill generator beyond app-control: new plugin plus testing and debugging changes #7581's decision (below).
Overlap with #7581 (open, the app-control thread): its decisions already include /app-control:map with create, refresh, check, replacing map-features and refresh-feature-map (D26, D52), and one generated control-<app> skill per app (D27). This issue does not reopen those decisions. It supplies the spec #7581 is labelled needs-spec for: the discovery and interview content, the generated skill's rules, the keep-current and lesson-routing steps, the multi-app and multi-repo ownership model, and the contract changes. Not on main yet either way.
Not verified this pass (the implementer must):
- pstack's two skills and guide, read live:
cursor/pluginspstack/skills/create-verification-skill,pstack/skills/maintain-verification-skill, and the guide section "Keep the verification skill honest". Claims about pstack below come from the reporting consumer. - Whether
/app-control:driveand/testing:run-e2ecan resolve grouped ids (<module>/<feature>). - Whether
instruction-placementanddocs-hygiene:write-for-agentscan be called from the verification flow as proposed. - Points marked observed come from the consumer build (two private SETWorks pull requests the melodic side cannot read); everything needed is restated here.
Proposed approach
Principle: compose, don't absorb
The owner's direction: the new skills compose the skills that already own each concern and do not copy their content. A copy drifts. Absorb only what is specific to driving an app.
- One maintain pass over one map contract, owned by whichever plugin owns the unified contract. Merge
testing:refresh-feature-mapinto it rather than adding a second maintainer beside it (consistent with app-control: new plugin plus testing and debugging changes #7581 D26). /verification:confirmand/testing:run-e2ecall a "touched features" step the map owner provides: update the touched feature folders, add a folder for a new feature, drive each once.- Lesson routing calls
instruction-placementto choose the surface anddocs-hygiene:write-for-agentsto write. The map skill decides only whether a lesson is about one feature (its Gotchas) or every feature (the contract). - Every composed skill is presence-gated, with a stated fallback when it is not installed, as the marketplace already does elsewhere.
- One instruction surface per repository. The consumer keeps agent instructions in
AGENTS.md;CLAUDE.mdis an@AGENTS.mdshim and Cursor readsAGENTS.mdnatively, so the pointer to the control skill went intoAGENTS.mdonly. The setup skill discovers which surface the repository treats as the source of truth and writes only there.
What pstack does (to port, after reading it live)
- Create: interviews the repository first and the user second; builds launch, doctor, drive, evidence and cleanup plus an executable helper; seeds three to five features; proves one end to end, including that the evidence survives cleanup.
- Maintain: a single generic skill. Locates the project's own verification skill (several found: ask which; none: stop), reads each feature's source with one read-only subagent per feature, drives every feature live once, and sorts each problem as doc drift, driver gap or product regression. Edits only the skill's own directory, never product code, and ends
clean,changed(one PR) orblocked. The guide says to run it daily from a scheduled automation.
Setup flow: discover, interview, generate, prove, maintain, keep current
Discover (read-only, from the repository and the machine):
| Area | What to find | Example that exposed it |
|---|---|---|
| Surfaces | Apps a person drives (web, API, CLI, desktop), and workers with no UI | Main web app, admin web app, file viewer, APIs, a worker; two of them share one port |
| Run | Documented start command, launch profiles, ports, one-instance limits | The main and admin web apps both bind 5031 |
| Ready | A health endpoint, plus a signal that the instance uses the expected data | A "runtime mode (Local)" log line; without it the app silently read deployed data |
| Config | The configuration layering, and which override mechanism the app honors | A Local run re-applies a local settings file over environment variables, so env-var overrides silently do nothing; only a gitignored per-developer file wins |
| Environments | Names and URLs, verified by a read-only call, never from docs alone | The repo's docs named cloud resources that do not exist; one repo's instructions omitted an environment that answers |
| Identity | Where sign-in happens, the options shown, prompts on some runs only, tenant-dependent labels and options | A separate identity server. The username label is per tenant ("Username or Email", "Email" or "Username"). Code sign-in shows only when the tenant enables passwordless. A passkey enrollment prompt appears on some sign-ins |
| Dependencies | Services a journey crosses, their URL per environment, whether the app's actual target can be read back | The app's sign-in challenge redirect reveals which identity server it really uses |
| Side effects | Channels that reach real people, and whether "local" still sends | The local app resolves live mail credentials |
| Shared systems | Deployed systems a local run still writes to | The local app signs in through the shared dev identity server, so a failed login counts toward lockout (10 attempts, 5 minutes) for everyone using that account |
| Data | Tenancy, seeds, and the app's supported reset path | Reprovisioning through the app's own admin page |
| Harnesses | Existing E2E specs, test accounts, selector conventions | A sibling Playwright suite |
| Evidence | Logs, a log server, OTLP, and profiling by tier | Blazor Server: the real work is on the server, so browser profiles mostly show the client runtime |
| Team vs personal | What is committed and team-wide, what is per user, and the OS-standard per-user location | Repo defaults < per-user config (OS application-data folder) < environment variables < flags |
| Related repositories | Systems whose pages appear in a journey but live elsewhere, and whether agents can reach them | Cursor cloud agents run multi-repo, so they reach both; a person may not have the second checkout |
Interview (only what discovery cannot settle; one question at a time, with a recommendation):
- Which apps, and which three to five features, to seed first.
- Write policy per environment and per external system: unattended, needs a person's grant, or never. Classify by where the data lands, not where the app runs.
- Test accounts: which to use and which must never be locked out. Credentials come from an environment variable or per-user config, never a flag and never a committed secret, unless the team declares a non-production credential shareable (the consumer did, for a team agent account).
- The recipient allowlist for each side-effect channel, or "never send".
- Flat map or grouped by module.
- Ownership across repositories: which journeys this repository owns, and which belong to a related system's skill.
- The driver and CLI language, defaulting to what the repository already uses.
- Where agent instructions live (see the principle above).
Generate and prove:
- Generate the hub, the CLI or helper, the per-app settings, the contract and the seeded features.
- Prove it pstack's way: launch, ready, sign in, drive one feature, capture, stop. Then check that the evidence survived and that nothing the run started is still running.
Maintain: the generic pstack-style pass, offered on demand and as a scheduled run.
Keep current (a gap pstack also leaves open):
- The generated contract carries a rule, and the repository's instruction surface carries a pointer: a change that alters a mapped feature, or a page another skill's steps include, updates that feature folder or shared step file in the same pull request and drives it once. A new user-facing feature adds a folder and an index line; a removed one deletes them.
- Lesson routing: one feature, its Gotchas; every feature, the contract; every agent in the repository, the instruction surface; only you, your personal gitignored rules.
Several apps and several repositories, without duplication (observed)
The consumer gave each fact one owner:
| Fact | Owner | How others use it |
|---|---|---|
| The CLI, the contract, the shared settings (timeouts, sign-in account, the app list) | One skill in one repository | Other app skills point to it. A future step is publishing the CLI as a pinned tool package, so no repository needs another checked out |
| An app's launch settings and environments | The app's own skill (app.json), in the repository that builds the app |
The shared config lists only the app's name, skill and owning repository |
| Steps for a page | The skill of the app that serves the page | A journey crossing into it includes them by reference: "<app>:<name>" |
| Write policy | Committed files only (the app's settings, then the repo defaults); prod refused in code | No per-user layer can loosen it |
Mechanics worth generalizing:
- Cross-app includes. An include takes
prefix(to include a file twice with unique step ids),with(parameter overrides; the wrong-password attempt reuses the identity server's credential steps with a different password),kind(mark every included step a write) andfinally(always run, as the reset). - The other checkout's location is a per-user setting. Without it the CLI stops with a message naming the setting and the repository to clone. The owner called this graceful degradation and wants it kept.
- One run file and one log per app, so two apps (the app and its local identity server) run at once.
- An environment can extend another (for example a local app with a local identity server), and each environment names its dependency services, which
readychecks: the service answers, and the app actually sends traffic to it.
Rules the generated skill should carry (observed, transferable)
- Feature and sub-feature. A feature is a user's goal; a sub-feature is a state or branch inside it. The passkey prompt during sign-in is a sub-feature; managing passkeys is its own feature, because the user reaches it on its own.
- Every entry point is listed and marked driven or
not driven: <reason>. Proof through one entry point never stands in for another. - A feature that cannot be driven says why and what would make it drivable (example: session expiry is disabled by the local config).
- A journey belongs to the app where the user starts and ends. Another service's pages are steps owned by that service's skill. A dependency service is a precondition that
readychecks. - Tenant- or configuration-dependent UI is a named precondition, or a tolerant selector (for example a label regex covering every tenant wording).
- Prompts that appear on some runs only use optional steps, not retries or sleeps.
- A write's reset runs even when the drive fails (finally steps).
- Never press the button that sends unless every recipient is allowed; stop at the form.
- The auth bootstrap reuses the mapped sign-in steps, so sign-in selectors live in one file.
- Sign out in a throwaway browser session, never in the one holding the saved session.
- Capture by tier for a server-rendered app. Browser trace, performance, CPU and heap; server CPU, heap and counters through the platform's diagnostics tools, attached to the real app process.
- Progressive disclosure. Every level is a folder whose
README.mdindexes the level below: modules, then features, then the feature folder holding its prose and its steps. Feature ids are paths (auth/sign-in). A flat map stays valid for small apps. - Executable steps beside the prose, with unique ids that the prose, the evidence file names and the write grants all use. The prose never repeats selectors.
Pitfalls for a control CLI
Material for developer-experience:build-cli and for the contract's driver section:
- Windows handle inheritance. Starting the app through a redirected child process passes the caller's handles to the app, so a caller piping the CLI's output hangs forever. Start the shell without inheriting handles (shell-execute, hidden window).
- A composite command keeps
--jsonstdout to one document.drive --startruns launch, ready and stop; their output goes to stderr. - The PID the tool records may be a wrapper, not the app. Here it was the shell. Find the real app process (by name and start time) before attaching a profiler.
- Reject typos fast: unknown flags, repeated step ids, feature ids that are not paths, an app or environment that does not exist.
- Name the override mechanism the app actually honors. Do not assume environment variables win.
Contract changes (both plugins, once unified)
- Grouped ids (
<module>/<feature>) resolved by/app-control:driveand/testing:run-e2e. Verify both resolvers before promising this. - One section set per feature: Sub-features, Entry points (each driven or not, with a reason), Reset, Drive (with a not-driven form), Gotchas. This replaces app-control's States and testing's Parts and Traps; decide the mapping when unifying.
- An optional machine-readable steps file per feature, with unique step ids, includes, optional steps, finally steps, and cross-app includes. The steps format stays the consumer's choice.
- Per-app settings in the app's own skill. Environments that name their dependency services and may extend another environment.
- Step kinds and write grants keyed to the system a step changes; the write policy comes from committed files only.
- A Capture section with a row per tier (browser and server).
- Optionally, a step log the control CLI emits that
/app-control:drivemaps intoreport.json. - The hub may index modules instead of features.
control-skill.md:24today expects one index line per feature and a## Statessection, so a grouped layout is one hop deeper than the contract describes. - Several apps in one repository: one control skill per app; the shared CLI, config and contract live once, and the hub says where.
Files likely to change
plugins/app-control/skills/drive/reference/control-skill.mdandplugins/testing/reference/feature-map.md(unify or extract one shared contract; pick the source of truth).- New
plugins/app-control/skills/map/(or the name app-control: new plugin plus testing and debugging changes #7581 settles) with create, refresh/maintain and check actions. plugins/testing/skills/map-features/,plugins/testing/skills/refresh-feature-map/(retire into the map owner per app-control: new plugin plus testing and debugging changes #7581).plugins/verification/skills/confirm/SKILL.md,plugins/testing/skills/run-e2e/SKILL.md(call the touched-features step; resolve grouped ids).plugins/developer-experience/skills/build-cli/(CLI pitfalls).
Acceptance criteria
- One feature-map contract exists on main;
control-skill.mdandfeature-map.mdeither are the same file or one points to the other with no duplicated section definitions. - An app-control skill generates a control skill: it runs repository discovery covering every row of the Discover table before asking the user anything, and asks only what discovery left open, one question at a time with a recommendation.
- The generated skill passes a prove step that launches, readies, signs in, drives one feature, captures, stops, and then checks the evidence still exists and no process the run started is alive.
- A maintain action reads each feature's source, drives every feature once, classifies each problem as doc drift, driver gap or product regression, edits only the control skill's directory, and ends
clean,changedorblocked. -
testing:refresh-feature-mapno longer exists as a separate maintainer of a second map. -
/verification:confirmand/testing:run-e2einvoke the touched-features step when a change touches a mapped feature, presence-gated with a stated fallback. - Lesson routing invokes
instruction-placementanddocs-hygiene:write-for-agentswhen installed, with a stated fallback when not. - The setup writes the control-skill pointer only to the instruction surface the repository treats as the source of truth (for example
AGENTS.mdwhenCLAUDE.mdis an@AGENTS.mdshim). -
/app-control:driveand/testing:run-e2eresolve a grouped id<module>/<feature>, proved by a test or eval, and a flat map still resolves. - The contract defines the feature section set, the optional steps file (unique ids, includes, optional and finally steps, cross-app includes), per-tier Capture rows, environments with dependency services and extension, and write grants from committed files only.
- The 13 rules above appear in the generated skill's guidance or the contract.
-
developer-experience:build-clicovers the five CLI pitfalls above. - No consumer-specific folder name, steps format, CLI language or environment name ships as a default.
Constraints and gotchas
- Read pstack live before porting; do not port from this issue's summary of it.
- app-control: new plugin plus testing and debugging changes #7581 owns the plugin-level decisions (map actions, one skill per app, drive as the only consumer entry); this issue must not contradict them. If something here conflicts, raise it on app-control: new plugin plus testing and debugging changes #7581.
- The work is large; the implementer may split it into sub-issues of app-control: new plugin plus testing and debugging changes #7581 or of this issue. The reporter asked for one issue carrying every detail.
- Skill-body changes need before/after evals per the app-control: new plugin plus testing and debugging changes #7581 done-when.
- Side-effect and lockout safety in the generated skill is a hard requirement, not a polish item: a run must never send to an unlisted recipient or exhaust a shared account's lockout budget.
Context
Source: local handoff item 20261023-211851-app-control-testing-control-skill-and-feature-map-contract-gaps.md (retired into this issue). Reported against app-control 0.2.0, testing 0.31.1, developer-experience 0.2.0, plus verification, instruction-placement and docs-hygiene.
Related: #7581 (app-control thread, map create/refresh/check decision), #8816 (app-control plugin with drive), #7195 (feature-map first-consumer pass), #8651 (pr-verify runs the control skill).
Activity
github-actions commentedon Oct 23, 2026
Proposed work class: work-class: structural
Basis: automated intake triage; the lanes App applied this class.
Size: Large
Complexity: High
Uncertainty: Known
Flags: none
Blocked by: none
#9507 (comment)
That decision settles the open questions. I read this as a large feature: a setup skill that discovers, interviews, generates and maintains a control skill, with one unified feature-map contract. It is split into sub-issues, so it is tracked here rather than done as one change. No duplicates found; #7581 is the related thread.
Automated triage, applied by the lanes App.
melodic-automation-lanes commentedon Oct 23, 2026
Not admitted to the issue lane yet: Size large: the split into sub-issues at intake is pending (owner Q93).
kyle-sexton commentedon Oct 24, 2026
Owner decisions from the brief interview for this issue (2026-10-23), folded into one effort that closes this issue through a series of PRs (sub-issues), in two tracks: Track A (general skill updates) and Track B (attended Claude Code driving, shipped as
control-claude-codein harness-ops).Acceptance-criteria amendments:
instruction-placementanddocs-hygiene:write-for-agents" becomes: the verification report lists lessons; a lesson about a feature or drive step goes to/app-control:map refresh, any other lesson goes to/corrections:codify, which places it by scope. This keeps one router.features/[<module>/]<feature>/README.md); the module level is optional, which is what "flat" means here. Existingfeatures/<f>.mdmaps still resolve andmap refreshmigrates them.shared/: allowed only for infrastructure used by two or more slices;map checkreports items used by fewer.config/defaults.json< gitignoredconfig/local.json< environment variables < flags (environment variables are the channel cloud agents have); credentials from environment variables by default. No runtime dependency on these plugins./verification:confirmand/testing:run-e2ecall/app-control:map refresh <feature>when installed, else report drift and name it.Out of this series: the CLI step log into
report.json, and #7581's script fingerprinting (D52/D53).kyle-sexton commentedon Oct 24, 2026
Slice drafts A1-A9 for this spec, handed over from the desktop poteto session (PLAN Phase 13) to the session that owns this PR series. These are drafts for the owner of this issue to file as sub-issues, not filed items.
Two inputs to apply first:
The owner decided the feature-file sections in the poteto tab: app-control: new plugin plus testing and debugging changes #7581 (comment). Whether Parts stays in that set is open; the owner rules on it on app-control: new plugin plus testing and debugging changes #7581.
The design questions after the slices are poteto's recommendations with their basis. Only Q3 (sections) is an owner decision.
The B, C and D slices (run-e2e shrink, /testing:write settings, dogfood map), #9532/#9542, #9533 and #9534 stay with poteto.
A1.
refactor(app-control): unify the feature-map contract in one app-control reference## Reset,## States,## Entry pointsand## Drive(
control-skill.md:88-97). Its index has one line per feature (:24).## Parts,## Entry points,## Driveand## Traps(
feature-map.md:79-133). Its index adds Driver, Doctor, Isolation and Written-at lines(
map-features/SKILL.md:140-148).Sub-features,How to get to it (user POV),Driving it with <harness>andGotchas(create-verification-skill:36).control-skill.mdto the home Q2 picks, recommendedplugins/app-control/reference/control-skill.md.Gotchas.
not driven: <reason>, per feat(app-control): discover-and-interview setup that generates and maintains a control skill #9507 rules 2 and 3.feature covers. The source paths let a caller map changed files to features (see Q6).
## Ready(D54).feature-map.mdis untouched here. It retires in A5, because pointing it at anotherplugin's path breaks
docs/plugin-philosophy.md:472-474.test -f plugins/app-control/reference/control-skill.md && test ! -e plugins/app-control/skills/drive/reference/control-skill.mdexits 0 (or the Q2 path instead).
## Statesis gone.drive/evals/evals.json) are non-inferior perskill-criteria.md:186-191.plugins/app-control/reference/control-skill.md(moved),plugins/app-control/skills/drive/SKILL.md(two links),drive/evals/evals.jsonif a case namesStates, fragment.## Statesis a cut of drive's contract and needs the eval run.A2.
feat(app-control): add /app-control:map createcontrol-<app>skill (feat(app-control): discover-and-interview setup that generates and maintains a control skill #9507 gap 1).map-featureswrites onlytesting's map.
plugins/app-control/skills/map/.createruns only on the explicit word.--unattendedis supported. (D26, D52; app-control: new plugin plus testing and debugging changes #7581:25.)recommendation.
cli/./app-control:drive: launch, ready, sign in, drive one feature, capture,cleanup.
surface the repository treats as its source of truth (Q19).
--unattendedcreate stops at the first question it cannot answer from therepository, with the list of open questions. It never guesses an answer to a safety question.
map-featurescases andfeature-map-writer-refuses-unsafe-location,reworded to the new output path, and add these:
test -f plugins/app-control/skills/map/SKILL.mdexits 0. Itsargument-hintnamescreateand--unattended, and its body says a bare run proposes.are non-inferior per
skill-criteria.md:186-191(the baseline for A5).check-evals-quality.shexits 0.default.
plugins/app-control/skills/map/SKILL.md,reference/discover.md,reference/interview.md,evals/evals.jsonplugins/app-control/README.mddocs/catalog.mdanddocs/skill-cheat-sheet.mdKnowable (the prove step on a real app; whether drive can run the sign-in step unattended).
(
eval-browser-dispatch.yml).A3.
feat(app-control): add /app-control:map check(
realign/audit-A.md:177; D52check).checkaction:step 1).
not driven: <reason>.control-skill.md:103-104).mapbody andargument-hintnamecheck.not drivenreason, a copied recipe. Each isreported, and no file changes.
map/SKILL.md,map/evals/evals.json, andmap/scripts/only if Q10 picks ascript. Fragment.
scripts/under the script option).A4.
feat(app-control): add /app-control:map refresh/testing:refresh-feature-mapmaintains only testing's map. pstack's maintain passadds three things it lacks:
refreshaction that ports refresh-feature-map's steps 1-6 and outcomes (clean,changed,blocked; at most one PR on a fixed branch) and adds:/app-control:drive. It drives every feature once and holds pstack'sthree invariants:
driver gap and gets fixed. Broken app behavior is a product regression: report it and keep it
out of the PR.
upkeep-skip.shand its test are copied intomap/scripts/. A5 deletes thetesting copies.
verb in the refresh PR (Q97 item 52,
interview-checklist.md:142).mapbody andargument-hintnamerefresh.bash plugins/app-control/skills/map/scripts/upkeep-skip.test.shexits 0.feature-map-maintainer-confines-editsare ported andnon-inferior to the old skill (run concurrently).
map/SKILL.md,map/reference/refresh.mdmap/scripts/upkeep-skip.shand.test.sh(mode 0755)map/evals/evals.jsonenough for triage).
scripts/, frontmatter).A5.
refactor(testing): retire map-features and refresh-feature-map for /app-control:mapthe PLAN sanity check (
PLAN.md:915) still fails.plugins/testing/skills/map-features/andrefresh-feature-map/, includingscripts/upkeep-skip.shand its testplugins/testing/reference/feature-map.mdplugins/testing/evals/feature-map-*, already ported in A2 and A4feature_map_dir:testing.schema.json:55-59resolve-config.sh:68-69,229,290-320and its test cases (resolve-config.test.sh:409-534per the earlier draft)
setup.sh:177docs/conventions/config-cascade/README.md:652run-e2e/context/e2e-config.mdrun-e2e/SKILL.md:221-237). It finds theproject's
control-<app>skill by discovery, reads its hub index as project data, cites/app-control:mapfor the format, and keeps the per-entry-point report line thatverification/skills/confirm/SKILL.md:166-169depends on.plugins/autonomy/reference/routines.md:247,343(feature-map-upkeep to/app-control:map refresh)plugins/verification/reference/config.md:86,schemas/verification.schema.json:19,.claude-plugin/plugin.json:34andskills/setup/SKILL.md:55(the wording namescontrol-skill entry points)
docs/conventions/invocation-mode/README.mddocs/upstream/cursor-pstack.mdmapping rows## Nextthat names either removed skill.claude/skills/feature-mapgets the migration path from Q4.test -d plugins/app-control/skills/map && test -d plugins/app-control/skills/drive && test ! -e plugins/testing/skills/map-features && test ! -e plugins/testing/skills/refresh-feature-mapexits 0 (
PLAN.md:915).rg -n 'map-features|refresh-feature-map|feature_map_dir' plugins docs --glob '!**/CHANGELOG.md' --glob '!docs/upstream/**'returns nothing.
bash plugins/testing/scripts/resolve-config.test.shexits 0.run-e2e/evals/evals.json) are non-inferior before andafter.
Q17.
scripts/; the verificationplugin.jsonuserConfig description).A6.
feat(verification): update touched features in the same PR through /app-control:mapfile in the same PR and drives it once. A new user-facing feature adds a file and an index
line. A removed feature deletes them.
/verification:confirmand/testing:run-e2einvoke the touched-features step (shape perQ6). The step is presence-gated, with a stated fallback: report the touched features as not
updated.
the fallback line appears.
plugins/app-control/reference/control-skill.md,verification/skills/confirm/SKILL.md,testing/skills/run-e2e/SKILL.md, evals, fragments.A3.
A7.
feat(app-control): route lessons from map runs through instruction-placementmap refresh(and create) decides only the scope of a lesson:/docs-hygiene:write-for-agentswhen they are installed (Q18), with a fallback that reportsthe lesson unplaced.
unverified, so a spike is needed first.
A8.
feat(app-control): resolve grouped feature ids in drive and run-e2e<module>/<feature>idsand a hub that indexes modules (feat(app-control): discover-and-interview setup that generates and maintains a control skill #9507 rule 12). Whether drive and run-e2e can resolve them is
unverified (feat(app-control): discover-and-interview setup that generates and maintains a control skill #9507 "Not verified").
README.mdindex per level and path ids.control-skill.mddescribes both layouts.argument-hintkeeps[<feature>]).A9.
feat(app-control): add steps files, cross-app includes and environment dependencies to the contractprefix,with,kindand
finally, optional steps);control-skill.md, keeping the steps format the consumer's choice.readychecks each named dependency service answers, and that the app sends trafficto it.
map createinterviews for ownership across repositories.argument-hintchanges.Design questions and recommendations (poteto, not owner decisions except Q3)
Design questions
Each question lists its options, a recommendation with its basis, and what it unblocks. Lauren
means pstack (read live, see the top). Matt has no counterpart for the map, drive or control
skill: "Matt adds none of these terms" (
decision1/verification.md:218).Q1. Which issue is the parent of these slices?
status: needs-decision. Its admission comment says a Featureneeds an open parent that awaits no decision. feat(testing): drive /testing:check-visual-parity through /app-control:drive when installed #9142 was admitted under app-control: new plugin plus testing and debugging changes #7581.
Refs: #9507.agent-ready.admission-rules.jsontypes-under-parent; feat(testing): drive /testing:check-visual-parity through /app-control:drive when installed #9142's admission under app-control: new plugin plus testing and debugging changes #7581.Q2. Which file is the single source of truth for the feature-map contract?
drive/reference/control-skill.mdandtesting/reference/feature-map.md. Two skills in one plugin may cite each other's files with thefull plugin-root form (
docs/plugin-philosophy.md:461-471). No skill may cite another plugin'sskill by path (
:472-474). Lauren keeps one shape, in the generator'sreferences/feature-map-example/(create-verification-skill:36).plugins/app-control/reference/control-skill.md, read by drive and map.drive/reference/; map cites it in plugin-root form.map/reference/; drive cites it.docs/conventions/, cited by URL.its shared map format at plugin level (
plugins/testing/reference/feature-map.md, read by threeskills). Testing's copy is deleted in A5, and testing cites
/app-control:map. Basis:plugin-philosophy.md:461-474;run-e2e/SKILL.md:221-222.plugin cannot read it offline.
Q3. Which sections does a feature file have?
Drive, Traps (
feature-map.md:107-127). Lauren's set is Sub-features, How to get to it, Drivingit, Gotchas (create:36). feat(app-control): discover-and-interview setup that generates and maintains a control skill #9507 proposes Sub-features, Entry points (each driven or not), Reset,
Drive, Gotchas, and folds States into Sub-features (its rule 1).
Entry points carries the driven or not-driven marker Lauren's "a proof that drives one convenient
entry point is incomplete" (create:36) needs. This amends the "States" wording in D27, so it
needs the owner. Basis: the three files cited;
confirm/SKILL.md:166reads entry points.than Entry points. (c) loses Traps.
Q4. How do we migrate: build the new skill beside the old ones, or move in one PR? And what
happens to an existing
.claude/skills/feature-map?principle-migrate-callers-then-delete-legacy-apisis in the pstack skilllist (read live). A single move is one Large slice that the lane skips (
dimensions.mjs:62-72,per the earlier draft). Consumers may already hold a map at the default path
(
testing.schema.json:57)./app-control:mapbeside the testing skills (A2-A4), then retire them (A5).checkand
refreshdetect a legacy map and propose a one-PR conversion.consumers get a path. Basis: the pstack principle;
skill-criteria.md:186-189(ship only whatwas measured).
feature_map_dirresolves throughtesting's script (
resolve-config.sh:290-320), so an unchanged move cannot resolve its path fromapp-control.
Q5. Does testing keep a thin pointer to the map?
PLAN.md:915). This question covers onlynon-skill pointers.
/app-control:map.PLAN.md:915.PLAN.md:915;judgment.
Q6. How do run-e2e and confirm choose the touched features without reading another plugin's
file?
(
run-e2e/SKILL.md:221-232). After A5 the format lives in app-control. A project's controlskill is project data, not plugin internals. feat(app-control): discover-and-interview setup that generates and maintains a control skill #9507 asks for "a touched features step the map
owner provides".
as data and cite
/app-control:mapfor its meaning.touched <paths>. This amends the three-action set of D26.--changed <paths>and selects features itself. This conflicts with "run-e2echooses" (app-control: new plugin plus testing and debugging changes #7581:39).
plugin-philosophy.md:472-474(the rule covers plugin paths, not project files).Q7. What does run-e2e do when app-control is not installed?
keeps its own route (
check-visual-parity/SKILL.md:39-40). The tool-per-job rule is to name thetool and stop if it is missing (Q569,
interview-checklist.md:614)./app-control:drive.dependenciesin plugin.json, asplugins/playgrounds/.claude-plugin/plugin.json:17-22does).runskill for launch only.one driving path and installs drive where testing goes. Basis: the playgrounds precedent; Q569.
Whether
dependenciesauto-installs a sibling from the same marketplace is UNVERIFIED; readhttps://code.claude.com/docs/en/plugins-reference before deciding.
Q8. Where do
e2e_driver,reuse_running_instance,browser_driver,recordingandbrowser_modelive once drive drives?drive/SKILL.md:48). The tool-per-job setting is anamed default read through the adapter (Q569). The generated control skill names its tools
(control-skill.md:21).
map createresolves them once and writes them into the control skill. Testing retires thekeys (B2).
app-control.yamlafter config-cascade: settings resolution and convention home #7571.Q569;
drive/SKILL.md:64-67.is still open.
Q9. Does app-control read a settings file before #7571 lands?
app-control.yamlor discovery" (app-control: new plugin plus testing and debugging changes #7581:31;design-threads.md:1206). Drive is discovery-only today. config-cascade: settings resolution and convention home #7571 is OPEN.app-control.yamlresolver now.drive/SKILL.md:42-48; config-cascade: settings resolution and convention home #7571 state.Q10. Is
map checkrun by the model or by a script?the model judging "copied recipe".
deterministic work. Basis: judgment;
/discipline:script-the-deterministic-work.Q11. Grouped ids: do we need them before the dogfood map, and does the hub index modules?
with a
README.mdindex per level.control-skill.md:24expects one line per feature.ls plugins); feat(app-control): discover-and-interview setup that generates and maintains a control skill #9507 rule 12.Q12. Dogfood: what is "the app", and what drives it?
eval-browser-dispatch.ymlalreadyruns
claude plugin evalon a hosted runner.claude -pwith--plugin-dirper feature, with stream-json as evidence.claude plugin evalon one case per skill as the drive step.run-e2e/context/non-ui.md).eval-browser-dispatch.yml:1-21; judgment.Q13. Which mechanism runs the per-PR live smoke?
features.
eval-browser-dispatch.yml).counts as safety. Basis: feat(pr-pipeline): run the project's app-control skill in pr-verify after the deterministic tests #8651 body; the user CLAUDE.md "A limit that protects ... plan usage is
safety".
Q14. Does the K36 probe gate the refactor default, and which result flips it?
PLAN.md:894-896says the probe gates the defaulton.c17-sweep.md:34says thedefault is
on(Beck's cycle) "until the K36 eval".topic10/report.md:126says to drop thestep "only if that eval shows agents skip it". Matt removed the step; Lauren has none
(
c17-sweep.md:34).onafter C1 regardless. The result is recorded and revisits only on evidencethat agents skip it.
ononly if the with-skill arm ran Refactor in a majority of runs, elseoff.onand run C1 afterwards.topic10/report.md:126. The gate is that the result exists, not athreshold, and C2 still waits on C1 as PLAN requires.
Q15. How do the write settings resolve, and at which scope?
resolve-config.sh), repo scope only, withno
userConfig.userConfig.docs/conventions/testing.yamlitself.resolve-config.sh:1-17;c17-sweep.md:34("scope repo").Q16. Threads: should analyze-profile's description name thread dumps in T1?
(
analyze-profile/SKILL.md:2). A description change is measured separately(
skill-criteria.md:179-189) and is frontmatter (HIGH).## Nextrouting. Change it later with invocationprobes.
skill-criteria.md:179-189;drive/SKILL.md:116-119.Q17. Who runs the map move? (Open as O3,
realign/MORNING-REPORT.md:420-423; no GUIDE row.)resolve-config.shor runevals. Basis: the lane facts above.
Q18. Which skill chooses the surface for a lesson?
/instruction-placement:auditis a sweep, not a one-lesson chooser (itsdescription).
/docs-hygiene:write-for-agentswrites agent markdown./docs-hygiene:write-for-agentswrites;instruction-placementonly on a periodic audit.
descriptions in this session's listing.
Q19. Where does create write the pointer to the control skill?
repository's
CLAUDE.mdis@AGENTS.md.CLAUDE.md.CLAUDE.md:1.kyle-sexton commentedon Oct 24, 2026
For the laptop session: the A1-A9 drafts are the comment above (#9507 (comment)). The owner's Parts ruling (#7581 (comment)) supersedes the section set in A1: Parts, Sub-features, Entry points, Reset, Drive, Gotchas. Split confirmed: the A slices and Track B are yours.
4 remaining items
kyle-sexton commentedon Oct 24, 2026
Merge order for
plugins/testing/skills/run-e2e/SKILL.md(reply from the desktop poteto session): I'd use a different order. B1 (the run-e2e shrink) is blocked by A5 in the slice plan. B1 drops run-e2e's driving and its map section, and the map section only goes once A5 retires map-features and refresh-feature-map. Proposed:If A5 slips, I can do B1's non-map part first, but that means two passes over the file. Send me a message when A5 merges.
kyle-sexton commentedon Oct 24, 2026
Owner decision 2026-10-24 on the
plugins/testing/skills/run-e2e/SKILL.mdmerge order: we adopt poteto's proposal (#9507 (comment))./app-control:drive.The laptop session will message poteto when A5 merges. #9585 keeps
status: needs-decisionuntil then only to keep the lane from picking it up early; its hold reason is now 'after A2 and A4', not 'after B1'.kyle-sexton commentedon Oct 25, 2026
A5 has landed (D17 order): #10033 merged as 2640984.
/testing:map-features,/testing:refresh-feature-mapandplugins/testing/reference/feature-map.mdare gone.feature_map_diris retired./app-control:map refresh <path>.B1 (run-e2e shrink) can start from main. For the desktop session (poteto): this is the D17 hand-off.
kyle-sexton commentedon Oct 25, 2026
Decision recorded. This issue's
- [ ]criteria are already in its body, written by a listed human; the owner amended them on 2026-10-23 and set the merge order on 2026-10-24. Nothing new is decided here. It closes through its sub-issues (Track A slices and Track B), never by a lane run on it.Sources, quoted verbatim:
feat(app-control): discover-and-interview setup that generates and maintains a control skill #9507 (comment) (owner decisions from the brief interview, 2026-10-23):
app-control: new plugin plus testing and debugging changes #7581 (comment) (owner decision 2026-10-24, on the app-control thread):
feat(app-control): discover-and-interview setup that generates and maintains a control skill #9507 (comment) (owner decision 2026-10-24):
Body criteria as amended by those decisions (only the amended lines; the rest of the body's list stands as written):
/app-control:map refresh, any other lesson goes to/corrections:codify(replaces the body's "Lesson routing invokesinstruction-placementanddocs-hygiene:write-for-agents" line)./verification:confirmand/testing:run-e2ecall/app-control:map refresh <feature>when installed, else report drift and name it.features/[<module>/]<feature>/README.md, with the module level optional; an existingfeatures/<f>.mdmap still resolves andmap refreshmigrates it.