Skip to content

feat(skills): bundle remaining tools + polymorphic pins - #1499

Merged
josephfung merged 5 commits into
mainfrom
cursor/phase-2-bundle-remaining-tools-ac7f
Jul 23, 2026
Merged

feat(skills): bundle remaining tools + polymorphic pins#1499
josephfung merged 5 commits into
mainfrom
cursor/phase-2-bundle-remaining-tools-ac7f

Conversation

@josephfung

@josephfung josephfung commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #1494 (Phase 2 follow-up of epic #1436). Builds on Phase 2 (#1489) and ADR-032.

  • Polymorphic pins (ADR-032)pinned_skills may name a skill, a tool, or an MCP-projected skill. Tool pins resolve to exactly that tool (never siblings).
  • MCP-as-skill (ADR-032) — each connected MCP server projects a skill into SkillRegistry with its live tools/list membership; coordinator pins google-workspace instead of ~24 MCP tool names.
  • Native bundlesemail, ceo-inbox, contacts, autonomy, diagnostics, scheduler, web, memory, learning, context-bridge, executive-profile, setup as SKILL.md + nested tools/.
  • tasks / memoryplan + checkpoint join tasks; decay-warnings-list joins memory.
  • Agent pin migrations — owners pin bundles; narrow consumers keep individual tool pins (scheduler-report, contact-update, meeting-debrief task-*, learning producer/consumer split, etc.) so resolved authority is unchanged.
  • Startup validator now checks nested skills/<bundle>/tools/<tool>/tool.json.
  • Docs + CHANGELOG [Unreleased].

Test plan

  • Unit tests for polymorphic pins, MCP projection, contacts mixed-risk, entity-context guard, agent resolved-pin regressions
  • pnpm run typecheck (+ console typecheck)
  • pnpm run lint
  • pnpm test — 5270 passed (integration skipped: no DATABASE_URL in this environment)
  • Confirm coordinator pins google-workspace + email + contact-update without contact-lookup
  • Confirm diagnostics resolves only the three query tools (+ date-resolve / request-clarification)
  • Confirm meeting-debrief does not gain plan / checkpoint via individual task-* pins

@josephfung
josephfung marked this pull request as ready for review July 22, 2026 22:50
@josephfung

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot added enhancement New feature or request infra Deployment, monitoring, and operational tooling orchestration Multi-agent coordination — delegation, specialist agents, skill routing labels Jul 22, 2026
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This change introduces native skill bundles and manifests for multiple tool clusters, updates agent pin configurations and default enabled skills, and adds polymorphic skill/tool pin resolution. MCP servers now expose projected skills through SkillRegistry. Startup validation scans nested tool manifests, while tests cover MCP projections, bundle expansion, individual tool pins, agent tool rosters, and relocated handlers. The web browser also gains a DOM extraction module for readable content and interactable references.

Possibly related issues

  • #1436 — Implements the bundle model, polymorphic pins, MCP projections, and preserved per-tool risk described by the parent epic.

Possibly related PRs

Suggested labels: enhancement, infra, orchestration

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes cover polymorphic pins, MCP projection, native bundles, tasks and memory additions, docs, and the requested regressions.
Out of Scope Changes check ✅ Passed No obvious unrelated code changes stand out; the edits stay within skills, startup, docs, and test wiring.
Title check ✅ Passed The title is concise and accurately captures the main change: bundling remaining tools and introducing polymorphic pins.
Description check ✅ Passed The description is clearly related to the changeset and summarizes the bundling, pinning, MCP projection, tests, and docs work.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 20

🧹 Nitpick comments (1)
src/skills/pin-resolution.ts (1)

26-30: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

resolvedPins is dead weight — it’s populated and returned, but nothing in src/index.ts or the rest of src/ reads it. Either thread it into the audit/log path, or drop it before it becomes another bit of decorative allocation.

🤖 Prompt for 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.

In `@src/skills/pin-resolution.ts` around lines 26 - 30, Remove the unused
resolvedPins field from the pin-resolution result type and eliminate its
population and return handling throughout the associated resolution flow. Keep
resolvedSkills and all existing resolution behavior unchanged.
🤖 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 `@agents/research-analyst.yaml`:
- Line 2: Remove the version bump in the agent metadata, restoring the previous
version value because this change only documents existing configuration and does
not alter the pin list or agent behavior.

In `@docs/dev/adding-an-agent.md`:
- Around line 235-238: Update the `tasks` bundle member list in the
documentation to include the sibling tools `plan` and `checkpoint` alongside the
existing four tools, keeping the surrounding bundle behavior and read-only
`task-list` guidance unchanged.

In `@skills/autonomy/tools/get-autonomy/tool.json`:
- Around line 7-11: Update the tool output manifests to match their handlers: in
skills/autonomy/tools/get-autonomy/tool.json lines 7-11, add lastSetBy, trend,
and scoredActionCount; in skills/autonomy/tools/list-pending-actions/tool.json
lines 8-10, declare displayTimezone; in
skills/autonomy/tools/set-autonomy/tool.json lines 10-14, add summary and allow
previous_score to be null; and in
skills/scheduler/tools/scheduler-cancel/tool.json lines 10-12, declare jobId or
remove it from the handler response.

In `@skills/ceo-inbox/tools/ceo-inbox-download-attachment/tool.json`:
- Line 3: Update the tool description to accurately state that the output may
provide a temporary file reference instead of content_base64 when temporary-file
storage succeeds, while preserving the existing attachment ID usage and 10 MB
limit details.

In `@skills/ceo-inbox/tools/ceo-inbox-search/tool.json`:
- Line 3: Add the runtime-enforced allowed_callers restriction with the owning
caller value “ceo-inbox” to the tool manifest in
skills/ceo-inbox/tools/ceo-inbox-search/tool.json at lines 3-3 and apply the
same restriction in skills/ceo-inbox/tools/ceo-inbox-update-folders/tool.json at
lines 3-3, before mailbox operations are permitted.

In `@skills/ceo-inbox/tools/ceo-inbox-sent-observe/tool.json`:
- Around line 10-16: Add the missing boolean output fields backfill_active and
tasks_truncated to the outputs contract in the ceo-inbox-sent-observe tool
manifest, matching the values returned by the handler’s sent-observe flow. Keep
the existing output fields unchanged.

In `@skills/contacts/tools/approve-grant-recommendation/tool.json`:
- Around line 5-6: Update the tool’s action_risk configuration from "low" to
"critical" so the immediate permission-grant approval uses the strongest
confirmation path. Preserve the existing sensitivity setting and other tool
configuration.

In `@skills/contacts/tools/contact-create/tool.json`:
- Around line 23-25: Add the required top-level "capabilities": [] field before
"timeout" in both skills/contacts/tools/contact-create/tool.json lines 23-25 and
skills/contacts/tools/contact-grant-permission/tool.json lines 17-19, preserving
the existing manifest structure.

In `@skills/contacts/tools/scan-grant-recommendations/tool.json`:
- Around line 20-23: Update the tool manifest’s caller restriction by adding the
required schedule-only allowed_callers configuration alongside capabilities in
the tool definition. Ensure the manifest contract permits invocation only by the
scheduler and prevents agents from calling the recommendation scan during user
requests.

In `@skills/context-bridge/tools/context-bridge-clear/tool.json`:
- Around line 7-10: The tool manifest’s inputs currently makes both alternative
fields required. Update the input definition for subjects and subject so callers
may provide either one, while preserving their existing types and mutual
alternative semantics.

In `@skills/context-bridge/tools/context-bridge-release/tool.json`:
- Around line 7-14: Update the manifest schema in the inputs and outputs
definitions: mark reply as optional to match the handler’s accepted release
requests, and make task_id optional because ordinary releases do not return it.
Keep entry_id and released required, preserving the existing types.

In `@skills/diagnostics/tools/audit-query/tool.json`:
- Around line 17-23: Update the outputs schema in the audit-query manifest so
displayTimezone is optional, matching the handler’s undefined result when no
timezone is available. Preserve its string type for responses that do provide a
timezone.

In `@skills/diagnostics/tools/audit-trace/tool.json`:
- Line 20: Make the displayTimezone property optional in the manifests for
audit-trace at skills/diagnostics/tools/audit-trace/tool.json:20-20 and
ops-lookup at skills/diagnostics/tools/ops-lookup/tool.json:26-26, so both tool
contracts allow handlers to omit it when timezone context is unavailable.

In `@skills/email/tools/email-download-attachment/tool.json`:
- Line 3: Update the tool description in tool.json to accurately document that
the output may provide temp_file_url instead of content_base64 when a temporary
file URL is available. Align the main description with the output fields
documented on lines 13-14, and remove the unconditional instruction to pass
content_base64 directly to file-parse.

In `@skills/email/tools/email-draft-save/tool.json`:
- Around line 13-14: Remove the unused export_items field from the tool schema
until EmailDraftSaveHandler and its gateway path read and forward it; update the
associated schema or contract test to ensure callers are not promised
unsupported export-control behavior.

In `@skills/learning/tools/list-learning-digest/tool.json`:
- Around line 3-11: Align the `list-learning-digest` manifest with the handler’s
actual empty-output behavior: update the `sections_markdown` output description
to state that it is always returned and is an empty string when no sections are
rendered. Keep the handler’s existing return shape unchanged.

In `@skills/memory/tools/memory-confirm/tool.json`:
- Around line 11-15: Remove the success field from the declared outputs in the
tool manifest, leaving only the payload fields that are actually present inside
data; keep MemoryConfirmHandler’s return behavior unchanged.

In `@skills/memory/tools/memory-store/tool.json`:
- Line 3: Update the memory-store manifest description and result schema to
match MemoryStoreHandler: include the auto_resolved and auto_rejected outcomes,
and model the ambiguous response as omitting action and stored. Mark fields that
are not present on every outcome as conditional/optional, while preserving the
existing contracts for created, updated, conflict, entity_not_found, and
rate_limited.

In `@skills/tasks/tools/checkpoint/tool.json`:
- Around line 8-13: Update the checkpoint schema exposed by toToolDefinitions()
to match the runtime contract: allow cursor values as objects as well as
strings, and allow accumulator entries to be either inline slice-result objects
or spilled document-pointer objects. Preserve the optional/default behavior
while ensuring valid handler and resumable-progress payloads pass tool
validation.

In `@skills/web/tools/web-browser/dom-extract.ts`:
- Around line 90-100: Update the ref-resolution flow around __curiaRefEpoch__
and the resolver’s ref validation to maintain a handler-owned navigation
generation that changes for each new document. Encode or associate the
generation with emitted refs and reject any ref whose generation predates the
current document, rather than trusting page-controlled DOM attributes such as
__curiaRefEpoch__. Preserve valid refs within the active document while failing
closed for refs reused after navigation.

---

Nitpick comments:
In `@src/skills/pin-resolution.ts`:
- Around line 26-30: Remove the unused resolvedPins field from the
pin-resolution result type and eliminate its population and return handling
throughout the associated resolution flow. Keep resolvedSkills and all existing
resolution behavior unchanged.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 54823ecd-7890-425a-a1c6-80fb27950c96

📥 Commits

Reviewing files that changed from the base of the PR and between 7c0cca3 and 0358067.

