Skip to content

feat(sdk): unified author-time preflight capstone — preflightExtension + assertExtensionPreflight - #351

Merged
unbraind merged 3 commits into
mainfrom
feat/sdk-preflight-extension-capstone
Jun 23, 2026
Merged

unbraind merged 3 commits into
mainfrom
feat/sdk-preflight-extension-capstone

Conversation

@unbraind

Copy link
Copy Markdown
Owner

Summary

Adds the SDK's author-time capstone: a single call that runs every pre-publish check for a declarative extension, the static analog of createExtensionTestHarness (which unified the runtime-test helpers). Before this, a package author had to chain lintExtensionBlueprint + synthesizeExtensionManifest + checkExtensionManifestCompatibility (and reconcile their separate results) by hand.

preflightExtension(blueprint, { identity?, target?, declaredCapabilities? }) — src/sdk/compose.ts

Pure and side-effect-free (no loading/activation/fs), exactly like the stages it composes:

  • always lints the blueprint (structural footguns + capability drift);
  • synthesizes the complete least-privilege manifest when an identity is given (so capabilities is never hand-synced);
  • version-checks against the synthesized bounds — or, absent an identity, the blueprint's in-module manifest mirror — when a target pm version is given.

Returns a consolidated ExtensionPreflightReport exposing each stage's structured result (report.blueprint / report.manifest / report.compatibility) plus a flattened, source-tagged report.findings; report.ok is false if any stage produced an error.

UX nicety (surfaced by the manual smoke test): once a manifest is synthesized, the lint's now-moot manifest_capabilities_absent advisory ("declares none…") is curated out of the consolidated report.findings — it contradicts the author-once flow that preflight itself performs. The raw report.blueprint.findings still reports it faithfully.

assertExtensionPreflight(blueprint, options?) — src/sdk/testing.ts

Throwing one-line CI/test bookend over preflightExtension: aggregates every blocking finding tagged [source:code] into one error; advisory warnings never throw; returns the full report on success. Re-exported from the SDK barrel and /sdk/testing.

SDK-only, consistent with lint/synthesize/compat (none have CLI surface).

Docs

  • docs/SDK.md: authoring + testing-helper export lists, plus a capstone prose section with examples.
  • docs/EXTENSIONS.md: author-time validation note.

Tracking

Closes pm-tcw1 (analyzer) + pm-t8yl (bookend) under feature pm-ozaf (epic pm-ugqx); related to pm-1w0d / pm-u5le / pm-9ect and the pm-jcyn runtime-test harness analog.

Verification

  • pnpm build
  • focused SDK tests (163 passing)
  • pnpm quality:static, pnpm quality:docs-skills, pnpm contracts:check, pnpm security:scan, pnpm changelog:pm:check — all green
  • full coverage: 4966 tests, 100/100/100/100
  • isolated temp node_modules/@unbrained/pm-cli symlink SDK smoke against the built dist (5 checks: clean pass, version block, assert-throws, assert clean-pass, composeExtension parity)

🤖 Generated with Claude Code

…n + assertExtensionPreflight

Add the author-time capstone that unifies the SDK's three separate
pre-publish checks into one call, the static analog of
createExtensionTestHarness (which unified the runtime-test helpers).

- preflightExtension(blueprint, { identity?, target?, declaredCapabilities? })
  in src/sdk/compose.ts: pure, side-effect-free. Always lints the blueprint;
  synthesizes the least-privilege manifest when an identity is given; runs the
  version-compat check against the synthesized (or blueprint-mirror) bounds when
  a target is given. Returns a consolidated ExtensionPreflightReport exposing
  every stage's structured result plus a flattened, source-tagged findings list.
  Once a manifest is synthesized, the now-moot manifest_capabilities_absent lint
  advisory is curated out of the consolidated view (the raw report.blueprint
  result still carries it) so the flagship author-once flow reads clean.

