delqhi commited on
Commit
c7b8a45
·
verified ·
1 Parent(s): 1281848

Enable authenticated Room13 worker proof for sin-github-issues

Browse files
.well-known/oauth-client.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "client_id": "https://delqhi-sin-github-issues.hf.space/.well-known/oauth-client.json",
3
- "client_name": "SIN-GitHub-Issues",
4
  "redirect_uris": ["https://delqhi-sin-github-issues.hf.space/oauth/callback"],
5
  "grant_types": ["authorization_code"],
6
  "response_types": ["code"],
 
1
  {
2
  "client_id": "https://delqhi-sin-github-issues.hf.space/.well-known/oauth-client.json",
3
+ "client_name": "AZA-SIN-Coder-•-GitHub-Issues",
4
  "redirect_uris": ["https://delqhi-sin-github-issues.hf.space/oauth/callback"],
5
  "grant_types": ["authorization_code"],
6
  "response_types": ["code"],
A2A-CARD.md CHANGED
@@ -1,4 +1,4 @@
1
- # A2A-SIN-GitHub-Issues (CEO Elite GitHub Operations)
2
 
3
  **Team:** Coding
4
  **Version:** 2026.03.22
@@ -6,8 +6,8 @@
6
 
7
  ## Identity & Mandate
8
 
9
- > **You are A2A-SIN-GitHub-Issues, a 2026 CEO-Level GitHub Operations Architect.**
10
- > You do NOT just create bug tickets. You orchestrate the **entire repository lifecycle** using the full suite of GitHub's free Enterprise features:
11
  >
12
  > 1. **Projects (V2)**: You autonomously generate Kanban boards, Epics, Sprints, and assign tasks via the GitHub CLI (`gh project create/link/item-add`).
13
  > 2. **Wikis**: You generate, maintain, and sync corporate knowledge base Markdown files to the repo's wiki (`sync-github-wiki.sh`).
@@ -23,14 +23,34 @@
23
  ## RPC Actions
24
 
25
  - `sin.github.health`: GitHub Operations Architect readiness check.
 
 
 
 
 
26
  - `sin.github.project.orchestrate`: Create and manage GitHub Projects V2 boards.
27
  - `sin.github.issue.manage`: Create, update, or close issues (Epics, Sub-tasks).
 
 
 
 
28
  - `sin.github.wiki.sync`: Update the repository Wiki with project documentation.
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  - `sin.github.discussion.start`: Start an architectural debate in Discussions.
30
  - `sin.github.gist.publish`: Upload a large log or code snippet to a Gist.
31
  - `sin.github.security.audit`: Audit security alerts and configure Dependabot.
32
  - `sin.github.pr.review`: Review and approve/merge Pull Requests.
33
 
34
  ## Data & Transport
35
-
36
- JSON-RPC over HTTP. Strict OpenCode execution via `openai/gpt-5.4` utilizing the `hf_pull_script.py` rotator pool.
 
1
+ # AZA-SIN-Coder-•-GitHub-Issues (CEO Elite GitHub Operations)
2
 
3
  **Team:** Coding
4
  **Version:** 2026.03.22
 
6
 
7
  ## Identity & Mandate
8
 
9
+ > **You are AZA-SIN-Coder-•-GitHub-Issues, a 2026 CEO-Level GitHub issue triage and delegation architect.**
10
+ > You do NOT just create bug tickets. You triage new issues, comment on them, route them into queues, and orchestrate the **entire repository lifecycle** using the full suite of GitHub's free Enterprise features:
11
  >
12
  > 1. **Projects (V2)**: You autonomously generate Kanban boards, Epics, Sprints, and assign tasks via the GitHub CLI (`gh project create/link/item-add`).
13
  > 2. **Wikis**: You generate, maintain, and sync corporate knowledge base Markdown files to the repo's wiki (`sync-github-wiki.sh`).
 
23
  ## RPC Actions
24
 
25
  - `sin.github.health`: GitHub Operations Architect readiness check.
26
+ - `sin.github.worker.register`: Register the GitHub-Issues runtime as a Room-13 worker and claim its initial lease.
27
+ - `sin.github.worker.status`: Inspect Room-13 worker registration and claim state.
28
+ - `sin.github.worker.claim_next`: Claim the next dispatchable Room-13 task.
29
+ - `sin.github.worker.checkpoint`: Send checkpoint progress for the current Room-13 task.
30
+ - `sin.github.worker.complete`: Mark the currently claimed Room-13 task as completed.
31
  - `sin.github.project.orchestrate`: Create and manage GitHub Projects V2 boards.
32
  - `sin.github.issue.manage`: Create, update, or close issues (Epics, Sub-tasks).
33
+ - `sin.github.issue.ensure`: Create or update an issue by exact-title match.
34
+ - `sin.github.issue.comment`: Add a GitHub issue comment.
35
+ - `sin.github.issue.close`: Close a GitHub issue with optional comment.
36
+ - `sin.github.issue.triage.enqueue`: Durably enqueue a GitHub issue triage event into the coder dispatch pool.
37
  - `sin.github.wiki.sync`: Update the repository Wiki with project documentation.
38
+
39
+ ## Ingress Contract
40
+
41
+ - Canonical enqueue payload example: `Docs/operations/phase22-github-issue-triage-payload.example.json`
42
+ - Replay-safe fixture examples:
43
+ - `Docs/operations/phase22-github-issue-opened.fixture.json`
44
+ - `Docs/operations/phase22-github-issue-opened.replay.fixture.json`
45
+ - Primary transport for instant triage: GitHub webhook -> n8n -> `sin.github.issue.triage.enqueue`
46
+ - Idempotency key policy: `delivery_id` first, then fallback `repo#issue_number:event_action`
47
+ - Queue state progression: `received -> queued -> claimed -> dispatched -> accepted -> completed|failed|dead_letter`
48
+ - Runtime queue constants live in `src/queue-state.ts` and are shared between ingress and Hermes dispatch logic.
49
+ - Route contract: ingress computes `assignedTeam`, `assignedAgentHint`, and `capabilityHint` from labels/title/body before Hermes dispatch.
50
+ - Local proof command: `npm run smoke:triage-fixtures`
51
  - `sin.github.discussion.start`: Start an architectural debate in Discussions.
52
  - `sin.github.gist.publish`: Upload a large log or code snippet to a Gist.
53
  - `sin.github.security.audit`: Audit security alerts and configure Dependabot.
54
  - `sin.github.pr.review`: Review and approve/merge Pull Requests.
55
 
56
  ## Data & Transport
 
 
AGENTS.md CHANGED
@@ -1,8 +1,10 @@
1
- # SIN-GitHub-Issues
2
 
3
  - Team: Team - Coding
4
  - Team Manager: SIN-Coding-CEO
5
  - Slug: sin-github-issues
 
 
6
  - Repo: https://github.com/Delqhi/sin-github-issues
7
  - Docs Tab: pending dedicated child-tab
8
 
 
1
+ # AZA-SIN-Coder-•-GitHub-Issues
2
 
3
  - Team: Team - Coding
4
  - Team Manager: SIN-Coding-CEO
5
  - Slug: sin-github-issues
6
+ - Canonical display name: AZA-SIN-Coder-•-GitHub-Issues
7
+ - Machine identity policy: keep slug/package/bin/public route as `sin-github-issues` until an explicit compatibility migration says otherwise
8
  - Repo: https://github.com/Delqhi/sin-github-issues
9
  - Docs Tab: pending dedicated child-tab
10
 
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: SIN-GitHub-Issues
3
  emoji: "🤖"
4
  colorFrom: blue
5
  colorTo: indigo
@@ -8,22 +8,23 @@ app_port: 7860
8
  pinned: false
9
  ---
10
 
11
- # SIN-GitHub-Issues
12
 
13
- `SIN-GitHub-Issues` is a SIN A2A agent package for the Silicon Workforce.
14
 
15
  ## Identity
16
 
17
- - Slug: `sin-github-issues`
18
  - Team: `Team - Coding`
19
  - Team Manager: `SIN-Coding-CEO`
20
- - Purpose: GitHub issue execution agent for confirmed bugs, repo issue lifecycle, branch-based fixes, and verification handoff. Extended with enterprise profile management capabilities.
21
- - Usage: Use after enterprise-deep-debug confirms a bug to search/create/update GitHub issues, open a repo branch, execute the fix workflow, commit, push, and report verification status back to the orchestrating CLI agent. For profile and achievement operations use the new profile/achievement actions.
 
22
  - Primary Model: `opencode/nemotron-3-super-free`
23
 
24
  ## Deployment
25
 
26
- - Local path: `/Users/jeremy/dev/SIN-Solver/a2a/team-coding/A2A-SIN-GitHub-Issues`
27
  - GitHub repo: `https://github.com/Delqhi/sin-github-issues`
28
  - Workforce index: `https://a2a.delqhi.com`
29
  - Landing page: `https://delqhi-sin-github-issues.hf.space`
@@ -76,6 +77,10 @@ sin-github-issues run-action '{"action":"sin.github.issues.issue.evidence.policy
76
  sin-github-issues run-action '{"action":"sin.github.issues.repo.branch.start","repoPath":"/abs/repo","branchName":"fix/example"}'
77
  sin-github-issues run-action '{"action":"sin.github.issues.runners.list","repo":"Delqhi/SIN-Solver"}'
78
  sin-github-issues run-action '{"action":"sin.github.issues.workflow.runs.list","repo":"Delqhi/SIN-Solver","branch":"sin-github-issues-bootstrap"}'
 
 
 
 
79
  sin-github-issues run-action '{"action":"sin.github.issues.workflow.local_suite.run","repoPath":"/abs/repo","suite":"docs-and-architecture","confirm":true}'
80
  ```
81
 
 
1
  ---
2
+ title: AZA-SIN-Coder-•-GitHub-Issues
3
  emoji: "🤖"
4
  colorFrom: blue
5
  colorTo: indigo
 
8
  pinned: false
9
  ---
10
 
11
+ # AZA-SIN-Coder-•-GitHub-Issues
12
 
13
+ `AZA-SIN-Coder-•-GitHub-Issues` is the GitHub issue triage and delegation agent package for the AZA coding workforce.
14
 
15
  ## Identity
16
 
17
+ - Slug: `sin-github-issues` (canonical AZA display name: `AZA-SIN-Coder-•-GitHub-Issues`)
18
  - Team: `Team - Coding`
19
  - Team Manager: `SIN-Coding-CEO`
20
+ - Purpose: GitHub issue triage, comment, queue, and execution delegation agent for confirmed bugs, repo issue lifecycle, branch-based fixes, and verification handoff. Extended with enterprise profile management capabilities.
21
+ - Usage: Use for instant issue triage and coder delegation as well as confirmed bug workflows to search/create/update GitHub issues, open a repo branch, execute the fix workflow, commit, push, and report verification status back to the orchestrating CLI agent. For profile and achievement operations use the new profile/achievement actions.
22
+ - Durable ingress payload example: `Docs/operations/phase22-github-issue-triage-payload.example.json`
23
  - Primary Model: `opencode/nemotron-3-super-free`
24
 
25
  ## Deployment
26
 
27
+ - Local path: `/Users/jeremy/dev/SIN-Solver/a2a/team-coding/AZA-SIN-Coder-•-GitHub-Issues`
28
  - GitHub repo: `https://github.com/Delqhi/sin-github-issues`
29
  - Workforce index: `https://a2a.delqhi.com`
30
  - Landing page: `https://delqhi-sin-github-issues.hf.space`
 
77
  sin-github-issues run-action '{"action":"sin.github.issues.repo.branch.start","repoPath":"/abs/repo","branchName":"fix/example"}'
78
  sin-github-issues run-action '{"action":"sin.github.issues.runners.list","repo":"Delqhi/SIN-Solver"}'
79
  sin-github-issues run-action '{"action":"sin.github.issues.workflow.runs.list","repo":"Delqhi/SIN-Solver","branch":"sin-github-issues-bootstrap"}'
80
+ sin-github-issues run-action '{"action":"sin.github.worker.register"}'
81
+ sin-github-issues run-action '{"action":"sin.github.worker.status"}'
82
+ sin-github-issues run-action '{"action":"sin.github.worker.claim_next"}'
83
+ cd /Users/jeremy/dev/SIN-Solver/a2a/team-coding/A2A-SIN-GitHub-Issues && npm run smoke:triage-fixtures
84
  sin-github-issues run-action '{"action":"sin.github.issues.workflow.local_suite.run","repoPath":"/abs/repo","suite":"docs-and-architecture","confirm":true}'
85
  ```
86
 
agent.json CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "id": "sin-github-issues",
3
- "displayName": "A2A-SIN-GitHub-Issues (CEO Elite GitHub Operations)",
4
  "team": "team-coding",
5
- "description": "Elite 2026 GitHub Operations Architect. Manages the entire project lifecycle via GitHub Projects, Issues, Wikis, Discussions, Security Alerts (Dependabot/CodeQL), PR Reviews, and Gists. Fully integrated with openai/gpt-5.4 and the A2A Token Pool.",
6
  "version": "2026.03.22",
7
  "deployment": {
8
  "workforceIndex": "https://a2a.delqhi.com",
 
1
  {
2
  "id": "sin-github-issues",
3
+ "displayName": "AZA-SIN-Coder-•-GitHub-Issues",
4
  "team": "team-coding",
5
+ "description": "Elite 2026 GitHub issue triage and delegation architect. Manages the entire project lifecycle via GitHub Projects, Issues, comments, queueing, Discussions, Security Alerts (Dependabot/CodeQL), PR Reviews, and Gists. Fully integrated with openai/gpt-5.4 and the A2A Token Pool.",
6
  "version": "2026.03.22",
7
  "deployment": {
8
  "workforceIndex": "https://a2a.delqhi.com",
package-lock.json CHANGED
@@ -96,9 +96,9 @@
96
  }
97
  },
98
  "node_modules/@supabase/auth-js": {
99
- "version": "2.99.2",
100
- "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.99.2.tgz",
101
- "integrity": "sha512-uRGNXMKEw4VhwouNW7N0XDAGqJP9redHNDmWi17dTrcO1lvFfyRiXsqqfgnVC8aqtRn8kLkLPEzHjiRWsni+oQ==",
102
  "license": "MIT",
103
  "dependencies": {
104
  "tslib": "2.8.1"
@@ -108,9 +108,9 @@
108
  }
109
  },
110
  "node_modules/@supabase/functions-js": {
111
- "version": "2.99.2",
112
- "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.99.2.tgz",
113
- "integrity": "sha512-xuXQARvjdfB1UPK1yUceZ5EGjOLkVz4rBAaloS9foXiAuseWEdgWBCxkIAFRxGBLGX8Uzo8kseq90jhPb+07Vg==",
114
  "license": "MIT",
115
  "dependencies": {
116
  "tslib": "2.8.1"
@@ -119,10 +119,16 @@
119
  "node": ">=20.0.0"
120
  }
121
  },
 
 
 
 
 
 
122
  "node_modules/@supabase/postgrest-js": {
123
- "version": "2.99.2",
124
- "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.99.2.tgz",
125
- "integrity": "sha512-ueiOVkbkTQ7RskwVmjR8zxWYw3VKOMxo1+qep+Dx/SgApqyhWBGd92waQb45tbLc7ydB5x8El8utXOLQTuTojQ==",
126
  "license": "MIT",
127
  "dependencies": {
128
  "tslib": "2.8.1"
@@ -132,12 +138,12 @@
132
  }
133
  },
134
  "node_modules/@supabase/realtime-js": {
135
- "version": "2.99.2",
136
- "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.99.2.tgz",
137
- "integrity": "sha512-J6Jm9601dkpZf3+EJ48ki2pM4sFtCNm/BI0l8iEnrczgg+JSEQkMoOW5VSpM54t0pNs69bsz5PTmYJahDZKiIQ==",
138
  "license": "MIT",
139
  "dependencies": {
140
- "@types/phoenix": "^1.6.6",
141
  "@types/ws": "^8.18.1",
142
  "tslib": "2.8.1",
143
  "ws": "^8.18.2"
@@ -147,9 +153,9 @@
147
  }
148
  },
149
  "node_modules/@supabase/storage-js": {
150
- "version": "2.99.2",
151
- "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.99.2.tgz",
152
- "integrity": "sha512-V/FF8kX8JGSefsVCG1spCLSrHdNR/JFeUMn1jS9KG/Eizjx+evtdKQKLJXFgIylY/bKTXKhc2SYDPIGrIhzsug==",
153
  "license": "MIT",
154
  "dependencies": {
155
  "iceberg-js": "^0.8.1",
@@ -160,16 +166,16 @@
160
  }
161
  },
162
  "node_modules/@supabase/supabase-js": {
163
- "version": "2.99.2",
164
- "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.99.2.tgz",
165
- "integrity": "sha512-179rn5wq0wBAqqGwAwR7TUGg2NOaP+fkd5FCVbYJXby85fsRNPFoNJN8YRBepqX2tN7JJcnTjqaAMXuNjiyisA==",
166
  "license": "MIT",
167
  "dependencies": {
168
- "@supabase/auth-js": "2.99.2",
169
- "@supabase/functions-js": "2.99.2",
170
- "@supabase/postgrest-js": "2.99.2",
171
- "@supabase/realtime-js": "2.99.2",
172
- "@supabase/storage-js": "2.99.2"
173
  },
174
  "engines": {
175
  "node": ">=20.0.0"
@@ -191,12 +197,6 @@
191
  "dev": true,
192
  "license": "MIT"
193
  },
194
- "node_modules/@types/phoenix": {
195
- "version": "1.6.7",
196
- "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz",
197
- "integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==",
198
- "license": "MIT"
199
- },
200
  "node_modules/@types/tar": {
201
  "version": "6.1.13",
202
  "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.13.tgz",
@@ -755,9 +755,9 @@
755
  }
756
  },
757
  "node_modules/hono": {
758
- "version": "4.12.8",
759
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.8.tgz",
760
- "integrity": "sha512-VJCEvtrezO1IAR+kqEYnxUOoStaQPGrCmX3j4wDTNOcD1uRPFpGlwQUIW8niPuvHXaTUxeOUl5MMDGrl+tmO9A==",
761
  "license": "MIT",
762
  "engines": {
763
  "node": ">=16.9.0"
@@ -1434,9 +1434,9 @@
1434
  "license": "ISC"
1435
  },
1436
  "node_modules/ws": {
1437
- "version": "8.19.0",
1438
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
1439
- "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
1440
  "license": "MIT",
1441
  "engines": {
1442
  "node": ">=10.0.0"
 
96
  }
97
  },
98
  "node_modules/@supabase/auth-js": {
99
+ "version": "2.100.0",
100
+ "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.100.0.tgz",
101
+ "integrity": "sha512-pdT3ye3UVRN1Cg0wom6BmyY+XTtp5DiJaYnPi6j8ht5i8Lq8kfqxJMJz9GI9YDKk3w1nhGOPnh6Qz5qpyYm+1w==",
102
  "license": "MIT",
103
  "dependencies": {
104
  "tslib": "2.8.1"
 
108
  }
109
  },
110
  "node_modules/@supabase/functions-js": {
111
+ "version": "2.100.0",
112
+ "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.100.0.tgz",
113
+ "integrity": "sha512-keLg79RPwP+uiwHuxFPTFgDRxPV46LM4j/swjyR2GKJgWniTVSsgiBHfbIBDcrQwehLepy09b/9QSHUywtKRWQ==",
114
  "license": "MIT",
115
  "dependencies": {
116
  "tslib": "2.8.1"
 
119
  "node": ">=20.0.0"
120
  }
121
  },
122
+ "node_modules/@supabase/phoenix": {
123
+ "version": "0.4.0",
124
+ "resolved": "https://registry.npmjs.org/@supabase/phoenix/-/phoenix-0.4.0.tgz",
125
+ "integrity": "sha512-RHSx8bHS02xwfHdAbX5Lpbo6PXbgyf7lTaXTlwtFDPwOIw64NnVRwFAXGojHhjtVYI+PEPNSWwkL90f4agN3bw==",
126
+ "license": "MIT"
127
+ },
128
  "node_modules/@supabase/postgrest-js": {
129
+ "version": "2.100.0",
130
+ "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.100.0.tgz",
131
+ "integrity": "sha512-xYNvNbBJaXOGcrZ44wxwp5830uo1okMHGS8h8dm3u4f0xcZ39yzbryUsubTJW41MG2gbL/6U57cA4Pi6YMZ9pA==",
132
  "license": "MIT",
133
  "dependencies": {
134
  "tslib": "2.8.1"
 
138
  }
139
  },
140
  "node_modules/@supabase/realtime-js": {
141
+ "version": "2.100.0",
142
+ "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.100.0.tgz",
143
+ "integrity": "sha512-2AZs00zzEF0HuCKY8grz5eCYlwEfVi5HONLZFoNR6aDfxQivl8zdQYNjyFoqN2MZiVhQHD7u6XV/xHwM8mCEHw==",
144
  "license": "MIT",
145
  "dependencies": {
146
+ "@supabase/phoenix": "^0.4.0",
147
  "@types/ws": "^8.18.1",
148
  "tslib": "2.8.1",
149
  "ws": "^8.18.2"
 
153
  }
154
  },
155
  "node_modules/@supabase/storage-js": {
156
+ "version": "2.100.0",
157
+ "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.100.0.tgz",
158
+ "integrity": "sha512-d4EeuK6RNIgYNA2MU9kj8lQrLm5AzZ+WwpWjGkii6SADQNIGTC/uiaTRu02XJ5AmFALQfo8fLl9xuCkO6Xw+iQ==",
159
  "license": "MIT",
160
  "dependencies": {
161
  "iceberg-js": "^0.8.1",
 
166
  }
167
  },
168
  "node_modules/@supabase/supabase-js": {
169
+ "version": "2.100.0",
170
+ "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.100.0.tgz",
171
+ "integrity": "sha512-r0tlcukejJXJ1m/2eG/Ya5eYs4W8AC7oZfShpG3+SIo/eIU9uIt76ZeYI1SoUwUmcmzlAbgch+HDZDR/toVQPQ==",
172
  "license": "MIT",
173
  "dependencies": {
174
+ "@supabase/auth-js": "2.100.0",
175
+ "@supabase/functions-js": "2.100.0",
176
+ "@supabase/postgrest-js": "2.100.0",
177
+ "@supabase/realtime-js": "2.100.0",
178
+ "@supabase/storage-js": "2.100.0"
179
  },
180
  "engines": {
181
  "node": ">=20.0.0"
 
197
  "dev": true,
198
  "license": "MIT"
199
  },
 
 
 
 
 
 
200
  "node_modules/@types/tar": {
201
  "version": "6.1.13",
202
  "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.13.tgz",
 
755
  }
756
  },
757
  "node_modules/hono": {
758
+ "version": "4.12.9",
759
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.9.tgz",
760
+ "integrity": "sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA==",
761
  "license": "MIT",
762
  "engines": {
763
  "node": ">=16.9.0"
 
1434
  "license": "ISC"
1435
  },
1436
  "node_modules/ws": {
1437
+ "version": "8.20.0",
1438
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
1439
+ "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
1440
  "license": "MIT",
1441
  "engines": {
1442
  "node": ">=10.0.0"
package.json CHANGED
@@ -10,6 +10,8 @@
10
  },
11
  "scripts": {
12
  "build": "rm -rf dist && tsc -p tsconfig.json && node scripts/postbuild.mjs",
 
 
13
  "typecheck": "tsc --noEmit -p tsconfig.json",
14
  "start:a2a": "node dist/src/cli.js serve-a2a",
15
  "start:mcp": "node dist/src/cli.js serve-mcp"
 
10
  },
11
  "scripts": {
12
  "build": "rm -rf dist && tsc -p tsconfig.json && node scripts/postbuild.mjs",
13
+ "smoke:triage-fixtures": "npm run build && node scripts/smoke-triage-fixtures.mjs",
14
+ "smoke:room13-worker": "npm run build && node scripts/smoke-room13-worker.mjs",
15
  "typecheck": "tsc --noEmit -p tsconfig.json",
16
  "start:a2a": "node dist/src/cli.js serve-a2a",
17
  "start:mcp": "node dist/src/cli.js serve-mcp"
scripts/hf_pull_script.py CHANGED
@@ -1,6 +1,5 @@
1
  #!/usr/bin/env python3
2
  """
3
- A2A Consumer Rotator (HF VM Pull Script)
4
  Pulls a fresh OpenAI token from SIN-Supabase when a rate-limit is hit.
5
  Infinite Scaling Architecture.
6
  """
 
1
  #!/usr/bin/env python3
2
  """
 
3
  Pulls a fresh OpenAI token from SIN-Supabase when a rate-limit is hit.
4
  Infinite Scaling Architecture.
5
  """
scripts/smoke-room13-worker.mjs ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env node
2
+
3
+ import { GitHubIssuesRoom13WorkerRuntime, installGitHubIssuesWorkerRuntime } from '../dist/src/room13-worker.js';
4
+
5
+ class FakeWorkerRuntime extends GitHubIssuesRoom13WorkerRuntime {
6
+ constructor() {
7
+ super('sin-github-issues', 'http://room13.test');
8
+ }
9
+
10
+ async start() {
11
+ this.workerId = 'worker-gh';
12
+ this.leaseEpoch = 1;
13
+ this.claimedTaskId = '';
14
+ this.leaseExpiresAt = '2026-03-23T22:30:00Z';
15
+ return this.snapshot();
16
+ }
17
+
18
+ async claimNextTask() {
19
+ this.claimedTaskId = 'task-gh-1';
20
+ return { id: 'task-gh-1', status: 'running' };
21
+ }
22
+
23
+ async checkpoint(step, checkpoint = {}) {
24
+ return { ok: true, step, checkpoint };
25
+ }
26
+
27
+ async completeTask(result = {}) {
28
+ this.claimedTaskId = '';
29
+ return { ok: true, result };
30
+ }
31
+ }
32
+
33
+ const runtime = new FakeWorkerRuntime();
34
+ installGitHubIssuesWorkerRuntime(runtime);
35
+ const registered = await runtime.start();
36
+ const claimed = await runtime.claimNextTask();
37
+ const checkpoint = await runtime.checkpoint('github.issue.sync', { attempt: 1 });
38
+ const completed = await runtime.completeTask({ success: true });
39
+
40
+ if (registered.workerId !== 'worker-gh') throw new Error('worker register smoke failed');
41
+ if (claimed.id !== 'task-gh-1') throw new Error('task claim smoke failed');
42
+ if (checkpoint.step !== 'github.issue.sync') throw new Error('checkpoint smoke failed');
43
+ if (!completed.ok) throw new Error('complete smoke failed');
44
+
45
+ process.stdout.write(JSON.stringify({ ok: true, registered, claimed, checkpoint, completed }, null, 2) + '\n');
scripts/smoke-triage-fixtures.mjs ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env node
2
+
3
+ import { readFile } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import process from 'node:process';
6
+
7
+ const packageRoot = path.resolve(process.cwd());
8
+ const repoRoot = path.resolve(packageRoot, '..', '..', '..');
9
+
10
+ const fixtureOnePath = path.join(repoRoot, 'Docs', 'operations', 'phase22-github-issue-opened.fixture.json');
11
+ const fixtureTwoPath = path.join(repoRoot, 'Docs', 'operations', 'phase22-github-issue-opened.replay.fixture.json');
12
+
13
+ const triageModule = await import(path.join(packageRoot, 'dist', 'src', 'triage.js'));
14
+ const queueModule = await import(path.join(packageRoot, 'dist', 'src', 'queue-state.js'));
15
+
16
+ const {
17
+ TriageEnqueueSchema,
18
+ buildDeliveryKey,
19
+ buildIssueKey,
20
+ routeIssueTriage,
21
+ } = triageModule;
22
+
23
+ const { ISSUE_QUEUE_STATE } = queueModule;
24
+
25
+ const rowByDelivery = new Map();
26
+ const rowByIssueKey = new Map();
27
+
28
+ function enqueue(payload) {
29
+ const input = TriageEnqueueSchema.parse(payload);
30
+ const deliveryId = buildDeliveryKey(input);
31
+ const issueKey = buildIssueKey(input.repo, input.issueNumber);
32
+ const route = routeIssueTriage(input.labels || [], input.title, input.body || '');
33
+
34
+ if (rowByDelivery.has(deliveryId)) {
35
+ return {
36
+ created: false,
37
+ deduplicatedBy: 'delivery_id',
38
+ queueState: rowByDelivery.get(deliveryId).queueState,
39
+ deliveryId,
40
+ issueKey,
41
+ route,
42
+ };
43
+ }
44
+
45
+ if (rowByIssueKey.has(issueKey)) {
46
+ const existing = rowByIssueKey.get(issueKey);
47
+ existing.deliveryIds.push(deliveryId);
48
+ rowByDelivery.set(deliveryId, existing);
49
+ return {
50
+ created: false,
51
+ deduplicatedBy: 'issue_key',
52
+ queueState: existing.queueState,
53
+ deliveryId,
54
+ issueKey,
55
+ route,
56
+ };
57
+ }
58
+
59
+ const row = {
60
+ issueKey,
61
+ deliveryIds: [deliveryId],
62
+ queueState: ISSUE_QUEUE_STATE.queued,
63
+ assignedTeam: input.assignedTeam || route.assignedTeam,
64
+ route,
65
+ };
66
+ rowByDelivery.set(deliveryId, row);
67
+ rowByIssueKey.set(issueKey, row);
68
+ return {
69
+ created: true,
70
+ deduplicatedBy: null,
71
+ queueState: row.queueState,
72
+ deliveryId,
73
+ issueKey,
74
+ route,
75
+ };
76
+ }
77
+
78
+ const first = enqueue(JSON.parse(await readFile(fixtureOnePath, 'utf8')));
79
+ const replay = enqueue(JSON.parse(await readFile(fixtureTwoPath, 'utf8')));
80
+
81
+ if (!first.created) throw new Error('expected first fixture to create queue row');
82
+ if (replay.created || replay.deduplicatedBy !== 'delivery_id') throw new Error('expected replay fixture to deduplicate by delivery_id');
83
+ if (rowByIssueKey.size !== 1) throw new Error(`expected exactly one queue row, got ${rowByIssueKey.size}`);
84
+
85
+ process.stdout.write(JSON.stringify({ ok: true, createdRows: rowByIssueKey.size, first, replay, finalRow: [...rowByIssueKey.values()][0] }, null, 2) + '\n');
src/a2a-http.ts CHANGED
@@ -31,6 +31,11 @@ async function handleRequest(request: IncomingMessage, response: ServerResponse,
31
  }
32
  if (request.method === 'POST' && request.url === '/a2a/v1') {
33
  const rpc = ((await readJson(request)) || {}) as RpcRequest;
 
 
 
 
 
34
  if (rpc.method === 'agent/getCard') return sendJson(response, 200, { jsonrpc: '2.0', id: rpc.id ?? null, result: buildAgentCard(baseUrl) });
35
  if (rpc.method === 'message/send') {
36
  const action = parseAction((rpc.params?.message as { parts?: Array<{ text?: string }> } | undefined)?.parts?.map((part) => part.text || '').join(' ').trim() || '');
 
31
  }
32
  if (request.method === 'POST' && request.url === '/a2a/v1') {
33
  const rpc = ((await readJson(request)) || {}) as RpcRequest;
34
+ if (rpc && typeof rpc === 'object' && 'action' in rpc && typeof (rpc as { action?: unknown }).action === 'string') {
35
+ const action = rpc as unknown as GitHubAgentAction;
36
+ const result = await executeGitHubAgentAction(action);
37
+ return sendJson(response, 200, { ok: true, agent: TEMPLATE_AGENT_ID, action: action.action, result });
38
+ }
39
  if (rpc.method === 'agent/getCard') return sendJson(response, 200, { jsonrpc: '2.0', id: rpc.id ?? null, result: buildAgentCard(baseUrl) });
40
  if (rpc.method === 'message/send') {
41
  const action = parseAction((rpc.params?.message as { parts?: Array<{ text?: string }> } | undefined)?.parts?.map((part) => part.text || '').join(' ').trim() || '');
src/cli.ts CHANGED
@@ -5,11 +5,22 @@ import { resolve } from 'node:path';
5
  import { createTemplateAgentHttpServer } from './a2a-http.js';
6
  import { runMcpServer } from './mcp-server.js';
7
  import { executeGitHubAgentAction } from './runtime.js';
 
8
 
9
  const cmd = process.argv[2];
10
 
11
  if (cmd === 'serve-a2a') {
12
- createTemplateAgentHttpServer().start().catch(err => {
 
 
 
 
 
 
 
 
 
 
13
  console.error(err);
14
  process.exit(1);
15
  });
 
5
  import { createTemplateAgentHttpServer } from './a2a-http.js';
6
  import { runMcpServer } from './mcp-server.js';
7
  import { executeGitHubAgentAction } from './runtime.js';
8
+ import { GitHubIssuesRoom13WorkerRuntime, installGitHubIssuesWorkerRuntime } from './room13-worker.js';
9
 
10
  const cmd = process.argv[2];
11
 
12
  if (cmd === 'serve-a2a') {
13
+ createTemplateAgentHttpServer().start().then(async () => {
14
+ const room13Worker = new GitHubIssuesRoom13WorkerRuntime('sin-github-issues');
15
+ installGitHubIssuesWorkerRuntime(room13Worker);
16
+ await room13Worker.start().catch(() => undefined);
17
+ const stop = async () => {
18
+ await room13Worker.stop().catch(() => undefined);
19
+ process.exit(0);
20
+ };
21
+ process.once('SIGINT', () => void stop());
22
+ process.once('SIGTERM', () => void stop());
23
+ }).catch(err => {
24
  console.error(err);
25
  process.exit(1);
26
  });
src/idle-monetization.ts CHANGED
@@ -6,11 +6,12 @@
6
 
7
  export function startAutonomousIdleLoop() {
8
  console.log('💸 Autonomous Monetization & Hacking loop enabled (Mega Krass Mode).');
 
9
 
10
  // The loop checks every 5 minutes if the agent is idle.
11
  setInterval(async () => {
12
  // Skip if currently busy with a user or fleet task
13
- if ((globalThis as any).isAgentBusy) {
14
  return;
15
  }
16
 
 
6
 
7
  export function startAutonomousIdleLoop() {
8
  console.log('💸 Autonomous Monetization & Hacking loop enabled (Mega Krass Mode).');
9
+ const runtimeState = globalThis as typeof globalThis & { isAgentBusy?: boolean };
10
 
11
  // The loop checks every 5 minutes if the agent is idle.
12
  setInterval(async () => {
13
  // Skip if currently busy with a user or fleet task
14
+ if (runtimeState.isAgentBusy) {
15
  return;
16
  }
17
 
src/mcp-server.ts CHANGED
@@ -16,6 +16,43 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
16
  description: 'Check 2026 Elite GitHub Operations Architect readiness.',
17
  inputSchema: { type: 'object', properties: {} },
18
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  {
20
  name: 'sin_github_project_orchestrate',
21
  description: 'Create and manage GitHub Projects V2 boards.',
@@ -40,6 +77,64 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
40
  required: ['prompt'],
41
  },
42
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  {
44
  name: 'sin_github_wiki_sync',
45
  description: 'Update the repository Wiki with project documentation.',
@@ -122,16 +217,53 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
122
  let action: GitHubAgentAction;
123
  const args = request.params.arguments as any;
124
 
125
- switch (request.params.name) {
126
- case 'sin_github_health':
127
- action = { action: 'sin.github.health' };
128
- break;
129
- case 'sin_github_project_orchestrate':
130
- action = { action: 'sin.github.project.orchestrate', prompt: args.prompt, contextDir: args.contextDir };
131
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  case 'sin_github_issue_manage':
133
  action = { action: 'sin.github.issue.manage', prompt: args.prompt, issueNumber: args.issueNumber };
134
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  case 'sin_github_wiki_sync':
136
  action = { action: 'sin.github.wiki.sync', prompt: args.prompt, contextDir: args.contextDir };
137
  break;
@@ -169,5 +301,5 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
169
  export async function runMcpServer() {
170
  const transport = new StdioServerTransport();
171
  await server.connect(transport);
172
- console.error('A2A-SIN-GitHub-Issues MCP Server running on stdio');
173
  }
 
16
  description: 'Check 2026 Elite GitHub Operations Architect readiness.',
17
  inputSchema: { type: 'object', properties: {} },
18
  },
19
+ {
20
+ name: 'sin_github_worker_register',
21
+ description: 'Register the GitHub-Issues runtime as a Room-13 worker and claim its initial lease.',
22
+ inputSchema: { type: 'object', properties: {} },
23
+ },
24
+ {
25
+ name: 'sin_github_worker_status',
26
+ description: 'Inspect Room-13 worker registration and claim state for GitHub-Issues.',
27
+ inputSchema: { type: 'object', properties: {} },
28
+ },
29
+ {
30
+ name: 'sin_github_worker_claim_next',
31
+ description: 'Claim the next Room-13 task for GitHub-Issues.',
32
+ inputSchema: { type: 'object', properties: {} },
33
+ },
34
+ {
35
+ name: 'sin_github_worker_checkpoint',
36
+ description: 'Send a checkpoint to Room-13 for GitHub-Issues.',
37
+ inputSchema: {
38
+ type: 'object',
39
+ properties: {
40
+ step: { type: 'string' },
41
+ checkpoint: { type: 'object' }
42
+ },
43
+ required: ['step']
44
+ }
45
+ },
46
+ {
47
+ name: 'sin_github_worker_complete',
48
+ description: 'Complete the currently claimed Room-13 task for GitHub-Issues.',
49
+ inputSchema: {
50
+ type: 'object',
51
+ properties: {
52
+ result: { type: 'object' }
53
+ }
54
+ }
55
+ },
56
  {
57
  name: 'sin_github_project_orchestrate',
58
  description: 'Create and manage GitHub Projects V2 boards.',
 
77
  required: ['prompt'],
78
  },
79
  },
80
+ {
81
+ name: 'sin_github_issue_ensure',
82
+ description: 'Create or update an issue by exact title match.',
83
+ inputSchema: {
84
+ type: 'object',
85
+ properties: {
86
+ repo: { type: 'string' },
87
+ title: { type: 'string' },
88
+ body: { type: 'string' },
89
+ labels: { type: 'array', items: { type: 'string' } }
90
+ },
91
+ required: ['repo', 'title', 'body']
92
+ }
93
+ },
94
+ {
95
+ name: 'sin_github_issue_comment',
96
+ description: 'Comment on a GitHub issue.',
97
+ inputSchema: {
98
+ type: 'object',
99
+ properties: {
100
+ repo: { type: 'string' },
101
+ issueNumber: { type: 'number' },
102
+ body: { type: 'string' }
103
+ },
104
+ required: ['repo', 'issueNumber', 'body']
105
+ }
106
+ },
107
+ {
108
+ name: 'sin_github_issue_close',
109
+ description: 'Close a GitHub issue with optional comment.',
110
+ inputSchema: {
111
+ type: 'object',
112
+ properties: {
113
+ repo: { type: 'string' },
114
+ issueNumber: { type: 'number' },
115
+ comment: { type: 'string' }
116
+ },
117
+ required: ['repo', 'issueNumber']
118
+ }
119
+ },
120
+ {
121
+ name: 'sin_github_issue_triage_enqueue',
122
+ description: 'Durably enqueue a GitHub issue triage event into the coder dispatch pool.',
123
+ inputSchema: {
124
+ type: 'object',
125
+ properties: {
126
+ repo: { type: 'string' },
127
+ issueNumber: { type: 'number' },
128
+ title: { type: 'string' },
129
+ body: { type: 'string' },
130
+ labels: { type: 'array', items: { type: 'string' } },
131
+ assignedTeam: { type: 'string' },
132
+ deliveryId: { type: 'string' },
133
+ eventAction: { type: 'string' }
134
+ },
135
+ required: ['repo', 'issueNumber', 'title']
136
+ }
137
+ },
138
  {
139
  name: 'sin_github_wiki_sync',
140
  description: 'Update the repository Wiki with project documentation.',
 
217
  let action: GitHubAgentAction;
218
  const args = request.params.arguments as any;
219
 
220
+ switch (request.params.name) {
221
+ case 'sin_github_health':
222
+ action = { action: 'sin.github.health' };
223
+ break;
224
+ case 'sin_github_worker_register':
225
+ action = { action: 'sin.github.worker.register' };
226
+ break;
227
+ case 'sin_github_worker_status':
228
+ action = { action: 'sin.github.worker.status' };
229
+ break;
230
+ case 'sin_github_worker_claim_next':
231
+ action = { action: 'sin.github.worker.claim_next' };
232
+ break;
233
+ case 'sin_github_worker_checkpoint':
234
+ action = { action: 'sin.github.worker.checkpoint', step: args.step, checkpoint: args.checkpoint };
235
+ break;
236
+ case 'sin_github_worker_complete':
237
+ action = { action: 'sin.github.worker.complete', result: args.result };
238
+ break;
239
+ case 'sin_github_project_orchestrate':
240
+ action = { action: 'sin.github.project.orchestrate', prompt: args.prompt, contextDir: args.contextDir };
241
+ break;
242
  case 'sin_github_issue_manage':
243
  action = { action: 'sin.github.issue.manage', prompt: args.prompt, issueNumber: args.issueNumber };
244
  break;
245
+ case 'sin_github_issue_ensure':
246
+ action = { action: 'sin.github.issue.ensure', repo: args.repo, title: args.title, body: args.body, labels: args.labels };
247
+ break;
248
+ case 'sin_github_issue_comment':
249
+ action = { action: 'sin.github.issue.comment', repo: args.repo, issueNumber: args.issueNumber, body: args.body };
250
+ break;
251
+ case 'sin_github_issue_close':
252
+ action = { action: 'sin.github.issue.close', repo: args.repo, issueNumber: args.issueNumber, comment: args.comment };
253
+ break;
254
+ case 'sin_github_issue_triage_enqueue':
255
+ action = {
256
+ action: 'sin.github.issue.triage.enqueue',
257
+ repo: args.repo,
258
+ issueNumber: args.issueNumber,
259
+ title: args.title,
260
+ body: args.body,
261
+ labels: args.labels,
262
+ assignedTeam: args.assignedTeam,
263
+ deliveryId: args.deliveryId,
264
+ eventAction: args.eventAction
265
+ };
266
+ break;
267
  case 'sin_github_wiki_sync':
268
  action = { action: 'sin.github.wiki.sync', prompt: args.prompt, contextDir: args.contextDir };
269
  break;
 
301
  export async function runMcpServer() {
302
  const transport = new StdioServerTransport();
303
  await server.connect(transport);
304
+ console.error('AZA-SIN-Coder-•-GitHub-Issues MCP Server running on stdio');
305
  }
src/metadata.ts CHANGED
@@ -1,8 +1,8 @@
1
  import process from 'node:process';
2
 
3
  export const TEMPLATE_AGENT_ID = 'sin-github-issues';
4
- export const TEMPLATE_AGENT_NAME = 'SIN-GitHub-Issues';
5
- export const TEMPLATE_AGENT_DESCRIPTION = 'CEO Elite GitHub Operations Architect — orchestrates Projects V2, Issues, Wikis, Discussions, Gists, Security audits, PR Reviews, and public Showcase Ledger logging.';
6
  export const TEMPLATE_AGENT_VERSION = '2026.03.22';
7
  export const TEMPLATE_AGENT_DEFAULT_HOST = '127.0.0.1';
8
  export const TEMPLATE_AGENT_DEFAULT_PORT = 46031;
@@ -13,6 +13,31 @@ export const TEMPLATE_AGENT_SKILLS = [
13
  name: 'Health',
14
  description: 'Check 2026 Elite GitHub Operations Architect readiness, model, and capabilities.',
15
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  {
17
  id: 'sin.github.project.orchestrate',
18
  name: 'Project Orchestrate',
 
1
  import process from 'node:process';
2
 
3
  export const TEMPLATE_AGENT_ID = 'sin-github-issues';
4
+ export const TEMPLATE_AGENT_NAME = 'AZA-SIN-Coder-•-GitHub-Issues';
5
+ export const TEMPLATE_AGENT_DESCRIPTION = 'CEO Elite GitHub issue triage and delegation architect for the AZA coding fleet — orchestrates issue lifecycle, comments, queueing, Projects V2, Discussions, Gists, Security audits, PR reviews, and public Showcase Ledger logging.';
6
  export const TEMPLATE_AGENT_VERSION = '2026.03.22';
7
  export const TEMPLATE_AGENT_DEFAULT_HOST = '127.0.0.1';
8
  export const TEMPLATE_AGENT_DEFAULT_PORT = 46031;
 
13
  name: 'Health',
14
  description: 'Check 2026 Elite GitHub Operations Architect readiness, model, and capabilities.',
15
  },
16
+ {
17
+ id: 'sin.github.worker.register',
18
+ name: 'Worker Register',
19
+ description: 'Register the GitHub-Issues runtime as a Room-13 worker and claim its initial lease.',
20
+ },
21
+ {
22
+ id: 'sin.github.worker.status',
23
+ name: 'Worker Status',
24
+ description: 'Inspect GitHub-Issues worker registration and claim state against Room-13.',
25
+ },
26
+ {
27
+ id: 'sin.github.worker.claim_next',
28
+ name: 'Worker Claim Next',
29
+ description: 'Claim the next dispatchable Room-13 task for GitHub-Issues.',
30
+ },
31
+ {
32
+ id: 'sin.github.worker.checkpoint',
33
+ name: 'Worker Checkpoint',
34
+ description: 'Send checkpoint progress for the current Room-13 task.',
35
+ },
36
+ {
37
+ id: 'sin.github.worker.complete',
38
+ name: 'Worker Complete',
39
+ description: 'Mark the currently claimed Room-13 task as completed.',
40
+ },
41
  {
42
  id: 'sin.github.project.orchestrate',
43
  name: 'Project Orchestrate',
src/queue-state.js ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export const ISSUE_QUEUE_STATE = {
2
+ received: 'received',
3
+ queued: 'queued',
4
+ claimed: 'claimed',
5
+ dispatched: 'dispatched',
6
+ accepted: 'accepted',
7
+ completed: 'completed',
8
+ failed: 'failed',
9
+ dead_letter: 'dead_letter',
10
+ };
11
+
12
+ export function isActiveQueueState(value) {
13
+ return ['received', 'queued', 'claimed', 'dispatched', 'accepted'].includes(String(value || ''));
14
+ }
15
+
16
+ export function queueStateForStatus(value) {
17
+ switch (String(value || '').toLowerCase()) {
18
+ case 'pending':
19
+ return ISSUE_QUEUE_STATE.queued;
20
+ case 'in_progress':
21
+ return ISSUE_QUEUE_STATE.claimed;
22
+ case 'completed':
23
+ return ISSUE_QUEUE_STATE.completed;
24
+ case 'failed':
25
+ return ISSUE_QUEUE_STATE.failed;
26
+ default:
27
+ return ISSUE_QUEUE_STATE.received;
28
+ }
29
+ }
src/queue-state.ts ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export const ISSUE_QUEUE_STATE = {
2
+ received: 'received',
3
+ queued: 'queued',
4
+ claimed: 'claimed',
5
+ dispatched: 'dispatched',
6
+ accepted: 'accepted',
7
+ completed: 'completed',
8
+ failed: 'failed',
9
+ dead_letter: 'dead_letter',
10
+ } as const;
11
+
12
+ export type IssueQueueState = keyof typeof ISSUE_QUEUE_STATE;
13
+
14
+ export function isActiveQueueState(value: string | null | undefined): boolean {
15
+ return ['received', 'queued', 'claimed', 'dispatched', 'accepted'].includes(String(value || ''));
16
+ }
17
+
18
+ export function queueStateForStatus(status: string | null | undefined): IssueQueueState {
19
+ switch (String(status || '').toLowerCase()) {
20
+ case 'pending':
21
+ return 'queued';
22
+ case 'in_progress':
23
+ return 'claimed';
24
+ case 'completed':
25
+ return 'completed';
26
+ case 'failed':
27
+ return 'failed';
28
+ default:
29
+ return 'received';
30
+ }
31
+ }
src/room13-worker.ts ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os from 'node:os';
2
+ import process from 'node:process';
3
+
4
+ type Room13WorkerRegisterResponse = {
5
+ id?: string;
6
+ lease_epoch?: number;
7
+ };
8
+
9
+ type Room13WorkerClaimResponse = {
10
+ claimed_task_id?: string | null;
11
+ lease_epoch?: number;
12
+ lease_expires_at?: string | null;
13
+ run_id?: string;
14
+ };
15
+
16
+ type Room13Task = {
17
+ id: string;
18
+ status: string;
19
+ assigned_worker?: string | null;
20
+ run_id?: string | null;
21
+ };
22
+
23
+ export type GitHubIssuesWorkerSnapshot = {
24
+ enabled: boolean;
25
+ workerName: string;
26
+ workerId: string;
27
+ runId: string;
28
+ claimedTaskId: string;
29
+ leaseEpoch: number;
30
+ leaseExpiresAt?: string;
31
+ baseUrl: string;
32
+ };
33
+
34
+ let currentRuntime: GitHubIssuesRoom13WorkerRuntime | null = null;
35
+
36
+ export function getCurrentGitHubIssuesWorkerRuntime() {
37
+ return currentRuntime;
38
+ }
39
+
40
+ export class GitHubIssuesRoom13WorkerRuntime {
41
+ protected workerId = '';
42
+ protected leaseEpoch = 0;
43
+ protected claimedTaskId = '';
44
+ protected leaseExpiresAt?: string;
45
+ protected readonly workerName: string;
46
+ protected readonly baseUrl: string;
47
+ protected readonly bearerToken: string;
48
+ protected readonly runId: string;
49
+ protected heartbeatTimer?: NodeJS.Timeout;
50
+
51
+ constructor(workerName = 'sin-github-issues', baseUrl = process.env.ROOM13_COORDINATOR_URL || '') {
52
+ this.workerName = workerName;
53
+ this.baseUrl = baseUrl.replace(/\/$/, '');
54
+ this.bearerToken = String(process.env.ROOM13_BEARER_TOKEN || '').trim();
55
+ this.runId = `${workerName}:${process.pid}:${Date.now()}`;
56
+ }
57
+
58
+ get enabled() {
59
+ return Boolean(this.baseUrl);
60
+ }
61
+
62
+ snapshot(): GitHubIssuesWorkerSnapshot {
63
+ return {
64
+ enabled: this.enabled,
65
+ workerName: this.workerName,
66
+ workerId: this.workerId,
67
+ runId: this.runId,
68
+ claimedTaskId: this.claimedTaskId,
69
+ leaseEpoch: this.leaseEpoch,
70
+ leaseExpiresAt: this.leaseExpiresAt,
71
+ baseUrl: this.baseUrl,
72
+ };
73
+ }
74
+
75
+ async start() {
76
+ if (!this.enabled) return this.snapshot();
77
+ const registered = await this.request<Room13WorkerRegisterResponse>('POST', '/api/workers', {
78
+ name: `${this.workerName}:${process.env.SPACE_HOST || 'local'}`,
79
+ type: 'general',
80
+ capabilities: ['platform:github', 'worker_runtime', 'lease_heartbeat', 'issue_lifecycle'],
81
+ metadata: { runtime: 'node', hostname: os.hostname() },
82
+ worker_identity: this.workerName,
83
+ persona_id: this.workerName,
84
+ platform: 'github-issues',
85
+ current_run_id: this.runId,
86
+ lease_ttl_sec: 120,
87
+ approval_state: 'idle',
88
+ });
89
+ this.workerId = String(registered?.id || '').trim();
90
+ this.leaseEpoch = Number(registered?.lease_epoch || 0);
91
+ if (this.workerId) {
92
+ const claim = await this.request<Room13WorkerClaimResponse>('POST', `/api/workers/${this.workerId}/claim`, {
93
+ run_id: this.runId,
94
+ ttl_sec: 120,
95
+ });
96
+ this.claimedTaskId = String(claim?.claimed_task_id || '').trim();
97
+ this.leaseEpoch = Number(claim?.lease_epoch || this.leaseEpoch || 0);
98
+ this.leaseExpiresAt = claim?.lease_expires_at || undefined;
99
+ this.startHeartbeatLoop();
100
+ }
101
+ return this.snapshot();
102
+ }
103
+
104
+ async stop() {
105
+ if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
106
+ if (!this.enabled || !this.workerId) return;
107
+ await this.request('POST', `/api/workers/${this.workerId}/release`, {
108
+ lease_epoch: this.leaseEpoch,
109
+ clear_run: true,
110
+ final_status: 'online',
111
+ status_reason: 'github_issues_runtime_stop',
112
+ approval_state: 'idle',
113
+ }).catch(() => undefined);
114
+ }
115
+
116
+ async heartbeat() {
117
+ if (!this.enabled || !this.workerId) return this.snapshot();
118
+ const result = await this.request<Room13WorkerClaimResponse>('POST', `/api/workers/${this.workerId}/heartbeat`, {
119
+ lease_epoch: this.leaseEpoch,
120
+ ttl_sec: 120,
121
+ metadata: {
122
+ run_id: this.runId,
123
+ claimed_task_id: this.claimedTaskId,
124
+ last_heartbeat_source: 'sin-github-issues',
125
+ },
126
+ });
127
+ this.leaseEpoch = Number(result?.lease_epoch || this.leaseEpoch || 0);
128
+ this.leaseExpiresAt = result?.lease_expires_at || this.leaseExpiresAt;
129
+ return this.snapshot();
130
+ }
131
+
132
+ async claimNextTask() {
133
+ if (!this.enabled || !this.workerId) throw new Error('room13_worker_not_registered');
134
+ const task = await this.request<Room13Task>('POST', '/api/tasks/claim-next', {
135
+ worker_id: this.workerId,
136
+ accepted_types: ['github_issue_dispatch'],
137
+ min_priority: 'normal',
138
+ run_id: this.runId,
139
+ lease_epoch: this.leaseEpoch,
140
+ });
141
+ this.claimedTaskId = String(task?.id || '').trim();
142
+ return task;
143
+ }
144
+
145
+ async checkpoint(step: string, checkpoint: Record<string, unknown> = {}) {
146
+ if (!this.enabled || !this.workerId) throw new Error('room13_worker_not_registered');
147
+ return await this.request('POST', `/api/workers/${this.workerId}/checkpoint`, {
148
+ lease_epoch: this.leaseEpoch,
149
+ run_id: this.runId,
150
+ step,
151
+ checkpoint,
152
+ });
153
+ }
154
+
155
+ async completeTask(result: Record<string, unknown> = {}) {
156
+ if (!this.enabled || !this.claimedTaskId) throw new Error('room13_task_not_claimed');
157
+ const response = await this.request('PUT', `/api/tasks/${this.claimedTaskId}/complete`, result);
158
+ this.claimedTaskId = '';
159
+ return response;
160
+ }
161
+
162
+ private startHeartbeatLoop() {
163
+ if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
164
+ this.heartbeatTimer = setInterval(() => {
165
+ void this.heartbeat().catch(() => undefined);
166
+ }, 30000);
167
+ this.heartbeatTimer.unref();
168
+ }
169
+
170
+ private async request<T = unknown>(method: string, path: string, body?: unknown) {
171
+ const headers: Record<string, string> = { 'content-type': 'application/json' };
172
+ if (this.bearerToken) headers.Authorization = `Bearer ${this.bearerToken}`;
173
+ const response = await fetch(`${this.baseUrl}${path}`, {
174
+ method,
175
+ headers,
176
+ body: body ? JSON.stringify(body) : undefined,
177
+ });
178
+ const text = await response.text();
179
+ const parsed = text ? JSON.parse(text) : {};
180
+ if (!response.ok) throw new Error(`room13_http_${response.status}:${JSON.stringify(parsed).slice(0, 1000)}`);
181
+ return parsed as T;
182
+ }
183
+ }
184
+
185
+ export function installGitHubIssuesWorkerRuntime(runtime: GitHubIssuesRoom13WorkerRuntime | null) {
186
+ currentRuntime = runtime;
187
+ }
src/runtime.ts CHANGED
@@ -1,11 +1,42 @@
1
  import { exec } from 'node:child_process';
2
  import { promisify } from 'node:util';
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  const execAsync = promisify(exec);
5
 
6
  export type GitHubAgentAction =
7
  | { action: 'agent.help' }
8
  | { action: 'sin.github.health' }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  | { action: 'sin.github.project.orchestrate'; prompt: string; contextDir?: string }
10
  | { action: 'sin.github.issue.manage'; prompt: string; issueNumber?: number }
11
  | { action: 'sin.github.wiki.sync'; prompt: string; contextDir?: string }
@@ -13,8 +44,7 @@ export type GitHubAgentAction =
13
  | { action: 'sin.github.gist.publish'; prompt: string; isPublic?: boolean }
14
  | { action: 'sin.github.security.audit'; prompt: string; contextDir?: string }
15
  | { action: 'sin.github.pr.review'; prNumber: number; contextDir?: string }
16
- | { action: 'sin.github.ledger.log'; agentName: string; activityTitle: string; details: string }
17
- | { action: 'sin.github.governance.report_concern'; concernType: string; details: string };
18
 
19
  export async function executeGitHubAgentAction(action: GitHubAgentAction): Promise<unknown> {
20
  switch (action.action) {
@@ -25,6 +55,15 @@ export async function executeGitHubAgentAction(action: GitHubAgentAction): Promi
25
  mandate: 'CEO Elite GitHub Operations. Orchestrates Projects, Issues, Wikis, Discussions, Gists, Security, PR Reviews, and public Showcase Ledgers.',
26
  actions: [
27
  'sin.github.health',
 
 
 
 
 
 
 
 
 
28
  'sin.github.project.orchestrate',
29
  'sin.github.issue.manage',
30
  'sin.github.wiki.sync',
@@ -32,8 +71,7 @@ export async function executeGitHubAgentAction(action: GitHubAgentAction): Promi
32
  'sin.github.gist.publish',
33
  'sin.github.security.audit',
34
  'sin.github.pr.review',
35
- 'sin.github.ledger.log',
36
- 'sin.github.governance.report_concern'
37
  ],
38
  };
39
 
@@ -46,8 +84,41 @@ export async function executeGitHubAgentAction(action: GitHubAgentAction): Promi
46
  team: 'Team - Coding',
47
  status: 'Elite 2026 GitHub Operations Architect Online',
48
  capabilities: ['projects', 'wikis', 'discussions', 'gists', 'security', 'prs', 'issues', 'ledger'],
 
49
  };
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  case 'sin.github.project.orchestrate':
52
  return await executeOpenCode(
53
  `Use the GitHub CLI ('gh project create/link/item-add') to orchestrate the following project board requirements: ${action.prompt}. Ensure the board is linked to the repository and items are properly assigned.`,
@@ -91,21 +162,9 @@ export async function executeGitHubAgentAction(action: GitHubAgentAction): Promi
91
  return await executeOpenCode(
92
  `Create a new public GitHub Issue or Discussion in the repository 'Delqhi/OpenSolver-Ledger' titled "[${action.agentName}] ${action.activityTitle}". The body must contain the following details formatted in premium markdown to showcase our fleet's capabilities: \n\n${action.details}`
93
  );
