mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-24 11:26:34 +00:00
c4d429d14c94de941ac761333cdac0a33895a05f
5 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a963e68395 |
docs(skills): de-assume the slash-command surface + route onboard shortcut through the canonical playbook (BUG-2573/2574/2575) (#1139)
* docs(skills): de-assume the slash-command surface + route onboard shortcut through the canonical playbook (BUG-2573, BUG-2574, BUG-2575)
Three coherent drift fixes across the two skill trees:
BUG-2573 — skills/pad/SKILL.md is the embed source `pad agent install`
writes for Claude Code, Codex, Cursor, Windsurf, OpenCode, Amazon Q,
Junie AND pure-MCP agents, but three sentences presented the Claude Code
slash command as THE invocation ("There is one command: /pad <anything>",
"On every /pad invocation", "the first token after /pad"). Reframed per
the PLAN-1847 house pattern: natural language is canonical, typed forms
are per-surface shortcuts, and a read-/pad-as-shorthand rule covers the
rest of the document. Verified through the installed artifact, not just
the diff: built the binary and ran `pad agent install codex` — the
reframed text reaches the non-Claude skill verbatim.
BUG-2574 — plugin/skills/onboard/SKILL.md (the most direct onboarding
route a plugin user has) inlined its own post-link setup script, silently
opting that surface out of the workspace-owned, user-editable onboard
playbook — a customized playbook never fired via the shortcut, and the
inline copy covered roughly the build mode only. The post-link half now
loads and follows the playbook (with exact-title library activation —
`pad library activate "Onboard a workspace"`, verified against the CLI's
actual arg form) and routes needs_onboarding=false to the playbook's
revisit mode. The pre-link whoami-gated half stays as BUG-2541 left it.
Checked the other dedicated plugin skills for the same class: status and
capture inline nothing playbook-owned — no change needed.
BUG-2575 — plugin/skills/pad/SKILL.md didn't know specs are decomposable:
added the "break SPEC-1 into tasks" routing entry and the plan-or-spec
wording in the decompose workflow, matching decomposePlaybookBody and the
embed source. Also synced the one other surface-agnostic drift found in
the sweep: the convention_index note that a list without --full has no
content field.
Claude-Session: https://claude.ai/code/session_017jD6t1zjxGSq47SQpZfp1V
* docs(skills): fix onboard-skill mode enum, needs_onboarding semantics, and reactivation path per Codex review (round 1)
Three corrections to the rewritten post-link half, all verified against
playbook_library_onboard.go: the mode enum is auto/build/audit/revisit
(auto default) with `defaults` a separate fast-path flag — the "four
modes incl. defaults" framing came from the tracking bug's own body and
was wrong; needs_onboarding:false only means a user-created item exists,
not that onboarding ever ran, so the skill no longer declares setup
complete on it; and a draft/deprecated onboard playbook must be
reactivated in place, since invocation_slug is workspace-unique and
library activation beside an existing entry duplicates or fails.
Claude-Session: https://claude.ai/code/session_017jD6t1zjxGSq47SQpZfp1V
* docs(skills): activation before load + honest auto-mode routing per Codex review (round 2)
The post-link half now runs as an ordered three-step: ensure-active
(reactivate in place, library only when absent), THEN load the body,
then mode framing — a literal reader of the previous text ran
`pad playbook show onboard` before the existence check, failing on
missing playbooks and loading stale drafts. And the mode note no longer
claims auto picks "a fuller pass": verified against the playbook's
pre-flight, auto routes ANY user-created item to revisit, so the skill
now says to pass an explicit mode=build/audit override (which the
playbook honors) when the user says the workspace was never really set
up.
Claude-Session: https://claude.ai/code/session_017jD6t1zjxGSq47SQpZfp1V
* docs(skills,mcp): propagate activation ordering + auto-mode routing to the sibling onboarding routes per Codex review (round 3)
The round-2 corrections lived only in the focused onboard skill; the
embed skill's Onboarding entry, the plugin pad skill's, and the
pad_onboard MCP prompt still said load-then-activate with a bare
library-activate fallback, and none warned that the playbook's auto mode
routes any workspace with user-created items to revisit. All three now
carry the same semantics: ensure-active first (reactivate a
draft/deprecated entry in place — invocation_slug is workspace-unique,
so library activation beside an existing entry duplicates or fails),
then load, plus the explicit mode=build/audit override note.
Claude-Session: https://claude.ai/code/session_017jD6t1zjxGSq47SQpZfp1V
|
||
|
|
2580c2c8bb |
fix(cli): gate pad init's Step-4 login on canPromptForConfig() (BUG-2592) (#1115)
* fix(cli): gate pad init's Step-4 login on canPromptForConfig() (BUG-2592) A configured-but-unauthenticated non-interactive `pad init` fell into doBrowserLogin and blocked on the poll wait (wall-clock-bounded since BUG-2572, still minutes of hang nobody can complete) instead of failing fast — Step 3 has had this exact gate since init.go:205, and cmd_workspace.go got it in PR #1111 (BUG-2538). The gate sits AFTER the saved-credentials check so a headless run with valid stored credentials proceeds untouched. Remedy text per the corrected trail ruling (the r1 constraint was refuted by r2): piped `pad auth login --interactive` IS a working non-interactive login (doInteractiveLogin reads a plain bufio.Reader, piped-bytes-safe since BUG-1886), so the message points there — and deliberately not at pad init's --email/--name/--password, which only fire when SetupRequired. Claude-Session: https://claude.ai/code/session_018qREYgDd6Ag1X1SDmqhyFM * docs(plugin): pad init no longer hangs in the session-expired case — update the three claims + plugin 0.2.1 The BUG-2592 gate makes three plugin-skill passages stale (same shape as PR #1111's codex r3 self-invalidation): capture and onboard said `pad init` can still hang on the browser flow when configured-but- unauthenticated, and the pad skill's whoami-guidance said the same at its "not a safer probe" sentence. All three now state the fixed truth, live-verified this session: fixed binary fails fast in 0.1s with the piped-login remedy; pre-fix control binary hangs to the timeout kill in the identical sandbox state; the remedy itself (piped `pad auth login --interactive`) logs in and restores credentials. Plugin 0.2.1 — text reaches nobody without a bump (version-pinned at install). Claude-Session: https://claude.ai/code/session_018qREYgDd6Ag1X1SDmqhyFM |
||
|
|
ac05d8a2b1 |
fix(cli): fail fast and quiet on non-interactive workspace init (BUG-2538, BUG-2577) (#1111)
* Fail fast and quiet on non-interactive `pad workspace init` BUG-2538: initCmd drove runBrowserSetup/doBrowserLogin unconditionally when the instance needed first-run setup or login, blocking a non-interactive caller (script, CI, headless agent) on a browser handoff nobody can complete. Gate both branches on canPromptForConfig(), mirroring the precedent already used by `pad init` (init.go:205-206), and fail fast with a hint pointing at `pad init --email/--name/--password` or `pad auth setup`/`pad auth login`. BUG-2577: offerSkillInstall (shared by workspace init and workspace link) printed a "(Y/n): " prompt even when the answer would be auto-defaulted rather than read, because it gated on cli.IsTerminal() (stdin only). Switch to canPromptForConfig() (stdin AND stdout), which is the same predicate now used for BUG-2538 and the more robust of the two checks already in the codebase. Claude-Session: https://claude.ai/code/session_01BhQoeaWXxJbvw86ezzK8dt * Fix wrong remedy in BUG-2538's !Authenticated error message codex r1: the !Authenticated branch suggested `pad init --email/--name/--password`, but those headless flags only bootstrap the first admin account and only fire when SetupRequired — for an already-set-up-but-unauthenticated instance, `pad init` falls through to its own ungated Step 4 re-auth (BUG-2592), so the suggestion relocated the hang instead of avoiding it. Drop the pad-init suggestion in this branch only; point at `pad auth login` and note there's no non-interactive login path yet. SetupRequired branch is unchanged — its pad-init suggestion is correct for that state. Claude-Session: https://claude.ai/code/session_01BhQoeaWXxJbvw86ezzK8dt * Fix two more inaccurate remedies flagged by codex r2 1. SetupRequired branch: `pad init --email/--name/--password` silently eats the caller's workspace name/--template — pad init creates its own CWD-named workspace as a side effect, so a re-run of the original `pad workspace init <name> --template <t>` short-circuits on the link pad init just made with no signal <name>/<t> were ignored. Switch the remedy to `pad auth setup --email/--name/--password`, which bootstraps the admin account only (no workspace side effects), then re-run the original command. 2. !Authenticated branch: the "no non-interactive login path exists" claim was false — `pad auth login --interactive` reads email/password off a plain, TTY-ungated bufio.Reader (doInteractiveLogin, cmd_auth.go:554+; BUG-1886 made it piped-bytes-safe), so it works fine when credentials are piped in. Reworded to point at it and dropped the incorrect BUG-2592 reference (that bug tracks pad init's ungated Step 4, not a missing login mechanism). TestWorkspaceInitNonTTYSetupRequired's assertion updated from "pad init" to "pad auth setup" to match; TestWorkspaceInitNonTTYNotAuthenticated needed no change (still asserts "pad auth login"). Claude-Session: https://claude.ai/code/session_01BhQoeaWXxJbvw86ezzK8dt * Update skill docs invalidated by the non-interactive fast-fail fix codex r3: BUG-2538/BUG-2577 made this diff's own docs stale. Four files (skills/pad/SKILL.md, plugin/skills/pad/SKILL.md, plugin/skills/onboard/SKILL.md, plugin/skills/capture/SKILL.md) still say non-interactive `pad workspace init` on a configured-but- unauthenticated machine "blocks for minutes with no non-interactive fallback" — that was true pre-fix (per BUG-2541's verification) and is false now. Reworded the WHY without dropping the underlying do-not-run-blind guidance: an agent's tool call is always non-interactive, so it now gets a fast, actionable error instead of a hang, but the error still just says a human needs an interactive terminal — `pad auth whoami` remains the right check to run instead. Where the docs' `pad init` claims are about the still-unfixed session-expired path (BUG-2592, this diff's Step-4 sibling, left untouched), those claims are unchanged and now cite BUG-2592 explicitly. skills/INSTALL.md:24 updated separately (P3): notes the non-interactive silent-install branch of `pad workspace init`'s skill offer, alongside the existing interactive-prompt description. Docs only, no Go changes — go build/test and embed.go's //go:embed skills/pad/SKILL.md still resolve; no test asserts the old wording. Claude-Session: https://claude.ai/code/session_01BhQoeaWXxJbvw86ezzK8dt |
||
|
|
403a6de19d |
docs(skill): structured bootstrap-failure branch + onboarding precondition in the embed source (BUG-2541) (#1100)
* docs(skill): structured bootstrap-failure branch + onboarding precondition in the embed source (BUG-2541) `skills/pad/SKILL.md` — the //go:embed source `pad agent install` writes into user projects — had TASK-2537's minimal safety note but not the structured branch the plugin copy carries. Ports it, minus the Claude-Code-specific shell advice (the embed source also serves Codex, Cursor, Windsurf, OpenCode and pure-MCP agents with no shell at all), so it now names the two stderr signatures as separate cases with opposite handling. Also adds the Onboarding routing entry's missing precondition. It sent the agent to load the onboard playbook, which lives IN a workspace — so on the unlinked path `pad playbook show onboard` fails exactly the way bootstrap just did, and the entry routed into a dead end. Ride-along from the lead's citation sweep: the stale "hangs indefinitely / no timeout" wording still shipped in plugin/skills/onboard/SKILL.md and plugin/skills/pad/SKILL.md (two places). All three now carry the bounded wording. RE-VERIFIED RATHER THAN INHERITED, per this item's own requirement — and the inherited correction needed one too: - Read the code myself. First-admin setup is capped at 20m (bootstrap.go::bootstrapPollTimeout). The auth poll (cmd_auth.go::pollAndSaveCLIAuth) has NO wall-clock limit of its own: it exits only on ctx.Done, `approved`, or `expired`, and `continue`s past transient errors. So the ~5m bound is entirely the server-side session TTL (cli_auth_sessions.go::cliAuthSessionTTL) — if the server becomes unreachable after the session is created, it polls forever. "Bounded, not indefinite" is right for the ordinary case and wrong for that one; the skill text now says both. Filed separately. - Observed it, not just read it. On a configured-but-unauthenticated HOME, `pad workspace init` printed the browser URL and was still waiting when a 25s cap killed it. `pad auth whoami` returned in 0.106s in that state AND in the unconfigured one, with distinguishable output — the "fast, safe" claim the whole branch rests on. - The exact stderr strings were wrong in both copies: the not-configured case has NO `Error:` prefix (`Pad is not configured. Run 'pad auth configure' first.`), only the unlinked one does. Corrected from captured output. Verified through `pad agent install claude` into a scratch project and read back off the installed file, not the diff. Claude-Session: https://claude.ai/code/session_01QCMLhHQBrMHVML3YKdm4Cd * docs(skill): `pad auth whoami` blocks in a TTY when unconfigured — qualify the claim (codex review) Both plugin copies said `pad auth whoami` "never blocks waiting on input". It does, in one state: `whoamiCmd` → `getConfiguredConfig()`, and on an unconfigured machine that enters the interactive configure flow whenever `canPromptForConfig()` is true — i.e. stdin AND stdout are both terminals (configure.go:357). My own measurement (0.106s) was non-interactive, so it could never have caught this; Codex found it by reading the call path. The embed copy already had the right qualification ("in non-interactive use it returns immediately"); this brings the two plugin copies in line and says why the qualification is the operative one for an agent. Codex's other finding — that the embed source's opening still frames `/pad` as THE command, for surfaces with no slash commands — is real but pre-existing and editorial rather than part of this port. Filed as BUG-2573. The auth-poll timeout gap found while re-verifying the hang is BUG-2572. Claude-Session: https://claude.ai/code/session_01QCMLhHQBrMHVML3YKdm4Cd * docs(skill): `pad init` does not fail fast either — correct both plugin copies (codex round 2) Both plugin copies told agents that in the configured-but-unauthenticated state, `pad init` "fails fast" and merely "needs a TTY to complete" — offered as the contrast to `pad workspace init`'s browser-poll block. It is false. `cmd/pad/init.go`'s Step 4 calls `doBrowserLogin` with no TTY guard when the server is already initialized but the client isn't authenticated. Observed: on a configured-but-unauthenticated HOME, non- interactive, `pad init` printed the same browser URL and was still waiting when a 20s cap killed it — identical to `pad workspace init`. That parenthetical was the one thing in the paragraph that could have made an agent run a command instead of handing back, so it was the worst line to have wrong. Both copies now say it is no safer as a probe. Third claim in these three files this task that was wrong because it was reasoned rather than run — the first two being "hangs indefinitely" (bounded, mostly) and "whoami never blocks" (it prompts in a TTY). Codex's other two round-2 findings are real but out of this port's scope and filed: BUG-2574 (the plugin onboard skill inlines its own script instead of loading the canonical onboard playbook) and BUG-2575 (plugin decompose entries omit SPEC targets the embed source and playbook both support). Claude-Session: https://claude.ai/code/session_01QCMLhHQBrMHVML3YKdm4Cd * docs(skill): narrow the `pad init` claim to the state it is actually true in (codex round 3) The previous commit replaced one over-broad claim with the opposite one. "Fails fast" was wrong for the configured-but-unauthenticated case; "no safer as a probe, blocks identically" is wrong for the genuinely-unconfigured one. Both measured, non-TTY, same binary: unconfigured → 0.106s, "Error: Pad is not configured..." configured-but-unauthenticated → browser URL, still waiting at 20s The instruction ("don't run it yourself") was right in both readings, so this is the justification being wrong rather than the advice — which is exactly the failure mode this whole item is about, and I reproduced it while fixing it. Both plugin copies now say which state each behaviour belongs to. Codex's other round-3 finding — that the plugin onboard skill gates its recovery branch on `.pad.toml` being absent, so a STALE link skips it entirely and dead-ends at the same bootstrap failure — is real and is the pre-link half of the same skill's problem. Added to BUG-2574 rather than widened into this port. Claude-Session: https://claude.ai/code/session_01QCMLhHQBrMHVML3YKdm4Cd |
||
|
|
d8627968d0 |
feat(plugin): pad Claude Code plugin — nested layout, monitors, skills (PLAN-2469 Phase 2) (TASK-2534) (#1085)
* feat(plugin): assemble Phase-0 scaffold v3 into a nested plugin layout — PLAN-2469 Phase 2 (TASK-2534)
Drops scaffold v3 (plugin.json, marketplace.json, monitors.json, the pad/
status/capture/onboard skills) in under plugin/, verbatim, rather than at
repo root. Repo root already embeds skills/pad/SKILL.md into the binary
as the surface-agnostic `pad agent install` source (embed.go); loading
the plugin flat at repo root would register BOTH that copy and the
plugin's Claude-Code-only trimmed copy as separate skills in the same
session (confirmed empirically via --plugin-dir) and would ship the
whole repo as the marketplace install payload (confirmed via a real
marketplace add + install + cache inspection). Nesting under plugin/
with marketplace.json's source: "./plugin" scopes both discovery and
the install payload to exactly the plugin's own files, with zero
content changes to the scaffold itself.
The stale minimal .claude-plugin/plugin.json at repo root is removed —
superseded by the real one at plugin/.claude-plugin/plugin.json; repo
root's .claude-plugin/ now holds only marketplace.json, which is what
`/plugin marketplace add PerpetualSoftware/pad` needs to find there.
`claude plugin validate --strict` passes clean on both the repo root
(marketplace) and plugin/ (plugin manifest) independently.
* fix(plugin): round-1 review fixes — invocation reality, degradation ordering, confirm-by-default, license (TASK-2534)
Six findings from codex round 1 + dispatcher's shallow pass:
- pad/SKILL.md's "How This Works" claimed a literal `/pad <anything>`
command, but under plugin namespacing this skill registers as
`pad:pad`, not a bare `/pad`. Rewrote to state the true DR-1 model
(contextual trigger by description, not typed) and defined the
document's own `/pad <anything>` notation as shorthand for "what the
user said," not literal syntax. Fixes the earlier /pad:pad cosmetic
note at its root and the two "onboarding" sections that repeated the
same wrong dual-syntax framing.
- status/SKILL.md and capture/SKILL.md invoked `pad` before stating
their missing-CLI fallback; reordered so the failure modes are
handled as part of the same instruction, not an afterthought.
monitors.json's command had no guard at all — a padless machine
would hit a raw spawn error, not silence. Added a `command -v pad`
shell guard (verified live, both branches: silent when pad is
absent, invokes correctly when present) and re-verified the two
original degradation legs (no .pad.toml, unreachable padd) through
the exact guarded command string, not just the bare binary.
- `pad bootstrap` hard-exits ("no workspace linked...") when unlinked
(cmd/pad/main.go's getWorkspace()), but the skill assumed it always
succeeds and the onboarding NL routing tried to load the onboard
PLAYBOOK before a workspace — and therefore that playbook — could
exist. Added the unlinked-workspace branch to Context Loading and
taught onboarding routing to run `pad workspace init` first in that
case, matching what skills/onboard/SKILL.md already did correctly.
- capture/SKILL.md's "no ceremony" immediate-create contradicted the
main skill's "always confirm before creating/modifying." Made
confirm-first the default, with an explicit opt-out for workspaces
whose conventions declare autonomous capture.
- Two `open "$IMG"` examples were macOS-only; added the Linux
(xdg-open) alternative and a describe-the-path fallback.
- plugin.json declared MIT; the repo is Apache-2.0 (LICENSE,
web/package.json). Corrected.
`claude plugin validate --strict` clean on both the repo root
(marketplace) and plugin/ (plugin manifest) after the fixes.
* fix(plugin): make DR-4's no-write default unmistakable (TASK-2534)
Second independent dogfood run found the etiquette text underdetermined
behavior: one run correctly parked a context nudge, another interpreted
"fold it in" as license to run pad item comments and post a real reply
to the watched item — a write action from a context notification, which
DR-4 never intended and the plugin's noise-discipline promise depends on
never happening. Rewrote the section: read-only one-line park-and-summarize
is now the explicit default for every watch notification and any addressed-
to-you event the model isn't certain about; writing to Pad in reaction to a
notification is called out as prohibited by name (no more "fold it in"
euphemism), with a single narrow exception (an assignment/ask explicitly
addressed to the session's user, where acting is unambiguously expected)
and an explicit "when in doubt, park" tiebreaker.
claude plugin validate --strict clean on both repo root (marketplace) and
plugin/ (plugin manifest).
* fix(plugin): loop the pad-missing monitor guard instead of a one-shot sleep (TASK-2534)
Verifying the finding-2 guard through Claude Code's REAL monitor spawn
path (--bg --plugin-dir, not a manual `sh -c` test) surfaced a real gap
the manual test couldn't: the runner does NOT relaunch a monitor command
after it exits. The round-1 guard (`command -v pad && exec ... || sleep
3600`) is a single check-then-sleep-then-exit — once that one hour
elapses, the process exits and, per this observed behavior, is never
restarted, leaving the session permanently monitor-less for the rest of
its life on a machine where pad wasn't yet on PATH at session start.
That silently breaks DOC-2479's "sleep-retry hourly" contract, which the
Go binary's own `pad watch --stream --for-session` loop honors correctly
for its two conditions (no .pad.toml, padd unreachable) via an actual
internal retry loop — this shell guard needs the same shape for its one
condition (pad binary absent).
Wrapped the check in `while ! command -v pad; do sleep 3600; done` so it
keeps re-checking indefinitely instead of dying after one interval, then
falls through to the same `exec pad watch --stream --for-session` once
pad becomes resolvable. Verified live through the real spawn path with a
shortened sleep interval on a throwaway plugin copy: a fresh sleep child
appears every cycle (confirms the loop keeps running, not one-shot), then
re-verified the actual committed command (real sleep 3600) resolves a
live `pad watch --stream --for-session` process when pad is present and
sits in a healthy, silent, no-error `sleep 3600` loop when it's absent —
both through claude --bg --plugin-dir, not manual shell invocation.
claude plugin validate --strict clean on both repo root (marketplace)
and plugin/ (plugin manifest).
* fix(plugin): probe watch capability, not just binary existence, in the monitor guard (TASK-2534)
Codex round 2, P1: the round-1 fix looped on `command -v pad`, but an
old pad binary predating `pad watch` resolves on PATH fine and then
dies non-zero the moment `exec pad watch --stream --for-session` runs
— and the previous commit already established the runner never
relaunches an exited monitor command, so that death is permanent for
the session. `command -v` only proves the binary exists, not that it
has the subcommand this guard needs.
Changed the loop condition to `pad watch --help`, which probes the
actual capability in one call: covers both missing-binary (no such
command) and old-binary-without-watch (unknown subcommand, non-zero
exit) with a single condition. Verified first that `--help` is safe to
call as a probe — it succeeds (exit 0) with no `.pad.toml` anywhere
and padd unreachable, so it can't deadlock a legitimate unlinked-
project or padd-down user behind the guard.
claude plugin validate --strict clean on both repo root (marketplace)
and plugin/ (plugin manifest).
* fix(plugin): round-2 doc fixes — capture routing, confirm scope, invocation wording, CLI accuracy (TASK-2534)
Findings 2-8 from codex round 2:
- capture/SKILL.md: no unlinked-workspace branch — would fail opaquely
on `pad collection list` without .pad.toml. Mirrors the same routing
fix the main skill already has: run `pad workspace init` first.
- pad/SKILL.md's notification write-exception didn't say whether the
confirm-always principle (Key Principles #3) still applies inside it.
It does — the exception only lifts never-write, not confirm-first —
now stated explicitly where the exception lives, same rule as
capture's autonomous-capture opt-out.
- The `/pad` shorthand disclaimer scoped itself to "the playbook-routing
and examples sections below," missing Context Loading's "on every
`/pad invocation`" a few lines above it. Widened to cover the whole
document. plugin.json's own description repeated the bare "/pad
conversational surface" claim; reworded to name the real typed
shortcuts instead, and synced marketplace.json's plugin-entry
description to match (was already a paraphrase, now identical).
- Ideation example passed both `--content` and `--stdin` to the same
`pad item create` call — verified --stdin wins and hangs on ReadAll
with no piped input. Dropped --stdin, kept --content.
- Plan-retro example was missing the mandatory `--comment` this same
doc teaches elsewhere. Key Principles #2's status enumeration listed
"blocked" as a task status — verified against
internal/collections/templates.go: the tasks schema's actual options
are open/in-progress/done/cancelled, no "blocked". Fixed both.
- Two role-board pointers claimed `pad server open` lands on
`/{workspace}/roles` directly; verified cmd/pad/cmd_server.go's open
command only appends the workspace slug, never a sub-path. Reworded
both to describe navigating to Roles from the opened UI rather than
asserting an unverified deep-link.
claude plugin validate --strict clean on both repo root (marketplace)
and plugin/ (plugin manifest).
* fix(plugin): safe (non-hanging) unlinked-workspace self-heal, onboarding offer in status, ask-events wording (TASK-2534)
Codex round 3, findings 1-3:
- The routing added in rounds 1-2 told the skill to run bare
`pad workspace init` whenever bootstrap reported "no workspace
linked." Verified live this can HANG INDEFINITELY: with pad
configured (mode/URL set) but no admin account created yet /
session not authenticated, `pad workspace init` calls a
browser-based setup/login flow with no TTY guard and no
non-interactive fallback — unlike `pad init`, which has an explicit
`!canPromptForConfig()` check at the same step and fails fast with a
headless-bootstrap hint instead. Bootstrap's own two failure
signatures ("Pad is not configured" vs "no workspace linked") don't
fully disambiguate this either — verified live that "no workspace
linked" fires even when the deeper problem is "no admin account
exists yet," which is exactly the state that hangs.
Fixed by adding a `pad auth whoami` preflight (verified live: fast,
safe, never blocks, in all three states — unconfigured, configured-
but-unauthenticated, and fully set up) before ever attempting
`pad workspace init`. Only self-heal when whoami reports a real
user; otherwise tell the user to run `pad init` themselves in an
interactive terminal (Claude Code: suggest `! pad init`). Applied
consistently across pad/SKILL.md's Context Loading and Onboarding
routing, onboard/SKILL.md, and capture/SKILL.md's unlinked-workspace
branch (round 2 addition, same hang risk).
- status/SKILL.md ran `pad project dashboard --format json` but never
checked its `needs_onboarding` field (verified present on that
response too, not just bootstrap's — internal/server/handlers_
dashboard.go's NeedsOnboarding), so the mandated onboarding offer
couldn't fire via `/pad:status`. Added the same offer wording the
main skill uses.
- monitors.json's description claimed the stream delivers "asks for
your role" alongside assignment; verified against
internal/watchevents/watchevents.go: KindAsk is contract-reserved
with no Phase 1 producer. Reworded to describe what ships today,
noting ask-events as reserved-not-yet-emitted.
Filed docapp TASK-2537 for the fourth finding (embed-source
skills/pad/SKILL.md has the same --content/--stdin bug and has
drifted from these corrections) — selective port, out of this diff's
scope per the two skills' by-design framing divergence.
claude plugin validate --strict clean on both repo root (marketplace)
and plugin/ (plugin manifest).
* fix(plugin): --full on body-promising queries, capture loads always-on conventions, onboard's already-set-up path (TASK-2534)
Codex round 4, findings 1-3:
- Every `pad item list conventions|playbooks --format json` example whose
surrounding prose promises "bodies" was missing `--full` — verified
against cmd/pad/cmd_item.go: the flag exists specifically because JSON
output defaults to a token-light summary shape with no content.
Without it, all 8 of these calls (the Context Loading bootstrap-field
description at :41, the 7 trigger-query examples under "Before
Performing Work") would return exactly what the surrounding text says
they're loading bodies to avoid: metadata with no content. Added
--full to all 8, not just the block the finding cited — the "Template"
lines carry the identical "pull their bodies" promise as the
"Concrete examples" lines a few lines below them, so leaving one set
fixed and the other not would just move the inconsistency.
Swept the rest of the file's `item list ... --format json` examples
(Ideation load-context, Status Check role queue, Daily Standup) —
left those alone; their surrounding prose asks for enumeration/counts
("3 items in your queue", "Yesterday/Today/Blockers"), not body
content. The one exception found: Retrospective's task-load line
promises "what shipped, what was deferred, lessons learned" — that
needs actual task content to synthesize, so it got --full too, with
a one-line note explaining why (the other fixed lines didn't need
one; their promise was already explicit in the surrounding prose).
- capture/SKILL.md never loaded conventions at all. Per the dispatcher's
ruling: low ceremony means skipping bootstrap's dashboard/playbook/
role weight, not skipping mandatory project rules (trigger=always
conventions exist precisely to be small and always-applied). Capture
now runs the always-on conventions query (with --full) before
creating and applies whatever it returns; the autonomous-capture
exception now checks the SAME load instead of running its own
separate (previously --full-less) query. One sentence documents the
tradeoff as deliberate: always-on rules yes, full bootstrap no.
- onboard/SKILL.md only defined the needs_onboarding=true branch. Added
the false branch: say the workspace is already set up, summarize what
exists (collection/convention counts from the bootstrap payload
already in hand), and offer extend/audit instead of re-running
first-time setup — same confirm-first rule as everywhere else.
claude plugin validate --strict clean on both repo root (marketplace)
and plugin/ (plugin manifest).
|