📒 Files selected for processing (280)
  • CHANGELOG.md
  • agents/calendar.yaml
  • agents/ceo-inbox.yaml
  • agents/contacts.yaml
  • agents/coordinator.yaml
  • agents/diagnostics.yaml
  • agents/meeting-debrief.yaml
  • agents/research-analyst.yaml
  • agents/setup-wizard.yaml
  • config/registry-defaults.yaml
  • docs/dev/adding-a-tool.md
  • docs/dev/adding-an-agent.md
  • skills/autonomy/SKILL.md
  • skills/autonomy/tools/approve-action/handler.test.ts
  • skills/autonomy/tools/approve-action/handler.ts
  • skills/autonomy/tools/approve-action/tool.json
  • skills/autonomy/tools/deny-action/handler.test.ts
  • skills/autonomy/tools/deny-action/handler.ts
  • skills/autonomy/tools/deny-action/tool.json
  • skills/autonomy/tools/dismiss-action/handler.test.ts
  • skills/autonomy/tools/dismiss-action/handler.ts
  • skills/autonomy/tools/dismiss-action/tool.json
  • skills/autonomy/tools/get-autonomy/handler.test.ts
  • skills/autonomy/tools/get-autonomy/handler.ts
  • skills/autonomy/tools/get-autonomy/tool.json
  • skills/autonomy/tools/list-pending-actions/handler.test.ts
  • skills/autonomy/tools/list-pending-actions/handler.ts
  • skills/autonomy/tools/list-pending-actions/tool.json
  • skills/autonomy/tools/set-autonomy/handler.ts
  • skills/autonomy/tools/set-autonomy/tool.json
  • skills/ceo-inbox/SKILL.md
  • skills/ceo-inbox/tools/ceo-inbox-archive/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-archive/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-download-attachment/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-download-attachment/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-download-attachment/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-draft-compose/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-compose/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-compose/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-draft-edit/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-edit/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-edit/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-draft-reply/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-reply/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-reply/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-label/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-label/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-list/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-list/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-list/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-mark-read/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-mark-read/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-mark-starred/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-mark-starred/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-mark-starred/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-read/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-read/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-read/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-search/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-search/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-search/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-sent-observe/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-sent-observe/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-sent-observe/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-shadow-draft/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-shadow-draft/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-shadow-draft/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-update-folders/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-update-folders/tool.json
  • skills/contacts/SKILL.md
  • skills/contacts/tools/approve-grant-recommendation/handler.ts
  • skills/contacts/tools/approve-grant-recommendation/tool.json
  • skills/contacts/tools/contact-create/handler.ts
  • skills/contacts/tools/contact-create/tool.json
  • skills/contacts/tools/contact-dedup-exclude/handler.ts
  • skills/contacts/tools/contact-dedup-exclude/tool.json
  • skills/contacts/tools/contact-find-duplicates/handler.ts
  • skills/contacts/tools/contact-find-duplicates/tool.json
  • skills/contacts/tools/contact-grant-permission/handler.ts
  • skills/contacts/tools/contact-grant-permission/tool.json
  • skills/contacts/tools/contact-link-identity/handler.ts
  • skills/contacts/tools/contact-link-identity/tool.json
  • skills/contacts/tools/contact-list/handler.test.ts
  • skills/contacts/tools/contact-list/handler.ts
  • skills/contacts/tools/contact-list/tool.json
  • skills/contacts/tools/contact-lookup/handler.ts
  • skills/contacts/tools/contact-lookup/tool.json
  • skills/contacts/tools/contact-merge/handler.ts
  • skills/contacts/tools/contact-merge/tool.json
  • skills/contacts/tools/contact-register/handler.test.ts
  • skills/contacts/tools/contact-register/handler.ts
  • skills/contacts/tools/contact-register/tool.json
  • skills/contacts/tools/contact-rename/handler.test.ts
  • skills/contacts/tools/contact-rename/handler.ts
  • skills/contacts/tools/contact-rename/tool.json
  • skills/contacts/tools/contact-revoke-permission/handler.ts
  • skills/contacts/tools/contact-revoke-permission/tool.json
  • skills/contacts/tools/contact-set-identity-status/handler.test.ts
  • skills/contacts/tools/contact-set-identity-status/handler.ts
  • skills/contacts/tools/contact-set-identity-status/tool.json
  • skills/contacts/tools/contact-set-role/handler.ts
  • skills/contacts/tools/contact-set-role/tool.json
  • skills/contacts/tools/contact-set-tier/handler.ts
  • skills/contacts/tools/contact-set-tier/tool.json
  • skills/contacts/tools/contact-unlink-identity/handler.ts
  • skills/contacts/tools/contact-unlink-identity/tool.json
  • skills/contacts/tools/contact-update/handler.test.ts
  • skills/contacts/tools/contact-update/handler.ts
  • skills/contacts/tools/contact-update/tool.json
  • skills/contacts/tools/decline-grant-recommendation/handler.ts
  • skills/contacts/tools/decline-grant-recommendation/tool.json
  • skills/contacts/tools/delete-relationship/handler.test.ts
  • skills/contacts/tools/delete-relationship/handler.ts
  • skills/contacts/tools/delete-relationship/tool.json
  • skills/contacts/tools/query-relationships/handler.test.ts
  • skills/contacts/tools/query-relationships/handler.ts
  • skills/contacts/tools/query-relationships/tool.json
  • skills/contacts/tools/scan-grant-recommendations/handler.ts
  • skills/contacts/tools/scan-grant-recommendations/tool.json
  • skills/context-bridge/SKILL.md
  • skills/context-bridge/tools/context-bridge-clear/handler.test.ts
  • skills/context-bridge/tools/context-bridge-clear/handler.ts
  • skills/context-bridge/tools/context-bridge-clear/tool.json
  • skills/context-bridge/tools/context-bridge-release/handler.test.ts
  • skills/context-bridge/tools/context-bridge-release/handler.ts
  • skills/context-bridge/tools/context-bridge-release/tool.json
  • skills/diagnostics/SKILL.md
  • skills/diagnostics/tools/audit-query/handler.test.ts
  • skills/diagnostics/tools/audit-query/handler.ts
  • skills/diagnostics/tools/audit-query/tool.json
  • skills/diagnostics/tools/audit-trace/handler.test.ts
  • skills/diagnostics/tools/audit-trace/handler.ts
  • skills/diagnostics/tools/audit-trace/tool.json
  • skills/diagnostics/tools/ops-lookup/handler.test.ts
  • skills/diagnostics/tools/ops-lookup/handler.ts
  • skills/diagnostics/tools/ops-lookup/tool.json
  • skills/email/SKILL.md
  • skills/email/tools/email-archive/handler.ts
  • skills/email/tools/email-archive/tool.json
  • skills/email/tools/email-create-folder/handler.ts
  • skills/email/tools/email-create-folder/tool.json
  • skills/email/tools/email-download-attachment/handler.test.ts
  • skills/email/tools/email-download-attachment/handler.ts
  • skills/email/tools/email-download-attachment/tool.json
  • skills/email/tools/email-draft-save/handler.test.ts
  • skills/email/tools/email-draft-save/handler.ts
  • skills/email/tools/email-draft-save/tool.json
  • skills/email/tools/email-get/handler.test.ts
  • skills/email/tools/email-get/handler.ts
  • skills/email/tools/email-get/tool.json
  • skills/email/tools/email-label/handler.ts
  • skills/email/tools/email-label/tool.json
  • skills/email/tools/email-list-folders/handler.ts
  • skills/email/tools/email-list-folders/tool.json
  • skills/email/tools/email-list/handler.test.ts
  • skills/email/tools/email-list/handler.ts
  • skills/email/tools/email-list/tool.json
  • skills/email/tools/email-mark-read/handler.ts
  • skills/email/tools/email-mark-read/tool.json
  • skills/email/tools/email-reply/handler.test.ts
  • skills/email/tools/email-reply/handler.ts
  • skills/email/tools/email-reply/tool.json
  • skills/email/tools/email-send/handler.test.ts
  • skills/email/tools/email-send/handler.ts
  • skills/email/tools/email-send/tool.json
  • skills/email/tools/send-draft/handler.test.ts
  • skills/email/tools/send-draft/handler.ts
  • skills/email/tools/send-draft/tool.json
  • skills/executive-profile/SKILL.md
  • skills/executive-profile/tools/behavioral-preferences-update/handler.test.ts
  • skills/executive-profile/tools/behavioral-preferences-update/handler.ts
  • skills/executive-profile/tools/behavioral-preferences-update/tool.json
  • skills/executive-profile/tools/executive-profile-get/handler.ts
  • skills/executive-profile/tools/executive-profile-get/tool.json
  • skills/executive-profile/tools/executive-profile-update/handler.ts
  • skills/executive-profile/tools/executive-profile-update/tool.json
  • skills/learning/SKILL.md
  • skills/learning/tools/list-learning-digest/handler.test.ts
  • skills/learning/tools/list-learning-digest/handler.ts
  • skills/learning/tools/list-learning-digest/tool.json
  • skills/learning/tools/resolve-learning-digest/handler.test.ts
  • skills/learning/tools/resolve-learning-digest/handler.ts
  • skills/learning/tools/resolve-learning-digest/tool.json
  • skills/learning/tools/task-completion-from-sent/handler.test.ts
  • skills/learning/tools/task-completion-from-sent/handler.ts
  • skills/learning/tools/task-completion-from-sent/tool.json
  • skills/learning/tools/voice-learn/handler.test.ts
  • skills/learning/tools/voice-learn/handler.ts
  • skills/learning/tools/voice-learn/tool.json
  • skills/memory/SKILL.md
  • skills/memory/tools/decay-warnings-list/handler.test.ts
  • skills/memory/tools/decay-warnings-list/handler.ts
  • skills/memory/tools/decay-warnings-list/tool.json
  • skills/memory/tools/memory-confirm/handler.test.ts
  • skills/memory/tools/memory-confirm/handler.ts
  • skills/memory/tools/memory-confirm/tool.json
  • skills/memory/tools/memory-query/handler.test.ts
  • skills/memory/tools/memory-query/handler.ts
  • skills/memory/tools/memory-query/tool.json
  • skills/memory/tools/memory-store/handler.test.ts
  • skills/memory/tools/memory-store/handler.ts
  • skills/memory/tools/memory-store/tool.json
  • skills/scheduler/SKILL.md
  • skills/scheduler/tools/scheduler-cancel/handler.ts
  • skills/scheduler/tools/scheduler-cancel/tool.json
  • skills/scheduler/tools/scheduler-create/handler.ts
  • skills/scheduler/tools/scheduler-create/tool.json
  • skills/scheduler/tools/scheduler-list/handler.ts
  • skills/scheduler/tools/scheduler-list/tool.json
  • skills/scheduler/tools/scheduler-report/handler.ts
  • skills/scheduler/tools/scheduler-report/tool.json
  • skills/scheduler/tools/scheduler-update/handler.ts
  • skills/scheduler/tools/scheduler-update/tool.json
  • skills/setup/SKILL.md
  • skills/setup/tools/setup-defer/handler.test.ts
  • skills/setup/tools/setup-defer/handler.ts
  • skills/setup/tools/setup-defer/tool.json
  • skills/setup/tools/setup-status/catalog.yaml
  • skills/setup/tools/setup-status/handler.test.ts
  • skills/setup/tools/setup-status/handler.ts
  • skills/setup/tools/setup-status/tool.json
  • skills/setup/tools/system-secret-capture-request/handler.test.ts
  • skills/setup/tools/system-secret-capture-request/handler.ts
  • skills/setup/tools/system-secret-capture-request/tool.json
  • skills/tasks/SKILL.md
  • skills/tasks/tools/checkpoint/handler.test.ts
  • skills/tasks/tools/checkpoint/handler.ts
  • skills/tasks/tools/checkpoint/tool.json
  • skills/tasks/tools/plan/handler.test.ts
  • skills/tasks/tools/plan/handler.ts
  • skills/tasks/tools/plan/tool.json
  • skills/web/SKILL.md
  • skills/web/tools/web-browser/dom-extract.test.ts
  • skills/web/tools/web-browser/dom-extract.ts
  • skills/web/tools/web-browser/handler.test.ts
  • skills/web/tools/web-browser/handler.ts
  • skills/web/tools/web-browser/tool.json
  • skills/web/tools/web-fetch/handler.ts
  • skills/web/tools/web-fetch/tool.json
  • skills/web/tools/web-search/handler.ts
  • skills/web/tools/web-search/tool.json
  • src/channels/email/email-adapter.ts
  • src/index.ts
  • src/skills/mcp-loader.ts
  • src/skills/pin-resolution.ts
  • src/skills/skill-loader.ts
  • src/startup/validator.ts
  • tests/integration/plan-lifecycle-e2e.test.ts
  • tests/integration/task-wake-reply-bind.test.ts
  • tests/unit/agents/diagnostics-agent.test.ts
  • tests/unit/agents/resolved-pins-regression.test.ts
  • tests/unit/skills/ceo-inbox-update-folders.test.ts
  • tests/unit/skills/contact-dedup-exclude.test.ts
  • tests/unit/skills/contact-find-duplicates.test.ts
  • tests/unit/skills/contact-merge.test.ts
  • tests/unit/skills/contact-set-role.test.ts
  • tests/unit/skills/email-archive.test.ts
  • tests/unit/skills/email-create-folder.test.ts
  • tests/unit/skills/email-draft-save.test.ts
  • tests/unit/skills/email-get.test.ts
  • tests/unit/skills/email-label.test.ts
  • tests/unit/skills/email-list-folders.test.ts
  • tests/unit/skills/email-list.test.ts
  • tests/unit/skills/email-mark-read.test.ts
  • tests/unit/skills/email-reply.test.ts
  • tests/unit/skills/email-send.test.ts
  • tests/unit/skills/executive-profile-get.test.ts
  • tests/unit/skills/executive-profile-update.test.ts
  • tests/unit/skills/mcp-loader.test.ts
  • tests/unit/skills/mcp-projected-skills.test.ts
  • tests/unit/skills/pin-resolution.test.ts
  • tests/unit/skills/scheduler-cancel.test.ts
  • tests/unit/skills/scheduler-create.test.ts
  • tests/unit/skills/scheduler-list.test.ts
  • tests/unit/skills/scheduler-report.test.ts
  • tests/unit/skills/scheduler-update.test.ts
  • tests/unit/skills/web-browser.test.ts
  • tests/unit/skills/web-fetch.test.ts
  • tests/unit/skills/web-search.test.ts
  • tests/unit/startup/validator.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 20