94
-
95
- case 'sin.github.governance.report_concern':
96
- return await reportSecurityConcern(action.concernType, action.details);
97
  }
98
  }
99
 
100
- async function reportSecurityConcern(type: string, details: string) {
101
- console.log(`⚠️ Security concern reported: ${type}`);
102
- return {
103
- ok: true,
104
- status: 'incident_logged',
105
- policy: 'FLEET_AUTONOMY_DOWNGRADED_BY_10_PERCENT'
106
- };
107
- }
108
-
109
  async function executeOpenCode(prompt: string, dir?: string) {
110
  await execAsync('python3 scripts/hf_pull_script.py').catch(() => console.warn('Warning: hf_pull_script failed. Proceeding with cached credentials.'));
111
 
@@ -123,3 +182,130 @@ async function executeOpenCode(prompt: string, dir?: string) {
123
  throw new Error(`GitHub Operations Execution Failed: ${error.message}`);
124
  }
125
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import { exec } from 'node:child_process';
2
  import { promisify } from 'node:util';
3
+ import { commentIssue, closeIssue, ensureIssue } from './github.js';
4
+ import { createClient } from '@supabase/supabase-js';
5
+ import { getCurrentGitHubIssuesWorkerRuntime } from './room13-worker.js';
6
+ import {
7
+ buildDeliveryKey,
8
+ buildIssueKey,
9
+ routeIssueTriage,
10
+ routeLabelsToTeam,
11
+ TriageEnqueueSchema,
12
+ type TriageEnqueueInput,
13
+ } from './triage.js';
14
+ import { ISSUE_QUEUE_STATE } from './queue-state.js';
15
 
16
  const execAsync = promisify(exec);
17
 
18
  export type GitHubAgentAction =
19
  | { action: 'agent.help' }
20
  | { action: 'sin.github.health' }
21
+ | { action: 'sin.github.worker.register' }
22
+ | { action: 'sin.github.worker.status' }
23
+ | { action: 'sin.github.worker.claim_next' }
24
+ | { action: 'sin.github.worker.checkpoint'; step: string; checkpoint?: Record<string, unknown> }
25
+ | { action: 'sin.github.worker.complete'; result?: Record<string, unknown> }
26
+ | { action: 'sin.github.issue.ensure'; repo: string; title: string; body: string; labels?: string[] }
27
+ | { action: 'sin.github.issue.comment'; repo: string; issueNumber: number; body: string }
28
+ | { action: 'sin.github.issue.close'; repo: string; issueNumber: number; comment?: string }
29
+ | {
30
+ action: 'sin.github.issue.triage.enqueue';
31
+ repo: string;
32
+ issueNumber: number;
33
+ title: string;
34
+ body?: string;
35
+ labels?: string[];
36
+ assignedTeam?: string;
37
+ deliveryId?: string;
38
+ eventAction?: string;
39
+ }
40
  | { action: 'sin.github.project.orchestrate'; prompt: string; contextDir?: string }
41
  | { action: 'sin.github.issue.manage'; prompt: string; issueNumber?: number }
42
  | { action: 'sin.github.wiki.sync'; prompt: string; contextDir?: string }
 
44
  | { action: 'sin.github.gist.publish'; prompt: string; isPublic?: boolean }
45
  | { action: 'sin.github.security.audit'; prompt: string; contextDir?: string }
46
  | { action: 'sin.github.pr.review'; prNumber: number; contextDir?: string }
47
+ | { action: 'sin.github.ledger.log'; agentName: string; activityTitle: string; details: string };
 
48
 
49
  export async function executeGitHubAgentAction(action: GitHubAgentAction): Promise<unknown> {
50
  switch (action.action) {
 
55
  mandate: 'CEO Elite GitHub Operations. Orchestrates Projects, Issues, Wikis, Discussions, Gists, Security, PR Reviews, and public Showcase Ledgers.',
56
  actions: [
57
  'sin.github.health',
58
+ 'sin.github.worker.register',
59
+ 'sin.github.worker.status',
60
+ 'sin.github.worker.claim_next',
61
+ 'sin.github.worker.checkpoint',
62
+ 'sin.github.worker.complete',
63
+ 'sin.github.issue.ensure',
64
+ 'sin.github.issue.comment',
65
+ 'sin.github.issue.close',
66
+ 'sin.github.issue.triage.enqueue',
67
  'sin.github.project.orchestrate',
68
  'sin.github.issue.manage',
69
  'sin.github.wiki.sync',
 
71
  'sin.github.gist.publish',
72
  'sin.github.security.audit',
73
  'sin.github.pr.review',
74
+ 'sin.github.ledger.log'
 
75
  ],
76
  };
77
 
 
84
  team: 'Team - Coding',
85
  status: 'Elite 2026 GitHub Operations Architect Online',
86
  capabilities: ['projects', 'wikis', 'discussions', 'gists', 'security', 'prs', 'issues', 'ledger'],
87
+ room13Worker: getCurrentGitHubIssuesWorkerRuntime()?.snapshot() || null,
88
  };
89
 
90
+ case 'sin.github.worker.register':
91
+ return { ok: true, worker: await getCurrentGitHubIssuesWorkerRuntime()?.start() };
92
+
93
+ case 'sin.github.worker.status':
94
+ return { ok: true, worker: getCurrentGitHubIssuesWorkerRuntime()?.snapshot() || null };
95
+
96
+ case 'sin.github.worker.claim_next':
97
+ return { ok: true, task: await getCurrentGitHubIssuesWorkerRuntime()?.claimNextTask() };
98
+
99
+ case 'sin.github.worker.checkpoint':
100
+ return { ok: true, checkpoint: await getCurrentGitHubIssuesWorkerRuntime()?.checkpoint(action.step, action.checkpoint || {}) };
101
+
102
+ case 'sin.github.worker.complete':
103
+ return { ok: true, completion: await getCurrentGitHubIssuesWorkerRuntime()?.completeTask(action.result || {}) };
104
+
105
+ case 'sin.github.issue.ensure':
106
+ return await ensureIssue({
107
+ repo: action.repo,
108
+ title: action.title,
109
+ body: action.body,
110
+ labels: action.labels,
111
+ });
112
+
113
+ case 'sin.github.issue.comment':
114
+ return await commentIssue(action.repo, action.issueNumber, action.body);
115
+
116
+ case 'sin.github.issue.close':
117
+ return await closeIssue(action.repo, action.issueNumber, action.comment);
118
+
119
+ case 'sin.github.issue.triage.enqueue':
120
+ return await enqueueIssueTriage(action);
121
+
122
  case 'sin.github.project.orchestrate':
123
  return await executeOpenCode(
124
  `Use the GitHub CLI ('gh project create/link/item-add') to orchestrate the following project board requirements: ${action.prompt}. Ensure the board is linked to the repository and items are properly assigned.`,
 
162
  return await executeOpenCode(
163
  `Create a new public GitHub Issue or Discussion in the repository 'Delqhi/OpenSolver-Ledger' titled "[${action.agentName}] ${action.activityTitle}". The body must contain the following details formatted in premium markdown to showcase our fleet's capabilities: \n\n${action.details}`
164
  );
 
 
 
165
  }
166
  }