- assertExtensionPreflight(blueprint, options?) in src/sdk/testing.ts: throwing
  one-line CI/test bookend that aggregates every blocking finding tagged
  [source:code]; advisory warnings never throw; returns the full report on
  success. Re-exported from the SDK barrel and /sdk/testing.

Docs: SDK.md export lists + capstone prose; EXTENSIONS.md author-time note.

Tracking: closes pm-tcw1 (analyzer) + pm-t8yl (bookend) under feature pm-ozaf
(epic pm-ugqx); related to pm-1w0d/pm-u5le/pm-9ect and the pm-jcyn harness analog.

Verification: pnpm build; focused SDK tests (163); pnpm quality:static;
pnpm quality:docs-skills; pnpm contracts:check; pnpm security:scan;
pnpm changelog:pm:check; full coverage 4966 tests 100/100/100/100;
isolated temp node_modules SDK smoke against built dist (5 checks).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9qGjDPgdp6iNZ8HbKB6MQ

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @unbraind, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@unbraind

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@unbraind

Copy link
Copy Markdown
Owner Author

/gemini review

@unbraind

Copy link
Copy Markdown
Owner Author

@codex review

@coderabbitai

coderabbitai Bot commented Jun 23, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@unbraind, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 40 minutes and 49 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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: d19792f2-1a3a-4422-a9c6-c87a70d71ff7

📥 Commits

Reviewing files that changed from the base of the PR and between d2ab679 and aab9f12.

📒 Files selected for processing (14)
  • .agents/pm/features/pm-ozaf.toon
  • .agents/pm/history/pm-ozaf.jsonl
  • .agents/pm/history/pm-t8yl.jsonl
  • .agents/pm/history/pm-tcw1.jsonl
  • .agents/pm/tasks/pm-t8yl.toon
  • .agents/pm/tasks/pm-tcw1.toon
  • CHANGELOG.md
  • docs/EXTENSIONS.md
  • docs/SDK.md
  • src/sdk/compose.ts
  • src/sdk/index.ts
  • src/sdk/testing.ts
  • tests/unit/sdk/sdk-compose.spec.ts
  • tests/unit/sdk/sdk-index.spec.ts
📝 Walkthrough

Walkthrough

Adds preflightExtension(blueprint, options) to src/sdk/compose.ts and assertExtensionPreflight(blueprint, options) to src/sdk/testing.ts. Both are re-exported from the SDK barrel. Four new exported types support the report shape. Unit tests, SDK/extension docs, changelog entries, and PM tracking files are included.

Changes

SDK Preflight Capstone

Layer / File(s) Summary
Preflight types and report contracts
src/sdk/compose.ts
Exports PreflightExtensionOptions, ExtensionPreflightFindingSource, ExtensionPreflightFinding, and ExtensionPreflightReport — the full type surface for the new preflight API.
preflightExtension implementation and tests
src/sdk/compose.ts, tests/unit/sdk/sdk-compose.spec.ts
Implements preflightExtension: unconditional blueprint lint, conditional manifest synthesis (when identity is set), conditional compatibility check (when target is set), manifest_capabilities_absent advisory suppression when a synthesized manifest exists, and flattened source-tagged findings with ok driven by error-severity presence. Tests cover all conditional branches, finding order/tagging, and barrel re-export identity.
assertExtensionPreflight, barrel wiring, and tests
src/sdk/testing.ts, src/sdk/index.ts, tests/unit/sdk/sdk-index.spec.ts
Adds assertExtensionPreflight to testing.ts (aggregates error-severity findings into a single thrown Error; returns report on success), re-exports it from the SDK index barrel, and validates re-export identity, success shape, advisory non-throw, and multi-stage error aggregation in tests.
Docs, changelog, and PM tracking
docs/SDK.md, docs/EXTENSIONS.md, CHANGELOG.md, .agents/pm/...
docs/SDK.md adds both functions to public export lists and a full usage documentation block with examples. docs/EXTENSIONS.md extends pm_min_version/pm_max_version guidance to reference the new capstone. CHANGELOG.md gains three Unreleased entries. PM task, feature, and history files record lifecycle of pm-ozaf, pm-tcw1, and pm-t8yl.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • unbraind/pm-cli#347: Introduced lintExtensionBlueprint and its /sdk/testing barrel re-export, which preflightExtension calls unconditionally as its first stage.
  • unbraind/pm-cli#350: Added checkExtensionManifestCompatibility and assertExtensionManifestCompatible, which preflightExtension calls conditionally when options.target is provided and whose findings are aggregated into ExtensionPreflightReport.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding two complementary SDK functions (preflightExtension and assertExtensionPreflight) that unify author-time preflight validation.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining both the motivation (consolidating manual chaining of checks), implementation details, and verification performed.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the unified author-time preflight capstone for the SDK, adding the preflightExtension analyzer and its throwing CI/test counterpart assertExtensionPreflight. These additions consolidate blueprint linting, manifest synthesis, and version-compatibility checks into a single call. The feedback identifies a critical issue where capability drift findings from an outdated in-module manifest mirror can cause false-positive blocking errors when a manifest is synthesized; the reviewer suggests curating these findings out of the consolidated report and adding a corresponding unit test to verify this behavior.

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.