🧹 Nitpick comments (1)
src/skills/pin-resolution.ts (1)

26-30: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

resolvedPins is dead weight — it’s populated and returned, but nothing in src/index.ts or the rest of src/ reads it. Either thread it into the audit/log path, or drop it before it becomes another bit of decorative allocation.

🤖 Prompt for 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.

In `@src/skills/pin-resolution.ts` around lines 26 - 30, Remove the unused
resolvedPins field from the pin-resolution result type and eliminate its
population and return handling throughout the associated resolution flow. Keep
resolvedSkills and all existing resolution behavior unchanged.
🤖 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 `@agents/research-analyst.yaml`:
- Line 2: Remove the version bump in the agent metadata, restoring the previous
version value because this change only documents existing configuration and does
not alter the pin list or agent behavior.

In `@docs/dev/adding-an-agent.md`:
- Around line 235-238: Update the `tasks` bundle member list in the
documentation to include the sibling tools `plan` and `checkpoint` alongside the
existing four tools, keeping the surrounding bundle behavior and read-only
`task-list` guidance unchanged.

In `@skills/autonomy/tools/get-autonomy/tool.json`:
- Around line 7-11: Update the tool output manifests to match their handlers: in
skills/autonomy/tools/get-autonomy/tool.json lines 7-11, add lastSetBy, trend,
and scoredActionCount; in skills/autonomy/tools/list-pending-actions/tool.json
lines 8-10, declare displayTimezone; in
skills/autonomy/tools/set-autonomy/tool.json lines 10-14, add summary and allow
previous_score to be null; and in
skills/scheduler/tools/scheduler-cancel/tool.json lines 10-12, declare jobId or
remove it from the handler response.

In `@skills/ceo-inbox/tools/ceo-inbox-download-attachment/tool.json`:
- Line 3: Update the tool description to accurately state that the output may
provide a temporary file reference instead of content_base64 when temporary-file
storage succeeds, while preserving the existing attachment ID usage and 10 MB
limit details.

In `@skills/ceo-inbox/tools/ceo-inbox-search/tool.json`:
- Line 3: Add the runtime-enforced allowed_callers restriction with the owning
caller value “ceo-inbox” to the tool manifest in
skills/ceo-inbox/tools/ceo-inbox-search/tool.json at lines 3-3 and apply the
same restriction in skills/ceo-inbox/tools/ceo-inbox-update-folders/tool.json at
lines 3-3, before mailbox operations are permitted.

In `@skills/ceo-inbox/tools/ceo-inbox-sent-observe/tool.json`:
- Around line 10-16: Add the missing boolean output fields backfill_active and
tasks_truncated to the outputs contract in the ceo-inbox-sent-observe tool
manifest, matching the values returned by the handler’s sent-observe flow. Keep
the existing output fields unchanged.

In `@skills/contacts/tools/approve-grant-recommendation/tool.json`:
- Around line 5-6: Update the tool’s action_risk configuration from "low" to
"critical" so the immediate permission-grant approval uses the strongest
confirmation path. Preserve the existing sensitivity setting and other tool
configuration.

In `@skills/contacts/tools/contact-create/tool.json`:
- Around line 23-25: Add the required top-level "capabilities": [] field before
"timeout" in both skills/contacts/tools/contact-create/tool.json lines 23-25 and
skills/contacts/tools/contact-grant-permission/tool.json lines 17-19, preserving
the existing manifest structure.

In `@skills/contacts/tools/scan-grant-recommendations/tool.json`:
- Around line 20-23: Update the tool manifest’s caller restriction by adding the
required schedule-only allowed_callers configuration alongside capabilities in
the tool definition. Ensure the manifest contract permits invocation only by the
scheduler and prevents agents from calling the recommendation scan during user
requests.

In `@skills/context-bridge/tools/context-bridge-clear/tool.json`:
- Around line 7-10: The tool manifest’s inputs currently makes both alternative
fields required. Update the input definition for subjects and subject so callers
may provide either one, while preserving their existing types and mutual
alternative semantics.

In `@skills/context-bridge/tools/context-bridge-release/tool.json`:
- Around line 7-14: Update the manifest schema in the inputs and outputs
definitions: mark reply as optional to match the handler’s accepted release
requests, and make task_id optional because ordinary releases do not return it.
Keep entry_id and released required, preserving the existing types.

In `@skills/diagnostics/tools/audit-query/tool.json`:
- Around line 17-23: Update the outputs schema in the audit-query manifest so
displayTimezone is optional, matching the handler’s undefined result when no
timezone is available. Preserve its string type for responses that do provide a
timezone.

In `@skills/diagnostics/tools/audit-trace/tool.json`:
- Line 20: Make the displayTimezone property optional in the manifests for
audit-trace at skills/diagnostics/tools/audit-trace/tool.json:20-20 and
ops-lookup at skills/diagnostics/tools/ops-lookup/tool.json:26-26, so both tool
contracts allow handlers to omit it when timezone context is unavailable.

In `@skills/email/tools/email-download-attachment/tool.json`:
- Line 3: Update the tool description in tool.json to accurately document that
the output may provide temp_file_url instead of content_base64 when a temporary
file URL is available. Align the main description with the output fields
documented on lines 13-14, and remove the unconditional instruction to pass
content_base64 directly to file-parse.

In `@skills/email/tools/email-draft-save/tool.json`:
- Around line 13-14: Remove the unused export_items field from the tool schema
until EmailDraftSaveHandler and its gateway path read and forward it; update the
associated schema or contract test to ensure callers are not promised
unsupported export-control behavior.

In `@skills/learning/tools/list-learning-digest/tool.json`:
- Around line 3-11: Align the `list-learning-digest` manifest with the handler’s
actual empty-output behavior: update the `sections_markdown` output description
to state that it is always returned and is an empty string when no sections are
rendered. Keep the handler’s existing return shape unchanged.

In `@skills/memory/tools/memory-confirm/tool.json`:
- Around line 11-15: Remove the success field from the declared outputs in the
tool manifest, leaving only the payload fields that are actually present inside
data; keep MemoryConfirmHandler’s return behavior unchanged.

In `@skills/memory/tools/memory-store/tool.json`:
- Line 3: Update the memory-store manifest description and result schema to
match MemoryStoreHandler: include the auto_resolved and auto_rejected outcomes,
and model the ambiguous response as omitting action and stored. Mark fields that
are not present on every outcome as conditional/optional, while preserving the
existing contracts for created, updated, conflict, entity_not_found, and
rate_limited.

In `@skills/tasks/tools/checkpoint/tool.json`:
- Around line 8-13: Update the checkpoint schema exposed by toToolDefinitions()
to match the runtime contract: allow cursor values as objects as well as
strings, and allow accumulator entries to be either inline slice-result objects
or spilled document-pointer objects. Preserve the optional/default behavior
while ensuring valid handler and resumable-progress payloads pass tool
validation.

In `@skills/web/tools/web-browser/dom-extract.ts`:
- Around line 90-100: Update the ref-resolution flow around __curiaRefEpoch__
and the resolver’s ref validation to maintain a handler-owned navigation
generation that changes for each new document. Encode or associate the
generation with emitted refs and reject any ref whose generation predates the
current document, rather than trusting page-controlled DOM attributes such as
__curiaRefEpoch__. Preserve valid refs within the active document while failing
closed for refs reused after navigation.

---

Nitpick comments:
In `@src/skills/pin-resolution.ts`:
- Around line 26-30: Remove the unused resolvedPins field from the
pin-resolution result type and eliminate its population and return handling
throughout the associated resolution flow. Keep resolvedSkills and all existing
resolution behavior unchanged.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 54823ecd-7890-425a-a1c6-80fb27950c96

📥 Commits

Reviewing files that changed from the base of the PR and between 7c0cca3 and 0358067.