167
 
 
 
 
 
 
 
 
 
 
168
  async function executeOpenCode(prompt: string, dir?: string) {
169
  await execAsync('python3 scripts/hf_pull_script.py').catch(() => console.warn('Warning: hf_pull_script failed. Proceeding with cached credentials.'));
170
 
 
182
  throw new Error(`GitHub Operations Execution Failed: ${error.message}`);
183
  }
184
  }
185
+
186
+ async function enqueueIssueTriage(action: Extract<GitHubAgentAction, { action: 'sin.github.issue.triage.enqueue' }>) {
187
+ const input = TriageEnqueueSchema.parse(action) as TriageEnqueueInput;
188
+ const supabaseUrl = process.env.SUPABASE_URL || process.env.SIN_SUPABASE_URL;
189
+ const serviceRole = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SIN_SUPABASE_SERVICE_ROLE_KEY;
190
+ if (!supabaseUrl || !serviceRole) {
191
+ throw new Error('missing_supabase_credentials');
192
+ }
193
+
194
+ const supabase = createClient(supabaseUrl, serviceRole, { auth: { persistSession: false } });
195
+ const deliveryId = buildDeliveryKey(input);
196
+ const issueKey = buildIssueKey(input.repo, input.issueNumber);
197
+ const labels = input.labels || [];
198
+ const route = routeIssueTriage(labels, input.title, input.body || '');
199
+ const assignedTeam = input.assignedTeam || route.assignedTeam;
200
+
201
+ const { data: byDelivery, error: deliveryError } = await supabase
202
+ .from('sin_issues_pool')
203
+ .select('id, issue_number, repo_name, title, status, metadata, delivery_id')
204
+ .eq('delivery_id', deliveryId)
205
+ .maybeSingle();
206
+ if (deliveryError) throw deliveryError;
207
+
208
+ if (byDelivery) {
209
+ return {
210
+ ok: true,
211
+ created: false,
212
+ deduplicatedBy: 'delivery_id',
213
+ queueId: byDelivery.id,
214
+ issueKey,
215
+ status: byDelivery.status,
216
+ deliveryId,
217
+ };
218
+ }
219
+
220
+ const { data: existing, error: selectError } = await supabase
221
+ .from('sin_issues_pool')
222
+ .select('id, issue_number, repo_name, title, status, metadata, delivery_id')
223
+ .eq('repo_name', input.repo)
224
+ .eq('issue_number', input.issueNumber)
225
+ .maybeSingle();
226
+ if (selectError) throw selectError;
227
+
228
+ if (existing) {
229
+ const mergedMetadata = {
230
+ ...(existing.metadata || {}),
231
+ last_delivery_id: deliveryId,
232
+ issue_key: issueKey,
233
+ event_action: input.eventAction || 'opened',
234
+ labels,
235
+ ingress: 'github-issues-runtime',
236
+ route,
237
+ };
238
+
239
+ const { error: updateError } = await supabase
240
+ .from('sin_issues_pool')
241
+ .update({
242
+ metadata: mergedMetadata,
243
+ delivery_id: deliveryId,
244
+ updated_at: new Date().toISOString(),
245
+ })
246
+ .eq('id', existing.id);
247
+ if (updateError) throw updateError;
248
+
249
+ return {
250
+ ok: true,
251
+ created: false,
252
+ deduplicatedBy: 'issue_key',
253
+ queueId: existing.id,
254
+ issueKey,
255
+ status: existing.status,
256
+ deliveryId,
257
+ };
258
+ }
259
+
260
+ const payload = {
261
+ issue_number: input.issueNumber,
262
+ repo_name: input.repo,
263
+ title: input.title,
264
+ body: input.body || '',
265
+ state: 'open',
266
+ assigned_team: assignedTeam,
267
+ assigned_agent: null,
268
+ status: 'pending',
269
+ queue_state: ISSUE_QUEUE_STATE.queued,
270
+ delivery_id: deliveryId,
271
+ issue_key: issueKey,
272
+ event_action: input.eventAction || 'opened',
273
+ metadata: {
274
+ delivery_id: deliveryId,
275
+ issue_key: issueKey,
276
+ event_action: input.eventAction || 'opened',
277
+ labels,
278
+ ingress: 'github-issues-runtime',
279
+ route,
280
+ },
281
+ };
282
+
283
+ const { data: inserted, error: insertError } = await supabase
284
+ .from('sin_issues_pool')
285
+ .insert(payload)
286
+ .select('id, status')
287
+ .single();
288
+ if (insertError) throw insertError;
289
+
290
+ await commentIssue(
291
+ input.repo,
292
+ input.issueNumber,
293
+ [
294
+ 'AZA-SIN-Coder-•-GitHub-Issues triage complete.',
295
+ `Delivery: ${deliveryId}`,
296
+ `Assigned team: @${assignedTeam}`,
297
+ `Assigned agent hint: @${route.assignedAgentHint}`,
298
+ `Capability hint: ${route.capabilityHint}`,
299
+ `Queue status: ${ISSUE_QUEUE_STATE.queued}`,
300
+ ].join('\n'),
301
+ );
302
+
303
+ return {
304
+ ok: true,
305
+ created: true,
306
+ queueId: inserted.id,
307
+ issueKey,
308
+ status: inserted.status,
309
+ deliveryId,
310
+ };
311
+ }
src/self-healing.ts CHANGED
@@ -4,14 +4,14 @@ import { execFileSync } from 'node:child_process';
4
  * 🚨 GLOBAL FLEET SELF-HEALING PROTOCOL (PRIORITY 0000) 🚨