Comment thread src/sdk/compose.ts Outdated
Comment on lines +1086 to +1089
const blueprintFindings =
manifest === null
? blueprintResult.findings
: blueprintResult.findings.filter((finding) => finding.code !== "manifest_capabilities_absent");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

When preflightExtension synthesizes the manifest (i.e., manifest !== null), the capability set is derived directly from the blueprint's actual usage. Therefore, any capability drift findings (such as capability_undeclared or capability_unused) reported by lintExtensionBlueprint against the outdated/empty in-module manifest mirror are moot and should be curated out of the consolidated report.findings (just like manifest_capabilities_absent is), unless options.declaredCapabilities is explicitly provided. Otherwise, an outdated in-module mirror will cause false-positive blocking errors and fail the preflight, defeating the 'author-once' flow where capabilities are never hand-synced.

  const blueprintFindings =
    manifest === null
      ? blueprintResult.findings
      : blueprintResult.findings.filter((finding) => {
          if (finding.code === "manifest_capabilities_absent") {
            return false;
          }
          if (options.declaredCapabilities === undefined) {
            return finding.code !== "capability_undeclared" && finding.code !== "capability_unused";
          }
          return true;
        });

Comment on lines +776 to +777
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Add a unit test to verify that capability drift findings from an outdated in-module manifest mirror are correctly curated out of the consolidated findings when the manifest is synthesized.