📒 Files selected for processing (280)
  • CHANGELOG.md
  • agents/calendar.yaml
  • agents/ceo-inbox.yaml
  • agents/contacts.yaml
  • agents/coordinator.yaml
  • agents/diagnostics.yaml
  • agents/meeting-debrief.yaml
  • agents/research-analyst.yaml
  • agents/setup-wizard.yaml
  • config/registry-defaults.yaml
  • docs/dev/adding-a-tool.md
  • docs/dev/adding-an-agent.md
  • skills/autonomy/SKILL.md
  • skills/autonomy/tools/approve-action/handler.test.ts
  • skills/autonomy/tools/approve-action/handler.ts
  • skills/autonomy/tools/approve-action/tool.json
  • skills/autonomy/tools/deny-action/handler.test.ts
  • skills/autonomy/tools/deny-action/handler.ts
  • skills/autonomy/tools/deny-action/tool.json
  • skills/autonomy/tools/dismiss-action/handler.test.ts
  • skills/autonomy/tools/dismiss-action/handler.ts
  • skills/autonomy/tools/dismiss-action/tool.json
  • skills/autonomy/tools/get-autonomy/handler.test.ts
  • skills/autonomy/tools/get-autonomy/handler.ts
  • skills/autonomy/tools/get-autonomy/tool.json
  • skills/autonomy/tools/list-pending-actions/handler.test.ts
  • skills/autonomy/tools/list-pending-actions/handler.ts
  • skills/autonomy/tools/list-pending-actions/tool.json
  • skills/autonomy/tools/set-autonomy/handler.ts
  • skills/autonomy/tools/set-autonomy/tool.json
  • skills/ceo-inbox/SKILL.md
  • skills/ceo-inbox/tools/ceo-inbox-archive/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-archive/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-download-attachment/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-download-attachment/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-download-attachment/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-draft-compose/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-compose/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-compose/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-draft-edit/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-edit/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-edit/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-draft-reply/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-reply/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-draft-reply/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-label/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-label/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-list/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-list/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-list/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-mark-read/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-mark-read/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-mark-starred/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-mark-starred/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-mark-starred/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-read/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-read/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-read/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-search/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-search/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-search/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-sent-observe/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-sent-observe/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-sent-observe/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-shadow-draft/handler.test.ts
  • skills/ceo-inbox/tools/ceo-inbox-shadow-draft/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-shadow-draft/tool.json
  • skills/ceo-inbox/tools/ceo-inbox-update-folders/handler.ts
  • skills/ceo-inbox/tools/ceo-inbox-update-folders/tool.json
  • skills/contacts/SKILL.md
  • skills/contacts/tools/approve-grant-recommendation/handler.ts
  • skills/contacts/tools/approve-grant-recommendation/tool.json
  • skills/contacts/tools/contact-create/handler.ts
  • skills/contacts/tools/contact-create/tool.json
  • skills/contacts/tools/contact-dedup-exclude/handler.ts
  • skills/contacts/tools/contact-dedup-exclude/tool.json
  • skills/contacts/tools/contact-find-duplicates/handler.ts
  • skills/contacts/tools/contact-find-duplicates/tool.json
  • skills/contacts/tools/contact-grant-permission/handler.ts
  • skills/contacts/tools/contact-grant-permission/tool.json
  • skills/contacts/tools/contact-link-identity/handler.ts
  • skills/contacts/tools/contact-link-identity/tool.json
  • skills/contacts/tools/contact-list/handler.test.ts
  • skills/contacts/tools/contact-list/handler.ts
  • skills/contacts/tools/contact-list/tool.json
  • skills/contacts/tools/contact-lookup/handler.ts
  • skills/contacts/tools/contact-lookup/tool.json
  • skills/contacts/tools/contact-merge/handler.ts
  • skills/contacts/tools/contact-merge/tool.json
  • skills/contacts/tools/contact-register/handler.test.ts
  • skills/contacts/tools/contact-register/handler.ts
  • skills/contacts/tools/contact-register/tool.json
  • skills/contacts/tools/contact-rename/handler.test.ts
  • skills/contacts/tools/contact-rename/handler.ts
  • skills/contacts/tools/contact-rename/tool.json
  • skills/contacts/tools/contact-revoke-permission/handler.ts
  • skills/contacts/tools/contact-revoke-permission/tool.json
  • skills/contacts/tools/contact-set-identity-status/handler.test.ts
  • skills/contacts/tools/contact-set-identity-status/handler.ts
  • skills/contacts/tools/contact-set-identity-status/tool.json
  • skills/contacts/tools/contact-set-role/handler.ts
  • skills/contacts/tools/contact-set-role/tool.json
  • skills/contacts/tools/contact-set-tier/handler.ts
  • skills/contacts/tools/contact-set-tier/tool.json
  • skills/contacts/tools/contact-unlink-identity/handler.ts
  • skills/contacts/tools/contact-unlink-identity/tool.json
  • skills/contacts/tools/contact-update/handler.test.ts
  • skills/contacts/tools/contact-update/handler.ts
  • skills/contacts/tools/contact-update/tool.json
  • skills/contacts/tools/decline-grant-recommendation/handler.ts
  • skills/contacts/tools/decline-grant-recommendation/tool.json
  • skills/contacts/tools/delete-relationship/handler.test.ts
  • skills/contacts/tools/delete-relationship/handler.ts
  • skills/contacts/tools/delete-relationship/tool.json
  • skills/contacts/tools/query-relationships/handler.test.ts
  • skills/contacts/tools/query-relationships/handler.ts
  • skills/contacts/tools/query-relationships/tool.json
  • skills/contacts/tools/scan-grant-recommendations/handler.ts
  • skills/contacts/tools/scan-grant-recommendations/tool.json
  • skills/context-bridge/SKILL.md
  • skills/context-bridge/tools/context-bridge-clear/handler.test.ts
  • skills/context-bridge/tools/context-bridge-clear/handler.ts
  • skills/context-bridge/tools/context-bridge-clear/tool.json
  • skills/context-bridge/tools/context-bridge-release/handler.test.ts
  • skills/context-bridge/tools/context-bridge-release/handler.ts
  • skills/context-bridge/tools/context-bridge-release/tool.json
  • skills/diagnostics/SKILL.md
  • skills/diagnostics/tools/audit-query/handler.test.ts
  • skills/diagnostics/tools/audit-query/handler.ts
  • skills/diagnostics/tools/audit-query/tool.json
  • skills/diagnostics/tools/audit-trace/handler.test.ts
  • skills/diagnostics/tools/audit-trace/handler.ts
  • skills/diagnostics/tools/audit-trace/tool.json
  • skills/diagnostics/tools/ops-lookup/handler.test.ts
  • skills/diagnostics/tools/ops-lookup/handler.ts
  • skills/diagnostics/tools/ops-lookup/tool.json
  • skills/email/SKILL.md
  • skills/email/tools/email-archive/handler.ts
  • skills/email/tools/email-archive/tool.json
  • skills/email/tools/email-create-folder/handler.ts
  • skills/email/tools/email-create-folder/tool.json
  • skills/email/tools/email-download-attachment/handler.test.ts
  • skills/email/tools/email-download-attachment/handler.ts
  • skills/email/tools/email-download-attachment/tool.json
  • skills/email/tools/email-draft-save/handler.test.ts
  • skills/email/tools/email-draft-save/handler.ts
  • skills/email/tools/email-draft-save/tool.json
  • skills/email/tools/email-get/handler.test.ts
  • skills/email/tools/email-get/handler.ts
  • skills/email/tools/email-get/tool.json
  • skills/email/tools/email-label/handler.ts
  • skills/email/tools/email-label/tool.json
  • skills/email/tools/email-list-folders/handler.ts
  • skills/email/tools/email-list-folders/tool.json
  • skills/email/tools/email-list/handler.test.ts
  • skills/email/tools/email-list/handler.ts
  • skills/email/tools/email-list/tool.json
  • skills/email/tools/email-mark-read/handler.ts
  • skills/email/tools/email-mark-read/tool.json
  • skills/email/tools/email-reply/handler.test.ts
  • skills/email/tools/email-reply/handler.ts
  • skills/email/tools/email-reply/tool.json
  • skills/email/tools/email-send/handler.test.ts
  • skills/email/tools/email-send/handler.ts
  • skills/email/tools/email-send/tool.json
  • skills/email/tools/send-draft/handler.test.ts
  • skills/email/tools/send-draft/handler.ts
  • skills/email/tools/send-draft/tool.json
  • skills/executive-profile/SKILL.md
  • skills/executive-profile/tools/behavioral-preferences-update/handler.test.ts
  • skills/executive-profile/tools/behavioral-preferences-update/handler.ts
  • skills/executive-profile/tools/behavioral-preferences-update/tool.json
  • skills/executive-profile/tools/executive-profile-get/handler.ts
  • skills/executive-profile/tools/executive-profile-get/tool.json
  • skills/executive-profile/tools/executive-profile-update/handler.ts
  • skills/executive-profile/tools/executive-profile-update/tool.json
  • skills/learning/SKILL.md
  • skills/learning/tools/list-learning-digest/handler.test.ts
  • skills/learning/tools/list-learning-digest/handler.ts
  • skills/learning/tools/list-learning-digest/tool.json
  • skills/learning/tools/resolve-learning-digest/handler.test.ts
  • skills/learning/tools/resolve-learning-digest/handler.ts
  • skills/learning/tools/resolve-learning-digest/tool.json
  • skills/learning/tools/task-completion-from-sent/handler.test.ts
  • skills/learning/tools/task-completion-from-sent/handler.ts
  • skills/learning/tools/task-completion-from-sent/tool.json
  • skills/learning/tools/voice-learn/handler.test.ts
  • skills/learning/tools/voice-learn/handler.ts
  • skills/learning/tools/voice-learn/tool.json
  • skills/memory/SKILL.md
  • skills/memory/tools/decay-warnings-list/handler.test.ts
  • skills/memory/tools/decay-warnings-list/handler.ts
  • skills/memory/tools/decay-warnings-list/tool.json
  • skills/memory/tools/memory-confirm/handler.test.ts
  • skills/memory/tools/memory-confirm/handler.ts
  • skills/memory/tools/memory-confirm/tool.json
  • skills/memory/tools/memory-query/handler.test.ts
  • skills/memory/tools/memory-query/handler.ts
  • skills/memory/tools/memory-query/tool.json
  • skills/memory/tools/memory-store/handler.test.ts
  • skills/memory/tools/memory-store/handler.ts
  • skills/memory/tools/memory-store/tool.json
  • skills/scheduler/SKILL.md
  • skills/scheduler/tools/scheduler-cancel/handler.ts
  • skills/scheduler/tools/scheduler-cancel/tool.json
  • skills/scheduler/tools/scheduler-create/handler.ts
  • skills/scheduler/tools/scheduler-create/tool.json
  • skills/scheduler/tools/scheduler-list/handler.ts
  • skills/scheduler/tools/scheduler-list/tool.json
  • skills/scheduler/tools/scheduler-report/handler.ts
  • skills/scheduler/tools/scheduler-report/tool.json
  • skills/scheduler/tools/scheduler-update/handler.ts
  • skills/scheduler/tools/scheduler-update/tool.json
  • skills/setup/SKILL.md
  • skills/setup/tools/setup-defer/handler.test.ts
  • skills/setup/tools/setup-defer/handler.ts
  • skills/setup/tools/setup-defer/tool.json
  • skills/setup/tools/setup-status/catalog.yaml
  • skills/setup/tools/setup-status/handler.test.ts
  • skills/setup/tools/setup-status/handler.ts
  • skills/setup/tools/setup-status/tool.json
  • skills/setup/tools/system-secret-capture-request/handler.test.ts
  • skills/setup/tools/system-secret-capture-request/handler.ts
  • skills/setup/tools/system-secret-capture-request/tool.json
  • skills/tasks/SKILL.md
  • skills/tasks/tools/checkpoint/handler.test.ts
  • skills/tasks/tools/checkpoint/handler.ts
  • skills/tasks/tools/checkpoint/tool.json
  • skills/tasks/tools/plan/handler.test.ts
  • skills/tasks/tools/plan/handler.ts
  • skills/tasks/tools/plan/tool.json
  • skills/web/SKILL.md
  • skills/web/tools/web-browser/dom-extract.test.ts
  • skills/web/tools/web-browser/dom-extract.ts
  • skills/web/tools/web-browser/handler.test.ts
  • skills/web/tools/web-browser/handler.ts
  • skills/web/tools/web-browser/tool.json
  • skills/web/tools/web-fetch/handler.ts
  • skills/web/tools/web-fetch/tool.json
  • skills/web/tools/web-search/handler.ts
  • skills/web/tools/web-search/tool.json
  • src/channels/email/email-adapter.ts
  • src/index.ts
  • src/skills/mcp-loader.ts
  • src/skills/pin-resolution.ts
  • src/skills/skill-loader.ts
  • src/startup/validator.ts
  • tests/integration/plan-lifecycle-e2e.test.ts
  • tests/integration/task-wake-reply-bind.test.ts
  • tests/unit/agents/diagnostics-agent.test.ts
  • tests/unit/agents/resolved-pins-regression.test.ts
  • tests/unit/skills/ceo-inbox-update-folders.test.ts
  • tests/unit/skills/contact-dedup-exclude.test.ts
  • tests/unit/skills/contact-find-duplicates.test.ts
  • tests/unit/skills/contact-merge.test.ts
  • tests/unit/skills/contact-set-role.test.ts
  • tests/unit/skills/email-archive.test.ts
  • tests/unit/skills/email-create-folder.test.ts
  • tests/unit/skills/email-draft-save.test.ts
  • tests/unit/skills/email-get.test.ts
  • tests/unit/skills/email-label.test.ts
  • tests/unit/skills/email-list-folders.test.ts
  • tests/unit/skills/email-list.test.ts
  • tests/unit/skills/email-mark-read.test.ts
  • tests/unit/skills/email-reply.test.ts
  • tests/unit/skills/email-send.test.ts
  • tests/unit/skills/executive-profile-get.test.ts
  • tests/unit/skills/executive-profile-update.test.ts
  • tests/unit/skills/mcp-loader.test.ts
  • tests/unit/skills/mcp-projected-skills.test.ts
  • tests/unit/skills/pin-resolution.test.ts
  • tests/unit/skills/scheduler-cancel.test.ts
  • tests/unit/skills/scheduler-create.test.ts
  • tests/unit/skills/scheduler-list.test.ts
  • tests/unit/skills/scheduler-report.test.ts
  • tests/unit/skills/scheduler-update.test.ts
  • tests/unit/skills/web-browser.test.ts
  • tests/unit/skills/web-fetch.test.ts
  • tests/unit/skills/web-search.test.ts
  • tests/unit/startup/validator.test.ts
