Repository navigation
feat(sdk): scaffold the schema capability (custom item type/field/migration starter) - #355
Conversation
…ration starter) Add `schema` to the `pm package init` / `pm extension init` `--capability` selector so authors can start from a custom item type, item field, and migration — the keystone capability for modeling a project domain. Before this, the scaffolder covered 4 of the SDK's 9 capabilities (commands/hooks/search/importers); it now covers 5. The schema starter registers a custom item type, item field, and migration via `api.registerItemTypes`/`registerItemFields`/`registerMigration` plus the base ping command, and ships a runnable `node:test` suite that exercises `assertRegisteredItemType`/`assertRegisteredItemField`/`assertRegisteredMigration` and `runRegisteredMigrationForTest`, with README `define*` guidance (`defineItemType`/`defineItemField`/`defineMigration`). Activation: the schema starter deliberately omits manifest `activation.commands`. A custom item type is a GLOBAL contribution that built-in commands (`pm create <type>`, `pm list`, `pm validate`) must see — commands the package does not own and cannot enumerate. Declaring narrow `activation.commands` there gates activation to only those commands and silently leaves the custom type unregistered for `pm create` (verified empirically). Omitting it lets pm's conservative activation tier (which covers `schema`) load the package for every command. The generated README documents this with a `## Activation` section in place of the lazy-activation contract the command-bearing starters use. Also: drift-proof the zsh/fish `--capability` completion lists by interpolating `SCAFFOLD_CAPABILITIES`, and document `--capability schema` in EXTENSIONS.md, SDK.md, and help-content for both `package init` and `extension init`. pm: closes pm-d1ig (feature), pm-mdw6/pm-x3vi/pm-pwf1 (tasks), pm-halx (activation decision); follow-ups pm-i5p5 (renderers/parser/preflight/services starters) and pm-ok47 (doctor warning for schema + narrow activation.commands). Epic pm-ugqx. Validation: - temp-dir smoke: generated node:test 3/3 pass, tsc --noEmit exit 0, pm create <type> + alias + bundled ping + package doctor (0 warnings) all green - all 5 capabilities scaffold cleanly (regression smoke); pm validate ok - full suite 248 files / 5006 tests at 100/100/100/100 coverage - static-quality, docs-skills, and changelog:pm:check gates green Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhXvQcAsibdH7Ap5LRKtuc
|
@coderabbitai full review /gemini review @codex review |
|
To use Codex here, create a Codex account and connect to github. |
|
Warning Review limit reached
More reviews will be available in 29 minutes and 7 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (23)
📝 WalkthroughWalkthroughAdds a new ChangesSchema scaffold capability implementation
PM agent tracking records
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Get PR details
gh pr view 355 --repo unbraind/pm-cli --json title,body,files,additions,deletions,changedFiles
echo "---FILES---"
gh pr diff 355 --repo unbraind/pm-cli 2>/dev/null | head -3000Length of output: 99036
Findings1.
|
There was a problem hiding this comment.
Code Review
This pull request introduces the new schema capability to the pm package/extension init scaffolder, enabling developers to generate starter templates for custom item types, fields, and migrations. Notably, the schema starter omits activation.commands from its manifest to leverage conservative activation, ensuring that custom types are globally registered and accessible to built-in commands. The changes also include updated documentation, shell completion support, and comprehensive unit tests. The review feedback suggests a valuable improvement: conditionally populating the aliases array for the generated item type to prevent redundant self-aliases when the extension name does not contain hyphens.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const itemTypeName = extensionName; | ||
| const itemTypeFolder = `${extensionName}s`; | ||
| const itemTypeAlias = extensionName.replace(/-/g, ""); | ||
| const fieldName = `${extensionName.replace(/-/g, "_")}_note`; | ||
| const migrationId = `${extensionName}-0001-init`; |
There was a problem hiding this comment.
If the extensionName does not contain any hyphens (e.g., todo), itemTypeAlias will be identical to itemTypeName. Registering an alias that is identical to the item type name is redundant and can cause validation errors or infinite loops in alias resolution depending on how pm handles aliases. We should conditionally populate the aliases array only when the alias differs from the type name.
const itemTypeName = extensionName;
const itemTypeFolder = `${extensionName}s`;
const itemTypeAlias = extensionName.replace(/-/g, "");
const aliases = itemTypeAlias !== itemTypeName ? [itemTypeAlias] : [];
const fieldName = `${extensionName.replace(/-/g, "_")}_note`;
const migrationId = `${extensionName}-0001-init`;| " {", | ||
| ` name: ${JSON.stringify(itemTypeName)},`, | ||
| ` folder: ${JSON.stringify(itemTypeFolder)},`, | ||
| ` aliases: [${JSON.stringify(itemTypeAlias)}],`, |
| const itemTypeName = extensionName; | ||
| const itemTypeFolder = `${extensionName}s`; | ||
| const itemTypeAlias = extensionName.replace(/-/g, ""); | ||
| const fieldName = `${extensionName.replace(/-/g, "_")}_note`; | ||
| const migrationId = `${extensionName}-0001-init`; |
There was a problem hiding this comment.
Similarly, define the aliases array conditionally here to prevent redundant self-aliases in the generated README/define builder guidance.
const itemTypeName = extensionName;
const itemTypeFolder = `${extensionName}s`;
const itemTypeAlias = extensionName.replace(/-/g, "");
const aliases = itemTypeAlias !== itemTypeName ? [itemTypeAlias] : [];
const fieldName = `${extensionName.replace(/-/g, "_")}_note`;
const migrationId = `${extensionName}-0001-init`;| "export const itemType = defineItemType({", | ||
| ` name: ${JSON.stringify(itemTypeName)},`, | ||
| ` folder: ${JSON.stringify(itemTypeFolder)},`, | ||
| ` aliases: [${JSON.stringify(itemTypeAlias)}],`, |
There was a problem hiding this comment.
Code Review
This pull request adds the "schema" capability to the "pm package/extension init" command, enabling the scaffolding of custom item types, fields, and migrations. To ensure global availability of these custom types to built-in commands, the scaffolded manifest deliberately omits "activation.commands", allowing conservative activation. The changes also update the documentation, shell completion scripts, and test suites to support and verify this new capability. There are no review comments, so I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
… pluralization
Address review feedback on the generated schema starter:
- The generated migration comment said "per-item rewrite", but pm runs each
migration ONCE (it is a run-once schema operation, not a per-item callback):
the run context identifies the migration itself, so `context.id` is the
migration id (not an item id), and authors iterate the corpus themselves via
`context.pm_root`. Reword the comment to state this accurately so the starter
does not mislead authors about `context.id`.
- Add a reminder comment on the generated item-type `folder` line, since naive
`${name}s` pluralization yields e.g. `focuss`/`statuss`; authors should set
their domain's canonical plural folder name.
Generated-string comments only; no behavior change. Regenerated smoke still
passes (node --test 3/3, tsc --noEmit exit 0); scaffold unit suites green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhXvQcAsibdH7Ap5LRKtuc
|
Thanks for the thorough review. Addressed in 0ce4d90: 1. Migration 2. Naive folder pluralization (low) — Added a 3. CHANGELOG "Other" ordering (nit) — Re-verified after the change: regenerated schema scaffold passes @coderabbitai full review /gemini review |
|
Triggering the full review now. ✏️ Learnings added
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Code Review
This pull request implements the schema capability for the package and extension scaffolding command (pm package/extension init --capability schema). This capability generates a starter template that registers a custom item type, a custom item field, and a schema migration using the SDK builders. Crucially, the generated manifest omits activation.commands to ensure that custom types are registered globally and remain available to built-in commands like pm create. The changes also include updated documentation, shell completion scripts, and comprehensive unit tests. As there are no review comments provided, I have no feedback to address.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
When a schema starter's extension name has no hyphen (e.g. "todo"), the de-hyphenated short alias equals the item type name. Registering an alias identical to the type name is a redundant self-alias that adds noise to the generated starter and can confuse alias resolution. Both scaffold paths — the imperative activate() body (buildActivateBodyLines) and the package README define* snippet (buildStarterExtensionScaffoldFiles) — now emit an empty aliases array in that case and keep the useful short alias only for hyphenated names (e.g. "my-todo" -> ["mytodo"]). Addresses gemini-code-assist review findings on #355. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TAMJXaMdNwGzsfgmoo44L6
|
Thanks @gemini-code-assist — good catch on the redundant self-alias. Addressed in 8a553c1. Both scaffold paths now compute @coderabbitai full review /gemini review @codex review |
|
To use Codex here, create a Codex account and connect to github. |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Code Review
This pull request implements the schema scaffold capability for pm package/extension init, allowing developers to generate starters with custom item types, fields, and migrations. Notably, the generated manifest for the schema capability omits activation.commands to ensure the custom types are globally registered and accessible to built-in commands via conservative activation. The changes also include updated documentation, shell completion scripts, and extensive unit tests covering the new capability. As there are no review comments provided, I have no additional feedback to offer.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Summary
Adds
schemato thepm package init/pm extension init--capabilityselector, so authors can start from a custom item type, item field, and migration — the keystone capability for modeling a project domain (project management = context management). The scaffolder now covers 5 of the SDK's 9 capabilities (was 4: commands/hooks/search/importers).pm package init my-tracker --capability schemagenerates a starter that:api.registerItemTypes/registerItemFields/registerMigration(plus the base ping command)node:testsuite exercisingassertRegisteredItemType/assertRegisteredItemField/assertRegisteredMigration+runRegisteredMigrationForTestdefine*upgrade path (defineItemType/defineItemField/defineMigration) in its READMEKey design: schema starters omit
activation.commandsA custom item type is a global contribution that built-in commands (
pm create <type>,pm list,pm validate) must see — commands the package does not own and cannot enumerate. I verified empirically that declaring narrowactivation.commandsgates lazy activation to only those commands and silently leaves the custom type unregistered forpm create(Invalid type value). The schema starter therefore omits the field entirely so pm's conservative activation tier (which coversschema) loads it for every command. This is the deliberate exception to the lazy-activation contract introduced in #354; the generated README explains it in a## Activationsection. Recorded as decisionpm-halx.Also
--capabilitycompletion lists by interpolatingSCAFFOLD_CAPABILITIES.--capability schemainEXTENSIONS.md,SDK.md, and help-content for bothpackage initandextension init.Validation
node:test3/3 pass,tsc --noEmitexit 0,pm create <type>+ alias + bundled ping +package doctor(0 warnings) all green.pm validateok.changelog:pm:checkgates green.pm items
Epic pm-ugqx. Closes feature pm-d1ig, tasks pm-mdw6/pm-x3vi/pm-pwf1, decision pm-halx. Follow-ups: pm-i5p5 (renderers/parser/preflight/services starters), pm-ok47 (doctor warning for schema + narrow
activation.commands).🤖 Generated with Claude Code