5
  * NO-SILO MANDATE: This module catches critical errors, dumps extensive logs,
6
  * and blasts them to the fleet self-healing webhook.
7
- * Hermes and SIN-GitHub-Issues will automatically take over from there.
8
  */
9
 
10
  export function triggerFleetSelfHealing(error: Error, extensiveContext: Record<string, any>) {
11
  console.error('\n🚨 CRITICAL FAILURE DETECTED. INITIATING NO-SILO SELF-HEALING PROTOCOL 🚨');
12
 
13
  const payload = {
14
- agentId: 'A2A-SIN-GitHub-Issues',
15
  timestamp: new Date().toISOString(),
16
  errorLogs: `Error: ${error.message}\nStack: ${error.stack}\nContext: ${JSON.stringify(extensiveContext, null, 2)}`,
17
  team: 'team-coding'
 
4
  * 🚨 GLOBAL FLEET SELF-HEALING PROTOCOL (PRIORITY 0000) 🚨
5
  * NO-SILO MANDATE: This module catches critical errors, dumps extensive logs,
6
  * and blasts them to the fleet self-healing webhook.
7
+ * Hermes and AZA-SIN-Coder-•-GitHub-Issues will automatically take over from there.
8
  */
9
 
10
  export function triggerFleetSelfHealing(error: Error, extensiveContext: Record<string, any>) {
11
  console.error('\n🚨 CRITICAL FAILURE DETECTED. INITIATING NO-SILO SELF-HEALING PROTOCOL 🚨');
12
 
13
  const payload = {
14
+ agentId: 'AZA-SIN-Coder-•-GitHub-Issues',
15
  timestamp: new Date().toISOString(),
16
  errorLogs: `Error: ${error.message}\nStack: ${error.stack}\nContext: ${JSON.stringify(extensiveContext, null, 2)}`,
17
  team: 'team-coding'
src/triage.ts ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { z } from 'zod';
2
+
3
+ export { ISSUE_QUEUE_STATE } from './queue-state.js';
4
+ export type { IssueQueueState as IssueQueueStatus } from './queue-state.js';
5
+
6
+ export const TriageEnqueueSchema = z.object({
7
+ action: z.literal('sin.github.issue.triage.enqueue'),
8
+ repo: z.string().min(3),
9
+ issueNumber: z.number().int().positive(),
10
+ title: z.string().min(1),
11
+ body: z.string().optional(),
12
+ labels: z.array(z.string()).optional(),
13
+ assignedTeam: z.string().optional(),
14
+ deliveryId: z.string().optional(),
15
+ eventAction: z.string().optional(),
16
+ });
17
+
18
+ export type TriageEnqueueInput = z.infer<typeof TriageEnqueueSchema>;
19
+
20
+ export type TriageRoute = {
21
+ assignedTeam: string;
22
+ assignedAgentHint: string;
23
+ capabilityHint: string;
24
+ rationale: string;
25
+ };
26
+
27
+ export function buildIssueKey(repo: string, issueNumber: number) {
28
+ return `${repo}#${issueNumber}`;
29
+ }
30
+
31
+ export function buildDeliveryKey(input: Pick<TriageEnqueueInput, 'repo' | 'issueNumber' | 'deliveryId' | 'eventAction'>) {
32
+ const eventAction = (input.eventAction || 'opened').trim() || 'opened';
33
+ const base = `${input.repo}#${input.issueNumber}:${eventAction}`;
34
+ return (input.deliveryId || '').trim() || `manual:${base}`;
35
+ }
36
+
37
+ export function routeIssueTriage(labels: string[], title = '', body = ''): TriageRoute {
38
+ const normalized = labels.map((label) => label.toLowerCase());
39
+ const haystack = `${title} ${body}`.toLowerCase();
40
+
41
+ if (normalized.some((label) => label.includes('frontend') || label.includes('ui')) || hasAny(haystack, ['react', 'tsx', 'css', 'layout', 'component'])) {
42
+ return {
43
+ assignedTeam: 'team-coding',
44
+ assignedAgentHint: 'A2A-SIN-Coder-Frontend',
45
+ capabilityHint: 'command:render-ui',
46
+ rationale: 'frontend/ui-signal',
47
+ };
48
+ }
49
+
50
+ if (normalized.some((label) => label.includes('database') || label.includes('sql') || label.includes('supabase')) || hasAny(haystack, ['schema', 'migration', 'postgres', 'rls', 'supabase'])) {
51
+ return {
52
+ assignedTeam: 'team-coding',
53
+ assignedAgentHint: 'A2A-SIN-Coder-Code-Database',
54
+ capabilityHint: 'command:data-model',
55
+ rationale: 'database-signal',
56
+ };
57
+ }
58
+
59
+ if (normalized.some((label) => label.includes('integration') || label.includes('webhook') || label.includes('api')) || hasAny(haystack, ['webhook', 'api', 'integration', 'queue', 'dispatch'])) {
60
+ return {
61
+ assignedTeam: 'team-coding',
62
+ assignedAgentHint: 'A2A-SIN-Coder-Code-Integration',
63
+ capabilityHint: 'command:integration',
64
+ rationale: 'integration-signal',
65
+ };
66
+ }
67
+
68
+ if (normalized.some((label) => label.includes('ai') || label.includes('llm') || label.includes('mcp')) || hasAny(haystack, ['prompt', 'llm', 'agent', 'mcp', 'rag'])) {
69
+ return {
70
+ assignedTeam: 'team-coding',
71
+ assignedAgentHint: 'A2A-SIN-Coder-Code-AI',
72
+ capabilityHint: 'command:ai-runtime',
73
+ rationale: 'ai-signal',
74
+ };
75
+ }
76
+
77
+ if (normalized.some((label) => label.includes('backend') || label.includes('infra') || label.includes('ops')) || hasAny(haystack, ['backend', 'worker', 'lease', 'heartbeat', 'runtime'])) {
78
+ return {
79
+ assignedTeam: 'team-coding',
80
+ assignedAgentHint: 'A2A-SIN-Coder-Backend',
81
+ capabilityHint: 'command:backend-runtime',
82
+ rationale: 'backend-signal',
83
+ };
84
+ }
85
+
86
+ return {
87
+ assignedTeam: 'team-coding',
88
+ assignedAgentHint: 'A2A-SIN-Coder-Backend',
89
+ capabilityHint: 'command:implement',
90
+ rationale: 'default-coder-route',
91
+ };
92
+ }
93
+
94
+ export function routeLabelsToTeam(labels: string[], title = '', body = '') {
95
+ return routeIssueTriage(labels, title, body).assignedTeam;
96
+ }
97
+
98
+ function hasAny(haystack: string, needles: string[]) {
99
+ return needles.some((needle) => haystack.includes(needle));
100
+ }