🛑 Comments failed to post (20)
agents/research-analyst.yaml (1)

2-2: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Do not mint a new agent version for a comment-only change.

The pin list is unchanged; Line 116 merely documents the existing polymorphic pins. Bumping 0.1.1 to 0.1.2 therefore advertises a meaningful agent change that this file does not contain. Remove the bump unless an actual configuration change was intended. A version number is not a mood ring, thankfully.

As per coding guidelines, bump an agent's version only for meaningful changes.

Also applies to: 116-116

🤖 Prompt for 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.

In `@agents/research-analyst.yaml` at line 2, Remove the version bump in the agent
metadata, restoring the previous version value because this change only
documents existing configuration and does not alter the pin list or agent
behavior.

Source: Coding guidelines

docs/dev/adding-an-agent.md (1)

235-238: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Complete the tasks bundle member list.

Line 235 says plan and checkpoint are sibling tools, but the bundle description immediately above claims tasks expands only to the four older tools. Add both there too; apparently even documentation now needs a backlog.

🤖 Prompt for 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.

In `@docs/dev/adding-an-agent.md` around lines 235 - 238, Update the `tasks`
bundle member list in the documentation to include the sibling tools `plan` and
`checkpoint` alongside the existing four tools, keeping the surrounding bundle
behavior and read-only `task-list` guidance unchanged.
skills/autonomy/tools/get-autonomy/tool.json (1)

7-11: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep the tool manifests honest about their returned data.

Several manifests describe narrower or incorrect output contracts than their handlers provide. This leaves callers with incomplete schemas, which is a remarkably efficient way to make useful data disappear.

  • skills/autonomy/tools/get-autonomy/tool.json#L7-L11: add lastSetBy, trend, and scoredActionCount.
  • skills/autonomy/tools/list-pending-actions/tool.json#L8-L10: declare displayTimezone.
  • skills/autonomy/tools/set-autonomy/tool.json#L10-L14: add summary and make previous_score nullable; the handler returns null before the first recorded update.
  • skills/scheduler/tools/scheduler-cancel/tool.json#L10-L12: declare jobId, or remove it from the handler response.
📍 Affects 4 files
  • skills/autonomy/tools/get-autonomy/tool.json#L7-L11 (this comment)
  • skills/autonomy/tools/list-pending-actions/tool.json#L8-L10
  • skills/autonomy/tools/set-autonomy/tool.json#L10-L14
  • skills/scheduler/tools/scheduler-cancel/tool.json#L10-L12
🤖 Prompt for 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.

In `@skills/autonomy/tools/get-autonomy/tool.json` around lines 7 - 11, Update the
tool output manifests to match their handlers: in
skills/autonomy/tools/get-autonomy/tool.json lines 7-11, add lastSetBy, trend,
and scoredActionCount; in skills/autonomy/tools/list-pending-actions/tool.json
lines 8-10, declare displayTimezone; in
skills/autonomy/tools/set-autonomy/tool.json lines 10-14, add summary and allow
previous_score to be null; and in
skills/scheduler/tools/scheduler-cancel/tool.json lines 10-12, declare jobId or
remove it from the handler response.
skills/ceo-inbox/tools/ceo-inbox-download-attachment/tool.json (1)

3-3: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the description match the actual output.

The description promises base64 content, but skills/ceo-inbox/tools/ceo-inbox-download-attachment/handler.ts omits content_base64 whenever temporary-file storage works. The agent may therefore expect a field the tool deliberately withholds. A marvellous little contract mismatch.

Proposed wording
-  "description": "Download an email attachment from the CEO's personal inbox by its Nylas attachment ID. Returns base64-encoded file content ready to pass directly to file-parse. Use ceo-inbox-read first to find attachment IDs. Enforces a 10 MB size limit.",
+  "description": "Download an email attachment from the CEO's personal inbox by its Nylas attachment ID. Returns a binary-safe temp_file_url when available, otherwise base64-encoded content. Use ceo-inbox-read first to find attachment IDs. Enforces a 10 MB size limit.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  "description": "Download an email attachment from the CEO's personal inbox by its Nylas attachment ID. Returns a binary-safe temp_file_url when available, otherwise base64-encoded content. Use ceo-inbox-read first to find attachment IDs. Enforces a 10 MB size limit.",
🤖 Prompt for 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.

In `@skills/ceo-inbox/tools/ceo-inbox-download-attachment/tool.json` at line 3,
Update the tool description to accurately state that the output may provide a
temporary file reference instead of content_base64 when temporary-file storage
succeeds, while preserving the existing attachment ID usage and 10 MB limit
details.
skills/ceo-inbox/tools/ceo-inbox-search/tool.json (1)

3-3: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Enforce caller restrictions on both CEO inbox tools.

Both manifests promise agent-level restrictions but omit the field the runtime actually enforces. Add the owning caller restriction instead of relying on prose.

  • skills/ceo-inbox/tools/ceo-inbox-search/tool.json#L3-L3: add allowed_callers: ["ceo-inbox"] or the verified owning caller.
  • skills/ceo-inbox/tools/ceo-inbox-update-folders/tool.json#L3-L3: add the same restriction before allowing mailbox mutations.
📍 Affects 2 files
  • skills/ceo-inbox/tools/ceo-inbox-search/tool.json#L3-L3 (this comment)
  • skills/ceo-inbox/tools/ceo-inbox-update-folders/tool.json#L3-L3
🤖 Prompt for 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.

In `@skills/ceo-inbox/tools/ceo-inbox-search/tool.json` at line 3, Add the
runtime-enforced allowed_callers restriction with the owning caller value
“ceo-inbox” to the tool manifest in
skills/ceo-inbox/tools/ceo-inbox-search/tool.json at lines 3-3 and apply the
same restriction in skills/ceo-inbox/tools/ceo-inbox-update-folders/tool.json at
lines 3-3, before mailbox operations are permitted.
skills/ceo-inbox/tools/ceo-inbox-sent-observe/tool.json (1)

10-16: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep the output contract in sync with the handler.

skills/ceo-inbox/tools/ceo-inbox-sent-observe/handler.ts:874-886 returns backfill_active and tasks_truncated, but this manifest omits both. Consumers therefore cannot distinguish an active backlog drain from a completed poll, nor detect partial task matching. Add both boolean output fields; otherwise the contract is quietly misleading, which is a rather efficient way to create operational confusion.

🤖 Prompt for 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.

In `@skills/ceo-inbox/tools/ceo-inbox-sent-observe/tool.json` around lines 10 -
16, Add the missing boolean output fields backfill_active and tasks_truncated to
the outputs contract in the ceo-inbox-sent-observe tool manifest, matching the
values returned by the handler’s sent-observe flow. Keep the existing output
fields unchanged.
skills/contacts/tools/approve-grant-recommendation/tool.json (1)

5-6: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Make this approval action critical.

This tool immediately grants a permission, yet advertises action_risk: "low". That can select a weaker confirmation path for the same authority change. Set it to critical, unless this flow is independently gated before invocation. Based on PR objectives, per-tool risk must be preserved.

🤖 Prompt for 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.

In `@skills/contacts/tools/approve-grant-recommendation/tool.json` around lines 5
- 6, Update the tool’s action_risk configuration from "low" to "critical" so the
immediate permission-grant approval uses the strongest confirmation path.
Preserve the existing sensitivity setting and other tool configuration.
skills/contacts/tools/contact-create/tool.json (1)

23-25: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Declare capabilities in both manifests.

Both manifests omit a required top-level field, so startup validation rejects the bundles before skills load. A remarkably efficient way to achieve nothing.

  • skills/contacts/tools/contact-create/tool.json#L23-L25: add "capabilities": [] before timeout.
  • skills/contacts/tools/contact-grant-permission/tool.json#L17-L19: add "capabilities": [] before timeout.

Based on the supplied validator context, capabilities is required by the tool-manifest schema.

📍 Affects 2 files
  • skills/contacts/tools/contact-create/tool.json#L23-L25 (this comment)
  • skills/contacts/tools/contact-grant-permission/tool.json#L17-L19
🤖 Prompt for 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.

In `@skills/contacts/tools/contact-create/tool.json` around lines 23 - 25, Add the
required top-level "capabilities": [] field before "timeout" in both
skills/contacts/tools/contact-create/tool.json lines 23-25 and
skills/contacts/tools/contact-grant-permission/tool.json lines 17-19, preserving
the existing manifest structure.
skills/contacts/tools/scan-grant-recommendations/tool.json (1)

20-23: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Enforce the schedule-only caller restriction.

allowed_callers is omitted, which makes this tool unrestricted under the manifest contract. An agent can therefore invoke the recommendation scan during a user request, despite the manifest explicitly requiring scheduled execution. A remarkably efficient way to turn background housekeeping into user-triggered side effects.

Suggested manifest guard
   "timeout": 60000,
+  "allowed_callers": ["system"],
   "capabilities": ["infraLlm"]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  "permissions": [],
  "secrets": [],
  "timeout": 60000,
  "allowed_callers": ["system"],
  "capabilities": ["infraLlm"]
🤖 Prompt for 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.

In `@skills/contacts/tools/scan-grant-recommendations/tool.json` around lines 20 -
23, Update the tool manifest’s caller restriction by adding the required
schedule-only allowed_callers configuration alongside capabilities in the tool
definition. Ensure the manifest contract permits invocation only by the
scheduler and prevents agents from calling the recommendation scan during user
requests.
skills/context-bridge/tools/context-bridge-clear/tool.json (1)

7-10: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not make both alternative inputs mandatory.

The handler supports either subjects or subject, but bare manifest types make both required. Calls providing only one value may be rejected before the handler is reached—an impressively efficient way to disable the feature.

