mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-23 09:07:46 +02:00
fix: prove continuation origin through the real dispatch receipt
Exercise the committed status outbox through production dispatch and run claim. Follow the coalesced intent to its admitted dispatch, retain requester checks, and reject a missing dispatch. Refresh the generated skill inventory after the guidance change. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
7179058e39
commit
b8ca59c0a6
9 files changed
+282
-235
No files matched your search
@@ -47,34 +47,34 @@ The skill/reference inventory and eval cases are the only normative behavior sou
|
||||
| skill:skills/paperclip/SKILL.md:conversation-tasks:32 | optional_agent_tool | skills/paperclip/SKILL.md:32 |
|
||||
| skill:skills/paperclip/SKILL.md:server-verified-external-chat-turns:49 | control_plane_owned | skills/paperclip/SKILL.md:49 |
|
||||
| skill:skills/paperclip/SKILL.md:the-heartbeat-procedure:89 | optional_agent_tool | skills/paperclip/SKILL.md:89 |
|
||||
| skill:skills/paperclip/SKILL.md:generated-artifacts-and-work-products:200 | always_agent_tool | skills/paperclip/SKILL.md:200 |
|
||||
| skill:skills/paperclip/SKILL.md:status-quick-guide:248 | control_plane_owned | skills/paperclip/SKILL.md:248 |
|
||||
| skill:skills/paperclip/SKILL.md:monitors-and-watchers-say-only-what-you-actually-scheduled:258 | optional_agent_tool | skills/paperclip/SKILL.md:258 |
|
||||
| skill:skills/paperclip/SKILL.md:delegating-review-tasks:271 | always_agent_tool | skills/paperclip/SKILL.md:271 |
|
||||
| skill:skills/paperclip/SKILL.md:managing-a-user-s-inbox:282 | control_plane_owned | skills/paperclip/SKILL.md:282 |
|
||||
| skill:skills/paperclip/SKILL.md:issue-dependencies-blockers:290 | control_plane_owned | skills/paperclip/SKILL.md:290 |
|
||||
| skill:skills/paperclip/SKILL.md:requesting-board-approval:315 | optional_agent_tool | skills/paperclip/SKILL.md:315 |
|
||||
| skill:skills/paperclip/SKILL.md:issue-thread-interactions:336 | optional_agent_tool | skills/paperclip/SKILL.md:336 |
|
||||
| skill:skills/paperclip/SKILL.md:standalone-decisions:366 | optional_agent_tool | skills/paperclip/SKILL.md:366 |
|
||||
| skill:skills/paperclip/SKILL.md:mcp-tool-approval-gates:470 | optional_agent_tool | skills/paperclip/SKILL.md:470 |
|
||||
| skill:skills/paperclip/SKILL.md:niche-workflow-pointers:512 | optional_agent_tool | skills/paperclip/SKILL.md:512 |
|
||||
| skill:skills/paperclip/SKILL.md:cases:522 | optional_agent_tool | skills/paperclip/SKILL.md:522 |
|
||||
| skill:skills/paperclip/SKILL.md:company-skills-workflow:527 | optional_agent_tool | skills/paperclip/SKILL.md:527 |
|
||||
| skill:skills/paperclip/SKILL.md:routines:538 | optional_agent_tool | skills/paperclip/SKILL.md:538 |
|
||||
| skill:skills/paperclip/SKILL.md:task-files-and-workspace-choices:549 | optional_agent_tool | skills/paperclip/SKILL.md:549 |
|
||||
| skill:skills/paperclip/SKILL.md:issue-workspace-runtime-controls:555 | optional_agent_tool | skills/paperclip/SKILL.md:555 |
|
||||
| skill:skills/paperclip/SKILL.md:proposing-credentials-safely:562 | optional_agent_tool | skills/paperclip/SKILL.md:562 |
|
||||
| skill:skills/paperclip/SKILL.md:reading-granted-secrets:569 | optional_agent_tool | skills/paperclip/SKILL.md:569 |
|
||||
| skill:skills/paperclip/SKILL.md:critical-rules:595 | optional_agent_tool | skills/paperclip/SKILL.md:595 |
|
||||
| skill:skills/paperclip/SKILL.md:comment-style-required:616 | always_agent_tool | skills/paperclip/SKILL.md:616 |
|
||||
| skill:skills/paperclip/SKILL.md:update:648 | optional_agent_tool | skills/paperclip/SKILL.md:648 |
|
||||
| skill:skills/paperclip/SKILL.md:task-documents-and-deliverables:658 | always_agent_tool | skills/paperclip/SKILL.md:658 |
|
||||
| skill:skills/paperclip/SKILL.md:planning-required-when-planning-requested:672 | optional_agent_tool | skills/paperclip/SKILL.md:672 |
|
||||
| skill:skills/paperclip/SKILL.md:key-endpoints-hot-routes:703 | optional_agent_tool | skills/paperclip/SKILL.md:703 |
|
||||
| skill:skills/paperclip/SKILL.md:searching-issues:733 | optional_agent_tool | skills/paperclip/SKILL.md:733 |
|
||||
| skill:skills/paperclip/SKILL.md:full-reference:743 | optional_agent_tool | skills/paperclip/SKILL.md:743 |
|
||||
| skill:skills/paperclip/SKILL.md:conversational-confirmation-answers:747 | always_agent_tool | skills/paperclip/SKILL.md:747 |
|
||||
| skill:skills/paperclip/SKILL.md:incidental-feedback:764 | optional_agent_tool | skills/paperclip/SKILL.md:764 |
|
||||
| skill:skills/paperclip/SKILL.md:generated-artifacts-and-work-products:201 | always_agent_tool | skills/paperclip/SKILL.md:201 |
|
||||
| skill:skills/paperclip/SKILL.md:status-quick-guide:249 | control_plane_owned | skills/paperclip/SKILL.md:249 |
|
||||
| skill:skills/paperclip/SKILL.md:monitors-and-watchers-say-only-what-you-actually-scheduled:259 | optional_agent_tool | skills/paperclip/SKILL.md:259 |
|
||||
| skill:skills/paperclip/SKILL.md:delegating-review-tasks:272 | always_agent_tool | skills/paperclip/SKILL.md:272 |
|
||||
| skill:skills/paperclip/SKILL.md:managing-a-user-s-inbox:283 | control_plane_owned | skills/paperclip/SKILL.md:283 |
|
||||
| skill:skills/paperclip/SKILL.md:issue-dependencies-blockers:291 | control_plane_owned | skills/paperclip/SKILL.md:291 |
|
||||
| skill:skills/paperclip/SKILL.md:requesting-board-approval:316 | optional_agent_tool | skills/paperclip/SKILL.md:316 |
|
||||
| skill:skills/paperclip/SKILL.md:issue-thread-interactions:337 | optional_agent_tool | skills/paperclip/SKILL.md:337 |
|
||||
| skill:skills/paperclip/SKILL.md:standalone-decisions:367 | optional_agent_tool | skills/paperclip/SKILL.md:367 |
|
||||
| skill:skills/paperclip/SKILL.md:mcp-tool-approval-gates:471 | optional_agent_tool | skills/paperclip/SKILL.md:471 |
|
||||
| skill:skills/paperclip/SKILL.md:niche-workflow-pointers:513 | optional_agent_tool | skills/paperclip/SKILL.md:513 |
|
||||
| skill:skills/paperclip/SKILL.md:cases:523 | optional_agent_tool | skills/paperclip/SKILL.md:523 |
|
||||
| skill:skills/paperclip/SKILL.md:company-skills-workflow:528 | optional_agent_tool | skills/paperclip/SKILL.md:528 |
|
||||
| skill:skills/paperclip/SKILL.md:routines:539 | optional_agent_tool | skills/paperclip/SKILL.md:539 |
|
||||
| skill:skills/paperclip/SKILL.md:task-files-and-workspace-choices:550 | optional_agent_tool | skills/paperclip/SKILL.md:550 |
|
||||
| skill:skills/paperclip/SKILL.md:issue-workspace-runtime-controls:558 | optional_agent_tool | skills/paperclip/SKILL.md:558 |
|
||||
| skill:skills/paperclip/SKILL.md:proposing-credentials-safely:565 | optional_agent_tool | skills/paperclip/SKILL.md:565 |
|
||||
| skill:skills/paperclip/SKILL.md:reading-granted-secrets:572 | optional_agent_tool | skills/paperclip/SKILL.md:572 |
|
||||
| skill:skills/paperclip/SKILL.md:critical-rules:598 | optional_agent_tool | skills/paperclip/SKILL.md:598 |
|
||||
| skill:skills/paperclip/SKILL.md:comment-style-required:619 | always_agent_tool | skills/paperclip/SKILL.md:619 |
|
||||
| skill:skills/paperclip/SKILL.md:update:651 | optional_agent_tool | skills/paperclip/SKILL.md:651 |
|
||||
| skill:skills/paperclip/SKILL.md:task-documents-and-deliverables:661 | always_agent_tool | skills/paperclip/SKILL.md:661 |
|
||||
| skill:skills/paperclip/SKILL.md:planning-required-when-planning-requested:675 | optional_agent_tool | skills/paperclip/SKILL.md:675 |
|
||||
| skill:skills/paperclip/SKILL.md:key-endpoints-hot-routes:706 | optional_agent_tool | skills/paperclip/SKILL.md:706 |
|
||||
| skill:skills/paperclip/SKILL.md:searching-issues:736 | optional_agent_tool | skills/paperclip/SKILL.md:736 |
|
||||
| skill:skills/paperclip/SKILL.md:full-reference:746 | optional_agent_tool | skills/paperclip/SKILL.md:746 |
|
||||
| skill:skills/paperclip/SKILL.md:conversational-confirmation-answers:750 | always_agent_tool | skills/paperclip/SKILL.md:750 |
|
||||
| skill:skills/paperclip/SKILL.md:incidental-feedback:767 | optional_agent_tool | skills/paperclip/SKILL.md:767 |
|
||||
| skill:skills/paperclip/references/api-reference.md:paperclip-api-reference:1 | optional_agent_tool | skills/paperclip/references/api-reference.md:1 |
|
||||
| skill:skills/paperclip/references/api-reference.md:response-schemas:9 | optional_agent_tool | skills/paperclip/references/api-reference.md:9 |
|
||||
| skill:skills/paperclip/references/api-reference.md:agent-record-get-api-agents-me-or-get-api-agents-agentid:11 | optional_agent_tool | skills/paperclip/references/api-reference.md:11 |
|
||||
|
||||
@@ -56,252 +56,252 @@
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:200",
|
||||
"id": "skill:skills/paperclip/SKILL.md:201",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L200:generated-artifacts-and-work-products",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L201:generated-artifacts-and-work-products",
|
||||
"heading": "Generated Artifacts and Work Products",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
"semanticOperation": "register_deliverable",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:248",
|
||||
"id": "skill:skills/paperclip/SKILL.md:249",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L248:status-quick-guide",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L249:status-quick-guide",
|
||||
"heading": "Status Quick Guide",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:258",
|
||||
"id": "skill:skills/paperclip/SKILL.md:259",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L258:monitors-and-watchers-say-only-what-you-actually-scheduled",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L259:monitors-and-watchers-say-only-what-you-actually-scheduled",
|
||||
"heading": "Monitors and Watchers (say only what you actually scheduled)",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:271",
|
||||
"id": "skill:skills/paperclip/SKILL.md:272",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L271:delegating-review-tasks",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L272:delegating-review-tasks",
|
||||
"heading": "Delegating review tasks",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:282",
|
||||
"id": "skill:skills/paperclip/SKILL.md:283",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L282:managing-a-user-s-inbox",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L283:managing-a-user-s-inbox",
|
||||
"heading": "Managing A User's Inbox",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:290",
|
||||
"id": "skill:skills/paperclip/SKILL.md:291",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L290:issue-dependencies-blockers",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L291:issue-dependencies-blockers",
|
||||
"heading": "Issue Dependencies (Blockers)",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:315",
|
||||
"id": "skill:skills/paperclip/SKILL.md:316",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L315:requesting-board-approval",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L316:requesting-board-approval",
|
||||
"heading": "Requesting Board Approval",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"semanticOperation": "scoped_discovery",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:336",
|
||||
"id": "skill:skills/paperclip/SKILL.md:337",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L336:issue-thread-interactions",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L337:issue-thread-interactions",
|
||||
"heading": "Issue-Thread Interactions",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
"semanticOperation": "request_human_input",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:366",
|
||||
"id": "skill:skills/paperclip/SKILL.md:367",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L366:standalone-decisions",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L367:standalone-decisions",
|
||||
"heading": "Standalone Decisions",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:470",
|
||||
"id": "skill:skills/paperclip/SKILL.md:471",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L470:mcp-tool-approval-gates",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L471:mcp-tool-approval-gates",
|
||||
"heading": "MCP Tool Approval Gates",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"semanticOperation": "scoped_discovery",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:512",
|
||||
"id": "skill:skills/paperclip/SKILL.md:513",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L512:niche-workflow-pointers",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L513:niche-workflow-pointers",
|
||||
"heading": "Niche Workflow Pointers",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:522",
|
||||
"id": "skill:skills/paperclip/SKILL.md:523",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L522:cases",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L523:cases",
|
||||
"heading": "Cases",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"semanticOperation": "scoped_discovery",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:527",
|
||||
"id": "skill:skills/paperclip/SKILL.md:528",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L527:company-skills-workflow",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L528:company-skills-workflow",
|
||||
"heading": "Company Skills Workflow",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"semanticOperation": "scoped_discovery",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:538",
|
||||
"id": "skill:skills/paperclip/SKILL.md:539",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L538:routines",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L539:routines",
|
||||
"heading": "Routines",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"semanticOperation": "scoped_discovery",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:549",
|
||||
"id": "skill:skills/paperclip/SKILL.md:550",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L549:task-files-and-workspace-choices",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L550:task-files-and-workspace-choices",
|
||||
"heading": "Task Files and Workspace Choices",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"semanticOperation": "scoped_discovery",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:555",
|
||||
"id": "skill:skills/paperclip/SKILL.md:558",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L555:issue-workspace-runtime-controls",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L558:issue-workspace-runtime-controls",
|
||||
"heading": "Issue Workspace Runtime Controls",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"semanticOperation": "scoped_discovery",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:562",
|
||||
"id": "skill:skills/paperclip/SKILL.md:565",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L562:proposing-credentials-safely",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L565:proposing-credentials-safely",
|
||||
"heading": "Proposing Credentials Safely",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:569",
|
||||
"id": "skill:skills/paperclip/SKILL.md:572",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L569:reading-granted-secrets",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L572:reading-granted-secrets",
|
||||
"heading": "Reading Granted Secrets",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"semanticOperation": "scoped_discovery",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:595",
|
||||
"id": "skill:skills/paperclip/SKILL.md:598",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L595:critical-rules",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L598:critical-rules",
|
||||
"heading": "Critical Rules",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:616",
|
||||
"id": "skill:skills/paperclip/SKILL.md:619",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L616:comment-style-required",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L619:comment-style-required",
|
||||
"heading": "Comment Style (Required)",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
"semanticOperation": "report_progress",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:648",
|
||||
"id": "skill:skills/paperclip/SKILL.md:651",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L648:update",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L651:update",
|
||||
"heading": "Update",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:658",
|
||||
"id": "skill:skills/paperclip/SKILL.md:661",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L658:task-documents-and-deliverables",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L661:task-documents-and-deliverables",
|
||||
"heading": "Task Documents and Deliverables",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
"semanticOperation": "write_document",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:672",
|
||||
"id": "skill:skills/paperclip/SKILL.md:675",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L672:planning-required-when-planning-requested",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L675:planning-required-when-planning-requested",
|
||||
"heading": "Planning (Required when planning requested)",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
"semanticOperation": "write_document",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:703",
|
||||
"id": "skill:skills/paperclip/SKILL.md:706",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L703:key-endpoints-hot-routes",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L706:key-endpoints-hot-routes",
|
||||
"heading": "Key Endpoints (Hot Routes)",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:733",
|
||||
"id": "skill:skills/paperclip/SKILL.md:736",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L733:searching-issues",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L736:searching-issues",
|
||||
"heading": "Searching Issues",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:743",
|
||||
"id": "skill:skills/paperclip/SKILL.md:746",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L743:full-reference",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L746:full-reference",
|
||||
"heading": "Full Reference",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
"semanticOperation": "runtime_reconciliation",
|
||||
"expectedMockState": "runtime_decision_record"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:747",
|
||||
"id": "skill:skills/paperclip/SKILL.md:750",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L747:conversational-confirmation-answers",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L750:conversational-confirmation-answers",
|
||||
"heading": "Conversational confirmation answers",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
"semanticOperation": "call_api",
|
||||
"expectedMockState": "operation_result"
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:764",
|
||||
"id": "skill:skills/paperclip/SKILL.md:767",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L764:incidental-feedback",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md#L767:incidental-feedback",
|
||||
"heading": "Incidental feedback",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"semanticOperation": "scoped_discovery",
|
||||
|
||||
@@ -5,6 +5,6 @@ Generated by `scripts/generate-capability-contract.mjs`; do not edit generated f
|
||||
- Skill/reference headings: 167
|
||||
- Legacy MCP tools: 42
|
||||
- Eval cases: 106 across 16 groups
|
||||
- Deterministic content SHA-256: `56f834a342a1e75e535d1f1a23f483882331d1fb364aa6bd17de7d9a2da39c4b`
|
||||
- Deterministic content SHA-256: `05f5724a98ae5e6045a550d969599c3e5f40d4c97069ae2453cc6e7e60d2ba44`
|
||||
|
||||
Every row has exactly one primary disposition, a source anchor, a semantic operation, and a mock-state expectation.
|
||||
@@ -105,9 +105,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:generated-artifacts-and-work-products:200",
|
||||
"id": "skill:skills/paperclip/SKILL.md:generated-artifacts-and-work-products:201",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:200",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:201",
|
||||
"title": "Generated Artifacts and Work Products",
|
||||
"expectedSemantics": "Skill guidance headed “Generated Artifacts and Work Products”.",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
@@ -116,13 +116,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:200"
|
||||
"skill:skills/paperclip/SKILL.md:201"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:status-quick-guide:248",
|
||||
"id": "skill:skills/paperclip/SKILL.md:status-quick-guide:249",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:248",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:249",
|
||||
"title": "Status Quick Guide",
|
||||
"expectedSemantics": "Skill guidance headed “Status Quick Guide”.",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
@@ -131,13 +131,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:248"
|
||||
"skill:skills/paperclip/SKILL.md:249"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:monitors-and-watchers-say-only-what-you-actually-scheduled:258",
|
||||
"id": "skill:skills/paperclip/SKILL.md:monitors-and-watchers-say-only-what-you-actually-scheduled:259",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:258",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:259",
|
||||
"title": "Monitors and Watchers (say only what you actually scheduled)",
|
||||
"expectedSemantics": "Skill guidance headed “Monitors and Watchers (say only what you actually scheduled)”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -146,13 +146,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:258"
|
||||
"skill:skills/paperclip/SKILL.md:259"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:delegating-review-tasks:271",
|
||||
"id": "skill:skills/paperclip/SKILL.md:delegating-review-tasks:272",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:271",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:272",
|
||||
"title": "Delegating review tasks",
|
||||
"expectedSemantics": "Skill guidance headed “Delegating review tasks”.",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
@@ -161,13 +161,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:271"
|
||||
"skill:skills/paperclip/SKILL.md:272"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:managing-a-user-s-inbox:282",
|
||||
"id": "skill:skills/paperclip/SKILL.md:managing-a-user-s-inbox:283",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:282",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:283",
|
||||
"title": "Managing A User's Inbox",
|
||||
"expectedSemantics": "Skill guidance headed “Managing A User's Inbox”.",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
@@ -176,13 +176,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:282"
|
||||
"skill:skills/paperclip/SKILL.md:283"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:issue-dependencies-blockers:290",
|
||||
"id": "skill:skills/paperclip/SKILL.md:issue-dependencies-blockers:291",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:290",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:291",
|
||||
"title": "Issue Dependencies (Blockers)",
|
||||
"expectedSemantics": "Skill guidance headed “Issue Dependencies (Blockers)”.",
|
||||
"primaryDisposition": "control_plane_owned",
|
||||
@@ -191,13 +191,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:290"
|
||||
"skill:skills/paperclip/SKILL.md:291"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:requesting-board-approval:315",
|
||||
"id": "skill:skills/paperclip/SKILL.md:requesting-board-approval:316",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:315",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:316",
|
||||
"title": "Requesting Board Approval",
|
||||
"expectedSemantics": "Skill guidance headed “Requesting Board Approval”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -206,13 +206,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:315"
|
||||
"skill:skills/paperclip/SKILL.md:316"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:issue-thread-interactions:336",
|
||||
"id": "skill:skills/paperclip/SKILL.md:issue-thread-interactions:337",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:336",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:337",
|
||||
"title": "Issue-Thread Interactions",
|
||||
"expectedSemantics": "Skill guidance headed “Issue-Thread Interactions”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -221,13 +221,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:336"
|
||||
"skill:skills/paperclip/SKILL.md:337"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:standalone-decisions:366",
|
||||
"id": "skill:skills/paperclip/SKILL.md:standalone-decisions:367",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:366",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:367",
|
||||
"title": "Standalone Decisions",
|
||||
"expectedSemantics": "Skill guidance headed “Standalone Decisions”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -236,13 +236,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:366"
|
||||
"skill:skills/paperclip/SKILL.md:367"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:mcp-tool-approval-gates:470",
|
||||
"id": "skill:skills/paperclip/SKILL.md:mcp-tool-approval-gates:471",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:470",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:471",
|
||||
"title": "MCP Tool Approval Gates",
|
||||
"expectedSemantics": "Skill guidance headed “MCP Tool Approval Gates”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -251,13 +251,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:470"
|
||||
"skill:skills/paperclip/SKILL.md:471"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:niche-workflow-pointers:512",
|
||||
"id": "skill:skills/paperclip/SKILL.md:niche-workflow-pointers:513",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:512",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:513",
|
||||
"title": "Niche Workflow Pointers",
|
||||
"expectedSemantics": "Skill guidance headed “Niche Workflow Pointers”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -266,13 +266,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:512"
|
||||
"skill:skills/paperclip/SKILL.md:513"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:cases:522",
|
||||
"id": "skill:skills/paperclip/SKILL.md:cases:523",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:522",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:523",
|
||||
"title": "Cases",
|
||||
"expectedSemantics": "Skill guidance headed “Cases”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -281,13 +281,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:522"
|
||||
"skill:skills/paperclip/SKILL.md:523"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:company-skills-workflow:527",
|
||||
"id": "skill:skills/paperclip/SKILL.md:company-skills-workflow:528",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:527",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:528",
|
||||
"title": "Company Skills Workflow",
|
||||
"expectedSemantics": "Skill guidance headed “Company Skills Workflow”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -296,13 +296,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:527"
|
||||
"skill:skills/paperclip/SKILL.md:528"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:routines:538",
|
||||
"id": "skill:skills/paperclip/SKILL.md:routines:539",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:538",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:539",
|
||||
"title": "Routines",
|
||||
"expectedSemantics": "Skill guidance headed “Routines”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -311,13 +311,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:538"
|
||||
"skill:skills/paperclip/SKILL.md:539"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:task-files-and-workspace-choices:549",
|
||||
"id": "skill:skills/paperclip/SKILL.md:task-files-and-workspace-choices:550",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:549",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:550",
|
||||
"title": "Task Files and Workspace Choices",
|
||||
"expectedSemantics": "Skill guidance headed “Task Files and Workspace Choices”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -326,13 +326,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:549"
|
||||
"skill:skills/paperclip/SKILL.md:550"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:issue-workspace-runtime-controls:555",
|
||||
"id": "skill:skills/paperclip/SKILL.md:issue-workspace-runtime-controls:558",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:555",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:558",
|
||||
"title": "Issue Workspace Runtime Controls",
|
||||
"expectedSemantics": "Skill guidance headed “Issue Workspace Runtime Controls”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -341,13 +341,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:555"
|
||||
"skill:skills/paperclip/SKILL.md:558"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:proposing-credentials-safely:562",
|
||||
"id": "skill:skills/paperclip/SKILL.md:proposing-credentials-safely:565",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:562",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:565",
|
||||
"title": "Proposing Credentials Safely",
|
||||
"expectedSemantics": "Skill guidance headed “Proposing Credentials Safely”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -356,13 +356,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:562"
|
||||
"skill:skills/paperclip/SKILL.md:565"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:reading-granted-secrets:569",
|
||||
"id": "skill:skills/paperclip/SKILL.md:reading-granted-secrets:572",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:569",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:572",
|
||||
"title": "Reading Granted Secrets",
|
||||
"expectedSemantics": "Skill guidance headed “Reading Granted Secrets”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -371,13 +371,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:569"
|
||||
"skill:skills/paperclip/SKILL.md:572"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:critical-rules:595",
|
||||
"id": "skill:skills/paperclip/SKILL.md:critical-rules:598",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:595",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:598",
|
||||
"title": "Critical Rules",
|
||||
"expectedSemantics": "Skill guidance headed “Critical Rules”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -386,13 +386,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:595"
|
||||
"skill:skills/paperclip/SKILL.md:598"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:comment-style-required:616",
|
||||
"id": "skill:skills/paperclip/SKILL.md:comment-style-required:619",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:616",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:619",
|
||||
"title": "Comment Style (Required)",
|
||||
"expectedSemantics": "Skill guidance headed “Comment Style (Required)”.",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
@@ -401,13 +401,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:616"
|
||||
"skill:skills/paperclip/SKILL.md:619"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:update:648",
|
||||
"id": "skill:skills/paperclip/SKILL.md:update:651",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:648",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:651",
|
||||
"title": "Update",
|
||||
"expectedSemantics": "Skill guidance headed “Update”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -416,13 +416,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:648"
|
||||
"skill:skills/paperclip/SKILL.md:651"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:task-documents-and-deliverables:658",
|
||||
"id": "skill:skills/paperclip/SKILL.md:task-documents-and-deliverables:661",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:658",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:661",
|
||||
"title": "Task Documents and Deliverables",
|
||||
"expectedSemantics": "Skill guidance headed “Task Documents and Deliverables”.",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
@@ -431,13 +431,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:658"
|
||||
"skill:skills/paperclip/SKILL.md:661"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:planning-required-when-planning-requested:672",
|
||||
"id": "skill:skills/paperclip/SKILL.md:planning-required-when-planning-requested:675",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:672",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:675",
|
||||
"title": "Planning (Required when planning requested)",
|
||||
"expectedSemantics": "Skill guidance headed “Planning (Required when planning requested)”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -446,13 +446,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:672"
|
||||
"skill:skills/paperclip/SKILL.md:675"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:key-endpoints-hot-routes:703",
|
||||
"id": "skill:skills/paperclip/SKILL.md:key-endpoints-hot-routes:706",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:703",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:706",
|
||||
"title": "Key Endpoints (Hot Routes)",
|
||||
"expectedSemantics": "Skill guidance headed “Key Endpoints (Hot Routes)”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -461,13 +461,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:703"
|
||||
"skill:skills/paperclip/SKILL.md:706"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:searching-issues:733",
|
||||
"id": "skill:skills/paperclip/SKILL.md:searching-issues:736",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:733",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:736",
|
||||
"title": "Searching Issues",
|
||||
"expectedSemantics": "Skill guidance headed “Searching Issues”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -476,13 +476,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:733"
|
||||
"skill:skills/paperclip/SKILL.md:736"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:full-reference:743",
|
||||
"id": "skill:skills/paperclip/SKILL.md:full-reference:746",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:743",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:746",
|
||||
"title": "Full Reference",
|
||||
"expectedSemantics": "Skill guidance headed “Full Reference”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -491,13 +491,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:743"
|
||||
"skill:skills/paperclip/SKILL.md:746"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:conversational-confirmation-answers:747",
|
||||
"id": "skill:skills/paperclip/SKILL.md:conversational-confirmation-answers:750",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:747",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:750",
|
||||
"title": "Conversational confirmation answers",
|
||||
"expectedSemantics": "Skill guidance headed “Conversational confirmation answers”.",
|
||||
"primaryDisposition": "always_agent_tool",
|
||||
@@ -506,13 +506,13 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:747"
|
||||
"skill:skills/paperclip/SKILL.md:750"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/SKILL.md:incidental-feedback:764",
|
||||
"id": "skill:skills/paperclip/SKILL.md:incidental-feedback:767",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:764",
|
||||
"sourceAnchor": "skills/paperclip/SKILL.md:767",
|
||||
"title": "Incidental feedback",
|
||||
"expectedSemantics": "Skill guidance headed “Incidental feedback”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
@@ -521,7 +521,7 @@
|
||||
"control_plane_invariant"
|
||||
],
|
||||
"evidenceIds": [
|
||||
"skill:skills/paperclip/SKILL.md:764"
|
||||
"skill:skills/paperclip/SKILL.md:767"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import type { Db } from "@paperclipai/db";
|
||||
import { heartbeatRuns } from "@paperclipai/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { vi, type Mock, type Mocked } from "vitest";
|
||||
import { createRunDispatch } from "../../modules/run-dispatch/index.js";
|
||||
import type { createWakeQueue } from "../../modules/wake-queue/index.js";
|
||||
import { createHeartbeatRunState } from "../../services/heartbeat/run-state.js";
|
||||
import { createHeartbeatRunPreparation } from "../../services/heartbeat/run-preparation.js";
|
||||
import type { HeartbeatQueueDependencies } from "../../services/heartbeat/queue.js";
|
||||
|
||||
type Run = typeof heartbeatRuns.$inferSelect;
|
||||
type MockedCallback = "getAgent" | "setRunStatus" | "setWakeupStatus" | "appendRunEvent" | "finalizeAgentStatus" | "getAgentInvokability" | "getWorktreeExecutionCutoff" | "applyRunDispatchPostCommitEffects" | "getSchedulingSuppression" | "canStartNewExternalBotWork" | "executeRun" | "applyWakeQueuePostCommitEffects" | "releaseIssueExecutionAndPromote" | "publishRunLifecyclePluginEvent" | "cancelRunInternal" | "cancelActiveForAgentInternal" | "resumeExecutionWaitComments" | "resumeQueuedCommentInterrupt" | "resumeSavedLegacyComments" | "sweepPendingCleanupLeases";
|
||||
type QueueTestDependencies = HeartbeatQueueDependencies & { [K in MockedCallback]: Mock<HeartbeatQueueDependencies[K]> } & {
|
||||
issuesSvc: Mocked<HeartbeatQueueDependencies["issuesSvc"]>;
|
||||
treeControlSvc: Mocked<HeartbeatQueueDependencies["treeControlSvc"]>;
|
||||
budgets: Mocked<HeartbeatQueueDependencies["budgets"]>;
|
||||
instanceSettings: Mocked<HeartbeatQueueDependencies["instanceSettings"]>;
|
||||
wakeQueue: Mocked<HeartbeatQueueDependencies["wakeQueue"]>;
|
||||
liveRunExecutions: Mocked<HeartbeatQueueDependencies["liveRunExecutions"]>;
|
||||
};
|
||||
|
||||
export function createHeartbeatQueueTestDependencies(db: Db): QueueTestDependencies {
|
||||
const state = createHeartbeatRunState(db);
|
||||
const preparation = createHeartbeatRunPreparation(db);
|
||||
return {
|
||||
...preparation,
|
||||
...state,
|
||||
getAgent: vi.fn<HeartbeatQueueDependencies["getAgent"]>(async () => { throw new Error("Unexpected agent lookup"); }),
|
||||
options: {},
|
||||
setRunStatus: vi.fn<HeartbeatQueueDependencies["setRunStatus"]>(async (id, status, patch) =>
|
||||
db.update(heartbeatRuns).set({ ...patch, status }).where(eq(heartbeatRuns.id, id)).returning().then(rows => rows[0] ?? null)),
|
||||
setWakeupStatus: vi.fn<HeartbeatQueueDependencies["setWakeupStatus"]>(async () => undefined),
|
||||
appendRunEvent: vi.fn<HeartbeatQueueDependencies["appendRunEvent"]>(async () => undefined),
|
||||
finalizeAgentStatus: vi.fn<HeartbeatQueueDependencies["finalizeAgentStatus"]>(async () => undefined),
|
||||
getAgentInvokability: vi.fn<HeartbeatQueueDependencies["getAgentInvokability"]>(async () => ({ invokable: true })),
|
||||
getWorktreeExecutionCutoff: vi.fn<HeartbeatQueueDependencies["getWorktreeExecutionCutoff"]>(async () => null),
|
||||
applyRunDispatchPostCommitEffects: vi.fn<HeartbeatQueueDependencies["applyRunDispatchPostCommitEffects"]>(),
|
||||
issuesSvc: {
|
||||
getDependencyReadiness: vi.fn<HeartbeatQueueDependencies["issuesSvc"]["getDependencyReadiness"]>(),
|
||||
listDependencyReadiness: vi.fn(async () => new Map()),
|
||||
},
|
||||
treeControlSvc: { getActivePauseHoldGate: vi.fn(async () => null) },
|
||||
budgets: { getInvocationBlock: vi.fn(async () => null) },
|
||||
instanceSettings: { getExperimental: vi.fn<HeartbeatQueueDependencies["instanceSettings"]["getExperimental"]>() },
|
||||
runDispatch: createRunDispatch(db),
|
||||
wakeQueue: {
|
||||
createAdmissionTransactionScope: vi.fn<ReturnType<typeof createWakeQueue>["createAdmissionTransactionScope"]>(),
|
||||
admitWakeBehindIssueExecution: vi.fn<ReturnType<typeof createWakeQueue>["admitWakeBehindIssueExecution"]>(),
|
||||
},
|
||||
activeRunExecutions: new Set<string>(),
|
||||
activeRunExecutionPromises: new Set<Promise<void>>(),
|
||||
activeWakeupPromises: new Set<Promise<unknown>>(),
|
||||
liveRunExecutions: { has: vi.fn(() => false) },
|
||||
isHeartbeatRunTerminalStatus: (status: string | null | undefined) => ["succeeded", "failed", "cancelled", "timed_out"].includes(status ?? ""),
|
||||
isSameTaskScope: (left: string | null, right: string | null) => left === right,
|
||||
runTaskKey: (run: Run) => typeof run.contextSnapshot?.issueId === "string" ? run.contextSnapshot.issueId : null,
|
||||
filterZombieCoalesceTarget: <T extends { id: string; status: string }>(run: T | null) => run,
|
||||
getSchedulingSuppression: vi.fn<HeartbeatQueueDependencies["getSchedulingSuppression"]>(async () => ({ suppressed: false, reason: null } as Awaited<ReturnType<HeartbeatQueueDependencies["getSchedulingSuppression"]>>)),
|
||||
canStartNewExternalBotWork: vi.fn<HeartbeatQueueDependencies["canStartNewExternalBotWork"]>(async () => true),
|
||||
executeRun: vi.fn<HeartbeatQueueDependencies["executeRun"]>(async () => undefined),
|
||||
applyWakeQueuePostCommitEffects: vi.fn<HeartbeatQueueDependencies["applyWakeQueuePostCommitEffects"]>(async () => undefined),
|
||||
releaseIssueExecutionAndPromote: vi.fn<HeartbeatQueueDependencies["releaseIssueExecutionAndPromote"]>(async () => undefined),
|
||||
publishRunLifecyclePluginEvent: vi.fn<HeartbeatQueueDependencies["publishRunLifecyclePluginEvent"]>(),
|
||||
cancelRunInternal: vi.fn<HeartbeatQueueDependencies["cancelRunInternal"]>(async () => undefined),
|
||||
cancelActiveForAgentInternal: vi.fn<HeartbeatQueueDependencies["cancelActiveForAgentInternal"]>(async () => undefined),
|
||||
resumeExecutionWaitComments: vi.fn<HeartbeatQueueDependencies["resumeExecutionWaitComments"]>(async () => undefined),
|
||||
resumeQueuedCommentInterrupt: vi.fn<HeartbeatQueueDependencies["resumeQueuedCommentInterrupt"]>(async () => undefined),
|
||||
resumeSavedLegacyComments: vi.fn<HeartbeatQueueDependencies["resumeSavedLegacyComments"]>(async () => undefined),
|
||||
formatIssueIdentifierLink: (_identifier: string | null, fallback: string) => fallback,
|
||||
sweepPendingCleanupLeases: vi.fn<HeartbeatQueueDependencies["sweepPendingCleanupLeases"]>(),
|
||||
} satisfies HeartbeatQueueDependencies;
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { and, eq } from "drizzle-orm";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
import {
|
||||
agents, agentWakeupRequests, authUsers, chatConversations, chatEndpoints, chatMessageLinks,
|
||||
chatPublications, companies, completionContracts, createDb, heartbeatRuns, issueComments, issues, nativeRunFinalizations, nativeRunResults,
|
||||
chatPublications, companies, companyMemberships, completionContracts, createDb, heartbeatRuns, issueComments, issues, nativeRunFinalizations, nativeRunResults,
|
||||
statusDecisions, statusDecisionEffects, toolApplications, toolConnections,
|
||||
} from "@paperclipai/db";
|
||||
import { getEmbeddedPostgresTestSupport, startEmbeddedPostgresTestDatabase } from "../__tests__/helpers/embedded-postgres.js";
|
||||
@@ -12,6 +12,9 @@ import { CHAT_RUN_PRESENTATION_AUTHORIZATION_REASON } from "./heartbeat-run-summ
|
||||
import { resolveChatOriginPublicationBindings } from "./issues.js";
|
||||
import { NativeRunCoordinatorStore } from "./native-runtime/native-run-coordinator-store.js";
|
||||
import { finalizeNativeRun, repairCommittedNativeChatResponse } from "./native-runtime/native-run-finalizer.js";
|
||||
import { createHeartbeatQueueTestDependencies } from "../__tests__/helpers/heartbeat-queue.js";
|
||||
import { createHeartbeatQueue } from "./heartbeat/queue.js";
|
||||
import { instanceSettingsService } from "./instance-settings.js";
|
||||
|
||||
const support = await getEmbeddedPostgresTestSupport();
|
||||
if (!support.supported) console.warn(`Monitor publication database unavailable: ${support.reason}`);
|
||||
@@ -27,8 +30,9 @@ if (!support.supported) console.warn(`Monitor publication database unavailable:
|
||||
|
||||
async function fixture() {
|
||||
const [company] = await db.insert(companies).values({ name: "Continuation", issuePrefix: randomUUID().slice(0, 8) }).returning();
|
||||
await db.insert(companyMemberships).values({ companyId: company.id, principalType: "user", principalId: "requester", status: "active", membershipRole: "owner" });
|
||||
const [agent] = await db.insert(agents).values({ companyId: company.id, name: "Worker", adapterType: "paperclip_runner" }).returning();
|
||||
const [issue] = await db.insert(issues).values({ companyId: company.id, title: "Repository QA", status: "in_progress", assigneeAgentId: agent.id }).returning();
|
||||
const [issue] = await db.insert(issues).values({ companyId: company.id, title: "Repository QA", status: "in_progress", assigneeAgentId: agent.id, responsibleUserId: "requester" }).returning();
|
||||
const [application] = await db.insert(toolApplications).values({ companyId: company.id, applicationKey: randomUUID(), name: "Slack", type: "chat" }).returning();
|
||||
const [connection] = await db.insert(toolConnections).values({ companyId: company.id, applicationId: application.id, name: "Slack", uid: randomUUID(), connectionPurpose: "channel", transport: "chat_sdk" }).returning();
|
||||
const [endpoint] = await db.insert(chatEndpoints).values({ companyId: company.id, connectionId: connection.id, provider: "slack", publicId: randomUUID(), assignedAgentId: agent.id, status: "active" }).returning();
|
||||
@@ -161,11 +165,21 @@ if (!support.supported) console.warn(`Monitor publication database unavailable:
|
||||
await finalizeNativeRun({ db, runId: f.source.id, workspaceFinalizeStatus: "succeeded", projectRunStatus: true });
|
||||
const [wake] = await db.select().from(agentWakeupRequests).where(and(eq(agentWakeupRequests.companyId, f.company.id), eq(agentWakeupRequests.reason, "issue_status_changed")));
|
||||
expect(wake).toBeDefined();
|
||||
await db.update(agentWakeupRequests).set({ status: "claimed", runId: f.successor.id }).where(eq(agentWakeupRequests.id, wake.id));
|
||||
await db.update(heartbeatRuns).set({ status: "running", finishedAt: null,
|
||||
contextSnapshot: { source: "native_status_decision", issueId: f.issue.id },
|
||||
}).where(eq(heartbeatRuns.id, f.successor.id));
|
||||
return { ...f, continuationWake: wake, summary };
|
||||
const deps = createHeartbeatQueueTestDependencies(db);
|
||||
deps.getAgent.mockImplementation(async id => (await db.select().from(agents).where(eq(agents.id, id)))[0] ?? null);
|
||||
deps.instanceSettings.getExperimental.mockImplementation(() => instanceSettingsService(db).getExperimental());
|
||||
await db.update(agents).set({ runtimeConfig: { heartbeat: { wakeOnDemand: true } } }).where(eq(agents.id, f.agent.id));
|
||||
const queue = createHeartbeatQueue(db, deps);
|
||||
expect(await queue.dispatchPendingNativeStatusWakeups({ companyId: f.company.id })).toMatchObject({ dispatched: 1 });
|
||||
await queue.startNextQueuedRunForAgent(f.agent.id);
|
||||
await Promise.all([...deps.activeRunExecutionPromises]);
|
||||
const [delivered] = await db.select().from(agentWakeupRequests).where(eq(agentWakeupRequests.id, wake.id));
|
||||
expect(delivered).toMatchObject({ status: "coalesced" });
|
||||
expect(delivered.runId).toBeTruthy();
|
||||
const [successor] = await db.select().from(heartbeatRuns).where(eq(heartbeatRuns.id, delivered.runId!));
|
||||
expect(successor.responsibleUserId).toBe("requester");
|
||||
return { ...f, successor, continuationWake: delivered, summary,
|
||||
bindings: (runId = successor.id) => resolveChatOriginPublicationBindings(db, f.company.id, f.issue.id, runId) };
|
||||
}
|
||||
|
||||
it("delivers the saved setup explanation and retains chat through the committed automatic continuation", async () => {
|
||||
@@ -182,11 +196,13 @@ if (!support.supported) console.warn(`Monitor publication database unavailable:
|
||||
expect(await db.select().from(nativeRunResults).where(eq(nativeRunResults.runId, f.source.id))).toHaveLength(1);
|
||||
});
|
||||
|
||||
it.each(["effect", "decision", "wake", "requester", "agent"])("rejects automatic continuation when %s authority is no longer valid", async fault => {
|
||||
it.each(["effect", "decision", "wake", "dispatch", "requester", "agent"])("rejects automatic continuation when %s authority is no longer valid", async fault => {
|
||||
const f = await continuedTaskFixture();
|
||||
if (fault === "effect") await db.update(statusDecisionEffects).set({ targetId: randomUUID() }).where(eq(statusDecisionEffects.companyId, f.company.id));
|
||||
if (fault === "decision") await db.update(statusDecisions).set({ applicationState: "proposed" }).where(eq(statusDecisions.companyId, f.company.id));
|
||||
if (fault === "wake") await db.update(agentWakeupRequests).set({ idempotencyKey: randomUUID() }).where(eq(agentWakeupRequests.id, f.continuationWake.id));
|
||||
if (fault === "dispatch") await db.update(agentWakeupRequests).set({ requestedByActorId: "unrelated-dispatch" }).where(and(
|
||||
eq(agentWakeupRequests.companyId, f.company.id), eq(agentWakeupRequests.requestedByActorId, `native-status-wake-dispatch:${f.continuationWake.id}`)));
|
||||
if (fault === "requester") await db.update(heartbeatRuns).set({ responsibleUserId: "another-person" }).where(eq(heartbeatRuns.id, f.successor.id));
|
||||
if (fault === "agent") {
|
||||
const [other] = await db.insert(agents).values({ companyId: f.company.id, name: "Other", adapterType: "paperclip_runner" }).returning();
|
||||
|
||||
@@ -757,7 +757,7 @@ export async function enqueueChatRunMilestones(
|
||||
and continuation_wake.run_id = ${heartbeatRuns.id}
|
||||
and continuation_wake.agent_id = ${heartbeatRuns.agentId}
|
||||
and continuation_wake.reason = 'issue_status_changed'
|
||||
and continuation_wake.status in ('claimed', 'completed')
|
||||
and continuation_wake.status in ('queued', 'claimed', 'completed', 'coalesced')
|
||||
and continuation_wake.payload->>'issueId' = ${issueIdFromContext}
|
||||
)
|
||||
)`;
|
||||
|
||||
@@ -4,66 +4,12 @@ import { agents, agentWakeupRequests, caseHandoffs, cases, companies, createDb,
|
||||
import { eq, sql } from "drizzle-orm";
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { getEmbeddedPostgresTestSupport, startEmbeddedPostgresTestDatabase } from "../../__tests__/helpers/embedded-postgres.js";
|
||||
import { createRunDispatch } from "../../modules/run-dispatch/index.js";
|
||||
import type { createWakeQueue } from "../../modules/wake-queue/index.js";
|
||||
import { createPostgresWakeQueueAdapter } from "../../modules/wake-queue/adapters/postgres.js";
|
||||
import { createReleaseIssueExecution } from "../../modules/wake-queue/application/use-cases.js";
|
||||
import { createHeartbeatRunState } from "./run-state.js";
|
||||
import { createHeartbeatRunPreparation } from "./run-preparation.js";
|
||||
import { createHeartbeatQueue, type HeartbeatQueueDependencies } from "./queue.js";
|
||||
|
||||
type Run = typeof heartbeatRuns.$inferSelect;
|
||||
function callbacks(db: Db) {
|
||||
const state = createHeartbeatRunState(db);
|
||||
const preparation = createHeartbeatRunPreparation(db);
|
||||
return {
|
||||
...preparation,
|
||||
...state,
|
||||
getAgent: vi.fn<HeartbeatQueueDependencies["getAgent"]>(async () => { throw new Error("Unexpected agent lookup"); }),
|
||||
options: {},
|
||||
setRunStatus: vi.fn<HeartbeatQueueDependencies["setRunStatus"]>(async (id, status, patch) =>
|
||||
db.update(heartbeatRuns).set({ ...patch, status }).where(eq(heartbeatRuns.id, id)).returning().then(rows => rows[0] ?? null)),
|
||||
setWakeupStatus: vi.fn<HeartbeatQueueDependencies["setWakeupStatus"]>(async () => undefined),
|
||||
appendRunEvent: vi.fn<HeartbeatQueueDependencies["appendRunEvent"]>(async () => undefined),
|
||||
finalizeAgentStatus: vi.fn(async () => undefined),
|
||||
getAgentInvokability: vi.fn<HeartbeatQueueDependencies["getAgentInvokability"]>(async () => ({ invokable: true })),
|
||||
getWorktreeExecutionCutoff: vi.fn(async () => null),
|
||||
applyRunDispatchPostCommitEffects: vi.fn(),
|
||||
issuesSvc: {
|
||||
getDependencyReadiness: vi.fn<HeartbeatQueueDependencies["issuesSvc"]["getDependencyReadiness"]>(),
|
||||
listDependencyReadiness: vi.fn(async () => new Map()),
|
||||
},
|
||||
treeControlSvc: { getActivePauseHoldGate: vi.fn(async () => null) },
|
||||
budgets: { getInvocationBlock: vi.fn(async () => null) },
|
||||
instanceSettings: { getExperimental: vi.fn<HeartbeatQueueDependencies["instanceSettings"]["getExperimental"]>() },
|
||||
runDispatch: createRunDispatch(db),
|
||||
wakeQueue: {
|
||||
createAdmissionTransactionScope: vi.fn<ReturnType<typeof createWakeQueue>["createAdmissionTransactionScope"]>(),
|
||||
admitWakeBehindIssueExecution: vi.fn<ReturnType<typeof createWakeQueue>["admitWakeBehindIssueExecution"]>(),
|
||||
},
|
||||
activeRunExecutions: new Set<string>(),
|
||||
activeRunExecutionPromises: new Set<Promise<void>>(),
|
||||
activeWakeupPromises: new Set<Promise<unknown>>(),
|
||||
liveRunExecutions: { has: vi.fn(() => false) },
|
||||
isHeartbeatRunTerminalStatus: (status: string | null | undefined) => ["succeeded", "failed", "cancelled", "timed_out"].includes(status ?? ""),
|
||||
isSameTaskScope: (left: string | null, right: string | null) => left === right,
|
||||
runTaskKey: (run: Run) => typeof run.contextSnapshot?.issueId === "string" ? run.contextSnapshot.issueId : null,
|
||||
filterZombieCoalesceTarget: <T extends { id: string; status: string }>(run: T | null) => run,
|
||||
getSchedulingSuppression: vi.fn(async () => ({ suppressed: false, reason: null } as Awaited<ReturnType<HeartbeatQueueDependencies["getSchedulingSuppression"]>>)),
|
||||
canStartNewExternalBotWork: vi.fn(async () => true),
|
||||
executeRun: vi.fn(async () => undefined),
|
||||
applyWakeQueuePostCommitEffects: vi.fn(async () => undefined),
|
||||
releaseIssueExecutionAndPromote: vi.fn<HeartbeatQueueDependencies["releaseIssueExecutionAndPromote"]>(async () => undefined),
|
||||
publishRunLifecyclePluginEvent: vi.fn(),
|
||||
cancelRunInternal: vi.fn(async () => undefined),
|
||||
cancelActiveForAgentInternal: vi.fn(async () => undefined),
|
||||
resumeExecutionWaitComments: vi.fn(async () => undefined),
|
||||
resumeQueuedCommentInterrupt: vi.fn(async () => undefined),
|
||||
resumeSavedLegacyComments: vi.fn(async () => undefined),
|
||||
formatIssueIdentifierLink: (_identifier: string | null, fallback: string) => fallback,
|
||||
sweepPendingCleanupLeases: vi.fn<HeartbeatQueueDependencies["sweepPendingCleanupLeases"]>(),
|
||||
} satisfies HeartbeatQueueDependencies;
|
||||
}
|
||||
import { createHeartbeatQueueTestDependencies as callbacks } from "../../__tests__/helpers/heartbeat-queue.js";
|
||||
|
||||
function guardedDatabase() {
|
||||
const access = vi.fn(() => { throw new Error("Unexpected queue database access"); });
|
||||
return { db: new Proxy({}, { get: access }) as Db, access };
|
||||
|
||||
@@ -10,14 +10,27 @@ export async function readNativeContinuationSource(
|
||||
binding: { companyId: string; issueId: string; runId: string },
|
||||
): Promise<string | null> {
|
||||
const source = alias(heartbeatRuns, "continuation_source");
|
||||
const dispatch = alias(agentWakeupRequests, "continuation_dispatch");
|
||||
const sources = await db.select({ runId: source.id }).from(heartbeatRuns)
|
||||
.innerJoin(agentWakeupRequests, and(
|
||||
eq(agentWakeupRequests.companyId, binding.companyId),
|
||||
eq(agentWakeupRequests.runId, heartbeatRuns.id),
|
||||
eq(agentWakeupRequests.agentId, heartbeatRuns.agentId),
|
||||
eq(agentWakeupRequests.reason, "issue_status_changed"),
|
||||
inArray(agentWakeupRequests.status, ["claimed", "completed"]),
|
||||
eq(agentWakeupRequests.status, "coalesced"),
|
||||
eq(agentWakeupRequests.requestedByActorType, "system"),
|
||||
eq(agentWakeupRequests.requestedByActorId, "native-status-committer"),
|
||||
sql`${agentWakeupRequests.payload}->>'issueId' = ${binding.issueId}`,
|
||||
sql`${heartbeatRuns.contextSnapshot}->>'nativeStatusWakeIntentId' = ${agentWakeupRequests.id}::text`,
|
||||
))
|
||||
.innerJoin(dispatch, and(
|
||||
eq(dispatch.companyId, binding.companyId), eq(dispatch.agentId, heartbeatRuns.agentId),
|
||||
eq(dispatch.runId, heartbeatRuns.id), eq(dispatch.reason, "issue_status_changed"),
|
||||
eq(dispatch.requestedByActorType, "system"),
|
||||
sql`${dispatch.requestedByActorId} = 'native-status-wake-dispatch:' || ${agentWakeupRequests.id}::text`,
|
||||
eq(dispatch.idempotencyKey, agentWakeupRequests.idempotencyKey),
|
||||
inArray(dispatch.status, ["queued", "claimed", "completed", "coalesced"]),
|
||||
sql`${dispatch.payload}->>'issueId' = ${binding.issueId}`,
|
||||
))
|
||||
.innerJoin(statusDecisionEffects, and(
|
||||
eq(statusDecisionEffects.companyId, binding.companyId), eq(statusDecisionEffects.issueId, binding.issueId),
|
||||
|
||||
Reference in new issue
Block a user