mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-25 03:42:06 +00:00
ca3428fa07061a8eb966f25b5432d2df19dfd77f
35 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4bacea530f |
feat(mcp): expose pad_project ready + stale actions (#878)
Add read-only `ready` and `stale` actions to the pad_project MCP tool, mirroring the existing CLI `pad project ready` / `pad project stale`. `ready` returns the actionable backlog (query-oriented counterpart to `next`); `stale` lists items needing attention. Both HTTP dispatchers already existed; this wires them onto the catalog surface. `pad project reconcile` stays CLI-only (shells out to `gh` for live PR state — a local-git dependency MCP agents lack). Bumps ToolSurfaceVersion 0.12 -> 0.13 across version.go, instructions.md, README, CLAUDE.md; adds readOnlyActions entries, drift-guard test entries, and a SKILL.md routing line. TASK-2019 Claude-Session: https://claude.ai/code/session_019knGmnHcx5rrgWXQ8V8DZS |
||
|
|
c846cff4fd |
feat(project): agent-accessible activity feed (pad project activity + MCP action) (#877)
* feat(project): agent-accessible activity feed (pad project activity + MCP action)
Add a non-streaming, bounded activity query so agents can catch up on
what other agents/users changed since they last worked — the query
counterpart to the live `pad project watch` SSE stream.
- CLI: `pad project activity [--limit N] [--actor user|agent] [--since DATE]`
backed by the existing GET /workspaces/{ws}/activity feed.
- MCP: `pad_project.activity` action (passThrough) + cloud HTTP route.
- Extend the activity endpoint with a server-side `since` date filter
(handler parse + store SQL clause) so limit/actor/since behave
identically across CLI, stdio MCP, and cloud HTTP transports.
- Bump ToolSurfaceVersion 0.11 -> 0.12 (drift guard, README, CLAUDE.md,
instructions.md) and add a SKILL.md querying-guidance line.
Tests: store since-filter test, HTTP dispatch test, catalog action test.
Claude-Session: https://claude.ai/code/session_019knGmnHcx5rrgWXQ8V8DZS
* fix(mcp): mark pad_project.activity read-only in tool surface
Add activity to readOnlyActions so the serialized MCP tool surface emits
read_only:true (missing entries default to write). Spot-check it in
tool_surface_test.go to guard against regression.
Claude-Session: https://claude.ai/code/session_019knGmnHcx5rrgWXQ8V8DZS
|
||
|
|
7aa5cb98f3 |
perf(bootstrap): compact JSON for agents; trim SKILL.md reference sections (#873)
Part A: `pad bootstrap --format json` now emits compact (no-indent) JSON via a new cli.PrintJSONCompact helper. Its canonical consumer is the /pad agent skill; pretty-print indentation was ~29% of the payload (49696 -> 35118 bytes on this workspace, saving 14578 bytes). Humans keep --format markdown. Part B (conservative): condense the Role Awareness section and the playbook-authoring guidance in skills/pad/SKILL.md to on-demand pointers, keeping the load-bearing core behavior + activation gotcha inline and ALL routing behavior intact. Saves 2764 bytes of fixed per-session overhead. No MCP tool-surface change; ToolSurfaceVersion unchanged. Claude-Session: https://claude.ai/code/session_019knGmnHcx5rrgWXQ8V8DZS |
||
|
|
15ad930d78 | feat(bootstrap): add convention_index for triggered-convention discovery (TASK-2004) (#848) | ||
|
|
7ec19b5f7f |
feat(skill): NL-canonical playbook invocation in SKILL.md + MCP catalog (TASK-1859) (#749)
* feat(skill): NL-canonical playbook invocation in SKILL.md + MCP catalog (TASK-1859) Generalizes PLAN-1847's onboarding treatment to every invokable playbook. The invocation-model intro now establishes that natural language is the canonical way to invoke a playbook and `/pad`·`$pad`·`pad_playbook run` are per-surface shortcuts; the greeting, the rendered intent-match message, the examples preface, the plan/decompose routing entries, the "creating a playbook" section, and the Planning/Decomposition workflow subsections all lead with intent and label the slug forms as shortcuts. catalog_playbook.go's tool description gets the same reframing. Left untouched: the skill's own `/pad <anything>` entry-point syntax (that's Claude Code skill invocation, not a playbook slug) and onboarding (already NL-canonical from PLAN-1847). The plan/ideate/retro MCP prompts had no `/pad <slug>` references. Parent: PLAN-1858. Claude-Session: https://claude.ai/code/session_01KmxkPxLksjf1pmrZDpsnTJ * fix(skill): use pad_playbook tool's action/ref form, not CLI-style 'run', per Codex review (round 1) Round-1 review noted that 'pad_playbook run <slug>' reads as a non-existent CLI command — pad_playbook is an MCP tool invoked with action: run, ref: <slug>. Reworded all MCP-shortcut mentions in SKILL.md and the catalog tool description to the structured tool-call form so agents don't try a bogus command. Claude-Session: https://claude.ai/code/session_01KmxkPxLksjf1pmrZDpsnTJ |
||
|
|
09335c4916 |
feat(onboard): active "want me to set it up?" offer on needs_onboarding (TASK-1850) (#742)
Convert the passive needs_onboarding nudge into an active, lead-with-it offer, mirrored across both agent-instruction surfaces: - SKILL.md: the nudge rule now leads with "Want me to set it up?" and codifies offer-not-auto-run + respect-a-decline-for-the-session. - internal/mcp/instructions.md: previously had NO needs_onboarding rule at all, so pure-MCP agents got the bootstrap flag but were never told to act on it. Added a "New workspace: offer to set it up" section with the same offer wording, pointing at the pad_onboard prompt / pad_playbook get ref:onboard to actually run onboarding once accepted. Agent offers, never auto-runs. Agent-instruction surfaces only. Parent: PLAN-1847. Claude-Session: https://claude.ai/code/session_01KmxkPxLksjf1pmrZDpsnTJ |
||
|
|
7962fabaeb |
feat(onboard): make natural language the canonical onboard trigger (TASK-1849) (#741)
* feat(onboard): make natural language the canonical onboard trigger (TASK-1849)
The onboard procedure already single-sourced to the seeded playbook body —
both SKILL.md and the MCP pad_onboard prompt deferred to it rather than
restating it. But two gaps remained:
- Both hardcoded `/pad onboard`, a Claude-Code-ism. SKILL.md installs into
Codex (`$pad`) and others too, so the nudge/routing copy was wrong off
Claude Code. Reframe NL ("set up my workspace") as the canonical trigger;
`/pad onboard` · `$pad onboard` · the `pad_onboard` MCP prompt are now
per-surface shortcuts into the same playbook.
- The MCP prompt resolved the playbook via CLI commands (`pad playbook
list`/`show`) that a shell-less MCP client can't run. Rewrite it to use
the `pad_playbook` tool (action:list / action:get ref:onboard); CLI form
kept as a secondary note. This closes the real single-source gap.
Agent-instruction surfaces only (SKILL.md + MCP prompt text); no CLI/MCP
catalog changes (CONVE-1741).
Parent: PLAN-1847. Absorbs cancelled TASK-1848.
Claude-Session: https://claude.ai/code/session_01KmxkPxLksjf1pmrZDpsnTJ
* fix(onboard): use pad_library activate for shell-less onboard recovery per Codex review (round 1)
Round-1 review flagged that the MCP prompt's missing-playbook fallback sent
agents to the web UI even though pad_library action=activate is callable from
a shell-less MCP client. Activate "Onboard a workspace" via the tool, then
re-list, before deferring to the user.
Claude-Session: https://claude.ai/code/session_01KmxkPxLksjf1pmrZDpsnTJ
|
||
|
|
96a32aa39d |
feat(bootstrap,skill): add needs_onboarding flag + retire legacy Onboarding workflow (TASK-1504,1505) (#578)
PLAN-1496's bootstrap-signal + skill-cleanup pair, shipped together
because TASK-1505's nudge rendering depends on TASK-1504's bootstrap
field.
TASK-1504 (bootstrap: needs_onboarding):
- internal/store/items.go: new WorkspaceHasUserCreatedItems(workspaceID)
store method. Backed by SELECT EXISTS with the predicate
`source != 'template'` — defined as the inverse of template seeding
rather than enumerating user-side source values, so new attribution
surfaces (mcp, api, future) count automatically.
- internal/server/handlers_bootstrap.go: AgentBootstrap struct gets
the NeedsOnboarding bool field (always emitted — not omitempty,
since the agent reads it on every /pad invocation). BuildAgentBootstrap
computes it via the new store method. On query error the flag falls
back to false (safe default: don't nag).
- Visibility filtering deliberately omitted — needs_onboarding is a
workspace-level state signal, not a per-user view. Two members
reading bootstrap concurrently should see the same answer.
- Two focused tests:
- TestBootstrapNeedsOnboardingFlag walks the lifecycle (fresh
workspace → create user item → flag flips).
- TestBootstrapNeedsOnboardingIgnoresTemplateSeeds locks the
template-seeds-don't-count invariant on the startup template,
which ships seeded conventions, playbooks, and the onboard
playbook itself.
TASK-1505 (skill update):
- skills/pad/SKILL.md:
- Context Loading section: new bullet documenting needs_onboarding
with the exact nudge wording the agent should render when true,
plus the "don't nag past first user item" + "respect prior
decline" rules.
- Onboarding workflow section: deleted (~30 lines). Replaced with
a one-paragraph pointer at the /pad onboard playbook. The skill
is the dispatcher; the playbook body is the script.
- Routing entry under "set up my workspace": simplified from the
bloated PR #577 round-3/4 text into a clean two-bullet form
(canonical phrasing + legacy IDEA-1 phrasing both → /pad onboard).
- internal/mcp/prompts_data.go: the pad_onboard MCP prompt body
was duplicating the same step-by-step script the SKILL.md section
carried. Replaced with the same dispatch-to-playbook pointer.
internal/mcp/prompts_test.go: TestPromptsLockstep_CoreCommands
fragments updated to assert the new dispatch fragments
(`pad playbook list`, `pad playbook show onboard`).
Parent: PLAN-1496.
|
||
|
|
0930743304 |
feat: retire IDEA-1 seed pattern + 'pad onboard' cobra + surface blank in init (TASK-1501/1502/1503) (#577)
* feat: retire IDEA-1 seed pattern + 'pad onboard' cobra + surface blank in init (TASK-1501,1502,1503)
PLAN-1496's legacy-onboarding teardown:
TASK-1501 (remove seed items + update banner):
- internal/collections/templates_onboarding.go (and the _product/_scrum
siblings) deleted — these generated the IDEA-1/PLAN-2/TASK-3/DOC-4 +
BACK-1/SPRINT-2/BUG-3/DOC-4 + FEAT-1/FB-2/ROAD-3/DOC-4 first-person
seeds. The /pad onboard playbook (TASK-1499 / TASK-1500) is the
replacement.
- startup/scrum/product templates: SeedItems lines removed.
- post-init banner in printOnboardingHints: now points at "/pad onboard"
in one line, then web UI link, then dashboard hint. The "use pad to
get IDEA-1 / BACK-1 / FEAT-1" branch is gone.
TASK-1502 (retire cobra + OnboardingPrimaryRef plumbing):
- OnboardingPrimaryRef struct field on WorkspaceTemplate removed. The
dashboard's banner auto-discovers seeds via item_number=1 +
source="template" + created_by="system", so the field was redundant
even before retirement.
- onboardingPrimaryRef() helper in cmd/pad/main.go removed.
- 'pad onboard' Cobra subcommand removed (~160 lines). It scanned the
project directory for build/test/CI markers and seeded library
conventions — useful behavior but CLI-only, unreachable from
MCP-only agents. The /pad onboard PLAYBOOK now covers it.
- internal/cli/detect.go and workspace_context_detect.go stay; still
used by the web-side workspace-context save path.
TASK-1503 (Blank in interactive picker):
- The picker already surfaces Blank because templates_picker.go iterates
GroupTemplatesByCategory, and the IDEA-1479 Blank template entry lives
in CategoryCustom. Verified the output renders correctly with the
TASK-1498 description + icon update.
- 'pad workspace init --help' Long now mentions Blank explicitly +
points users at /pad onboard. Helps discoverability without restructuring
the picker.
Test changes (delete or rewrite tests that exercised the retired pattern):
- internal/collections/templates_test.go: six tests deleted (StartupOnboardingItemsOrderAndShape,
ScrumOnboardingItemsOrderAndShape, ProductOnboardingItemsOrderAndShape,
Startup/ScrumProduct/TemplatesDeclareOnboardingPrimaryRef). New
TestSoftwareTemplatesShipNoSeedItems replaces them with the inverse
invariant: software templates ship zero seed items.
- internal/server/handlers_dashboard_test.go: three IDEA-1/BACK-1/FEAT-1
expectation tests collapsed into TestDashboardOnboardingSeed_NilForAllTemplates,
which asserts the auto-discovery finds no seed because seeds no longer
ship. (Hiring + EmptyWorkspace tests untouched — they already expect
nil for unrelated reasons.)
- internal/store/items_test.go: TestSeedCollectionsFromTemplate{Startup,Scrum,Product}RefSequence
and TestOnboardingFlow_FullWalkthrough_{Startup,Scrum,Product} deleted;
these locked the IDEA-1 ref-sequence + walkthrough behavior. Unused
helpers (findItemByTitle, extractStatus, safeFields, setItemStatus,
countItemsInCollection) deleted alongside them.
- internal/mcp/resources_test.go: TestReadItem_PreservesIDEAOneOnboardingBodyVerbatim
→ TestReadItem_PreservesBodyVerbatim. Property is the same (resource
pipeline doesn't mangle markdown), but the fixture is now synthetic
markdown instead of the IDEA-1 seed.
Note: handlers_dashboard.go still has the auto-discovery code path
(onboardingPrimaryCollectionSlugs map + the loop that probes for
item_number=1 + source="template"). It's now dead code — no item
will ever match the criteria after this PR. Left in place for a
follow-up cleanup pass to keep this PR focused.
Parent: PLAN-1496.
* docs: replace 'pad workspace onboard' references with /pad onboard (Codex round 1)
P2 finding on PR #577: README + CLAUDE.md still advertise the
'pad workspace onboard' subcommand in four places (README §Onboard
agents to a new codebase, README §3 Teach your agents the rules,
README CLI Reference, CLAUDE.md CLI). After this branch lands, those
instructions return "unknown command."
Replaced each with guidance pointing at /pad onboard (the playbook,
auto-seeded into every workspace). The library-list commands still
work and stay where they are.
Parent: PLAN-1496.
* docs: replace 'use pad to get IDEA-1' guidance with /pad onboard (Codex round 2)
P1 finding on PR #577: README.md:33-39 and CLAUDE.md:111-117 still
told users to 'use pad to get IDEA-1' after the post-init banner.
Since this branch deletes templates_onboarding.go and stops seeding
IDEA-1/PLAN-2/TASK-3/DOC-4, the quickstart instructions in both
top-level docs pointed at items that no longer exist.
Replaced each with /pad onboard guidance (the playbook is auto-seeded
into every new workspace by TASK-1500). CLAUDE.md's CLI reference
gets a one-line historical note explaining the pre-PLAN-1496 IDEA-1
pattern so readers reviewing older code/blame have context.
Parent: PLAN-1496.
* docs(skill): retire 'use pad to get IDEA-1' guidance in agent skill (Codex round 3)
P1 finding on PR #577: skills/pad/SKILL.md:175 still taught agents
that '"use pad to get IDEA-1"' should dispatch to 'pad item show IDEA-1'.
This branch deletes the seed items, so any agent following the
shipped skill in a fresh workspace would try to fetch a missing ref
instead of running /pad onboard.
Updated the routing entry to dispatch the legacy phrasing (kept as a
recognized intent so older docs/conversations still work) to the
/pad onboard playbook. Explicit "do NOT try to fetch IDEA-1
directly" to short-circuit the previously-trained behavior.
A broader skill cleanup — removing the standalone Onboarding
workflow section and adding the bootstrap nudge rendering — is
TASK-1505's scope. This PR's update is the minimal change needed to
unbreak the agent-facing routing.
Parent: PLAN-1496.
* docs(skill): add library-activation caveat to onboard routing entry (round 4)
P2 finding on PR #577: the routing entry said /pad onboard is
'always invokable because every workspace auto-seeds it.' True for
newly-created workspaces, but pre-existing workspaces (created before
PLAN-1496 lands) won't have it. Auto-upgrade is intentionally not
wired into SeedCollectionsFromTemplate for empty-template-name paths.
Mirrored the same activation-fallback caveat /pad plan and
/pad decompose carry: 'activate via library if the bootstrap's
playbooks array lacks invocation_slug=onboard, status=active.'
Parent: PLAN-1496.
|
||
|
|
aaa581b105 |
refactor(bootstrap): extend dashboard caps to active_items/active_plans/by_role (TASK-1422) (#541)
* refactor(bootstrap): extend dashboard caps to active_items/active_plans/by_role/suggested_next (TASK-1422) Implements IDEA-1421 (absorbed into PLAN-1410's v0.4 envelope). Extends the BootstrapDashboard wrapper from TASK-1413 to cap four more dashboard sub-arrays with parallel overflow counts, same shape and semantics as the existing attention/recent_activity caps. ## Struct + caps Four new int fields on BootstrapDashboard (all `,omitempty`): - active_items_overflow_count - active_plans_overflow_count - by_role_overflow_count - suggested_next_overflow_count Four new cap constants alongside the existing two: - bootstrapActiveItemsCap = 5 - bootstrapActivePlansCap = 5 - bootstrapByRoleCap = 5 - bootstrapSuggestedNextCap = 5 capBootstrapDashboard extended with four parallel truncate-and-count blocks — same shallow-copy mutation pattern, source pointer untouched (the dashboard endpoint still returns its full-length arrays per its own contract). ## Tests TestCapBootstrapDashboard rewritten to cover all six caps under one contract. `mk` now takes a `dashCounts` struct (Att/Rec/Items/Plans/ Role/Sugg) so each subtest exercises specific caps without populating the others. Each of the four existing subtests (under-cap-no-overflow, over-cap-truncates-and-counts-overflow, source-pointer-unchanged, exact-cap-no-overflow) now asserts the new caps too. Added tiny assertLen/assertOverflow helpers to keep the per-array assertion noise from drowning the contract being tested. bootstrapSectionBytes extended to surface the four new cap-effect lines when triggered, table-driven so future caps drop in cleanly. seedBootstrapSizeFixture updated to seed 6 in_progress tasks (was 5 open) so the new active_items cap fires visibly in the per-section breakdown: "active_items capped: 5 shown, 1 overflow". The status flip is deliberate — dashboard.active_items filters on isActiveStatus(), which excludes initial/terminal statuses; open tasks never appeared in the section. ## Budget bootstrapSizeBudget 7 KiB → 9 KiB. Note that this is FIXTURE-side growth, not shape-side regression: the fixture now seeds enough active items to exercise the new cap (active_items section was 0 bytes when tasks were status=open). The cap itself is purely a SAVINGS — on docapp it drops active_items from 7 → 5 entries with overflow_count=2. Budget history note in handlers_bootstrap_test.go updated with the TASK-1422 line and an explicit "fixture-side, not shape-side" explanation so future readers understand why the budget moved up. ## Out of scope - Slim BootstrapRole projection — TASK-1423. - Schema label + sort_order trim — TASK-1424. - ToolSurfaceVersion 0.3 → 0.4 bump — TASK-1418 (final PR). Parent: PLAN-1410. Resolves IDEA-1421 once merged. * fix(bootstrap): drop unreachable suggested_next cap (TASK-1422 follow-up) Address Codex P1 finding on PR #541: `suggested_next_overflow_count` was unreachable in production responses because `buildDashboardResponse` already truncates `SuggestedNext` to 3 upstream (see "Take top 3" comment in handlers_dashboard.go:854-858), while my bootstrap cap was 5. The cap-and-overflow logic could only have fired against synthetic test state, never against the real dashboard pipeline. Two responses to consider: 1. Lower bootstrap's cap to a number smaller than 3 — defeats the upstream design choice (3 IS the intentional limit). 2. Drop the bootstrap-side cap — clean, no dead surface. Going with (2). If the upstream cap is ever raised or removed, that's the moment to add a suggested_next_overflow_count back. Removed: - SuggestedNextOverflowCount field on BootstrapDashboard - bootstrapSuggestedNextCap constant - The truncate-and-count block in capBootstrapDashboard - The suggested_next row in TestCapBootstrapDashboard's dashCounts helper and all five subtest assertions - The suggested_next entry in bootstrapSectionBytes's cap-line loop The fixture still seeds tasks and a plan, so the no-cap path on SuggestedNext is naturally exercised through TestBootstrapSizeBudget. The godoc on BootstrapDashboard now explicitly calls out the exclusion + the upstream-cap rationale so a future reader knows why suggested_next is missing from the otherwise-uniform cap set. Parent: PLAN-1410 / TASK-1422. * docs(skill): align SKILL.md dashboard cap description with TASK-1422 Address Codex P3 finding on PR #541: the SKILL.md `Context Loading` section described only the two original cap fields (attention_overflow_count, recent_activity_overflow_count). After TASK-1422 the bootstrap response carries three more (active_items_overflow_count, active_plans_overflow_count, by_role_overflow_count), and the agent needs to know to pull the full set via `pad project dashboard` when any of them are > 0. Updated the bullet to enumerate all five capped sub-arrays and state the overflow-field pattern generically rather than per-field. Same in-PR-sync pattern used for TASK-1413, TASK-1415, TASK-1416. Parent: PLAN-1410 / TASK-1422. * docs(bootstrap): fix three stale comments after dropping suggested_next cap (TASK-1422 follow-up) Address Codex P3 finding on PR #541 round 3: three stale doc strings referenced the old shape (with suggested_next) after the cap was dropped in the prior commit. Updated: 1. handlers_bootstrap_test.go budget-history line for TASK-1422 — removed `suggested_next` from the cap list and added the "deliberately excluded — already capped to 3 upstream" rationale so future readers know why the otherwise-uniform cap set is missing one. 2. handlers_bootstrap.go BootstrapDashboard godoc — changed "two overflow counts" to "five overflow counts (one per capped sub-array)". 3. handlers_bootstrap.go capBootstrapDashboard godoc — changed "both caps are untriggered" to "all caps are untriggered". Tidy-up only, no behavior change. Same skill-↔-code sync hygiene that has been the running theme across PLAN-1410's review loops. Parent: PLAN-1410 / TASK-1422. * docs(bootstrap): update remaining stale call-site comment for capBootstrapDashboard (TASK-1422 follow-up) Final stale-doc cleanup per Codex P3 on PR #541 round 4: the BuildAgentBootstrap dashboard-wrapping call-site comment still listed only attention + recent_activity. Updated to enumerate all five capped sub-arrays for parity with the godoc on BootstrapDashboard / capBootstrapDashboard. Same hygiene as the previous commit; no behavior change. Parent: PLAN-1410 / TASK-1422. |
||
|
|
6a981e7433 |
docs(skill): compress NL Routing examples, trim playbook authoring, drop MCP note (TASK-1416) (#539)
* docs(skill): compress NL Routing examples, trim playbook authoring section, drop MCP note (TASK-1416) Final SKILL.md trim in PLAN-1410's skill-side compression series. Three targeted changes: 1. NATURAL LANGUAGE ROUTING — compress example density The "example phrasing → command" pairs in each sub-category were over-enumerated — the model handles intent matching without an exhaustive lookup table. Compressed each sub-category to its canonical pattern(s) while keeping the section structural map intact (Role management, Creating items, Querying, Updating, Working with attachments, Planning, Ideation, Dependencies, Reports, Retrospective, Onboarding, Creating a playbook). Pattern: where a section had 5-11 "intent → command" lines all illustrating the same command verb with slight wording variants, collapsed to a 1-2 line summary that describes the routing rule directly. Where a section had genuinely-distinct commands (e.g. Querying covers dashboard / next / list / search), kept one canonical line per command verb. 2. PLAYBOOK AUTHORING — replace worked examples with a compact pointer The "Authoring trigger-only" and "Authoring slug-invocable with arguments" subsections previously included full ~25-line heredoc examples — useful when the schema-aware --field parsing was new, now memorizable scaffolding. Replaced with a 2-line pointer listing the two authoring surfaces (CLI / Web UI) and the key `--field 'arguments=[...]'` shape. The model knows the heredoc pattern; the worked example was redundant. 3. MCP NOTE — dropped The "Note for agents using MCP instead of this skill" preamble (~700 B) only applied to readers of the file — agents loading this skill are by definition using the CLI surface, not MCP. The MCP catalog reference at getpad.dev/mcp/local stays the canonical source for that surface; removing the note avoids carrying its bytes in every skill load. Measurements: Before TASK-1416: 34,786 b / 479 lines After: 29,448 b / 393 lines Delta this PR: -5,338 b (-15%) Cumulative PLAN-1410 skill-side reduction (TASK-1414/1415/1416): Baseline (TASK-1410 start): 40,193 b / 567 lines After all three trims: 29,448 b / 393 lines Total reduction: -10,745 b (-26.7%) Parent: PLAN-1410. Remaining: TASK-1417 (final measurement back into the plan body) and TASK-1418 (ToolSurfaceVersion 0.3 → 0.4). * fix(skill): add status=active activation requirement to playbook authoring (TASK-1416 follow-up) Address Codex P2 finding on PR #539: the compressed authoring pointer dropped `--field status=active` from the example. New playbooks default to status=draft, but slug routing and trigger-intent matching only dispatch status=active entries. Following the trimmed instructions would create /pad <slug> playbooks that silently fall through to NL routing. The original (pre-TASK-1416) worked example included status=active; I lost it when collapsing to a pointer. Restored explicitly: - New "**Activation matters**" paragraph calling out the default-draft pitfall and the silent-fall-through behavior. - CLI example now includes `--field status=active`. - Web UI bullet explicitly mentions flipping draft → active before save. Same in-PR-sync pattern as TASK-1413's SKILL.md alignment commit and TASK-1415's activation-check correction. Parent: PLAN-1410 / TASK-1416. |
||
|
|
335b145343 |
docs(skill): replace Planning/Decomposition workflow fallbacks with one-liner playbook pointers (TASK-1415) (#538)
* docs(skill): replace Planning/Decomposition workflow fallbacks with one-liner playbook pointers (TASK-1415)
The Planning and Decomposition workflows in SKILL.md each had:
1. A leading "use the <slug> playbook" pointer (the canonical
entry point).
2. A multi-line "if the playbook isn't activated, fall back to
this inline workflow" block duplicating most of the playbook's
contract.
For software templates the playbooks auto-seed via
softwareStarterPlaybookTitles, so the fallback fires approximately
never. Non-software workspaces activate from the library UI, which
also makes the fallback transient at best.
Replaced each section with a one-liner pointer that:
- Names the canonical /pad <slug> invocation
- Explains how to confirm activation (bootstrap's playbooks array
or `pad playbook show <slug>`)
- Tells the user to activate via the library UI when missing,
and offer to walk through manually in the meantime — without
duplicating the playbook's step contract here
Measurements:
SKILL.md total: 36,473 → 34,786 bytes (-1,687 b / -5%)
SKILL.md lines: 501 → 479
Cumulative against PLAN-1410 baseline:
SKILL.md total: 40,193 → 34,786 bytes (-13.5% so far)
Parent: PLAN-1410. Next: TASK-1416 (NL Routing + authoring example + MCP note).
* fix(skill): correct playbook activation-check guidance (TASK-1415 follow-up)
Address Codex review findings on PR #538:
P2 — `pad playbook show <slug>` is not a valid activation check.
The resolver returns playbooks by invocation_slug regardless of
status, and default output omits status. A draft/deprecated
`plan` playbook would be treated as active. Corrected to direct
the agent at the bootstrap's `playbooks` array (which carries
status) for the activation check, and noted explicitly that
`pad playbook show` alone is insufficient.
P3 — The "**Planning:**" routing bullet still pointed at
"otherwise inline workflow (see below)" after the inline
fallbacks were removed in the parent commit. Replaced with a
pointer to library activation, matching the (now-trimmed)
workflow section.
Both findings would have left agents in a workspace without
active plan/decompose playbooks pointing at the wrong fallback.
Fixed in-PR so skill ↔ playbook contract stays strictly
synchronized (same pattern as TASK-1413's SKILL.md sync commit).
Parent: PLAN-1410 / TASK-1415.
|
||
|
|
efccea6dfe |
docs(skill): compress CLI Reference to patterns the skill drives (TASK-1414) (#537)
The CLI Reference section grew over time with every-flag enumeration,
multiple worked examples per command, and edge-case commands the
skill never invokes (webhooks REST API trivia, full --fields DSL
walkthrough for collection create, multiple per-command examples
that all illustrate the same flag pattern).
Compressed to the patterns the natural-language routing actually
drives, with `pad <cmd> --help` as the explicit escape hatch for
anything else.
Measurements:
- SKILL.md total: 40,193 → 36,473 bytes (-3,720 b / -9%)
- SKILL.md line count: 567 → 501
- CLI Reference section: ~6,500 → ~3,400 bytes (-48%)
Preserved:
- All command verbs the NL routing references (item create/list/
show/update/delete/search/comment/comments/bulk-update, role
list/create/delete, project dashboard/next/standup/changelog,
playbook list/show/run, attachment list/show/view/upload/
download, collection list/create, server info/open, auth whoami,
bootstrap).
- The hard rule against reading ~/.pad/attachments/ directly
(kept the explanation tight: "bypasses ACLs, breaks on Pad
Cloud / S3, skips the variant pipeline").
- The `--field key=value` schema-aware pattern with concrete
examples for convention + playbook (the two collections most
likely to drive its use).
- The two-mode collection create (`--fields` DSL vs `--schema`
full CollectionSchema), with the when-to-use guidance retained.
Dropped or compressed:
- Per-command multi-example listings (one canonical pattern each).
- The full Webhooks subsection — webhooks are REST-API-only and
the skill never invokes them directly; pointer in the catch-all.
- The trailing "Output Formats" footer — replaced by an inline
note at the section header that --format json works everywhere.
- Verbose per-line comments inside code blocks; the patterns are
self-documenting at this scale.
Parent: PLAN-1410 / TASK-1414. Bootstrap-shape work already in main
(TASK-1411/1412/1413). Remaining: SKILL.md workflow + NL routing
trims (TASK-1415/1416), then final measurement + version bump.
|
||
|
|
638a456f98 |
refactor(bootstrap): dedup recent_activity, drop convention slug, cap dashboard arrays (TASK-1413) (#536)
* refactor(bootstrap): dedup recent_activity, drop convention slug, cap dashboard arrays (TASK-1413)
Three bundled handler-level cleanups against PLAN-1410's bootstrap
shape. Total fixture savings: 8,992 → 6,355 bytes (-2,637 b / -29%).
1. Drop duplicate top-level `recent_activity`
AgentBootstrap.RecentActivity was bit-for-bit identical to
AgentBootstrap.Dashboard.RecentActivity. Removed:
- AgentBootstrap.RecentActivity field
- capRecentActivity() helper
- recentActivityWindow constant
- the time import (no longer used)
Fixture savings: -1,751 bytes.
2. Drop `slug` from AgentBootstrapConvention
Agents address convention items by ref (CONVE-N); slug was dead
weight. Removed the field + the population line in
collectAlwaysOnConventions.
Fixture savings: -78 bytes.
3. Cap dashboard.attention + dashboard.recent_activity to 5 in bootstrap
New BootstrapDashboard wrapper embeds *DashboardResponse (so the
wire shape stays compatible — same field names, same nesting) and
adds two overflow counts:
- attention_overflow_count (omitempty when zero)
- recent_activity_overflow_count (omitempty when zero)
The cap is applied via capBootstrapDashboard which shallow-copies
the DashboardResponse before truncating the slices, so callers
downstream of buildDashboardResponse (the dashboard endpoint
itself, the web UI) see their original full-length arrays
unchanged. `pad project dashboard` contract is preserved verbatim.
Fixture savings: -789 bytes (recent_activity capped 9 → 5;
attention untouched, fixture has 0 attention items).
Coverage:
- TestCapBootstrapDashboard (4 subtests): under-cap-no-overflow,
over-cap-truncates-and-counts-overflow, source-pointer-unchanged,
exact-cap-no-overflow. Locks in the cap contract independent of
the full bootstrap pipeline.
- TestBootstrapEmptyArraysNotNull updated: the top-level
recent_activity key was removed from the required-keys list,
with a separate assertion that guards against it reappearing.
- TestBootstrapEmptyWorkspace updated: removed the b.RecentActivity
nil-check; added a (defensive) check that dashboard's nested
recent_activity is non-nil when dashboard is present.
- bootstrapSectionBytes now surfaces the cap effect ("attention
capped: 5 shown, 4 overflow") when triggered, so the trim's
value is legible from CI output.
bootstrapSizeBudget tightened 11 KiB → 8 KiB to lock in the win.
Budget-history comment updated.
Out of scope (handled by later PLAN-1410 PRs):
- Skill-file trim (TASK-1414/1415/1416)
- Final measurement (TASK-1417)
- ToolSurfaceVersion 0.3 → 0.4 (TASK-1418, after all shape
changes land)
Parent: PLAN-1410.
* docs(skill): align SKILL.md bootstrap shape with PLAN-1410 / TASK-1413
The skill's `Context Loading` section described the old wire shape:
- `dashboard {...}` — active items, attention, suggested next, recent activity
- `recent_activity [...]` — capped to the last 24h
After TASK-1413 the top-level `recent_activity` field is gone (it was
a bit-for-bit duplicate of `dashboard.recent_activity`), and the
remaining `dashboard.recent_activity` is capped by COUNT (top 5) not
by TIME (24h window). The two cap fields (attention_overflow_count
and recent_activity_overflow_count) tell the agent how much was
trimmed so it can decide whether to follow up with a full
`pad project dashboard` query.
Per the Codex P2 finding on PR #536: documenting the new contract
in this PR keeps skill ↔ wire-shape strictly synchronized (no
window where the docs are wrong about the shape this PR ships).
Parent: PLAN-1410 / TASK-1413.
|
||
|
|
1db0e6a505 |
docs+test: closes the PLAN-1397 library overhaul loop (TASK-1404) (#533)
* docs+test: closes the PLAN-1397 library overhaul loop (TASK-1404)
## Tests
New `internal/collections/playbook_library_test.go` with 4 regression
guards for the invokable-first library:
- TestPlaybookLibrary_InvokableEntriesPresent — asserts ship + plan +
decompose are all present by invocation_slug, that each has at
least one Argument declared, and that at least 3 invokable entries
exist. Catches T1 widening getting half-reverted or T6's library
rebuild dropping an entry.
- TestPlaybookLibrary_AllTriggersKnown — asserts every library
entry's Trigger is one of the canonical values (manual,
on-implement, on-review, on-plan, on-triage, on-release,
on-deploy, on-pr-create, on-task-complete, always). Catches typos
that would seed an invalid trigger.
- TestPlaybookLibrary_ShipBodyShared — confirms the library `ship`
entry and ShipPlaybook() seed share the same body constant. The
whole point of T3 was to avoid duplication; this prevents drift.
- TestPlaybookLibraryArchive_BodiesCompiled — keeps archivedPlaybooks()
greppable and verifies the canonical retired title ("Implementation
Workflow") is still in the archive.
## CLAUDE.md
- Added a "Library — discovery surface" subsection to the Playbooks
section explaining the invokable-first lineup, the archive, and
how `softwareStarterPlaybookTitles` seeds plan + decompose into
software workspaces.
- Expanded "Code map" with the four new/refactored library files
(playbook_library.go, playbook_library_plan.go,
playbook_library_decompose.go, playbook_library_archive.go).
- Cross-referenced PLAN-1397 alongside PLAN-1377 for design history.
## skills/pad/SKILL.md
- "Planning: 'Let's create a plan'" and "Decomposition: 'Break plan
X into tasks'" now name `/pad plan` and `/pad decompose` as the
canonical entry points, with the inline workflow as the fallback
when those playbooks aren't activated in the workspace.
- The high-level "Planning:" intent list at the top of the routing
section updated to match.
- Note: SKILL.md is embedded into the Go binary at build time. The
next `make install` distributes the skill update; the .agents/
copy regenerates automatically.
Parent: PLAN-1397. Closes the loop — all 7 tasks of the playbook
library overhaul shipped.
* fix(test): source knownPlaybookTriggers from SoftwarePlaybookTriggers per Codex review (round 1)
Round 1: the hand-maintained `knownPlaybookTriggers` map admitted
`on-pr-create`, `on-task-complete`, and `always` — all valid in
the schema for *conventions*, but NOT in `SoftwarePlaybookTriggers`
(templates.go:266). A library entry could ship one of those and
the regression test would pass, but the same trigger would be
rejected when seeded into a software workspace at activation.
Fix: derive the test's known-set from `SoftwarePlaybookTriggers`
directly. If the schema widens or narrows, the test follows
automatically — no drift between the assertion baseline and the
actual schema. Also added a note clarifying that templates with
domain-specific trigger vocabularies (e.g. hiring's
on-candidate-advance) would need their own library scoped to
that template.
The set is now exactly: manual, on-implement, on-triage,
on-release, on-plan, on-review, on-deploy.
|
||
|
|
c2014fa7f8 |
fix(cli): schema-aware --field parsing for non-string typed fields (BUG-1125)
pad item create/update --field key=value previously stored every value
as a string, so json / number / checkbox / multi_select fields were
rejected by the server-side validator. The new parseFieldFlag helper
fetches the collection schema once per command and parses each value
according to its declared field type:
- json / multi_select → json.Unmarshal
- number → strconv.ParseFloat
- checkbox → strconv.ParseBool
- text / url / select / date / relation / unknown → raw string
Schema-fetch failure degrades gracefully to pre-fix string-only behavior.
pad item list --field is unchanged (URL query param, not validator).
Verified against both repros: --field reading_time=3 on blogs (the
original number case) and --field 'arguments=[{...}]' on playbooks (the
json case that surfaced authoring the ship playbook). String fields show
no regression.
Skill update folded in: the "Authoring slug-invocable playbooks with
arguments" section in skills/pad/SKILL.md previously routed users to the
web editor as the only path for structured arguments. With this fix the
CLI handles it in one command, so the section now leads with the CLI
flow and demotes the web editor to an alternative.
|
||
|
|
9764b2fe92 |
docs: document playbook invocation surface (TASK-1387) (#525)
* docs: document playbook invocation surface (TASK-1387)
Closes out PLAN-1377 — Make Playbooks first-class invokable procedures —
by bringing the four user-facing docs surfaces up to date with the
shipped invocation model. The pad-web docs ship in a separate commit
(../pad-web@main: docs: document playbook invocation surface).
- CLAUDE.md — new Playbooks section after Data Model covering the
three invocation surfaces, the invocation_slug/arguments schema
fields, bootstrap-returns-metadata, the seeded ship playbook, the
web UI editor, and a code map. MCP section grows pad_playbook,
pad://workspace/{ws}/bootstrap, and the pad_set_workspace embedded
response note.
- skills/pad/SKILL.md — adds a "Creating a playbook" subsection under
natural-language routing with CLI examples for trigger-only and
slug-invocable playbooks, plus a Playbooks block in the CLI
reference (pad playbook list/show/run with parsing rules).
- README.md — one-line bump in the feature list mentioning the new
/pad <slug> invocation form and the seeded ship playbook.
Parent: PLAN-1377.
* fix(docs): correct bootstrap route + CLI arguments authoring per Codex review (round 1)
Codex round 1 findings:
[P2] CLAUDE.md cited GET /api/v1/workspaces/{ws}/bootstrap but the
implemented route is /api/v1/workspaces/{ws}/agent/bootstrap (server.go
line 1182). Documented endpoint would 404 for HTTP integrators.
[P2] SKILL.md '--field arguments=[...]' example would fail validation
— pad item create stores all --field values as strings, while
arguments is a json field type. Rewrote the slug-invocable-playbook
authoring guidance to direct agents at the web UI editor for
structured argument authoring (the canonical path the editor was
built for) with the CLI handling everything else. Same fix applied
to the pad-web /docs/agent-integration page in a separate
../pad-web@main commit.
Parent: TASK-1387 / PLAN-1377.
* fix(docs): use full /{username}/{workspace}/playbooks route in SKILL.md per Codex review (round 2)
Codex round 2 finding:
[P3] SKILL.md's recommended web editor path was '/{workspace}/playbooks',
but the SvelteKit route is '/{username}/{workspace}/playbooks'. The
prior path would 404 or land on the wrong workspace. Fixed.
The pad-web docs ship the matching fix in a separate commit at
../pad-web@main: docs(playbooks): use full /{username}/{workspace}
route path per review.
Parent: TASK-1387 / PLAN-1377.
* fix(docs): bump CLAUDE.md MCP tool surface to v0.3 + close SKILL.md backtick per Codex review (round 3)
Codex round 3 findings:
[P2] CLAUDE.md still labelled the tool surface as v0.2; internal/mcp/
version.go advertises ToolSurfaceVersion = '0.3' (since PLAN-1377 /
TASK-1380). Updated to v0.3 and added a note about what v0.3 introduced
(pad_meta.action: bootstrap, pad_set_workspace embedded-bootstrap
response, pad://workspace/{ws}/bootstrap resource).
[P3] SKILL.md's web-editor route had the parenthetical inside the
code span: '`/{username}/{workspace}/playbooks (click "+ New
Playbook")`' — closed the backtick after '/playbooks' so the
rendered code span is the literal path.
The pad-web docs ship the matching v0.3 bump in a separate commit at
../pad-web@main: docs(mcp/tools): bump tool surface to v0.3.
Parent: TASK-1387 / PLAN-1377.
* fix(docs): bump stale MCP catalog references to v0.3 per Codex review (round 4)
Codex round 4 finding [P2]:
Three places still described the MCP catalog as v0.2, contradicting the
v0.3 surface block that landed in this PR:
- CLAUDE.md 'MCP server' lede paragraph — bumped to v0.3, added
pad_playbook to the listed tools, and noted what v0.3 introduced.
- skills/pad/SKILL.md MCP note for MCP-using agents — bumped to v0.3,
added pad_playbook to the listed tools and called out the playbook
invocation surface + bootstrap action.
- README.md 'Tool catalog (v0.2)' block — bumped to v0.3, added the
pad_playbook row, the pad_meta.action: bootstrap row, the bootstrap
resource, and bumped tool_surface_version.
Parent: TASK-1387 / PLAN-1377.
* fix(docs): bump MCP server-side self-description to v0.3 per Codex review (round 5)
Codex round 5 finding [P2]:
Two MCP-server-internal documentation surfaces still advertised v0.2:
- internal/mcp/instructions.md — the markdown blob the server returns
to MCP clients as initialization instructions. Updated 'Tool surface
(v0.2) / Eight tools' to 'Tool surface (v0.3) / Nine tools', added
pad_playbook with list/get/run, added bootstrap to pad_meta's actions,
noted pad_set_workspace's embedded-bootstrap response, and added
pad://workspace/{ws}/bootstrap to the resource list.
- internal/mcp/catalog_meta.go — the pad_meta tool's Description string
said 'v0.2 tool catalog' twice. Bumped both to v0.3.
These ship inside the binary; MCP clients read them directly so v0.2
mentions there contradict the v0.3 catalog the handshake actually
advertises (ToolSurfaceVersion in version.go).
Parent: TASK-1387 / PLAN-1377.
* fix(docs): finish MCP self-description v0.3 cleanup per Codex review (round 6)
Codex round 6 findings [P3]:
[1] catalog_meta.go's padMetaTool block-comment said 'Three actions,
all handled inline' even though bootstrap (the v0.3 fourth action)
dispatches through env.Dispatch. Fixed both the count and the
dispatch description, added the bootstrap row to the action list.
Also corrected the v0.2 mentions in actionMetaToolSurface's comment
and removed the rollout-era language now that the cmdhelp walker is
retired.
[2] instructions.md said 'Nine tools, each with an action enum' but
pad_set_workspace doesn't take an action. Clarified the count as
'eight resource × action tools, plus pad_set_workspace (which takes
a workspace slug only)' and scoped the 'Always pass action' rule to
the eight resource × action tools.
Parent: TASK-1387 / PLAN-1377.
* fix(docs): finish MCP self-description nine-tool wording per Codex review (round 7)
Codex round 7 findings:
[1] catalog_meta.go's padMetaToolDescription still mentioned the
PLAN-969-rollout cmdhelp walker contributing to tools/list. The walker
was retired in TASK-981. Rewrote the tool-surface action description
to match current behavior and explicitly note pad_set_workspace is
registered separately (not enumerated by tool-surface).
[2] actionMetaToolSurface's comment claimed scope includes
pad_set_workspace; the impl only loops env.Catalog. Updated the
comment to be accurate — tool-surface enumerates the eight catalog
tools only, callers should account for pad_set_workspace as a known
extra.
[3] CLAUDE.md and README.md described the MCP surface as if every
listed tool was resource × action. pad_set_workspace takes
'workspace' only. Reworded both to match instructions.md's
'eight resource × action tools plus pad_set_workspace' framing.
Parent: TASK-1387 / PLAN-1377.
|
||
|
|
955553b6c2 |
docs(skill): rewrite /pad skill for bootstrap + slug routing (TASK-1383) (#522)
* docs(skill): rewrite /pad skill for bootstrap + slug routing (TASK-1383)
PLAN-1377 T6. Three substantive changes to skills/pad/SKILL.md:
1. Context Loading section now uses a single `pad bootstrap --format
json` call instead of four separate ones (project dashboard,
collection list, conventions list, role list). Documents the
AgentBootstrap struct's shape and explains why one call beats
four (~200-400ms saved per /pad invocation, stable shape,
no view stitching).
2. New "Playbook Invocation (slug routing)" section ahead of the
natural-language routing. Spells out the rule: if the first token
after /pad is an exact match against a kebab-case invocation_slug
from the bootstrap's playbooks array, dispatch to that playbook.
Otherwise fall through to NL routing. Examples cover /pad ship
PLAN-1377, /pad release 0.5.0, /pad draft-tweet TASK-X
platforms=x,bluesky, and the kebab-case discipline that keeps
/pad let's discuss IDEA-3 from misrouting.
3. "Before Performing Work" reframes the trigger-specific
convention/playbook lookup: bootstrap already carries the
always-on conventions + full playbook metadata, so the only
on-demand load is trigger-matched conventions. Schema vocabulary
reads from the bootstrap's collections[] payload, not a separate
`pad collection list` call.
Greeting note added: if bootstrap returns any playbooks with
invocation_slug, surface the user-callable set ("Playbooks available:
/pad ship, /pad release, ...") so users discover what's invokable —
same shape as the existing roles greeting.
Parent: PLAN-1377.
* fix(skill): filter playbook routing/greeting on status=active (TASK-1383)
Codex round 1: the skill's playbook routing rule and greeting surfaced
every entry with an invocation_slug, but bootstrap returns all
playbooks regardless of status (so draft/deprecated entries with a
slug got advertised as runnable). The skill now explicitly requires
status=active for both the greeting list and the slug dispatch
decision — drafts can keep their slug while in-flight without
accidentally firing.
Parent: PLAN-1377.
* fix(skill): trigger-based intent match also filters status=active (TASK-1383)
Codex round 2: the slug-routing fix from round 1 didn't extend to the
trigger-based intent-matching branch, so 'let's do a release' could
still surface a draft on-release playbook. Apply the same status=active
filter consistently.
Parent: PLAN-1377.
|
||
|
|
9fecb82e82 |
docs: surface --schema flag in SKILL.md + CLAUDE.md (TASK-1336) (#484)
PR #482 / TASK-1334 added the --schema flag to `pad collection create`. PR #483 / TASK-1335 wired it through MCP. Agents reading the live SKILL.md (embedded in the binary) need to see the new path or they'll keep reaching for --fields DSL and hit the original BUG-1284 symptom. Updates: - skills/pad/SKILL.md "Collections" section: now shows both --fields DSL and --schema JSON forms side-by-side. Calls out exactly when --schema is required (terminal_options et al.), and notes the label-from-key auto-fill so agents know empty labels are safe. - CLAUDE.md command list: adds the --schema variant alongside the existing --fields example so the project-level cheat sheet stays accurate. The CLI Long help (`pad collection create --help`) and the MCP tool description were already updated in TASK-1334 / TASK-1335. Parent: PLAN-1333. |
||
|
|
d1fb61097e |
docs(onboarding): document IDEA-1 trigger phrase across README, CLAUDE.md, and /pad skill (TASK-1138) (#406)
* docs(onboarding): document the IDEA-1 trigger phrase across README, CLAUDE.md, and the /pad skill (TASK-1138) Make the seeded onboarding entry point (PLAN-1131) discoverable in every doc surface a fresh user might land on. README.md Quick Start gains a follow-up paragraph after `pad init`. Names the trigger phrase verbatim so a copy-paste lands deterministically. Tone matches in-product hint copy from PR #403; no "tutorial" / "lesson" language. CLAUDE.md Authentication section gets a paragraph after `pad auth setup` pointing developers + agents at the same trigger phrase. Also enumerates the four seeded refs (IDEA-1 / PLAN-2 / TASK-3 / DOC-4) for context, with pointers to the source-of-truth code (internal/collections/templates_onboarding.go) and design history (PLAN-1131). skills/pad/SKILL.md Adds a bullet under the Onboarding routing section: an explicit "use pad to get IDEA-1" trigger and the schema-aware terminal-status guidance per collection (Ideas → implemented, Plans → completed, Tasks → done, Docs → archived). Frames the seed items as ordinary items the agent reads and acts on — no "onboarding mode" — so the no-marker / no-skill-detection design from PLAN-1131 stays clean. pad-web (../pad-web) is intentionally not touched — separate repo per CONVE-159. Spawned TASK-1142 to pick up the pad-web getting-started flow as a follow-up. Parent: PLAN-1131. Origin: IDEA-1128. * fix(docs): scope the IDEA-1 hint to post-workspace-creation, not bootstrap setup, per Codex review (round 1) Codex caught that the original wording suggested users could go straight to `use pad to get IDEA-1` after `pad auth setup`. But `pad auth setup` only creates the first admin account — no workspace. IDEA-1 is only seeded when a `startup`-template workspace is created (`pad init` or `pad workspace init`). Tightened to call out the precondition explicitly: a startup-template workspace must exist before the trigger phrase resolves. Spawned TASK-1143 to fix the matching CLI hint behavior — PR #403's `printIdeaOneTriggerHint` after `pad auth setup` has the same imprecision and should either drop the IDEA-1 mention or point users at `pad init` first. Out of scope for this docs PR. |
||
|
|
273d75c06e |
docs(mcp): refresh README + SKILL.md for v0.2 surface (TASK-976) (#359)
Updates the in-repo documentation to match what shipped in PLAN-969: - README.md's MCP section now describes the v0.2 catalog (8 tools, resource × action shape) instead of the retired v0.1 verb explosion. Documents both stability constants (CmdhelpVersion 0.1 + ToolSurfaceVersion 0.2) and points consumers at the structured error envelope contract. - skills/pad/SKILL.md gets a one-line callout that the MCP surface is hand-curated and distinct from the CLI verb tree this skill drives. Prevents future "I added a CLI command, why isn't it in MCP?" confusion. - CLAUDE.md was already updated in TASK-981; verified to match. Companion change for getpad.dev/mcp/local lives in ../pad-web. Parent: TASK-976 → PLAN-969. |
||
|
|
5e27989ab8 |
feat(attachment): add pad attachment view|show|list CLI surfaces (IDEA-898) (#321)
* feat(attachment): add `pad attachment view|show|list` CLI surfaces (IDEA-898) Agents and CLI users had no first-class way to fetch attachment bytes through the API: the only path to read an `` reference was to read the raw blob out of `~/.pad/attachments/<storage_key>`, which bypasses workspace ACLs, doesn't work on Pad Cloud / remote / Postgres deployments, skips the variant pipeline (TASK-872 / TASK-879 / TASK-880), and breaks when storage moves to S3. Three new subcommands wrap the existing REST endpoints: - `pad attachment view <id> [-o path]` — agent-friendly: with no `-o`, fetches to a fresh OS temp directory using the stored filename and prints just the absolute path on stdout (so `$(pad attachment view <id>)` composes cleanly into shell pipelines). Reuses `download`'s atomic temp-then-rename pattern via a shared helper. - `pad attachment show <id>` — HEAD-based metadata only; surfaces MIME, size, filename, ETag, Last-Modified. - `pad attachment list [--item REF] [--category X] [--attached|--unattached] [--collection ID] [--sort ...] [--limit N] [--offset N]` — workspace list. The `--item REF` flag resolves a TASK-5-style ref to a UUID client-side and passes it to a new `item_id` query param on the list endpoint (server side: AttachmentListFilters.ItemID, ~6 lines in the store + 1 in the handler). Skill update: `skills/pad/SKILL.md` gains a "Working with attachments" subsection plus a CLI Reference entry, both ending in the hard rule that agents must NEVER read directly from `~/.pad/attachments/`. * style(cli): gofmt AttachmentListParams field alignment CI's golangci-lint v2 flagged this with the gofmt formatter (configured with simplify: true in .golangci.yml). The contiguous Sort/Limit/Offset block at the end of the struct needs uniform column alignment — gofmt considers the doc comment above Sort attached to that field rather than a block separator, so the three int/string fields get aligned together. Verified locally with `golangci-lint run --timeout=5m ./...` (v2.11.4 to match CI) — 0 issues. Local make lint only runs `go vet ./...` and `golangci-lint` wasn't installed, which is why this slipped through; filing a separate follow-up to mirror the CI checks in the local workflow. |
||
|
|
7cda0d7896 |
feat: rebrand to Perpetual Software + new tagline (IDEA-832) (#273)
Migrates from xarmian/pad to PerpetualSoftware/pad across the entire
repo and updates the product subtitle to "Collaborate with your AI
agents".
Go module rename
- go.mod: github.com/xarmian/pad → github.com/PerpetualSoftware/pad
- All Go imports updated across cmd/pad, internal/{cli,server,store,
models,collections,items,events,metrics,webhooks} (~130 files)
- Test fixtures with the literal repo slug ("xarmian/pad" in JSON
shapes, SSH/HTTPS git URL strings, workspace_context fixtures)
also updated, including the secondary repo entry
(xarmian/pad-web → PerpetualSoftware/pad-web — pad-web was also
moved to the org per branch context)
Docs / config
- README badges, install instructions, brew tap, Docker image, source
build path, sponsor link (sponsor link kept as personal @xarmian)
- Subtitle: "Project management for developers and AI agents." →
"Collaborate with your AI agents." (README, manifests, web layout
meta, .goreleaser homebrew description)
- CONTRIBUTING.md, SECURITY.md, skills/INSTALL.md
- .goreleaser.yaml: homebrew_casks owner, GHCR image, release github
owner, cosign cert-identity regex, comments
- .github/workflows/release.yml: tap/release comments
- deploy/k8s/deployment.yaml: container image
- docs/deployment.md: clone URL
- web/static/{site.webmanifest,manifest.json}: description
- web/src/routes/+layout.svelte: meta description + og:description
Brew tap path is PerpetualSoftware/tap/pad (CamelCase, matches
GitHub user case). GHCR image is ghcr.io/perpetualsoftware/pad
(lowercased per GHCR's URL normalization). CODEOWNERS @xarmian and
FUNDING.yml github: xarmian intentionally retained — those are the
personal maintainer / sponsor account, separate from the org repo.
Verification: go build ./..., go test ./... (all pkgs pass), web
build, and make install all clean (TASK-844, TASK-845).
|
||
|
|
4d02616d54 |
refactor(skill): generalize /pad for domain-agnostic workspaces (TASK-613) (#145)
* refactor(skill): generalize /pad for domain-agnostic workspaces (TASK-613) The /pad skill is baked into the binary and runs the same regardless of whether the workspace is a software project, a hiring pipeline, or a research notebook. This change strips the software-centric framing without losing any dev workflow — dev-specific rules that used to live in SKILL.md are already shipped as conventions by the software templates (TASK-612). Changes ------- - Always-on conventions blurb now frames trigger vocabulary as workspace-dependent and gives non-software examples (anonymize candidate names, always cite sources). - "Before Performing Work" no longer hardcodes on-commit / on-pr-create as if they were universal. Replaced with a generic X→on-X mapping and a note that each template defines its own trigger set, with the software set called out as the common case. - "Creating items" examples mix dev and non-dev patterns and add a guiding note to match intent to the workspace's actual collections. - Planning workflow drops "Each task should be PR-sized" — replaced with a domain-neutral sizing guideline (software=PR, hiring=loop, research=question, etc.). PR-sizing for software workspaces is captured in the template's conventions. - Onboarding workflow now prefers the template's onboarding playbook as its first step, falls back to the codebase scan only when a playbook isn't present or is software-flavored. Makes room for hiring/interviewing/research templates to ship their own onboarding flows without skill churn. - Key principle #7 ("Keep it practical — tasks should be PR-sized") rewritten to reference the workspace's conventions. No CLI, API, or store changes — skill file only. Parent: PLAN-609. * fix(skill): replace literal on-X placeholder, include playbook triggers Per Codex review on PR #145: - The on-X placeholder in the pre-action example commands would be run literally by an agent and return 0 results, causing required conventions to be skipped. Replaced with explicit <trigger> angle- bracket placeholders plus concrete examples (on-implement, on-commit, on-review) an agent can substitute or run directly. - Software playbooks use a slightly different trigger vocabulary from software conventions (on-triage, on-release, on-review, on-deploy, manual). Updated the \"inspect the schema\" guidance to call out that agents should inspect BOTH the Conventions and Playbooks schemas to discover triggers, not the Conventions one alone. |
||
|
|
bde15d45ca |
Rename Phases to Plans, clean up deprecated aliases (#71)
* Rename "Phases" to "Plans" and clean up deprecated phase aliases
Renames the default "Phases" collection to "Plans" across the full stack:
- DB migration renames existing collections in-place (name, slug, prefix PLAN, icon 🗺️)
- Removes all deprecated Phase* backward-compat aliases from models and store
- Removes --phase CLI flag (use --parent instead)
- Updates convention triggers: on-phase-start/complete → on-plan-start/complete
- Updates dashboard API: active_phases → active_plans, /phases-progress → /plans-progress
- Updates all frontend components, types, and documentation
Closes IDEA-124
* Fix CSRF cookie not being cleared on logout
The SessionAuth middleware was re-issuing a CSRF cookie before the
logout handler could clear it, resulting in two Set-Cookie headers.
Skip CSRF re-issue for /api/v1/auth/ paths since auth endpoints
manage their own CSRF cookies (login sets, logout clears).
* Fix migration issues found in Codex review
- P1: Move doc_type UPDATE from migration 024 into 025, which recreates
the table with the new CHECK constraint first (SQLite enforces CHECK
on UPDATE, so the old constraint would reject 'plan')
- P1: Add PostgreSQL migration 005 for the collection rename (phases →
plans) — previously only existed on the SQLite path
- P2: Recreate FTS triggers, indexes, and rebuild FTS after the table
swap in migration 025 (DROP TABLE drops associated objects in SQLite)
* Fix parent filter field name and sync .agents skill copy
Codex review round 2 findings:
- P1: Parent filter compared against `parent_id` (wrong) instead of
`parent_link_id` — plan filtering in collection view was broken
- P1: .agents/skills/pad/SKILL.md still had old --phase flags and
"Phases" references — synced from the updated .claude copy
- P2: Accept legacy 'phase' filter key for backward compat with
existing saved views that serialized the old key name
* Fix PG migration JSONB casting and add slug collision guards
Codex PR review bot findings:
- P1: PostgreSQL REPLACE/LIKE don't work on JSONB columns — cast
schema::text and fields::text before string ops, then back to ::jsonb
- P1: If a workspace already has a custom 'plans' collection, the
rename hits UNIQUE(workspace_id, slug) — added NOT EXISTS guard
to both SQLite and PostgreSQL migrations
|
||
|
|
063ff92d00 |
feat: generalized parent/child items with progress tracking (#70)
* feat: generalize parent/child items — any item can have children with progress tracking
Replaces the phases-only task widget with a generalized parent/child system.
Any item (Phase, Idea, Doc, Task, etc.) can now be a parent of child items,
getting automatic progress bars, burndown charts, status grouping, drag-drop
reordering, and recursive expand/collapse up to 3 levels deep.
DB: migrate link_type 'phase' → 'parent' (migration 023)
Store: generalized methods (GetChildItems, GetItemProgress, SetParentLink
with cycle detection), drop collection filters, per-child terminal status
API: new /items/{slug}/children and /items/{slug}/progress endpoints
Frontend: ChildItems, ChildChart, NestedChildren components replace PhaseTasks
CLI: --parent flag (--phase kept as hidden alias), list/show/changelog updated
Docs: CLAUDE.md, SKILL.md, pad-web updated for parent/child model
Full backward compatibility: old 'phase' link_type, --phase flags, phase_id/
phase_ref JSON fields all still work as deprecated aliases.
Closes PHASE-16 (9 tasks).
* fix: update collection list page to use item_id from phasesProgress response
The TS client return type changed from phase_id to item_id but the
collection list page still referenced p.phase_id, causing svelte-check
type errors in CI.
* fix: address Codex review findings — PG migration, terminal statuses, metrics, CSRF resilience
- Add PostgreSQL migration 003 to rename 'phase' links to 'parent'
- Use schema-defined terminal statuses in GetAllItemProgress instead of hardcoded defaults
- Pass computed terminal statuses from page to ChildItems component
- Only special-case 'parent' field key when not defined in collection schema
- Move MetricsMiddleware before Recoverer so panics are counted
- Always mount ChildItems for SSE subscriptions even with 0 children
- Exclude soft-deleted children from has_children enrichment query
- Re-issue CSRF cookie when session is valid but cookie is missing
- Show actual API error messages in create-item toasts
|
||
|
|
edd259b1b0 |
feat: role board — cross-collection view, dashboard breakdown, agent bindings (#60)
* feat: role board — cross-collection view, dashboard breakdown, agent bindings (#PHASE-11)
Add a standalone role board page showing all work organized by agent
role across every collection. This is the "human orchestrator" view —
see at a glance what's queued for each capability and who's working it.
Agent bindings:
- Add `tools` text field to agent_roles table (migration 019)
- CLI: `pad role create "Implementer" --tools "Claude Code + Sonnet"`
- Lightweight notes about preferred tools — no per-user binding table
Dashboard role breakdown:
- `pad project dashboard` now includes `by_role` section
- Shows item count, assigned users, and tools per role
- CLI renders role summary table with icons
Role board API:
- `GET /workspaces/{ws}/roles/board` — items from all collections grouped by role
- Filters terminal-status items (done, cancelled, etc.)
- Supports `?assigned_user_id=X` for "my work" filtering
- Returns role info, items, and assigned user list per lane
Web UI:
- New page at /{workspace}/roles with horizontal lane layout
- Collection badges on cards (items span collections)
- "My Work" toggle to filter by current user
- Empty states for no roles and empty lanes
- Sidebar nav: 🎭 Roles link added
- Responsive: stacks vertically on mobile
Skill:
- References role board in greeting and "who's working on what" patterns
* feat: add assignment picker to item detail page
Replace read-only assignment display with interactive dropdowns for
assigning users and roles directly from the item detail page.
- User dropdown populated from workspace members
- Role dropdown populated from agent roles
- Either can be set or cleared independently
- Saves immediately on change via PATCH API
- Added assigned_user_id/agent_role_id/clear_* to ItemUpdate type
* feat: add role management UI to roles page
Add a "Manage" toggle in the role board header that reveals an inline
panel for creating, editing, and deleting roles directly from the UI.
- Role cards show icon, name, description, tools, and item count
- Edit inline: name, icon, description, tools
- Create new roles with a dashed card form
- Delete with confirmation dialog
- Board auto-refreshes after changes
* refactor: replace inline role management with dialog modal
The inline horizontal card grid was cramped and hard to use. Replace
with a proper <dialog> modal that opens from the ⚙ Manage button.
- Vertical list of role rows with icon, name, description, tools, item count
- Inline edit mode per row with labeled fields
- Create new role form at the bottom with clear field labels
- Click backdrop or ✕ to close, board refreshes on close
- Native dialog handles backdrop, escape key, and focus trapping
* fix: role board mobile layout matches collection kanban, unassigned first
- Unassigned lane now appears first (before role lanes)
- Mobile: horizontal swipe with scroll-snap at 75vw columns, matching
the collection BoardView pattern (no vertical stacking)
* feat: add drag-and-drop between role board lanes
Items can now be dragged between role lanes to reassign their role.
Uses svelte-dnd-action matching the collection BoardView pattern.
- Drag items between role lanes to change role assignment
- Drag to Unassigned lane to clear role
- Drop target highlight on hover
- Touch support with 500ms delay (same as collection board)
- Haptic feedback on mobile drag start
- Board refreshes after drop to sync server state
* fix: auto-assign user on drag to role lane, show unassigned in My Work
- When dragging an unassigned item into a role lane, automatically
assign the current user alongside the role
- "My Work" filter now shows items assigned to you OR items with no
user assignment, so unassigned work remains visible and claimable
* fix: three-state filter on role board — All, My Work, Unassigned
Replace the My Work toggle with a segmented button group offering
three filter modes:
- All: show everything (default)
- My Work: items explicitly assigned to the current user
- Unassigned: items with no user assignment
* fix: replace filter buttons with Highlight Mine toggle
Remove the three-state filter (All/My Work/Unassigned) and replace
with a single "Highlight Mine" toggle that dims cards not assigned
to the current user. All items remain visible and draggable — your
items just visually pop while others fade to 35% opacity (hovering
restores to 70%).
* fix: resolve undefined loadBoard and myWorkOnly in role board page
Replace 6 references to nonexistent `loadBoard()` with `loadData()`
(the actual data-loading function), and replace `myWorkOnly` with
`highlightMine` (the actual state variable). Fixes svelte-check errors
that caused CI Web Build to fail.
* fix: role breakdown pointer aliasing and terminal status filtering
P1: Copy role.ID to a local variable before taking its address in
GetRoleBreakdown, avoiding potential pointer aliasing from the range
variable (safe in Go 1.22+ but clearer with an explicit copy).
P2: Add terminal status exclusion to the GetRoleBreakdown SQL query
so dashboard counts match the board view. Previously, done/completed/
cancelled items were included in role counts, inflating active load.
Addresses Codex review comments on PR #60.
|
||
|
|
9fedbe4ad6 |
feat: skill role awareness + role-specific conventions (#59)
* feat: skill role awareness + role-specific conventions (#PHASE-10) Make the /pad skill role-aware so agents know what role they're acting as and load conventions scoped to that role. Role context lives in the conversation — no server state, no files, no new CLI commands. Skill changes: - Ask for role on first invocation when roles exist - Parse "as <role>" inline: /pad as implementer, /pad what's next as reviewer - Auto-filter work queue by active (user, role) pair - Role-aware greeting: "Working as 🔨 Implementer. Your queue: ..." - Load role-specific + global conventions before performing work - Support mid-session role switching - Updated CLI reference: --role/--assign flags, pad role commands, --comment best practice Convention schema: - Migration 018: add optional `role` field to Conventions collection - Conventions with a role value apply only to that role - Conventions without a role apply to all (backward compatible) - Updated defaults.go with role field * fix: use json_insert for conventions role field migration Replace fragile REPLACE() on exact JSON string literal with SQLite's json_insert(schema, '$.fields[#]', ...) which appends the role field regardless of field order or custom fields in the schema. Adds a NOT EXISTS guard via json_each() to skip if role already present. Also adds role field to shared conventions template for non-default workspace templates, and regression tests for schema seeding. Addresses Codex review comment on PR #59. |
||
|
|
998716ae49 |
feat: unified item timeline with comment-on-update, threading, and reactions (#54)
* feat: unified item timeline with comment-on-update, threading, and reactions (IDEA-115) Replace the separate Comments section and Version History modal on the item detail page with a single chronological timeline that interleaves comments, activities, and content versions. Key changes: - Add --comment flag to `pad item update` so agents/users can explain status changes inline (creates a comment linked to the activity) - Add threaded replies (parent_id on comments) with inline reply UI - Add emoji reactions on comments (new comment_reactions table) - New /timeline API endpoint merges comments, activities, and versions server-side with dedup and collapsing of rapid edits - New Svelte timeline components: ItemTimeline, TimelineCommentCard, TimelineActivityCard, TimelineVersionCard, ReactionPicker - Remove Implementation Notes and Decision Log inputs from web UI - Update skill docs to encourage --comment on status changes * fix: address review findings for PR #54 (iteration 1) - Use ListItemVersions instead of ListVersions in timeline endpoint so item content history renders correctly - Add workspace validation to reply and reaction handlers to prevent cross-workspace comment mutation - Raise activity cap from 500 to 10000 to avoid silently truncating long timelines - Fix toggleReaction to always POST (idempotent) instead of incorrectly matching other users' reactions for DELETE - Await onReply promise before clearing draft to prevent duplicate submissions and lost drafts on failure - Register reaction_added/reaction_removed in SSE ITEM_EVENTS so reactions from other sessions appear in real-time Co-Authored-By: Claude <noreply@anthropic.com> * fix: address review findings for PR #54 (iteration 2) - Fix nil pointer dereference in timeline handler when item not found - Store empty string instead of NULL for reaction user_id so UNIQUE constraint works correctly in SQLite - Add workspace validation to handleDeleteComment (cross-workspace deletion was possible) - Fix SKILL.md duplicate numbering (4. appeared twice) - Remove || true debug artifacts from reaction conditionals - Replace SvelteMap with plain Map in non-reactive groupReactions - Use != null checks for timeline API params to handle offset=0 - Log warning on comment creation failure during item update Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
89db556e29 | feat(server): add info command for TASK-134 (#52) | ||
|
|
f5649b912e | refactor(cli): group first-release commands for TASK-127 (#45) | ||
|
|
a219f81633 |
fix: CLI and skill file now use issue IDs (TASK-5) instead of slugs (#15)
Agents were using verbose slugs because: 1. The skill file (SKILL.md) taught them to use `<slug>` in every example 2. CLI output showed slugs in parentheses rather than issue IDs 3. CLI usage strings said `<slug>` not `<ref>` 4. JSON output lacked a `ref` field, so agents parsing JSON only saw slugs Changes: - Add computed `ref` field to Item model (e.g. "TASK-5") in JSON output - CLI create/update/delete/edit output now prominently shows issue IDs - All CLI usage strings changed from `<slug>` to `<ref>` - Issue IDs displayed in bold cyan (not dim) in list/show/grouped views - Skill file rewritten to use issue IDs in all examples and instructions - Dashboard API includes `item_ref`/`ref` in attention, suggestions, phases - Search results now include item_number and collection_prefix for refs - CLAUDE.md updated to document issue ID usage |
||
|
|
4708e5bacf |
docs: Update README, SKILL.md, CLAUDE.md, and add GitHub templates
README: Complete rewrite with value proposition, comparison table, feature showcase, installation guide, architecture diagram, CLI reference. SKILL.md: Add standup, changelog, watch, dependencies, and webhooks to the agent skill so AI tools know about new capabilities. CLAUDE.md: Document webhooks package, new API endpoints, and all new CLI commands. GitHub templates: Bug report and feature request issue templates (YAML), pull request template with checklist. |
||
|
|
d318ecf7fc |
Add workspace onboarding: CLI hints, web checklist, codebase detection, and relation field fix
- Print suggested /pad prompts after `pad init` creates a new workspace - Add `pad onboard` command that detects project tooling (language, build system, test runner, CI, linter) and suggests matching conventions from the library - Replace empty workspace welcome box with OnboardingChecklist component showing a 4-step guided setup with progress bar and /pad prompt hints - Add contextual tips with /pad prompts to empty collection states - Add onboarding workflow to /pad skill for agent-driven codebase analysis - Fix relation fields storing slugs instead of UUIDs: server now resolves slugs/refs to UUIDs for relation-type fields on both create and update |
||
|
|
81579847c6 |
Initial release
Pad — project management for developers and AI agents. Single Go binary with embedded SvelteKit web UI, SQLite storage, CLI, and Claude Code /pad skill integration. https://getpad.dev |