Proposed manifest fix
   "inputs": {
-    "subjects": "string[]",
-    "subject": "string"
+    "subjects": "string[]?",
+    "subject": "string?"
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  "inputs": {
    "subjects": "string[]?",
    "subject": "string?"
  },
🤖 Prompt for 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.

In `@skills/context-bridge/tools/context-bridge-clear/tool.json` around lines 7 -
10, The tool manifest’s inputs currently makes both alternative fields required.
Update the input definition for subjects and subject so callers may provide
either one, while preserving their existing types and mutual alternative
semantics.
skills/context-bridge/tools/context-bridge-release/tool.json (1)

7-14: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Align the manifest with ordinary releases.

reply is optional in the handler, and ordinary releases return no task_id. Declaring both as required can reject normal releases or produce a result that violates the advertised schema. Because apparently one release path was not enough.

Proposed manifest fix
   "inputs": {
     "entry_id": "string",
-    "reply": "string"
+    "reply": "string?"
   },
   "outputs": {
     "released": "string",
-    "task_id": "string"
+    "task_id": "string?"
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  "inputs": {
    "entry_id": "string",
    "reply": "string?"
  },
  "outputs": {
    "released": "string",
    "task_id": "string?"
  },
🤖 Prompt for 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.

In `@skills/context-bridge/tools/context-bridge-release/tool.json` around lines 7
- 14, Update the manifest schema in the inputs and outputs definitions: mark
reply as optional to match the handler’s accepted release requests, and make
task_id optional because ordinary releases do not return it. Keep entry_id and
released required, preserving the existing types.
skills/diagnostics/tools/audit-query/tool.json (1)

17-23: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Declare displayTimezone as optional.

The handler returns undefined when no timezone is available (Line 60), while this manifest promises a required string. The schema should describe the actual result shape, unless surprising consumers is now considered a diagnostics feature.

Proposed manifest fix
   "available": "boolean",
-  "displayTimezone": "string"
+  "displayTimezone": "string?"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  "outputs": {
    "events": "object[]",
    "count": "number",
    "hasMore": "boolean",
    "available": "boolean",
    "displayTimezone": "string?"
  },
🤖 Prompt for 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.

In `@skills/diagnostics/tools/audit-query/tool.json` around lines 17 - 23, Update
the outputs schema in the audit-query manifest so displayTimezone is optional,
matching the handler’s undefined result when no timezone is available. Preserve
its string type for responses that do provide a timezone.
skills/diagnostics/tools/audit-trace/tool.json (1)

20-20: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the diagnostics timezone output contract optional.

Both handlers can omit displayTimezone when no timezone is available, while their manifests advertise a required string.

  • skills/diagnostics/tools/audit-trace/tool.json#L20-L20: mark displayTimezone optional or guarantee timezone context upstream.
  • skills/diagnostics/tools/ops-lookup/tool.json#L26-L26: make the same contract correction.
📍 Affects 2 files
  • skills/diagnostics/tools/audit-trace/tool.json#L20-L20 (this comment)
  • skills/diagnostics/tools/ops-lookup/tool.json#L26-L26
🤖 Prompt for 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.

In `@skills/diagnostics/tools/audit-trace/tool.json` at line 20, Make the
displayTimezone property optional in the manifests for audit-trace at
skills/diagnostics/tools/audit-trace/tool.json:20-20 and ops-lookup at
skills/diagnostics/tools/ops-lookup/tool.json:26-26, so both tool contracts
allow handlers to omit it when timezone context is unavailable.
skills/email/tools/email-download-attachment/tool.json (1)

3-3: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Align the attachment description with the actual output.

Line 3 says the tool returns base64 and tells callers to pass content_base64 to file-parse, but the handler omits that field whenever temp_file_url is available. The manifest already admits this on Lines 13-14; the two contracts cannot both be true, which is rather unfortunate for a tool intended to guide an LLM.

Suggested description
-  "description": "Download an email attachment by its Nylas attachment ID and return the file content as base64. Use email-get first to get the attachment ID. Pass the returned content_base64 and content_type directly to file-parse for processing. Enforces a 10 MB size limit.",
+  "description": "Download an email attachment by its Nylas attachment ID. Returns a temporary file URL when temp storage is available, otherwise base64 content. Use the field that is present; the download is limited to 10 MB.",

Also applies to: 13-14

🤖 Prompt for 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.

In `@skills/email/tools/email-download-attachment/tool.json` at line 3, Update the
tool description in tool.json to accurately document that the output may provide
temp_file_url instead of content_base64 when a temporary file URL is available.
Align the main description with the output fields documented on lines 13-14, and
remove the unconditional instruction to pass content_base64 directly to
file-parse.
skills/email/tools/email-draft-save/tool.json (1)

13-14: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not advertise an ignored export-control field.

export_items is documented as input to bulk-export gating, but EmailDraftSaveHandler never reads or forwards it. Any caller-supplied tagging is silently discarded, so the declared privacy control cannot influence this path. Wire it through the gateway and cover it with a test, or remove the field until the implementation exists. Apparently even metadata now requires supervision.

🤖 Prompt for 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.

In `@skills/email/tools/email-draft-save/tool.json` around lines 13 - 14, Remove
the unused export_items field from the tool schema until EmailDraftSaveHandler
and its gateway path read and forward it; update the associated schema or
contract test to ensure callers are not promised unsupported export-control
behavior.
skills/learning/tools/list-learning-digest/tool.json (1)

3-11: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Align the empty-output contract with the handler.

The manifest says the markdown sections are “omitted when empty”, but skills/learning/tools/list-learning-digest/handler.ts always returns sections_markdown, using '' when there is nothing to render. Either omit the field in the handler or document the empty-string behaviour. A tiny discrepancy, naturally destined to waste someone’s afternoon.

🤖 Prompt for 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.

In `@skills/learning/tools/list-learning-digest/tool.json` around lines 3 - 11,
Align the `list-learning-digest` manifest with the handler’s actual empty-output
behavior: update the `sections_markdown` output description to state that it is
always returned and is an empty string when no sections are rendered. Keep the
handler’s existing return shape unchanged.
skills/memory/tools/memory-confirm/tool.json (1)

11-15: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Remove success from the declared payload outputs.

MemoryConfirmHandler returns success beside data (Line 46), while sibling manifests such as skills/web/tools/web-fetch/tool.json describe only the fields inside data. This currently advertises data.success even though successful calls do not provide it—a remarkably efficient way to confuse consumers and schema checks.

Suggested correction
  "outputs": {
-   "success": "boolean",
    "action": "string",
    "nodeId": "string",
    "label": "string"
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  "outputs": {
    "action": "string",
    "nodeId": "string",
    "label": "string"
🤖 Prompt for 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.

In `@skills/memory/tools/memory-confirm/tool.json` around lines 11 - 15, Remove
the success field from the declared outputs in the tool manifest, leaving only
the payload fields that are actually present inside data; keep
MemoryConfirmHandler’s return behavior unchanged.
skills/memory/tools/memory-store/tool.json (1)

3-3: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Align the manifest with the handler’s actual result contract.

MemoryStoreHandler returns auto_resolved and auto_rejected, while the ambiguous branch omits both action and stored. The manifest currently omits those variants and presents several fields as unconditional. Consumers may therefore misinterpret valid results. A small correction, mercifully, before the paperwork becomes archaeology.

Suggested contract correction
-  "description": "... Returns one of five outcomes: ..."
+  "description": "... Returns created, updated, auto_resolved, conflict, entity_not_found, rate_limited, auto_rejected, redirected_to_contact, or an ambiguous candidate list."

-    "stored": "boolean — true when the fact was persisted (created or updated)",
-    "action": "string — one of: created, updated, conflict, entity_not_found, rate_limited, redirected_to_contact",
+    "stored": "boolean? — true when the fact was persisted",
+    "action": "string? — one of: created, updated, auto_resolved, conflict, entity_not_found, rate_limited, auto_rejected, redirected_to_contact; omitted when ambiguous",

Also applies to: 20-28

🤖 Prompt for 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.

In `@skills/memory/tools/memory-store/tool.json` at line 3, Update the
memory-store manifest description and result schema to match MemoryStoreHandler:
include the auto_resolved and auto_rejected outcomes, and model the ambiguous
response as omitting action and stored. Mark fields that are not present on
every outcome as conditional/optional, while preserving the existing contracts
for created, updated, conflict, entity_not_found, and rate_limited.
skills/tasks/tools/checkpoint/tool.json (1)

8-13: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files 'skills/tasks/tools/checkpoint/*' && printf '\n---\n' &&
cat -n skills/tasks/tools/checkpoint/tool.json && printf '\n---\n' &&
cat -n skills/tasks/tools/checkpoint/handler.ts

Repository: josephfung/curia

Length of output: 7903


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' \
  -e 'tool\.json' -e 'inputs"' -e 'parse.*tool' -e 'ToolHandler' -e 'action_risk' \
  src skills | sed -n '1,220p'

Repository: josephfung/curia

Length of output: 21272


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,220p' src/skills/types.ts && printf '\n---\n' &&
sed -n '1,220p' src/skills/registry.ts && printf '\n---\n' &&
sed -n '1,260p' src/skills/loader.ts && printf '\n---\n' &&
sed -n '1,260p' src/startup/validator.ts

Repository: josephfung/curia

Length of output: 42310


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' \
  -e 'input_schema' -e 'validate.*input' -e 'ajv' -e 'tool definitions' -e 'toToolDefinitions\(' \
  src skills | sed -n '1,260p'

Repository: josephfung/curia

Length of output: 6961


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '220,320p' src/skills/registry.ts && printf '\n---\n' &&
sed -n '1,220p' src/skills/execution.ts && printf '\n---\n' &&
sed -n '1,240p' skills/tasks/tools/checkpoint/handler.test.ts

Repository: josephfung/curia

Length of output: 18091


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' \
  -e 'validated input' -e 'validate.*input' -e 'input schema' -e 'input_schema' \
  -e 'ToolContext' -e 'ToolResult' -e 'execute\(ctx' -e 'parse.*input' \
  src/skills src/agents src/index.ts | sed -n '1,260p'

Repository: josephfung/curia

Length of output: 11734


🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -a 'tool-manifest.schema.json' schemas src skills && printf '\n---\n' &&
cat -n schemas/tool-manifest.schema.json

Repository: josephfung/curia

Length of output: 3491


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' \
  -e 'setResumableBlock' -e 'cursor:' -e 'kind: document' -e 'document-pointer' -e 'spill' \
  src skills | sed -n '1,260p'

Repository: josephfung/curia

Length of output: 11963


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,260p' src/db/resumable-progress.ts && printf '\n---\n' &&
sed -n '1,420p' src/agents/resumable-task.ts

Repository: josephfung/curia

Length of output: 23876


Align the checkpoint input contract with the runtime shape. toToolDefinitions() turns cursor into string? and accumulator into object[]?, but the handler and resumable-progress types accept object cursors and spilled document pointers. Valid checkpoint payloads will be rejected at the tool boundary.

🤖 Prompt for 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.

In `@skills/tasks/tools/checkpoint/tool.json` around lines 8 - 13, Update the
checkpoint schema exposed by toToolDefinitions() to match the runtime contract:
allow cursor values as objects as well as strings, and allow accumulator entries
to be either inline slice-result objects or spilled document-pointer objects.
Preserve the optional/default behavior while ensuring valid handler and
resumable-progress payloads pass tool validation.
skills/web/tools/web-browser/dom-extract.ts (1)

90-100: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Reject stale refs after navigation.

A hostile page can record an emitted ref, navigate, then assign that old value to one new element. The documented uniqueness-only resolver would then act on that element, rather than failing closed. Track a handler-owned navigation generation and reject refs from prior documents; page-owned attributes are not an authority boundary. Grimly, the page is allowed to edit its own DOM.

🤖 Prompt for 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.

In `@skills/web/tools/web-browser/dom-extract.ts` around lines 90 - 100, Update
the ref-resolution flow around __curiaRefEpoch__ and the resolver’s ref
validation to maintain a handler-owned navigation generation that changes for
each new document. Encode or associate the generation with emitted refs and
reject any ref whose generation predates the current document, rather than
trusting page-controlled DOM attributes such as __curiaRefEpoch__. Preserve
valid refs within the active document while failing closed for refs reused after
navigation.

josephfung added a commit that referenced this pull request Jul 22, 2026
Sync manifest contracts to actual handler behavior and fix two genuine
regressions surfaced by the Phase 2 bundling review:

Output/description contracts (docs shown to the LLM; handler is ground truth):
- get-autonomy: add lastSetBy, trend (nullable), scoredActionCount
- list-pending-actions: declare optional displayTimezone + empty-case message
- set-autonomy: previous_score nullable, add summary
- scheduler-cancel: declare jobId
- ceo-inbox-sent-observe: add backfill_active, tasks_truncated
- ceo-inbox/email download-attachment: descriptions document the temp-file
  path (temp_file_url) vs base64, no longer promising unconditional base64
- context-bridge-clear: subjects/subject are either-or, both optional
- context-bridge-release: reply optional (in), task_id optional (out)
- audit-query / audit-trace / ops-lookup: displayTimezone optional
- list-learning-digest: sections_markdown always returned (empty when none)
- memory-confirm: drop success (only in the ToolResult envelope, not data)
- memory-store: document auto_resolved/auto_rejected + ambiguous outcomes
- contact-create / contact-grant-permission: restore required capabilities:[]

Behavior fixes:
- approve-grant-recommendation: action_risk low -> critical. Approving a
  recommendation writes the same AuthOverride grant as contact-grant-permission
  (critical), so it must require the same standing (min score 90).
- Tool input shorthand: generalize the string|null union parser to arbitrary
  multi-type unions (string|object|null, object[]|object), so checkpoint can
  declare its polymorphic cursor (ResumableCursor) and accumulator (inline
  array or spilled document pointer) instead of under-constraining the LLM.

Declined (verified against the code, left unchanged):
- email-draft-save export_items: still consumed by the export-controls gate
  (#201) for confidential-attachment sensitivity resolution.
- ceo-inbox-search/update-folders allowed_callers: never existed pre-move, no
  sibling ceo-inbox tool restricts callers; adding it would block real callers.
- scan-grant-recommendations allowed_callers: the scheduled run arrives as
  agentId 'contacts', so the suggested ['scheduler']/['system'] restriction
  would break the cron job.
- dom-extract __curiaRefEpoch__: the resolver never trusts the epoch; it matches
  the data-curia-ref attribute and accepts only on a unique live-DOM hit, failing
  closed. The seed is already handler-owned and monotonic.
- research-analyst version revert: the only change was a clarifying comment.
- pin-resolution resolvedPins: consumed by the ADR-032 polymorphic-pin tests.

Signed-off-by: Joseph Fung <joseph@josephfung.ca>
@josephfung

josephfung commented Jul 22, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review addressed (commit 745952a)

Went through all 21 comments (20 actionable + 1 nitpick) and verified each against the actual handler/runtime rather than applying blindly. 15 fixed, 6 declined with reasoning below. pnpm run typecheck passes; 614 skills unit tests + the targeted suites (registry, pin-resolution, checkpoint, resolved-pins regression) pass.

Fixed (15)

Manifest output/description contracts synced to what the handler actually returns/accepts (these are the doc contract shown to the LLM; the handler is ground truth):

  • get-autonomy — add lastSetBy, trend (nullable), scoredActionCount
  • list-pending-actions — declare optional displayTimezone + empty-case message
  • set-autonomyprevious_score nullable, add summary
  • scheduler-cancel — declare jobId
  • ceo-inbox-sent-observe — add backfill_active, tasks_truncated
  • ceo-inbox-download-attachment / email-download-attachment — descriptions document the temp-file path (temp_file_url) instead of promising unconditional base64
  • context-bridge-clearsubjects/subject are either-or, both optional
  • context-bridge-releasereply optional (in), task_id optional (out)
  • audit-query / audit-trace / ops-lookupdisplayTimezone optional
  • list-learning-digestsections_markdown always returned (empty string when none)
  • memory-confirm — drop success (it's only in the ToolResult envelope, not data)
  • memory-store — document auto_resolved/auto_rejected + ambiguous outcomes
  • contact-create / contact-grant-permission — restore required capabilities: []
  • docs/dev/adding-an-agent.mdtasks bundle member list now includes plan and checkpoint

Two behavior changes:

  • approve-grant-recommendation action_risk low → critical. Approving writes the same AuthOverride grant as contact-grant-permission (already critical), so it must require the same standing (min score 90). Good catch.
  • checkpoint polymorphic schema (root-cause fix). Rather than special-casing, generalized the tool-input shorthand parser from string|null-only to arbitrary multi-type unions (string|object|null, object[]|object). checkpoint now declares its real cursor (ResumableCursor = string | object | null) and accumulator (inline object array or a single spilled { kind: document, path, section? } pointer) instead of under-constraining the model. Added parser unit tests.

Declined (6) — verified against the code

  • email-draft-save export_items — still consumed by the export-controls gate (Bulk export controls: item count threshold, destination allowlisting, and sensitivity ceiling #201): email-draft-save is in GATEWAY_ATTACHMENT_TOOLS, so evaluateSkillExportextractAttachmentExportItems reads input.export_items to resolve each attachment's node_id/sensitivity for the confidential-export gate. Removing it would break sensitivity resolution for confidential draft attachments.
  • scan-grant-recommendations allowed_callers — the scheduled run dispatches to the contacts agent, so it arrives as agentId: "contacts", not "scheduler"/"system". The suggested restriction would block the real caller and break the weekly cron job. allowed_callers gates on agent identity, not schedule-vs-user origin, so it can't express "schedule-only" here anyway. Sibling scheduled tool contact-find-duplicates is likewise unrestricted.
  • ceo-inbox-search / ceo-inbox-update-folders allowed_callers — never present pre-bundle (the move was a 100% rename), and none of the 14 ceo-inbox tools restrict callers. Adding ["ceo-inbox"] to just these two would newly block any other caller and be inconsistent with the family. Reasonable hardening idea, but it should be a deliberate, uniform, separately-reviewed change — not a one-off in a file-move PR.
  • dom-extract __curiaRefEpoch__ — the resolver never trusts the epoch semantically. resolveLocator matches the literal data-curia-ref attribute on the live DOM and accepts only when exactly one element carries it (0 → stale, >1 → ambiguous), failing closed. The epoch seed is already handler-owned and monotonic (++refEpochSeed); it's a namespacing device for the ref string, not a trust token. A hostile page controls its own DOM regardless, and the uniqueness check is the actual guard — documented inline at dom-extract.ts:86-89. No wrong-element hazard.
  • research-analyst.yaml version bump — reverted the bump. The only change to that file was a clarifying comment; the pin list and behavior are unchanged, so there's no correlatable state change to version.
  • pin-resolution.ts resolvedPins (nitpick) — kept. It's not dead: the ADR-032 polymorphic-pin tests in pin-resolution.test.ts assert on it to distinguish a tool-pin (kind: 'tool', no bundle expansion) from a skill-pin (kind: 'skill'), which is this PR's headline behavior. The per-pin kind is also emitted via the inline logger.debug audit calls.

Full per-item rationale is in the commit body of 745952a.

cursoragent and others added 4 commits July 22, 2026 19:40
Implement ADR-032 prerequisites and finish Phase 2 native bundling:
polymorphic capability pins, MCP server skill projection, and twelve new
SKILL.md bundles (plus plan/checkpoint on tasks). Agent pin lists migrate
to bundles while narrow consumers keep individual tool pins so resolved
authority is unchanged.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Joseph Fung <josephfung@users.noreply.github.com>
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Joseph Fung <josephfung@users.noreply.github.com>
Learning tools import ceo-inbox-sent-observe across bundles; web-browser
tests needed updated vi.mock and on-disk paths after the move under
skills/web/tools/.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Joseph Fung <josephfung@users.noreply.github.com>
Sync manifest contracts to actual handler behavior and fix two genuine
regressions surfaced by the Phase 2 bundling review:

Output/description contracts (docs shown to the LLM; handler is ground truth):
- get-autonomy: add lastSetBy, trend (nullable), scoredActionCount
- list-pending-actions: declare optional displayTimezone + empty-case message
- set-autonomy: previous_score nullable, add summary
- scheduler-cancel: declare jobId
- ceo-inbox-sent-observe: add backfill_active, tasks_truncated
- ceo-inbox/email download-attachment: descriptions document the temp-file
  path (temp_file_url) vs base64, no longer promising unconditional base64
- context-bridge-clear: subjects/subject are either-or, both optional
- context-bridge-release: reply optional (in), task_id optional (out)
- audit-query / audit-trace / ops-lookup: displayTimezone optional
- list-learning-digest: sections_markdown always returned (empty when none)
- memory-confirm: drop success (only in the ToolResult envelope, not data)
- memory-store: document auto_resolved/auto_rejected + ambiguous outcomes
- contact-create / contact-grant-permission: restore required capabilities:[]

Behavior fixes:
- approve-grant-recommendation: action_risk low -> critical. Approving a
  recommendation writes the same AuthOverride grant as contact-grant-permission
  (critical), so it must require the same standing (min score 90).
- Tool input shorthand: generalize the string|null union parser to arbitrary
  multi-type unions (string|object|null, object[]|object), so checkpoint can
  declare its polymorphic cursor (ResumableCursor) and accumulator (inline
  array or spilled document pointer) instead of under-constraining the LLM.

Declined (verified against the code, left unchanged):
- email-draft-save export_items: still consumed by the export-controls gate
  (#201) for confidential-attachment sensitivity resolution.
- ceo-inbox-search/update-folders allowed_callers: never existed pre-move, no
  sibling ceo-inbox tool restricts callers; adding it would block real callers.
- scan-grant-recommendations allowed_callers: the scheduled run arrives as
  agentId 'contacts', so the suggested ['scheduler']/['system'] restriction
  would break the cron job.
- dom-extract __curiaRefEpoch__: the resolver never trusts the epoch; it matches
  the data-curia-ref attribute and accepts only on a unique live-DOM hit, failing
  closed. The seed is already handler-owned and monotonic.
- research-analyst version revert: the only change was a clarifying comment.
- pin-resolution resolvedPins: consumed by the ADR-032 polymorphic-pin tests.

Signed-off-by: Joseph Fung <joseph@josephfung.ca>
@josephfung
josephfung force-pushed the cursor/phase-2-bundle-remaining-tools-ac7f branch from 745952a to c1ddad0 Compare July 22, 2026 23:41
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

git show --stat --oneline --decorate --no-renames 745952a0
printf '\n--- Changed paths ---\n'
git diff-tree --no-commit-id --name-only -r 745952a0

printf '\n--- Commit patch for core runtime/parser/test changes ---\n'
git show --format=fuller --no-ext-diff --unified=45 745952a0 -- \
  src \
  tests/unit/skills \
  tests/unit/startup \
  docs/dev/adding-an-agent.md \
  'skills/**/tool.json' \
  'skills/**/SKILL.md' \
  | sed -n '1,2200p'

printf '\n--- Locate declined-case symbols and their enclosing contexts ---\n'
rg -n -C 4 \
  'GATEWAY_ATTACHMENT_TOOLS|evaluateSkillExport|extractAttachmentExportItems|scan-grant-recommendations|contact-find-duplicates|resolveLocator|__curiaRefEpoch__|refEpochSeed|resolvedPins|allowed_callers' \
  src skills tests agents \
  | sed -n '1,1800p'

Length of output: 1319


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="josephfung/curia"
sha="745952a0"

gh api "repos/${repo}/commits/${sha}" \
  --jq '{
    sha,
    html_url,
    message: .commit.message,
    author: .commit.author,
    parents: [.parents[].sha],
    files: [.files[] | {filename, status, additions, deletions, patch}]
  }' \
  > /tmp/commit-745952a0.json

printf '%s\n' '--- Commit metadata ---'
jq '{sha, html_url, author, parents, message}' /tmp/commit-745952a0.json

printf '%s\n' '--- Changed files ---'
jq -r '.files[] | "\(.status)\t+\(.additions)/-\(.deletions)\t\(.filename)"' /tmp/commit-745952a0.json

printf '%s\n' '--- Relevant patch excerpts ---'
jq -r '
  .files[]
  | select(
      .filename == "src/skills/tool-schema.ts"
      or .filename == "src/skills/pin-resolution.ts"
      or .filename == "skills/tasks/tools/checkpoint/tool.json"
      or .filename == "tests/unit/skills/pin-resolution.test.ts"
      or .filename == "tests/unit/skills/tool-schema.test.ts"
      or .filename == "docs/dev/adding-an-agent.md"
      or (.filename | endswith("/tool.json"))
    )
  | "\n### \(.filename)\n\(.patch // "[No patch returned by GitHub]")"
' /tmp/commit-745952a0.json | sed -n '1,2600p'

Length of output: 19380


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="josephfung/curia"
pr_number="1499"

head_sha=$(gh api "repos/${repo}/pulls/${pr_number}" --jq '.head.sha')
printf '%s\n' "--- PR head ---"
printf '%s\n' "$head_sha"

gh api "repos/${repo}/git/trees/${head_sha}?recursive=1" --paginate \
  --jq '.tree[] | select(.type == "blob") | .path' \
  > /tmp/curia-pr-1499-paths.txt

printf '%s\n' '--- Candidate source/test paths ---'
rg -n \
  '(^|/)(registry|registry\.test|dom-extract|handler|export|controls|pin-resolution)(\.test)?\.(ts|js)$|email-draft-save|scan-grant-recommendations|contact-find-duplicates' \
  /tmp/curia-pr-1499-paths.txt | sed -n '1,500p'

fetch_file() {
  local path="$1"
  printf '\n### %s ###\n' "$path"
  gh api \
    -H 'Accept: application/vnd.github.raw+json' \
    "repos/${repo}/contents/${path}?ref=${head_sha}" \
    2>/dev/null || true
}

printf '%s\n' '--- Parser implementation and its test ---'
fetch_file 'src/skills/registry.ts' | sed -n '1,850p'
fetch_file 'tests/unit/skills/registry.test.ts' | sed -n '1,900p'

printf '%s\n' '--- Locate declined-case implementation paths ---'
for p in \
  "$(rg '(^|/)dom-extract\.ts$' /tmp/curia-pr-1499-paths.txt | head -n1)" \
  "$(rg '(^|/)email-draft-save/handler\.ts$' /tmp/curia-pr-1499-paths.txt | head -n1)" \
  "$(rg '(^|/)scan-grant-recommendations/handler\.ts$' /tmp/curia-pr-1499-paths.txt | head -n1)" \
  "$(rg '(^|/)contact-find-duplicates/handler\.ts$' /tmp/curia-pr-1499-paths.txt | head -n1)" \
  "$(rg '(^|/)pin-resolution\.ts$' /tmp/curia-pr-1499-paths.txt | head -n1)" \
  "$(rg '(^|/)pin-resolution\.test\.ts$' /tmp/curia-pr-1499-paths.txt | head -n1)"
do
  [ -n "$p" ] && printf '%s\n' "$p"
done

Length of output: 38523


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="josephfung/curia"
head_sha="c1ddad0e3454c76b0be184616286142f24f08926"

# Locate candidate export-control modules from the already-fetched PR tree.
printf '%s\n' '--- Export-control candidate paths ---'
rg -n -i 'export.*(control|gate)|gate.*export|attachment.*export' \
  /tmp/curia-pr-1499-paths.txt | sed -n '1,300p'

fetch_file() {
  local path="$1"
  printf '\n### %s ###\n' "$path"
  gh api \
    -H 'Accept: application/vnd.github.raw+json' \
    "repos/${repo}/contents/${path}?ref=${head_sha}" \
    2>/dev/null || true
}

printf '%s\n' '--- Declined-case source and configuration ---'
for path in \
  'skills/email/tools/email-draft-save/handler.ts' \
  'skills/email/tools/email-draft-save/tool.json' \
  'skills/contacts/tools/scan-grant-recommendations/handler.ts' \
  'skills/contacts/tools/scan-grant-recommendations/tool.json' \
  'skills/contacts/tools/contact-find-duplicates/tool.json' \
  'skills/ceo-inbox/tools/ceo-inbox-search/tool.json' \
  'skills/ceo-inbox/tools/ceo-inbox-update-folders/tool.json' \
  'skills/web/tools/web-browser/dom-extract.ts' \
  'skills/web/tools/web-browser/handler.ts' \
  'src/skills/pin-resolution.ts' \
  'tests/unit/skills/pin-resolution.test.ts' \
  'agents/research-analyst.yaml'
do
  fetch_file "$path"
done | sed -n '1,4000p'

printf '%s\n' '--- Fetch likely export-control modules discovered above ---'
while IFS= read -r path; do
  fetch_file "$path"
done < <(
  rg -i 'export.*(control|gate)|gate.*export|attachment.*export' \
    /tmp/curia-pr-1499-paths.txt \
    | cut -d: -f2- \
    | head -n 15
) | sed -n '1,4000p'

Length of output: 114641


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="josephfung/curia"
head_sha="c1ddad0e3454c76b0be184616286142f24f08926"

printf '%s\n' '--- Export-control implementation ---'
gh api \
  -H 'Accept: application/vnd.github.raw+json' \
  "repos/${repo}/contents/src/security/export-controls.ts?ref=${head_sha}" \
  | nl -ba \
  | grep -E -C 20 \
    'GATEWAY_ATTACHMENT_TOOLS|evaluateSkillExport|extractAttachmentExportItems|export_items|email-draft-save' \
  | sed -n '1,1000p'

printf '%s\n' '--- Export-control tests covering draft saves / export_items ---'
gh api \
  -H 'Accept: application/vnd.github.raw+json' \
  "repos/${repo}/contents/src/security/export-controls.test.ts?ref=${head_sha}" \
  | nl -ba \
  | grep -E -C 12 \
    'email-draft-save|export_items|GATEWAY_ATTACHMENT_TOOLS|extractAttachmentExportItems' \
  | sed -n '1,1400p'

Length of output: 1213


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="josephfung/curia"
head_sha="c1ddad0e3454c76b0be184616286142f24f08926"

fetch_and_match() {
  local path="$1"
  printf '\n--- %s ---\n' "$path"
  gh api \
    -H 'Accept: application/vnd.github.raw+json' \
    "repos/${repo}/contents/${path}?ref=${head_sha}" \
  | awk '
      {
        lines[NR] = $0
      }
      /GATEWAY_ATTACHMENT_TOOLS|evaluateSkillExport|extractAttachmentExportItems|export_items|email-draft-save/ {
        for (i = NR - 12; i <= NR + 20; i++) wanted[i] = 1
      }
      END {
        for (i = 1; i <= NR; i++) {
          if (wanted[i]) printf "%d:%s\n", i, lines[i]
        }
      }
    ' \
  | sed -n '1,1800p'
}

fetch_and_match 'src/security/export-controls.ts'
fetch_and_match 'src/security/export-controls.test.ts'

Length of output: 11849


The PR description image 1 shows a dark, rounded “Open in Web” button with an up-right external-link icon. The PR description image 2 shows the matching dark “Open in Cursor” button with the Cursor logo. A small oasis of visual consistency amid the usual administrative abyss.

@josephfung, verified against the remote PR head and commit 745952a0:

  • The manifest contracts, approve-grant-recommendation risk upgrade, checkpoint schema correction, parser implementation, and parser regression tests are all present.
  • email-draft-save genuinely needs export_items: ExportControlService.evaluateSkillExport() routes it through extractAttachmentExportItems(), which consumes that metadata for attachment sensitivity resolution.
  • The allowed_callers rationale, browser ref fail-closed uniqueness check, unchanged research-agent version, and resolvedPins test/audit use are substantiated by the current source.

The 15 fixes are addressed; the six declined findings are withdrawn. I did not independently execute the reported test suites in this environment, but the source-level verification is complete. Grimly competent work.

[resolve]


✏️ Learnings added
Learnt from: josephfung
URL: https://github.com/josephfung/curia/pull/1499

Timestamp: 2026-07-22T23:43:59.873Z
Learning: In `src/security/export-controls.ts`, `email-draft-save` is a `GATEWAY_ATTACHMENT_TOOLS` member. `ExportControlService.evaluateSkillExport()` calls `extractExportItemsFromInput()`, which uses `extractAttachmentExportItems()` to merge top-level `input.export_items` with attachment metadata for export-sensitivity resolution; the `email-draft-save` manifest must retain `export_items`.

Learnt from: josephfung
URL: https://github.com/josephfung/curia/pull/1499

Timestamp: 2026-07-22T23:43:59.873Z
Learning: In Curia skill manifests, `allowed_callers` gates on the executing agent identity rather than whether a run was scheduled. `scan-grant-recommendations` scheduled work executes as agentId `contacts`, so a scheduler/system-only caller restriction would block its intended cron execution.

Learnt from: josephfung
URL: https://github.com/josephfung/curia/pull/1499

Timestamp: 2026-07-22T23:43:59.873Z
Learning: In `skills/web/tools/web-browser/handler.ts`, browser reference tokens are resolved only by a unique live-DOM `data-curia-ref` attribute match. Zero matches are treated as stale and multiple matches as ambiguous, both failing closed; the epoch encoded in the token is namespacing rather than a trusted resolver input.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

The bundling epic (#1485/#1489/#1494/#1495) plus the #1499 review pass
accumulated ~18 Unreleased bullets for one reader-facing theme. Fold the
per-PR entries into a tight set (Added 2, Changed 3, Fixed 1) and drop the

Signed-off-by: Joseph Fung <joseph@josephfung.ca>
#1499 lines that only corrected still-unreleased #1494 code. Unrelated
#1487 scheduler entries left as-is.
@josephfung

Copy link
Copy Markdown
Owner Author

@coderabbitai approve

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Comments resolved and changes approved.

@josephfung
josephfung merged commit 858cad1 into main Jul 23, 2026
12 checks passed
josephfung added a commit that referenced this pull request Jul 23, 2026
Sync manifest contracts to actual handler behavior and fix two genuine
regressions surfaced by the Phase 2 bundling review:

Output/description contracts (docs shown to the LLM; handler is ground truth):
- get-autonomy: add lastSetBy, trend (nullable), scoredActionCount
- list-pending-actions: declare optional displayTimezone + empty-case message
- set-autonomy: previous_score nullable, add summary
- scheduler-cancel: declare jobId
- ceo-inbox-sent-observe: add backfill_active, tasks_truncated
- ceo-inbox/email download-attachment: descriptions document the temp-file
  path (temp_file_url) vs base64, no longer promising unconditional base64
- context-bridge-clear: subjects/subject are either-or, both optional
- context-bridge-release: reply optional (in), task_id optional (out)
- audit-query / audit-trace / ops-lookup: displayTimezone optional
- list-learning-digest: sections_markdown always returned (empty when none)
- memory-confirm: drop success (only in the ToolResult envelope, not data)
- memory-store: document auto_resolved/auto_rejected + ambiguous outcomes
- contact-create / contact-grant-permission: restore required capabilities:[]

Behavior fixes:
- approve-grant-recommendation: action_risk low -> critical. Approving a
  recommendation writes the same AuthOverride grant as contact-grant-permission
  (critical), so it must require the same standing (min score 90).
- Tool input shorthand: generalize the string|null union parser to arbitrary
  multi-type unions (string|object|null, object[]|object), so checkpoint can
  declare its polymorphic cursor (ResumableCursor) and accumulator (inline
  array or spilled document pointer) instead of under-constraining the LLM.

Declined (verified against the code, left unchanged):
- email-draft-save export_items: still consumed by the export-controls gate
  (#201) for confidential-attachment sensitivity resolution.
- ceo-inbox-search/update-folders allowed_callers: never existed pre-move, no
  sibling ceo-inbox tool restricts callers; adding it would block real callers.
- scan-grant-recommendations allowed_callers: the scheduled run arrives as
  agentId 'contacts', so the suggested ['scheduler']/['system'] restriction
  would break the cron job.
- dom-extract __curiaRefEpoch__: the resolver never trusts the epoch; it matches
  the data-curia-ref attribute and accepts only on a unique live-DOM hit, failing
  closed. The seed is already handler-owned and monotonic.
- research-analyst version revert: the only change was a clarifying comment.
- pin-resolution resolvedPins: consumed by the ADR-032 polymorphic-pin tests.

Signed-off-by: Joseph Fung <joseph@josephfung.ca>
@cursor
cursor Bot deleted the cursor/phase-2-bundle-remaining-tools-ac7f branch July 23, 2026 00:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request infra Deployment, monitoring, and operational tooling orchestration Multi-agent coordination — delegation, specialist agents, skill routing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Phase 2 follow-up: bundle the remaining tool clusters into skills

2 participants