Bug sweep — Agent Pants (determined product)
State: open/active · Genre: analysis
A top-to-bottom survey of the agent-pants determined application: the web
build under Playwright against the checked-in fixture vaults, the desktop
shell’s static parity checks, the agent-pants CLI verb by verb, a targeted
static read of the frame and verdict code, and the bug-finder pipeline over
ten territories. Fixes land as PRs stacked on this report’s branch, each
citing the AP-NN rows it closes.
Surveyed commit: a1ef1512b (main, 2026-09-12).
How it was run
Section titled “How it was run”Everything below is re-runnable from a clean worktree at the surveyed commit.
git worktree add ../ap-survey origin/maincd ../ap-survey && bun installcargo build -p platform-core --bin platform-serverbun run --cwd solutions/determined/products/agent-pants build # nuxt generate; a stale .output/public silently tests the old buildFixture servers, each a throwaway copy of a fixture vault over the built SPA
with its own state dir (run from solutions/determined/products/agent-pants):
| port | script | vault |
|---|---|---|
| 4895 | bun tests/serve.ts | recommended + install geometry (<root>/vault, <root>/dest) |
| 4896 | bun tests/serve-authoring.ts | empty |
| 4897 | bun tests/serve-walkthrough.ts | recommended, editable |
| 4898 | bun tests/serve-marketplace.ts | freeform, two marketplaces |
| 4900 | bun tests/serve-dialogs.ts | recommended, for rename/move/delete |
Each publishes its run paths to tests/.paths-<port>.
The survey scripts use Playwright’s library API, not the test runner, so a
wedged page yields one evidence record per action instead of one timeout.
Every action captures console (with source location), pageerror,
requestfailed, and every response ≥ 400, then screenshots. An action that
looks dead is re-run on a fresh page: if it works there, the finding belongs
to the earlier action that wedged the page.
CLI: at the surveyed commit, the TypeScript CLI’s now-deleted cli.ts entry
point, run through the package’s bun script for each verb, --config <scratch>/config.yaml against a copy of the recommended fixture, every verb
in every documented mode, exit codes and stream placement checked against the
package README and --help. The CLI has since moved to the native
agent-pants Rust crate — cargo run -q -p agent-pants -- <verb> --config <scratch>/config.yaml is today’s equivalent, and re-running this sweep at
HEAD would use that instead.
Desktop: Playwright cannot drive the Tauri webview and there is no devtools or
log plugin, so the desktop check is static — the invoke() names the
generated TS transport uses against the generated IPC handler list, and the
Tauri API calls the frame makes against the product’s capability files — plus
a browser run of the same routes over a copy of a real vault.
Code level: bug-finder (solutions/ontological/skills/bug-finder) scan
workflow, three altitude lenses per territory then adversarial refuters, over
the agent-pants experience (components, pages/composables, utils), the product
wrapper, the platform-core handlers and vault registry, determined-agent-skills,
agent-adapt-core, the CLI, the app-frame layer, and the determined shell.
Findings
Section titled “Findings”Legend for disposition: fix-now · filed → task · `not-a-bug` · `already-open → `task. Severity: S1 blocker (unusable screen or data
loss) · S2 major (a documented operation cannot complete, no in-app
workaround) · S3 minor (wrong report, or an obvious workaround) · S4 cosmetic
or documentation.
| id | sev | surface | file:line | what breaks | disposition | PR |
|---|---|---|---|---|---|---|
| AP-09 | S1 | static | solutions/determined/experiences/agent-pants/app/utils/metadata.ts:25 | parseMetadata silently drops a __proto__ key | fix-now | #2057 |
| AP-106 | S1 | web | solutions/determined/crates/determined-agent-skills/src/lib.rs:3528-3595 | Plugin delete lands in .trash/…/review 1/ (directory suffixed, entry note not), so the trashed bundle no longer matches the | fix-now | #2052 |
| AP-107 | S1 | web | solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/plugins/[...path].vue:401-433 | Undo of a plugin delete answers HTTP 500 (no bundle entry note at …/review 1/review 1.md); nothing is restored and the page has already navigated away | fix-now | #2052 |
| AP-108 | S1 | web | solutions/determined/crates/determined-notes/src/content.rs:251-263 (free_path disambiguation) | ROOT CAUSE for a4-015/a4-016: trash-name disambiguation on a bundle delete breaks the | fix-now | #2052 |
| AP-12 | S1 | static | solutions/determined/crates/platform-core/src/vault_workspace.rs:400 | relocate() can create two roster entries for the same path | fix-now | #2052 |
| AP-13 | S1 | static | solutions/determined/crates/platform-core/src/vault_workspace.rs:205 | write_anchor_id demotes existing frontmatter to body text when the anchor note’s fence isn’t at byte 0 | fix-now | #2052 |
| AP-14 | S1 | static | solutions/determined/crates/determined-agent-skills/src/git_source.rs:316 | Slice range panic parsing a bare .../tree GitHub URL with no ref | fix-now | #2052 |
| AP-17 | S1 | static | solutions/determined/crates/determined-agent-skills/src/git_source.rs:244 | is_local_path panics on a non-ASCII byte at index 1-2 of the source string | fix-now | #2052 |
| AP-71 | S1 | static | solutions/agent-pants/crates/agent-adapt-core/src/export.rs:923 | Command peer-resource refusal runs before compile discovers link/embed resources, so a linked file is silently dropped instead of refused | fix-now | #2054 |
| AP-75 | S1 | static | packages/rust/agent-adapt/src/compose.rs:41 | render_pack and render_pack_no_mcp_no_hooks never render PackBundle::roles | fix-now | #2054 |
| AP-76 | S1 | static | solutions/agent-pants/packages/agent-pants/src/git-source.ts:205 | Git checkout cache key collides across distinct repository URLs | fix-now | #2048 |
| AP-96 | S1 | cli | packages/agent-pants/src/core.generated.ts:389 (EntityKind missing hook — same root cause as c1-001) | CLI-vs-native cross-check: publishing/status-ing a hook note BY PATH silently misclassifies it as a skill and WRITES a wrong SKILL.md (native correctly refuses it as a hook, exit-equivalent no-renderer, at every target) | fix-now | #2048 |
| AP-01 | S2 | static | solutions/determined/experiences/agent-pants/app/components/ApConfirmationsSettings.vue:14 | Confirmations settings list omits plugin/marketplace rename and delete keys | fix-now | #2055 |
| AP-02 | S2 | static | solutions/determined/experiences/agent-pants/app/components/ApInstallModal.vue:275 | check() stamps checkedSignature from the post-await signature, not the one it actually checked | fix-now | #2055 |
| AP-03 | S2 | static | solutions/determined/experiences/agent-pants/app/components/ApMoveDialog.vue:83 | Move button re-enables after a failed plugin-preview fetch | fix-now | #2055 |
| AP-04 | S2 | static | solutions/determined/experiences/agent-pants/app/components/ApFieldSections.vue:428 | Hook timeout field silently accepts garbage-suffixed/decimal input via parseInt’s partial parsing | fix-now | #2046 |
| AP-05 | S2 | static | solutions/determined/experiences/agent-pants/app/composables/useAgentPantsLiveUpdates.ts:53 | Visibility-change poll drops the refresh callback, silently consuming changes | fix-now | #2050 |
| AP-06 | S2 | static | solutions/determined/experiences/agent-pants/app/composables/useAgentPantsLiveUpdates.ts:50 | Visibility-triggered repoll drops the registered callback, silently swallowing changes | fix-now | #2050 |
| AP-07 | S2 | static | solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/index.vue:118 | Marketplace identity-note fetch has no stale-response guard, so a fast marketplace switch (or an automatic marketplace-list change) can leave the wrong marketplace’s note in the buffer, and Save then writes it under the visible marketplace | fix-now | #2050 |
| AP-08 | S2 | static | solutions/determined/experiences/agent-pants/app/utils/harnessGap.ts:313 | Gap table treats a refused override as if it were applied | fix-now | #2044 |
| AP-11 | S2 | static | solutions/determined/crates/platform-core/src/vault_workspace.rs:400 | relocate() overwrites a path onto an entry without checking another entry already owns that path | fix-now | #2052 |
| AP-15 | S2 | static | solutions/determined/crates/determined-agent-skills/src/git_source.rs:244 | Windows drive path with forward slashes is misclassified as a git remote source | fix-now | #2052 |
| AP-16 | S2 | static | solutions/determined/crates/determined-agent-skills/src/lib.rs:4298 | convert_kind’s undroppable-key guard is bypassed by whitespace in drop_keys | fix-now | #2052 |
| AP-18 | S2 | static | solutions/determined/crates/determined-agent-skills/src/lib.rs:3058 | rename_collision checks the destination’s folder-derived plugin, not the note’s resolved (ap-plugin-overridden) plugin | fix-now | #2052 |
| AP-19 | S2 | static | packages/ts/app-frame/app/components/ShellContextDock.vue:143 | ShellContextDock guards a panel’s badge() but not its component render | fix-now | #2050 |
| AP-25 | S2 | static | solutions/determined/experiences/agent-pants/app/utils/harnessGap.ts:151 | cellFor’s override-rescue path claims a per-target override delivers a hook event the harness’s own renderer refuses outright, for any target whose whole Hook asset is Rejected | fix-now | #2044 |
| AP-26 | S2 | static | solutions/determined/experiences/agent-pants/app/utils/harnessGap.ts:38 | harnessGap.ts never reads the capability matrix’s asset-level (Skill/Agent/Command/Hook/McpServer/Script) verdict, so a note whose whole kind is Rejected for a destination still shows its individual field rows as ‘honoured’ there | fix-now | #2044 |
| AP-30 | S2 | static | solutions/determined/experiences/agent-pants/app/utils/fieldSpec.ts:87-104 | Neither the hook form’s field model nor create_note/write_note enforce the fields agent-adapt-core’s own hook renderer requires (event, and the payload key the chosen type licenses), so a Hook note can be created/saved successfully and only refuse much later at publish/export time | fix-now | #2046 |
| AP-38 | S2 | static | solutions/agent-pants/docs/vault/tasks/fix-mcp-transport-keys.md:2 | fix-mcp-transport-keys: still live — Gemini HTTP MCP servers still get ‘url’ instead of ‘httpUrl’ | fix-now (vault task closed) | #2057 |
| AP-66 | S2 | web | solutions/determined/experiences/agent-pants/app/components/ApNewComponentWizard.vue:177 | No entry point into “create a component” ever offers hook, across all 4 launchers exercised (missing-feature) | fix-now | #2046 |
| AP-67 | S2 | web | solutions/determined/experiences/agent-pants/app/components/ApNewComponentWizard.vue:130 | No in-app flow authors a plain note — every creation entry point produces a kind-typed component, never an untyped reference note (missing-feature) | docs hint shipped; flow filed (see Missing features) | #2045 |
| AP-69 | S2 | static | solutions/agent-pants/crates/agent-adapt-core/src/publish.rs:1235 | Acknowledged overwrite of a foreign file is reported with the ‘already byte-identical’ Claimed reason | fix-now | #2054 |
| AP-70 | S2 | static | solutions/agent-pants/crates/agent-adapt-core/src/adopt.rs:1535 | Adoption’s link rewrite doesn’t invert compile’s percent-encoding, corrupting wikilink targets | fix-now | #2054 |
| AP-72 | S2 | static | solutions/agent-pants/crates/agent-adapt-core/src/export.rs:461 | diff_root only sees skill groups; commands/hooks-only plugins misreported as stale | fix-now | #2054 |
| AP-73 | S2 | static | packages/rust/agent-adapt/src/render/command_md.rs:65 | render_command_md never applies Command::overrides | fix-now | #2054 |
| AP-77 | S2 | static | solutions/agent-pants/packages/agent-pants/src/commands/adopt.ts:137 | A failed —from-git fetch aborts the whole adopt run instead of just that source | fix-now | #2048 |
| AP-78 | S2 | static | packages/ts/app-frame/app/composables/useSettingsSection.ts:115 | save()‘s finally clobbers a newer save’s saving flag after a namespace switch | fix-now | #2050 |
| AP-79 | S2 | static | packages/ts/app-frame/app/composables/useSettingsSection.ts:140 | Stale save’s finally clears saving for a different, still-in-flight save | fix-now | #2050 |
| AP-81 | S2 | static | solutions/determined/packages/shell/app/composables/useVaultRegistry.ts:241 | remove()‘s rollback snapshot clobbers concurrent add()/remove() mutations to vaults.value | fix-now | #2056 |
| AP-82 | S2 | static | solutions/determined/packages/shell/app/composables/useVaultRegistry.ts:178 | add()/rename()/remove() mutate the registry without taking a read ticket, so a slower in-flight fetch() clobbers them | fix-now | #2056 |
| AP-83 | S2 | static | solutions/determined/packages/shell/app/composables/useModelAcquisition.ts:30 | Model job never syncs/progresses in a desktop Settings window because vaultId can never resolve there | fix-now | #2056 |
| AP-84 | S2 | static | solutions/determined/packages/shell/app/composables/useVaultRegistry.ts:221 | rename()‘s rollback can clobber a later, successful rename to the same vault | fix-now | #2056 |
| AP-85 | S2 | static | solutions/determined/packages/shell/app/composables/useVaultRegistry.ts:256 | recheck()/recheckAll() write through stale object references, clobbered by a concurrent fetch()/adopt() | fix-now | #2056 |
| AP-87 | S2 | cli | packages/agent-pants/src/core.generated.ts:389 | build/check hard-fail (exit 2, nothing written) on the vault fixture’s own recommended shape, because the stale wasm can’t discover a hooks/ note | fix-now | #2048 |
| AP-88 | S2 | cli | crates/agent-adapt-core/src/export.rs:352-393 (not_carried filter is kind-only, ignores plugin_format_carries_commands per root) | A command excluded from one root’s pack format (codex has no commands concept) is silently dropped from the build/check report and tally, on both surfaces | refused, needs core change (see PR) | #2048 |
| AP-89 | S2 | cli | packages/agent-pants/src/commands/status.ts:83-88 (notePaths built from the full scan.components with no EntityKind filter, unlike publish's roster) | status —check can never pass on a vault holding a marketplace note: the note is permanently ‘unknown · no-renderer’ at every destination, forever | fix-now | #2048 |
| AP-91 | S2 | cli | packages/agent-pants/src/commands/publish.ts:123-131 (destination filter is a raw string ===, no canonicalization) | publish —target claude does not match a destination configured as target: claude-code, contradicting the documented alias fold (same for codex/codex-cli) | fix-now | #2048 |
| AP-97 | S2 | cli | packages/agent-pants/wasm/agent_adapt_wasm_bg.wasm (stale, raw-copies hooks/ as an ordinary peer file) | CLI-vs-native cross-check: publishing an ap-kind: plugin PACK handles its hook member completely differently — CLI raw-copies the hook note verbatim into hooks/ | fix-now (wasm rebuilt; verify at closure) | #2048 |
| AP-99 | S2 | desktop | solutions/determined/products/agent-pants/src-tauri/capabilities/default.json:4 | dialog:default is granted only to window label ‘main’; native directory picker is denied in every focus-* and surface-* window | fix-now | #2056 |
| AP-100 | S3 | desktop | solutions/determined/products/agent-pants/src-tauri/capabilities/default.json:4 | notification:default granted only to ‘main’; OS notifications rejected in focus-/surface- windows (in-app toast still shows) | fix-now | #2056 |
| AP-101 | S3 | desktop | solutions/determined/products/agent-pants/src-tauri/capabilities/default.json:4 | deep-link:default granted only to ‘main’, but deep-link.client.ts runs in every window and calls getCurrent() unconditionally | fix-now | #2056 |
| AP-102 | S3 | web | solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/notes/[...path].vue | Deep-linking directly to a note URL renders the note but creates NO document tab — the tab strip is empty even though a document is open and being read/edited (ux) | fix-now | #2055 |
| AP-104 | S3 | web | packages/ts/app-frame/app/composables/useContextPath.ts | The breadcrumb (context path) is IDENTICAL on Home, a skill note, and a plugin page — it never reflects the vault path of the document/plugin currently open, so it carries no navigational information beyond “Agent Pants app, 1 vault scoped, Agent Manager experience” (ux) | fix-now | #2055 |
| AP-105 | S3 | web | “ | Confirmed A0 finding: the Vaults modal intercepts clicks on background chrome (rail/settings link) — the click neither dismisses the modal nor reaches the background control, matching the documented “wedges behind modals” behavior (ux) | refused: modal is dismissible (scrim, Close, Escape); timeouts were a Playwright actionability artifact | #2056 |
| AP-109 | S3 | static | solutions/determined/products/agent-pants/tests/e2e/authoring.e2e.ts:328 | authoring e2e project fails on main: the plugin-row plus-menu seed opens the wizard on step 2 (Where) while the test expects step 1 (What is it?) with skill preselected; 9 later tests never run | fix-now | #2055 |
| AP-111 | S3 | web | solutions/determined/experiences/agent-pants/app/components/ApFieldSections.vue:842 | The Matcher row says nothing per destination, while the Event row names who drops or translates the event (ux) | fix-now | #2075 |
| AP-112 | S3 | web | solutions/determined/experiences/agent-pants/app/components/ApComponentTree.vue:586 | Hook rows in the navigation tree show only the file name; the event that fires the hook and the command it runs are not visible without opening the note (ux) | fix-now | #2076 |
| AP-113 | S3 | static | packages/rust/agent-adapt/src/runtimes/opencode.rs:187 | OpenCode and Amp carry a hook renderer, so their hook asset claim is native and the form says they receive a matcher, while render_hooks_json refuses every event for them | filed → render-hooks-as-opencode-and-amp-plugins | #2058 |
| AP-20 | S3 | static | “ | Zero error-boundary primitives anywhere in app-frame, shell, or experiences (missing-feature) | fix-now | #2050 |
| AP-24 | S3 | static | solutions/determined/experiences/agent-pants/app/utils/harnessGap.ts:35 | harnessGap.ts’s ‘dropped’ copy (‘Nothing fails’) is false for the Rejected half of the collapsed verdict (ux) | fix-now | #2044 |
| AP-27 | S3 | static | solutions/determined/experiences/agent-pants/app/utils/publishVerdict.ts:114-121 | publishVerdict.ts collapses multiple distinct per-file refusal reasons for one target into the single generic word ‘refused’ (ux) | fix-now | #2044 |
| AP-28 | S3 | static | solutions/agent-pants/crates/agent-adapt-core/src/export.rs:219-231 | core.generated.ts’s ExportUnit ‘plugin’ variant is missing the version_bump_suggestion field (and the VersionBumpSuggestion type entirely) that export.rs’s ExportUnit::Plugin already carries on this tree | fix-now | #2048 |
| AP-31 | S3 | static | solutions/determined/experiences/agent-pants/docs/getting-started.md:9 | getting-started.md still says ‘no delete and no rename’ though both ship (doc-drift) | fix-now | #2045 |
| AP-32 | S3 | static | solutions/determined/experiences/agent-pants/docs/getting-started.md:91 | getting-started.md ‘What is not here yet’ repeats the same stale no-delete/no-rename/no-watching claim (doc-drift) | fix-now | #2045 |
| AP-39 | S3 | static | solutions/agent-pants/docs/vault/tasks/ci-covers-determined-agent-pants.md:2 | ci-covers-determined-agent-pants: partially fixed — Playwright now runs, but only on manual dispatch, never gating a PR (missing-feature) | filed (CI gating decision) | |
| AP-42 | S3 | web | “ | Missing note/plugin on an empty vault answers HTTP 500, not 404 (/apps/agent-pants/notes/marketplaces/acme/plugins/review/skills/code-review.md) | fix-now (page); backend NotFound→500 reopened at closure, filed T-GIB9 | #2055 |
| AP-43 | S3 | web | “ | Missing note/plugin on an empty vault answers HTTP 500, not 404 (/apps/agent-pants/plugins/acme/review) | fix-now (page); backend NotFound→500 reopened at closure, filed T-GIB9 | #2055 |
| AP-44 | S3 | web | solutions/determined/experiences/agent-pants/app/utils/pluginRoute.ts:12 | Note route needs the .md suffix; without it the app fires an API call that answers HTTP 500 for a not-found note | fix-now (page); backend maps NotFound to 500, filed | #2055 |
| AP-45 | S3 | web | “ | Pane-collapse state survives a full page reload, so every control inside a collapsed pane looks permanently dead — 28 of 74 Home controls went dead in Pass A despite a reload before each click (ux) | fix-now | #2050 |
| AP-46 | S3 | web | “ | Same reload-surviving collapse on the skill page: 42 of 77 controls dead in Pass A, including the whole Publish rail (Dry run / Install… / Related) (ux) | duplicate of AP-45 | #2050 |
| AP-47 | S3 | web | “ | Cumulative pass (no reloads) wedges on the very first control: the “vault” scope switcher opens a modal and every later click is intercepted (ux) | refused: modal is dismissible (scrim, Close, Escape); timeouts were a Playwright actionability artifact | #2056 |
| AP-48 | S3 | web | “ | Skill page cumulative pass wedges identically on control 0 (“vault”) (ux) | duplicate of AP-47 (refused) | #2056 |
| AP-49 | S3 | web | “ | A note page that failed to load still offers an enabled, primary-styled Save button next to the error (ux) | refused: Save is disabled on load failure; the dimmed solid button reads as enabled | #2057 |
| AP-50 | S3 | web | solutions/determined/experiences/agent-pants/app/utils/pluginRoute.ts:12 | A0 verdict: boot is clean on both fixtures; the cumulative pass wedges on the first modal-opening control, and the isolated pass wedges on reload-surviving pane collapse (ux) | verdict record; see AP-45 and AP-47 | |
| AP-52 | S3 | web | packages/ts/app-frame/app/components/ShellLayoutControl.vue:87 | A collapsed pane has NO in-pane visible affordance to re-expand; recovery requires knowing the ◫ Layout menu in the titlebar (not discoverable without prior knowledge) or the mod+1 keybinding (ux) | fix-now | #2050 |
| AP-53 | S3 | web | packages/ts/app-frame/app/composables/usePaneCommands.ts:55 | No keybinding toggles the “scope” pane — mod+1/2/3 cover only secondary/main/aux; scope pane is reachable only via the titlebar Layout menu (ux) | fix-now | #2050 |
| AP-54 | S3 | web | packages/ts/app-frame/app/layouts/default.vue:164 | The frame’s tabbed context dock (ShellContextDock, data-shell-dock-*) never renders in agent-pants — every page (Home, skill note, plugin) registers its own | filed (dock ownership, see Missing features) | |
| AP-56 | S3 | web | solutions/determined/experiences/agent-pants/app/components/ApComponentTree.vue:131 | Opening a note via the sidebar SEARCH result navigates correctly but creates NO document tab, while opening the same note via a plain tree-row click DOES — two paths to the same note disagree on tab bookkeeping | fix-now | #2055 |
| AP-61 | S3 | web | solutions/determined/experiences/agent-pants/app/components/ApNewComponentWizard.vue:730 | Skill Review step composed source compared byte-for-byte against the file on disk | refused: page sends identical bytes; divergence is in determined-agent-skills | #2055 |
| AP-62 | S3 | web | solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/plugins/[...path].vue:249 | ”Add skill” split-button dropdown half offers Command/Agent, each seeding the wizard the same way | refused: recorded actual matches expected; probe missed portalled menu | #2055 |
| AP-63 | S3 | web | solutions/determined/experiences/agent-pants/app/components/ApComponentTree.vue:635 | Header ‘New’ plus-menu offers exactly New skill/New command/New agent (never hook, never plugin/marketplace, never a plain note); picking New skill seeds kind+marketplace but NOT plugin | refused: recorded actual matches expected; probe missed portalled menu | #2055 |
| AP-64 | S3 | web | solutions/determined/experiences/agent-pants/app/components/ApComponentTree.vue:652 | A plugin row’s own hover-revealed plus button offers the same 3 kinds and additionally seeds plugin=review | refused: recorded actual matches expected; probe missed portalled menu | #2055 |
| AP-68 | S3 | web | solutions/determined/experiences/agent-pants/app/composables/useAgentSkillAdopt.ts:25 | Import preview ignores “Group under plugin” and always reports paths under the default “adopted” group; the actual Import correctly honours the typed plugin | fix-now (page label); preview plugin param is a wire change, filed | #2055 |
| AP-74 | S3 | static | packages/rust/agent-adapt/src/tools.rs:97 | translate_body_tool_refs corrupts prose via non-word-boundary substring replace | fix-now | #2054 |
| AP-80 | S3 | static | packages/ts/app-frame/app/components/ShellConfigNoteForm.vue:51 | jsonDrafts never cleared, so a ‘json’-kind field permanently ignores modelValue after one edit | fix-now | #2050 |
| AP-86 | S3 | cli | packages/agent-pants/src/core.generated.ts:389 (EntityKind union missing "hook") | list treats a hooks/ note as an unreadable stray; wasm/core.generated.ts predate the ‘hook is a vault entity’ feature | fix-now | #2048 |
| AP-90 | S3 | cli | packages/agent-pants/src/core.generated.ts:389 (EntityKind missing hook) | publish —all always exits 1 on the recommended vault: the hook note gets a spurious top-level ‘refused · unreadable-note’ line even though it publishes correctly as part of its plugin’s pack | fix-now | #2048 |
| AP-93 | S3 | cli | crates/agent-adapt-core/src/publish.rs (pack/plugin compile path: member-level validation refusals collapsed into a generic unreadable-note/io reason rather than surfacing the member's own refusal token) | A pack refused because one member fails ap-targets validation is mislabeled ‘io: unreadable-note … this scan could not read’, though the member is fully readable | refused, needs core change (see PR) | #2048 |
| AP-98 | S3 | cli | solutions/determined/products/agent-pants/tests/serve-harness.ts:78-96 (pinVaultIdentity, documents exactly this write-on-first-registration behavior) | Booting platform-server over a vault writes a _system/vault.md identity anchor into the vault root on first registration, even for a session that only calls read-only preview/status endpoints (ux) | not-a-bug: the identity anchor is the vault roster by design | |
| AP-10 | S4 | static | solutions/determined/products/agent-pants/tests/e2e/capture.e2e.ts:936 | Duplicate ‘skill-transclusion’ test silently supersedes its own predecessor | fix-now | #2050 |
| AP-103 | S4 | web | packages/ts/app-frame/app/composables/useDocumentTabs.ts | Document tabs do NOT survive a full page reload — unlike pane-collapse state (which is persisted to localStorage), the open-tabs list is purely in-memory and a refresh silently loses it (ux) | filed (tab persistence) | |
| AP-110 | S4 | web | solutions/determined/experiences/agent-pants/app/components/ApFieldSections.vue:869 | Multi-line fields (Command, Prompt, Metadata, body) use a raw UTextarea and draw a primary-blue focus ring beside neutral single-line controls (ux) | fix-now | #2110 |
| AP-21 | S4 | static | solutions/determined/packages/shell/app/composables/useVaultRegistry.ts:285-291 | useVaultRegistry.openers()/fileOpeners() are the only two methods in the file with no internal try/catch | fix-now | #2056 |
| AP-22 | S4 | static | .moon/tasks/ts-lib.yml:31-32 | app-frame DOES have a check/typecheck task now; two comments elsewhere still claim it does not (doc-drift) | fix-now | #2045 |
| AP-23 | S4 | static | solutions/determined/packages/platform/src/generated/transport.ts:328 | Every TAURI_INTERNALS probe is guarded; one @tauri-apps import breaks the repo’s own ‘always dynamic-import Tauri modules’ rule (currently harmless) | refused: transport.ts is generated by rust-ontogen (external repo) | #2057 |
| AP-29 | S4 | static | solutions/agent-pants/docs/vault/tasks/gate-cli-wasm-types-against-core.md:2 | gate-cli-wasm-types-against-core.md’s ‘renders as literal undefined’ claim (about ExportUnit::NotCarried) is no longer live on this tree, but the task is still marked status: open and describes a hand-written core.ts that no longer exists (doc-drift) | fix-now | #2045 |
| AP-33 | S4 | static | solutions/determined/experiences/agent-pants/docs/current-limits.md:82 | current-limits.md still reports the ‘Shell / no experiences installed’ window-title bug, already fixed (doc-drift) | fix-now | #2045 |
| AP-34 | S4 | static | solutions/determined/experiences/agent-pants/docs/current-limits.md:60 | current-limits.md’s ‘Resolving a conflict in the app’ row is stale: the install dialog now has a per-file acknowledge control (doc-drift) | fix-now | #2045 |
| AP-35 | S4 | static | solutions/determined/experiences/agent-pants/docs/publishing.md:177 | publishing.md’s ‘Deciding’ section still tells readers the only way to discard a conflict is the CLI’s —overwrite flag (doc-drift) | fix-now | #2045 |
| AP-36 | S4 | static | solutions/determined/experiences/agent-pants/app/components/ApNewComponentWizard.vue:177 | Hooks cannot be created via the New Component Wizard, and no manual chapter’s ‘Not yet built’ table says so (missing-feature) | fix-now | #2046 |
| AP-37 | S4 | static | solutions/determined/experiences/agent-pants/app/components/ApNewComponentWizard.vue:142 | A plain/reference note has no authoring path in the app; only skill/command/agent/plugin/marketplace can be created (missing-feature) | fix-now | #2045 |
| AP-40 | S4 | static | docs/planning/tasks/T-0AF7-hook-editor-and-harness-gap-table.md:5 | T-0AF7 (hook editor + harness gap table) is status planning/proposed but ApHookFieldsForm.vue and ApHarnessGapTable.vue are shipped and wired (doc-drift) | not-fixed: sdlc has no status-transition verb; needs the op owner | |
| AP-41 | S4 | static | docs/planning/tasks/T-H56N-hooks-as-vault-entities.md:5 | T-H56N (hooks as vault entities) is status planning/proposed but the hook kind, its frontmatter, and its build output are all fully implemented (doc-drift) | not-fixed: sdlc has no status-transition verb; needs the op owner | |
| AP-51 | S4 | web | packages/ts/app-frame/app/composables/usePanePersistence.ts | Confirmed: collapsed secondary pane state survives page.reload() (persisted, no in-app “restore layout” affordance beyond the ◫ Layout menu) (ux) | fix-now | #2050 |
| AP-65 | S4 | web | solutions/determined/experiences/agent-pants/app/components/ApNewComponentWizard.vue:80 | ”Skill-notes-only index” comment and the note page’s “completes against the other skill notes” hint both understate what [[ actually offers: commands and agents too (doc-drift) | ||
| AP-92 | S4 | cli | docs/vault/reference/cli-usage.md:531 (stale known-targets list) | cli-usage.md’s known-targets transcript is stale: lists 9 targets, runtime now has 11 (copilot, github-copilot added) (doc-drift) | fix-now | #2048 |
| AP-94 | S4 | cli | packages/agent-pants/src/cli.ts:253-258 (--overwrite option description doesn't mention destination-relative) | —overwrite silently no-ops (still refused · conflict) if given an absolute path instead of a destination-relative one; —help doesn’t say which is required (doc-drift) | fix-now | #2048 |
| AP-95 | S4 | cli | packages/agent-pants/README.md:116-121 (marketplace-config table doesn't mention the single-marketplace fallback) | README’s marketplace-config table claims an absent name/—marketplace is always a usage error; in fact it falls back cleanly to the vault’s sole marketplace note when there is exactly one (doc-drift) | fix-now | #2048 |
Refuted and not-a-bug
Section titled “Refuted and not-a-bug”AP-88— refused. The core’snot_carriedcomputation is kind-only and runs once for the whole build;ExportUnit::NotCarriedcarries norootfield, so neither the CLI nor the native app can report a per-root exclusion the report type does not carry. Filed assolutions/agent-pants/docs/vault/tasks/report-not-carried-per-root.md.AP-93— refused. The mislabel is the core’s own:publish.rsraisesunreadable-notefor a pack member that actually failsap-targetsvalidation, discarding the member’s real refusal token;unreadable-noteis also not in the wireReasonTokenclosed set, so the CLI adds anio:prefix on top of the mislabel. Filed assolutions/agent-pants/docs/vault/tasks/skipped-note-keeps-its-real-reason.md.
Missing features, sized
Section titled “Missing features, sized”- Hook creation (AP-36, AP-66) — the survey’s headline complaint. The
New Component wizard filtered
hookout of the kind list even though the vault, the build, and the skill page already supported it. Shipped in #2046. - Plain reference-note authoring (AP-37, AP-67) — still missing. No entry point in the app creates an untyped note; every wizard path produces a kind-typed component. #2045 added a docs hint on how a reference note comes to exist, but the authoring flow itself is open. Filed as T-FSMC-author-a-plain-reference-note-in-app.
- Two pre-existing tracked tasks understated what shipped —
T-H56N(hooks are vault entities) andT-0AF7(hook editor + harness gap table) stayedstatus: planning/proposedafter their features shipped. AP-40 and AP-41 flagged the drift; neither could be closed here because sdlc exposes no status-transition verb outsidetask update’s generic field patcher. - The context dock never renders in agent-pants (AP-54), and no
product feeds its
panelcapability at all — an ownership decision, not a mechanical fix. Filed as T-MMZK-context-dock-never-renders-in-agent-pants. - Document tabs don’t survive a reload (AP-103), unlike pane-collapse state. Filed as T-G564-document-tabs-do-not-survive-reload.
- Import preview ignores the typed plugin group (AP-68). Filed as T-QK1S-adopt-preview-honours-group-under-plugin.
- A missing note or plugin answers 500, not 404 (AP-42, AP-43, AP-44, backend half) — the generated HTTP transport’s own doing, upstream of this repo. Filed as T-GIB9-not-found-status-in-generated-http.
- A single-note trash restore keeps its collision-suffixed name — pre-existing, left open when the bundle-delete data-loss bug was fixed. Filed as T-PKMM-single-note-restore-keeps-suffixed-trash-name.
- Desktop console capture needs a human pass — Playwright cannot drive the Tauri webview, and the survey’s own boot attempts were blocked. Filed as T-9VUY-desktop-console-capture-needs-a-human-pass.
- Desktop capabilities limited to the main window, beyond agent-pants —
21 other determined products still grant
dialog:default,notification:default, anddeep-link:defaultonmainonly, the same gap AP-99/AP-100/AP-101 found in agent-pants. Filed as T-727P-desktop-capabilities-limited-to-main-window-across-products. - Agent-pants e2e is manual-dispatch only, never gates a pull request (AP-39) — the tracked vault task is only partially done. Filed as T-B2VW-agent-pants-e2e-gates-pull-requests.
What the user saw
Section titled “What the user saw”The desktop “dead buttons” and console-error symptoms reported going into this survey did not reproduce in web mode: two full-page control sweeps (74 Home controls, 77 skill-page controls — 151 total) produced zero console errors, page errors, failed requests, or HTTP ≥ 400 responses (A0).
The actual symptom is persisted pane collapse with no way back. A page
reload keeps a collapsed pane collapsed (by design, via localStorage),
but nothing inside the collapsed pane offers to re-expand it — 28 of 74
Home controls and 42 of 77 skill-page controls looked permanently dead for
exactly this reason, not because anything was broken. Fixed in
#2050: every collapsed pane
now draws its own labelled expand button.
Desktop-only console errors remain open. Playwright cannot drive the Tauri webview, so no desktop console was ever actually watched — the survey’s two attempts to boot the desktop binary were blocked by the assignment’s own rules and by the automation session’s permission classifier, not by the app itself. See T-9VUY-desktop-console-capture-needs-a-human-pass.
Closure
Section titled “Closure”Re-run on 2026-09-12 against an integration tree: the report branch plus
every fix branch merged (chore/agent-pants-closure-integration, no
conflicts), with platform-server and the SPA rebuilt from it. Each
fix-now row was re-run by its own repro: the web rows by Playwright
scripts over the fixture servers, the CLI rows against a fresh copy of the
recommended fixture, the code-level rows by the regression test named in
the PR that closed them, the desktop capability rows by the shell’s
capability unit test. The machine record is
findings.jsonl (closure fields) and the per-row evidence
is listed there.
| status | rows |
|---|---|
| closed | 80 |
| reopened | 3 (one of them fixed and re-run in the same pass) |
| not re-runnable | 0 |
Boot and click sweep on the integrated build (recommended and empty fixtures, eleven routes): zero page errors, zero failed requests, and zero console errors on every route except the two below. Every collapsed pane draws its own enabled expand control, and it restores the pane on click.
Reopened:
AP-42,AP-43— the page half is fixed (a missing note renders its not-found state and a malformed route fires no request), but the API still answers 500 for a note that does not exist, so one console error remains on each route. The mapping lives in ontogen-generated code and is tracked by T-GIB9-not-found-status-in-generated-http. The same 500 shows once more after a plugin delete, when the page navigates to the note that was just trashed.AP-102— a cold deep link to a note rendered it without opening a document tab, because the route-driven tab open waited on the note detail alone and the vault workspace resolved later. Fixed in #2055 after the first re-run, then re-run against the integrated tree: the tab opens on the cold link and survives a reload, with no console errors. Counted as closed.AP-36— not the original defect: two fix branches were each correct and contradicted each other. The docs row saying the wizard cannot create a hook was dropped on the report branch once the wizard could.
Everything else in the table with a fix-now disposition no longer
reproduces. Rows marked refused, filed, duplicate or not-a-bug were not
re-run; their status is the disposition column.
After closure
Section titled “After closure”The user’s review of the fix PRs added four rows, outside the closure
re-run: AP-110 (multi-line fields drew a primary-blue focus ring;
#2073 added a DTextarea wrapper
and was closed unmerged, and the fix is neutral defaultVariants for every
form control in the ui package’s app config,
#2110),
AP-111 (the Matcher row now says which destinations honour, translate or
refuse the matcher, #2075),
AP-112 (hook rows in the navigation tree show the event and the command,
carried by a new hook summary on the listing row,
#2076), and AP-113 (OpenCode and
Amp claim the hook asset as native while every event is refused for them;
filed with the research on generating plugin modules for both,
render-hooks-as-opencode-and-amp-plugins). The same round removed a
duplicate expand chevron the AP-45 fix had introduced on the scope rail.