Suggested change
});
});
});
it("omits capability drift findings from the consolidated view once the manifest is synthesized", () => {
const report = preflightExtension(
{
...commandBlueprint,
manifest: { ...identity, capabilities: [] },
},
{ identity },
);
expect(report.findings).toEqual([]);
expect(report.ok).toBe(true);
expect(report.blueprint.findings).toContainEqual(
expect.objectContaining({ code: "capability_undeclared" }),
);
});
});

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the SDK unified author-time preflight capstone. It adds preflightExtension in src/sdk/compose.ts to unify blueprint linting, manifest synthesis, and version compatibility checks into a single report, alongside its throwing CI/test counterpart assertExtensionPreflight in src/sdk/testing.ts. Both utilities are re-exported from the SDK barrel, fully documented, and backed by comprehensive unit tests. There are no review comments, and 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/SDK.md`:
- Around line 921-955: The documentation block for the preflightExtension
function is missing a tracker reference to pm-ozaf as required by the docs
guidelines. Add a tracker reference link to pm-ozaf near the top of the
preflightExtension documentation block, either immediately after the opening
line describing it as the author-time capstone, or as a separate line just
before the code example showing the usage of preflightExtension and
assertExtensionPreflight. This maintains traceability to the feature that
created this documentation change.

In `@src/sdk/testing.ts`:
- Line 2070: In the JSDoc comment block around line 2070, replace the
non-standard JSDoc link syntax `{`@link` ../sdk/compose.js#preflightExtension}`
with the standard format `{`@link` preflightExtension}` to match the consistent
style used in the rest of the documentation and improve
IDE/documentation-generator support.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 12779208-5a37-48ab-8585-c3259d084abd

📥 Commits

Reviewing files that changed from the base of the PR and between d2ab679 and f1c30ef.

📒 Files selected for processing (14)
  • .agents/pm/features/pm-ozaf.toon
  • .agents/pm/history/pm-ozaf.jsonl
  • .agents/pm/history/pm-t8yl.jsonl
  • .agents/pm/history/pm-tcw1.jsonl
  • .agents/pm/tasks/pm-t8yl.toon
  • .agents/pm/tasks/pm-tcw1.toon
  • CHANGELOG.md
  • docs/EXTENSIONS.md
  • docs/SDK.md
  • src/sdk/compose.ts
  • src/sdk/index.ts
  • src/sdk/testing.ts
  • tests/unit/sdk/sdk-compose.spec.ts
  • tests/unit/sdk/sdk-index.spec.ts

Comment thread docs/SDK.md Resolved
Comment thread src/sdk/testing.ts Resolved
…onsolidated view

Address PR #351 review feedback.

Gemini: in the author-once flow (identity given, no explicit declaredCapabilities),
the blueprint lint reconciles against the blueprint's in-module `manifest` mirror —
which the synthesized manifest supersedes. A stale mirror missing a capability raised
a *blocking* `capability_undeclared` error that falsely flipped report.ok to false,
even though the synthesized manifest declares it. Broaden the consolidated-view
curation from just `manifest_capabilities_absent` to every capability-drift code
(via CAPABILITY_DRIFT_LINT_CODES), suppressed only when synthesizing without an
explicit declaredCapabilities set (an explicit set is a deliberate "check exactly
this" request and is always honored). Structural findings are never suppressed and
the raw report.blueprint result keeps every finding.

CodeRabbit: add the pm-ozaf tracker reference to the new SDK.md capstone block
(declined the cross-module {@link ../sdk/compose.js#preflightExtension} nitpick —
file-qualified links are the codebase convention for cross-module refs, matching the
sibling assertExtensionManifestCompatible docstring).

Verification: pnpm build; focused SDK tests (165); pnpm quality:static;
pnpm quality:docs-skills; pnpm contracts:check; full coverage 4968 tests
100/100/100/100; temp-dir SDK smoke against built dist (6 checks incl. stale mirror).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9qGjDPgdp6iNZ8HbKB6MQ
@unbraind

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@unbraind

Copy link
Copy Markdown
Owner Author

/gemini review

@coderabbitai

coderabbitai Bot commented Jun 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the unified author-time preflight capstone for the SDK, adding the preflightExtension analyzer in src/sdk/compose.ts and its throwing test/CI counterpart assertExtensionPreflight in src/sdk/testing.ts. These additions consolidate blueprint linting, manifest synthesis, and version-compatibility checks into a single report or assertion. The changes also include comprehensive unit tests, documentation updates in docs/EXTENSIONS.md and docs/SDK.md, and project management tracking files. There are no review comments to address, and the implementation is clean and well-tested.

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.

Append the bot-review note to pm-ozaf: Gemini's stale-mirror capability-drift
finding (fixed in acf1621), CodeRabbit's accepted SDK.md tracker ref + declined
cross-module {@link} nitpick, Codex not connected, Sourcery weekly-capped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9qGjDPgdp6iNZ8HbKB6MQ
@unbraind

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@unbraind

Copy link
Copy Markdown
Owner Author

/gemini review

@coderabbitai

coderabbitai Bot commented Jun 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the unified author-time preflight capstone, adding preflightExtension in src/sdk/compose.ts and its throwing test counterpart assertExtensionPreflight in src/sdk/testing.ts. These utilities consolidate blueprint linting, manifest synthesis, and version-compatibility checks into a single operation. The changes also include comprehensive unit tests, documentation updates, and barrel re-exports. No review comments were provided, so there is no additional 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant