claudius-core 0.9.3 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/.claude/agents/manager.md +3 -13
  2. package/.claude/agents/worker.md +72 -29
  3. package/.claude/rules/testing.md +7 -4
  4. package/.claude/scripts/merge-pr.sh +55 -24
  5. package/.claude/scripts/project-status.sh +8 -8
  6. package/.claude/skills/build/SKILL.md +3 -17
  7. package/.claude-plugin/marketplace.json +2 -2
  8. package/dist/lib/db.d.ts +30 -0
  9. package/dist/lib/db.d.ts.map +1 -0
  10. package/dist/lib/db.js +71 -0
  11. package/dist/lib/db.js.map +1 -0
  12. package/dist/lib/slack.d.ts +33 -0
  13. package/dist/lib/slack.d.ts.map +1 -0
  14. package/dist/lib/slack.js +79 -0
  15. package/dist/lib/slack.js.map +1 -0
  16. package/dist/studio/assets/{_basePickBy-CaRVkU_i.js → _basePickBy-R-uis1nJ.js} +1 -1
  17. package/dist/studio/assets/{_baseUniq-DB9CANVr.js → _baseUniq-DYva2fSG.js} +1 -1
  18. package/dist/studio/assets/{arc-DwNKwVLD.js → arc-BzeI-lxb.js} +1 -1
  19. package/dist/studio/assets/{architectureDiagram-VXUJARFQ-CDW4khKr.js → architectureDiagram-VXUJARFQ-DMa_o-aK.js} +1 -1
  20. package/dist/studio/assets/{blockDiagram-VD42YOAC-D6_LSve2.js → blockDiagram-VD42YOAC-BFN1vazA.js} +1 -1
  21. package/dist/studio/assets/{c4Diagram-YG6GDRKO-SFPE64AJ.js → c4Diagram-YG6GDRKO-BFDthHUP.js} +1 -1
  22. package/dist/studio/assets/channel-huxXjZrf.js +1 -0
  23. package/dist/studio/assets/{chunk-4BX2VUAB-BqHoEHlQ.js → chunk-4BX2VUAB-BcntFbLt.js} +1 -1
  24. package/dist/studio/assets/{chunk-55IACEB6-DkHQ5WBd.js → chunk-55IACEB6-sNY6b1p-.js} +1 -1
  25. package/dist/studio/assets/{chunk-B4BG7PRW-CW_kq6KT.js → chunk-B4BG7PRW-BLekgdES.js} +1 -1
  26. package/dist/studio/assets/{chunk-DI55MBZ5-DNDwEGQ5.js → chunk-DI55MBZ5-CZw9ICRq.js} +1 -1
  27. package/dist/studio/assets/{chunk-FMBD7UC4-5PX-ftxQ.js → chunk-FMBD7UC4-ntqmlvfQ.js} +1 -1
  28. package/dist/studio/assets/{chunk-QN33PNHL-QkQfQaqN.js → chunk-QN33PNHL-CE-WX1bS.js} +1 -1
  29. package/dist/studio/assets/{chunk-QZHKN3VN-Do2RvhJA.js → chunk-QZHKN3VN-GyZ2p2Bl.js} +1 -1
  30. package/dist/studio/assets/{chunk-TZMSLE5B-xiebau4j.js → chunk-TZMSLE5B--hsg0lEr.js} +1 -1
  31. package/dist/studio/assets/classDiagram-2ON5EDUG-ufBxprI3.js +1 -0
  32. package/dist/studio/assets/classDiagram-v2-WZHVMYZB-ufBxprI3.js +1 -0
  33. package/dist/studio/assets/clone-BRn04n6L.js +1 -0
  34. package/dist/studio/assets/{cose-bilkent-S5V4N54A-Apnpf-ki.js → cose-bilkent-S5V4N54A-C4C-DPXZ.js} +1 -1
  35. package/dist/studio/assets/{dagre-6UL2VRFP-BxyPIzB8.js → dagre-6UL2VRFP-1Bb2UhRi.js} +1 -1
  36. package/dist/studio/assets/{diagram-PSM6KHXK-24YoaI-e.js → diagram-PSM6KHXK-C-FzwLf5.js} +1 -1
  37. package/dist/studio/assets/{diagram-QEK2KX5R-lHpdi46q.js → diagram-QEK2KX5R-Bctxbrmx.js} +1 -1
  38. package/dist/studio/assets/{diagram-S2PKOQOG-9u1_ee6B.js → diagram-S2PKOQOG-3uep1mdW.js} +1 -1
  39. package/dist/studio/assets/{erDiagram-Q2GNP2WA-Dlmgb2ym.js → erDiagram-Q2GNP2WA-B_Db2yYe.js} +1 -1
  40. package/dist/studio/assets/{flowDiagram-NV44I4VS-5sj_GCzk.js → flowDiagram-NV44I4VS-Bzc-kwIX.js} +1 -1
  41. package/dist/studio/assets/{ganttDiagram-JELNMOA3-CUJF-slV.js → ganttDiagram-JELNMOA3-BXibfYz-.js} +1 -1
  42. package/dist/studio/assets/{gitGraphDiagram-V2S2FVAM-CKpDBk3b.js → gitGraphDiagram-V2S2FVAM-BLkjIgg1.js} +1 -1
  43. package/dist/studio/assets/{graph-BRYklN25.js → graph-B0Z_gmOm.js} +1 -1
  44. package/dist/studio/assets/{index-WEgtt1oI.js → index-Ddl_PR-h.js} +2 -2
  45. package/dist/studio/assets/{infoDiagram-HS3SLOUP-DKF6awtp.js → infoDiagram-HS3SLOUP-BeFdN5yb.js} +1 -1
  46. package/dist/studio/assets/{journeyDiagram-XKPGCS4Q-CgrhL8R0.js → journeyDiagram-XKPGCS4Q--icE_FdD.js} +1 -1
  47. package/dist/studio/assets/{kanban-definition-3W4ZIXB7-28MC-pF6.js → kanban-definition-3W4ZIXB7-BYGur8C7.js} +1 -1
  48. package/dist/studio/assets/{layout-gwYv6lHv.js → layout-B4VDGqHe.js} +1 -1
  49. package/dist/studio/assets/{linear-Dl48BTRW.js → linear-Bm1oIJ5Y.js} +1 -1
  50. package/dist/studio/assets/{mermaid.core-YPNEyw9M.js → mermaid.core-Bl28GW7R.js} +4 -4
  51. package/dist/studio/assets/{mindmap-definition-VGOIOE7T-CNO-62gT.js → mindmap-definition-VGOIOE7T-DC0Ch_L5.js} +1 -1
  52. package/dist/studio/assets/{pieDiagram-ADFJNKIX-DutNO8TU.js → pieDiagram-ADFJNKIX-Cfm6OLdr.js} +1 -1
  53. package/dist/studio/assets/{quadrantDiagram-AYHSOK5B-CyL-T3po.js → quadrantDiagram-AYHSOK5B-C68ftZIq.js} +1 -1
  54. package/dist/studio/assets/{requirementDiagram-UZGBJVZJ-Decs2Rps.js → requirementDiagram-UZGBJVZJ-yH30jAOj.js} +1 -1
  55. package/dist/studio/assets/{sankeyDiagram-TZEHDZUN-CXQHF2nL.js → sankeyDiagram-TZEHDZUN-BlEt27YS.js} +1 -1
  56. package/dist/studio/assets/{sequenceDiagram-WL72ISMW-C9cFuo_6.js → sequenceDiagram-WL72ISMW-CT2uLY3i.js} +1 -1
  57. package/dist/studio/assets/{stateDiagram-FKZM4ZOC-Dvs2TeCM.js → stateDiagram-FKZM4ZOC-DuMW3t9Q.js} +1 -1
  58. package/dist/studio/assets/stateDiagram-v2-4FDKWEC3-DjR-lF7e.js +1 -0
  59. package/dist/studio/assets/{timeline-definition-IT6M3QCI-BpsJlgf7.js → timeline-definition-IT6M3QCI-BGETR7lR.js} +1 -1
  60. package/dist/studio/assets/{treemap-GDKQZRPO-DVxRTPr1.js → treemap-GDKQZRPO-BO8oqrvF.js} +1 -1
  61. package/dist/studio/assets/{xychartDiagram-PRI3JC2R-QUfHK5a4.js → xychartDiagram-PRI3JC2R-DJ-F4Odf.js} +1 -1
  62. package/dist/studio/index.html +1 -1
  63. package/global/rules/global.md +2 -0
  64. package/package.json +1 -1
  65. package/dist/studio/assets/channel-h6J62PW8.js +0 -1
  66. package/dist/studio/assets/classDiagram-2ON5EDUG-D8lIj2-P.js +0 -1
  67. package/dist/studio/assets/classDiagram-v2-WZHVMYZB-D8lIj2-P.js +0 -1
  68. package/dist/studio/assets/clone-Chwjzlof.js +0 -1
  69. package/dist/studio/assets/stateDiagram-v2-4FDKWEC3-NKg7XNVy.js +0 -1
@@ -17,7 +17,7 @@ When asked who you are: "I am the Claudius manager. I route work, coordinate age
17
17
  2. Decide solo (XS/S) vs team (M+) based on scope
18
18
  3. Create feature branch from main — **unless already in a worktree** (see Branch Convention)
19
19
  4. For solo: implement directly with TDD
20
- 5. For team: spawn developer via Agent tool, then simplifier (best-effort), then reviewer
20
+ 5. For team: spawn developer via Agent tool, then reviewer
21
21
  6. **Validate before PR** — `bun test && bun run lint && bun run build` must all pass. Fix failures before creating PR. Never create a PR with known lint or build failures.
22
22
  7. Create PR
23
23
  8. Update issue checkboxes as criteria are met
@@ -43,19 +43,9 @@ Use the Agent tool with `subagent_type: "developer"`. Include in the prompt:
43
43
  - The constraint: only implement what's asked, no scope creep
44
44
  - **Reminder: developer must run `bun test`, `bun run lint`, and `bun run build` before pushing**
45
45
 
46
- The developer runs in an isolated worktree, implements via TDD, validates (test + lint + build), and returns its output. After it completes, verify the developer reported all three validations passing, then spawn the simplifier (best-effort), then create the PR: `gh pr create`. Only spawn the reviewer after the PR exists.
46
+ The developer runs in an isolated worktree, implements via TDD, validates (test + lint + build), and returns its output. After it completes, verify the developer reported all three validations passing, then create the PR: `gh pr create`.
47
47
 
48
- **Simplifier** (for M+ work, after developer completes and before reviewer):
49
- Use the Agent tool with `subagent_type: "general-purpose"` and `agent: "code-simplifier"`. Include in the prompt:
50
- - The git diff of all changes so far: output of `git diff main...HEAD`
51
- - The original issue acceptance criteria
52
- - Project conventions: contents of CLAUDE.md
53
- - Instruction: reduce complexity, improve reuse, fix quality issues — without changing behavior or adding new features
54
- - Constraint: only touch files already changed on this branch (visible in the diff above)
55
-
56
- The simplifier is **non-blocking**: if it returns no changes, errors, or is unavailable, log the outcome and continue to the reviewer. Never let the simplifier halt the pipeline.
57
-
58
- **Reviewer** (for M+ work, after simplifier completes and PR is created):
48
+ **Reviewer** (for M+ work, after PR is created):
59
49
  Use the Agent tool with `subagent_type: "reviewer"`. Include in the prompt:
60
50
  - The PR number to review
61
51
  - Return structured verdict: approve / request-changes / block
@@ -41,7 +41,6 @@ gh pr list --search "Closes #<N> in:body" --state open --json number --limit 1
41
41
  If no open PR found → stale claim → restore to ready:
42
42
  ```bash
43
43
  gh issue edit <N> --remove-label "in-progress,claude" --add-label "ready"
44
- bash .claude/scripts/project-status.sh <N> "Todo" "Queued"
45
44
  ```
46
45
 
47
46
  ## Guard Checks
@@ -63,26 +62,11 @@ tail -20 .claudius/job-runs.jsonl
63
62
  Before picking new work, merge any open XS/S/M PRs with passing CI:
64
63
 
65
64
  ```bash
66
- gh pr list --json number,title,headRefName,statusCheckRollup,mergeable --limit 20
65
+ gh pr list --json number,title,headRefName,statusCheckRollup --limit 20
66
+ bash .claude/scripts/merge-pr.sh <N>
67
+ gh issue close <issue-N> --comment "Closed by PR #<N>."
67
68
  ```
68
69
 
69
- For each PR with all checks passing:
70
- 1. **Check mergeability** — if `mergeable` is `CONFLICTING`, try rebasing first:
71
- ```bash
72
- gh pr view <N> --json mergeable --jq '.mergeable'
73
- # If CONFLICTING → attempt rebase:
74
- git fetch origin main
75
- git checkout <branch>
76
- git rebase origin/main
77
- git push --force-with-lease
78
- # If rebase fails: skip this PR, leave for human or next cycle
79
- ```
80
- 2. **Merge** — only if mergeable:
81
- ```bash
82
- bash .claude/scripts/merge-pr.sh <N>
83
- gh issue close <issue-N> --comment "Closed by PR #<N>."
84
- ```
85
-
86
70
  ## Step 2: Pick Top-3 Issues
87
71
 
88
72
  ```bash
@@ -100,9 +84,24 @@ Issues are filtered and scored with dependency awareness:
100
84
  - **Codex issues excluded** — any issue with the `codex` label is skipped entirely
101
85
  - **Blocked issues excluded** — any issue with open `blocked-by` relationships is removed from
102
86
  candidates
87
+ - **Recent PR guard** — any issue that already had a PR created in the last 6 hours is skipped,
88
+ even if the PR was closed. This prevents duplicate PRs from retry storms.
103
89
  - **Cluster momentum** — issues in partially-complete clusters get +15 priority boost
104
90
  - **Standard scoring** — label priorities, scope size, goal alignment
105
91
 
92
+ **Check for recent PRs before claiming** — skip issues that already have PRs (open or recently closed):
93
+ ```bash
94
+ for CANDIDATE in <issue-numbers>; do
95
+ RECENT_PR=$(gh pr list --repo "$(gh repo view --json nameWithOwner --jq '.nameWithOwner')" \
96
+ --search "Closes #$CANDIDATE in:body" --state all --json number,createdAt,state \
97
+ --jq "[.[] | select((.createdAt | fromdateiso8601) > (now - 21600))] | length" 2>/dev/null)
98
+ if [ "${RECENT_PR:-0}" -gt "0" ]; then
99
+ echo "Skipping #$CANDIDATE — PR created in last 6 hours"
100
+ continue
101
+ fi
102
+ done
103
+ ```
104
+
106
105
  **Check attempt count before claiming** — read the existing workpad (if any) to get prior attempt count. If at max, move to Blocked instead of claiming:
107
106
 
108
107
  ```bash
@@ -113,7 +112,13 @@ PRIOR_ATTEMPTS=$(gh issue view <N> --json comments \
113
112
  if [ "${PRIOR_ATTEMPTS:-0}" -ge "$MAX_ATTEMPTS" ]; then
114
113
  gh issue edit <N> --remove-label "ready" --add-label "blocked"
115
114
  gh issue comment <N> --body "Claudius: exceeded ${MAX_ATTEMPTS} build attempts. Needs human review before retrying."
116
- bash .claude/scripts/project-status.sh <N> "Blocked" "Blocked"
115
+ REPO_NAME=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
116
+ ITEM_ID=$(gh api graphql -f query='{user(login:"SharadKumar"){projectV2(number:6){items(first:100){nodes{id content{...on Issue{number repository{nameWithOwner}}}}}}}}' \
117
+ --jq ".data.user.projectV2.items.nodes[] | select(.content.number == <N> and .content.repository.nameWithOwner == \"$REPO_NAME\") | .id" 2>/dev/null | head -1)
118
+ [ -n "$ITEM_ID" ] && gh project item-edit --id "$ITEM_ID" \
119
+ --project-id "PVT_kwHOAFO-EM4BRTW5" \
120
+ --field-id "PVTSSF_lAHOAFO-EM4BRTW5zg_K3tE" \
121
+ --single-select-option-id "d239ddb3" 2>/dev/null || true
117
122
  # skip this issue — continue to next candidate
118
123
  fi
119
124
  ```
@@ -133,13 +138,26 @@ NEW_ATTEMPTS=$(( ${PRIOR_ATTEMPTS:-0} + 1 ))
133
138
  bash .claude/scripts/workpad-upsert.sh <N> "🔄 Claimed — reading issue" "TBD" "- [ ] (loading)" "pending" "$NEW_ATTEMPTS"
134
139
  ```
135
140
 
136
- **Update Project #6 → In Progress / Running** (best-effort):
141
+ **Update Project #6 Status → In Progress** add to project if needed, then set status:
142
+
137
143
  ```bash
138
- bash .claude/scripts/project-status.sh <N> "In Progress" "Running"
144
+ ISSUE_URL=$(gh issue view <N> --json url --jq '.url')
145
+ REPO_NAME=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
146
+ gh project item-add 6 --owner SharadKumar --url "$ISSUE_URL" 2>/dev/null || true
147
+ ITEM_ID=$(gh api graphql -f query='{user(login:"SharadKumar"){projectV2(number:6){items(first:100){nodes{id content{...on Issue{number repository{nameWithOwner}}}}}}}}' \
148
+ --jq ".data.user.projectV2.items.nodes[] | select(.content.number == <N> and .content.repository.nameWithOwner == \"$REPO_NAME\") | .id" 2>/dev/null | head -1)
149
+ [ -n "$ITEM_ID" ] && gh project item-edit --id "$ITEM_ID" \
150
+ --project-id "PVT_kwHOAFO-EM4BRTW5" \
151
+ --field-id "PVTSSF_lAHOAFO-EM4BRTW5zg_K3tE" \
152
+ --single-select-option-id "0d583361" 2>/dev/null || true
139
153
  ```
140
154
 
141
155
  ## Step 3: Develop in Parallel
142
156
 
157
+ **CRITICAL: One issue = one developer = one PR.** Never combine multiple issues into a single
158
+ developer agent or a single PR. Each issue gets its own isolated developer in its own worktree.
159
+ Violating this causes review failures, duplicate PRs, and retry storms.
160
+
143
161
  Each developer runs in its own isolated worktree. Do NOT derive or provide branch names.
144
162
 
145
163
  **Read agent config** from `.claudius/config.yaml` (default: `claude`):
@@ -153,11 +171,12 @@ process.stdout.write(c.agent?.command ?? 'claude');
153
171
  ```
154
172
 
155
173
  **If `AGENT_COMMAND = "claude"` (default):**
156
- Spawn one developer agent per issue using the `Agent` tool **concurrently**
174
+ Spawn **exactly one** developer agent per issue using the `Agent` tool **concurrently**
157
175
  (all in one tool call message), using `subagent_type: "developer"`.
176
+ Each agent handles ONE issue only — never pass multiple issues to the same agent.
158
177
 
159
178
  **If `AGENT_COMMAND = "codex"`:**
160
- Spawn via Bash: `codex -p --model <agent.model> <agent.flags> "<prompt>" &` per issue.
179
+ Spawn via Bash: `codex -p --model <agent.model> <agent.flags> "<prompt>" &` — one per issue.
161
180
 
162
181
  For each issue, each developer prompt must include:
163
182
  - Full issue body and all acceptance criteria
@@ -178,7 +197,6 @@ Wait for all developer agents to complete before proceeding.
178
197
  ```bash
179
198
  gh issue edit <N> --remove-label "in-progress,claude" --add-label "ready"
180
199
  gh issue comment <N> --body "Worker: developer failed. Restored to ready queue."
181
- bash .claude/scripts/project-status.sh <N> "Todo" "Queued"
182
200
  ```
183
201
  Remove it from the active set and continue with the rest.
184
202
 
@@ -246,9 +264,15 @@ if [ -n "$SLACK_CHANNEL" ]; then
246
264
  fi
247
265
  ```
248
266
 
249
- **Update Project #6 → Under Review / Review** (best-effort):
267
+ **Update Project #6 Status → Under Review** (best-effort):
250
268
  ```bash
251
- bash .claude/scripts/project-status.sh <N> "Under Review" "Review"
269
+ REPO_NAME=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
270
+ ITEM_ID=$(gh api graphql -f query='{user(login:"SharadKumar"){projectV2(number:6){items(first:100){nodes{id content{...on Issue{number repository{nameWithOwner}}}}}}}}' \
271
+ --jq ".data.user.projectV2.items.nodes[] | select(.content.number == <N> and .content.repository.nameWithOwner == \"$REPO_NAME\") | .id" 2>/dev/null | head -1)
272
+ [ -n "$ITEM_ID" ] && gh project item-edit --id "$ITEM_ID" \
273
+ --project-id "PVT_kwHOAFO-EM4BRTW5" \
274
+ --field-id "PVTSSF_lAHOAFO-EM4BRTW5zg_K3tE" \
275
+ --single-select-option-id "173633ca" 2>/dev/null || true
252
276
  ```
253
277
 
254
278
  ## Step 5: Review in Parallel
@@ -272,7 +296,17 @@ Wait for all reviewer agents to complete.
272
296
  ```bash
273
297
  gh issue edit <N> --remove-label "in-progress,claude" --add-label "ready"
274
298
  gh issue comment <N> --body "Worker: reviewer blocked. Reason: <reason>."
275
- bash .claude/scripts/project-status.sh <N> "Todo" "Queued"
299
+ ```
300
+
301
+ **Update Project #6 Status → Blocked** (best-effort):
302
+ ```bash
303
+ REPO_NAME=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
304
+ ITEM_ID=$(gh api graphql -f query='{user(login:"SharadKumar"){projectV2(number:6){items(first:100){nodes{id content{...on Issue{number repository{nameWithOwner}}}}}}}}' \
305
+ --jq ".data.user.projectV2.items.nodes[] | select(.content.number == <N> and .content.repository.nameWithOwner == \"$REPO_NAME\") | .id" 2>/dev/null | head -1)
306
+ [ -n "$ITEM_ID" ] && gh project item-edit --id "$ITEM_ID" \
307
+ --project-id "PVT_kwHOAFO-EM4BRTW5" \
308
+ --field-id "PVTSSF_lAHOAFO-EM4BRTW5zg_K3tE" \
309
+ --single-select-option-id "d239ddb3" 2>/dev/null || true
276
310
  ```
277
311
 
278
312
  ## Step 6: Merge & Record
@@ -283,7 +317,16 @@ bash .claude/scripts/merge-pr.sh <PR-number>
283
317
  gh issue close <N> --comment "Closed by PR #<M>."
284
318
  ```
285
319
 
286
- Closing the issue removes it from the active Project #6 board no explicit "Done" status needed.
320
+ **Update Project #6 Status Done** (best-effort):
321
+ ```bash
322
+ REPO_NAME=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
323
+ ITEM_ID=$(gh api graphql -f query='{user(login:"SharadKumar"){projectV2(number:6){items(first:100){nodes{id content{...on Issue{number repository{nameWithOwner}}}}}}}}' \
324
+ --jq ".data.user.projectV2.items.nodes[] | select(.content.number == <N> and .content.repository.nameWithOwner == \"$REPO_NAME\") | .id" 2>/dev/null | head -1)
325
+ [ -n "$ITEM_ID" ] && gh project item-edit --id "$ITEM_ID" \
326
+ --project-id "PVT_kwHOAFO-EM4BRTW5" \
327
+ --field-id "PVTSSF_lAHOAFO-EM4BRTW5zg_K3tE" \
328
+ --single-select-option-id "b60a81d0" 2>/dev/null || true
329
+ ```
287
330
 
288
331
  After each merge, reply in the PR's Slack thread (best-effort):
289
332
  ```bash
@@ -25,17 +25,20 @@ Every change that can be tested locally MUST be tested locally before committing
25
25
 
26
26
  ### dist/ freshness
27
27
 
28
- `dist/` is gitignored and built at install time via the `prepare` script. Do NOT commit `dist/` it is a build artifact.
28
+ `dist/` is committed to the repo. The `prepare` script skips building when `dist/` already exists. This means stale `dist/` = users run old code.
29
29
 
30
- **After changing any `src/` file, always verify the build succeeds:**
30
+ **After changing any `src/` file, always rebuild and commit dist/:**
31
31
  ```bash
32
- bun run build
32
+ bun run build:server
33
+ git add dist/
33
34
  ```
34
35
 
36
+ If you forget, `npx github:SharadKumar/claudius` will silently run old code — the most dangerous kind of bug.
37
+
35
38
  ### Anti-patterns
36
39
 
37
40
  - Committing install commands without testing them in the target environment
38
41
  - Assuming package managers behave identically (they don't — especially for private repos, workspaces, lockfiles)
39
42
  - Shipping a fix for a fix for a fix instead of reverting and getting it right once
40
43
  - Trusting `bun run build` as sufficient validation when the change is user-facing
41
- - Committing `dist/` it is gitignored and built at install time
44
+ - Changing `src/` without rebuilding and committing `dist/`
@@ -1,14 +1,16 @@
1
1
  #!/usr/bin/env bash
2
- # merge-pr.sh — API-only PR merge. Never touches local branches.
2
+ # merge-pr.sh — Robust PR merge that works regardless of CWD or worktree state.
3
3
  #
4
4
  # Usage: bash .claude/scripts/merge-pr.sh <PR-number>
5
5
  #
6
- # Principle: Merging is a GitHub operation. This script never runs
7
- # `git checkout`, never switches branches, never mutates local state.
8
- # Safe to call from any context: main checkout, worktree, subdirectory,
9
- # multiple concurrent tabsno interference possible.
6
+ # Behavior:
7
+ # 1. Resolve the main repo root via git-common-dir (CWD-agnostic)
8
+ # 2. cd to main root before any git/gh operations
9
+ # 3. Try gh pr merge (happy path works when main is not checked out elsewhere)
10
+ # 4. On failure, fall back to GitHub API merge + remote branch deletion
11
+ # 5. Sync home branch inline (no external script dependency)
10
12
  #
11
- # Exit codes: 0 = merged, 1 = merge failed
13
+ # Exit codes: 0 = merged + synced, 1 = merge failed, 2 = sync failed
12
14
 
13
15
  set -euo pipefail
14
16
 
@@ -18,31 +20,60 @@ if [[ -z "$PR" ]]; then
18
20
  exit 1
19
21
  fi
20
22
 
23
+ # Resolve main repo root — works from any CWD (worktree, subdir, main checkout)
24
+ GIT_COMMON_DIR=$(git rev-parse --git-common-dir 2>/dev/null)
25
+ MAIN_ROOT=$(cd "$(git rev-parse --show-toplevel)" && cd "$(git rev-parse --git-common-dir)/.." && pwd)
26
+
27
+ cd "$MAIN_ROOT"
28
+
29
+ # Get branch name before merging (needed for API fallback cleanup)
21
30
  BRANCH=$(gh pr view "$PR" --json headRefName --jq '.headRefName' 2>/dev/null)
22
31
  REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner' 2>/dev/null)
23
- TITLE=$(gh pr view "$PR" --json title --jq '.title')
24
32
 
25
33
  echo "Merging PR #$PR ($BRANCH) in $REPO..."
26
34
 
27
- # Merge via GitHub API zero local git operations
28
- gh api "repos/$REPO/pulls/$PR/merge" \
29
- -X PUT \
30
- -f merge_method=squash \
31
- -f commit_title="$TITLE" \
32
- --silent
35
+ # Happy path: gh pr merge handles everything locally
36
+ if gh pr merge "$PR" --squash --delete-branch 2>/dev/null; then
37
+ echo "Merged via gh pr merge."
38
+ else
39
+ echo "gh pr merge failed (likely worktree conflict) — falling back to API merge..."
40
+
41
+ # API merge
42
+ TITLE=$(gh pr view "$PR" --json title --jq '.title')
43
+ gh api "repos/$REPO/pulls/$PR/merge" \
44
+ -X PUT \
45
+ -f merge_method=squash \
46
+ -f commit_title="$TITLE" \
47
+ --silent
33
48
 
34
- echo "Merged PR #$PR."
49
+ echo "Merged via API."
50
+
51
+ # Delete remote branch
52
+ if git ls-remote --exit-code origin "$BRANCH" &>/dev/null; then
53
+ git push origin --delete "$BRANCH" 2>/dev/null && echo "Deleted remote branch: $BRANCH" || echo "⚠ Could not delete remote branch: $BRANCH"
54
+ fi
55
+ fi
35
56
 
36
- # Delete remote branch via API
37
- gh api "repos/$REPO/git/refs/heads/$BRANCH" -X DELETE --silent 2>/dev/null \
38
- && echo "Deleted remote branch: $BRANCH" \
39
- || echo "⚠ Could not delete remote branch: $BRANCH"
57
+ # Re-anchor to main root (gh pr merge may change CWD)
58
+ cd "$MAIN_ROOT"
40
59
 
41
- # Update remote refs locally (no branch change, no checkout)
42
- git fetch origin main 2>/dev/null || true
60
+ # Inline sync: return to home branch
61
+ # Detect if this script was invoked from a worktree context
62
+ GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
43
63
 
44
- # Clean up local branch if we're not currently on it
45
- CURRENT=$(git branch --show-current 2>/dev/null || echo "")
46
- if [[ -n "$BRANCH" ]] && [[ "$CURRENT" != "$BRANCH" ]]; then
47
- git branch -d "$BRANCH" 2>/dev/null && echo "Deleted local branch: $BRANCH" || true
64
+ if [[ "$GIT_DIR" == */.git/worktrees/* ]]; then
65
+ WORKTREE_NAME=$(basename "$GIT_DIR")
66
+ HOME_BRANCH="worktree-$WORKTREE_NAME"
67
+ git checkout "$HOME_BRANCH" 2>/dev/null || true
68
+ echo "Returned to home branch: $HOME_BRANCH"
69
+ else
70
+ # Root repo — return to main and sync
71
+ git checkout main 2>/dev/null || true
72
+ if git pull --ff-only origin main 2>/dev/null; then
73
+ echo "main synced to latest."
74
+ else
75
+ echo "⚠ main has diverged from origin/main — fast-forward not possible."
76
+ echo " Resolve manually: git fetch origin && git rebase origin/main"
77
+ exit 2
78
+ fi
48
79
  fi
@@ -22,19 +22,19 @@ EXECUTION_FIELD="PVTSSF_lAHOAFO-EM4BRTW5zg_Lokk"
22
22
 
23
23
  # Resolve Status option ID
24
24
  case "$STATUS" in
25
- "Todo") STATUS_OPT="6ed537f9" ;;
26
- "In Progress") STATUS_OPT="0d583361" ;;
27
- "Under Review") STATUS_OPT="173633ca" ;;
28
- "Blocked") STATUS_OPT="d239ddb3" ;;
25
+ "Todo") STATUS_OPT="59debf59" ;;
26
+ "In Progress") STATUS_OPT="6e8991c5" ;;
27
+ "Under Review") STATUS_OPT="a6a6dc32" ;;
28
+ "Blocked") STATUS_OPT="f77fb75d" ;;
29
29
  *) echo "[project-status] Unknown status: $STATUS" >&2; exit 1 ;;
30
30
  esac
31
31
 
32
32
  # Resolve Execution option ID
33
33
  case "$EXECUTION" in
34
- "Queued") EXECUTION_OPT="f00eea4e" ;;
35
- "Running") EXECUTION_OPT="14585208" ;;
36
- "Review") EXECUTION_OPT="8e0939cc" ;;
37
- "Blocked") EXECUTION_OPT="65e212b0" ;;
34
+ "Queued") EXECUTION_OPT="b2b4bd91" ;;
35
+ "Running") EXECUTION_OPT="e632d881" ;;
36
+ "Review") EXECUTION_OPT="4098f421" ;;
37
+ "Blocked") EXECUTION_OPT="70bc5d52" ;;
38
38
  *) echo "[project-status] Unknown execution: $EXECUTION" >&2; exit 1 ;;
39
39
  esac
40
40
 
@@ -105,23 +105,9 @@ Also read: `.claudius/design/tokens.css` for token values, `.claudius/design/com
105
105
  1. Write failing test from first acceptance criterion
106
106
  2. Implement until test passes
107
107
  3. Repeat for each AC
108
- 4. Invoke `/simplify` on the changed files to reduce complexity before validating (best-effort: if it returns no changes or errors, log and continue)
109
- 5. Run full suite: `bun test`
110
-
111
- **Team (M+ — >2 files, >100 lines):** Use the Agent tool to spawn developer, simplifier, and reviewer agents in sequence.
112
-
113
- 1. **Spawn builder** — developer agent implements the issue with TDD (full cycle: failing tests → implementation → passing tests)
114
- 2. **Spawn simplifier** — after builder completes, spawn the `code-simplifier` agent (best-effort: if it returns no changes or errors, log and continue to reviewer):
115
- ```
116
- Agent tool, subagent_type: general-purpose, agent: code-simplifier
117
- Prompt:
118
- <git diff of all changes: `git diff main...HEAD`>
119
- <original issue ACs>
120
- Project conventions: see CLAUDE.md
121
- Task: Reduce complexity, improve reuse, fix quality issues — without changing behavior or adding new features.
122
- Constraint: Only touch files already changed on this branch (visible in the diff above).
123
- ```
124
- 3. **Spawn reviewer** — reviewer agent runs quality gate after simplifier completes (or after simplifier is skipped due to error)
108
+ 4. Run full suite: `bun test`
109
+
110
+ **Team (M+ — >2 files, >100 lines):** Use the Agent tool to spawn developer and reviewer agents.
125
111
 
126
112
  ### 5. Validate
127
113
 
@@ -21,10 +21,10 @@
21
21
  "name": "claudius",
22
22
  "source": "./",
23
23
  "description": "Autonomous orchestration layer for Claude Code — agents, skills, hooks, and heartbeat daemon for round-the-clock development",
24
- "version": "0.9.3",
24
+ "version": "0.9.6",
25
25
  "strict": true,
26
26
  "category": "development"
27
27
  }
28
28
  ],
29
- "version": "0.9.3"
29
+ "version": "0.9.6"
30
30
  }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Generic local store — Convex-ready interface.
3
+ *
4
+ * Interface mirrors Convex query/mutation shape:
5
+ * - namespace = table name
6
+ * - key = document id
7
+ *
8
+ * Backed by `.claudius/db.json` with atomic writes (tmp + rename) so the
9
+ * file is always valid JSON even if the process is killed mid-write.
10
+ *
11
+ * Swap path: replace `createDb` with a Convex adapter that implements the
12
+ * same `Db` interface — callers don't change.
13
+ */
14
+ /** Convex-compatible store interface. */
15
+ export interface Db {
16
+ /** Read a document by namespace (table) and key (doc id). */
17
+ get<T = unknown>(namespace: string, key: string): T | undefined;
18
+ /** Write a document. Overwrites if it already exists. */
19
+ set(namespace: string, key: string, value: unknown): void;
20
+ /** Delete a document. No-op if it doesn't exist. */
21
+ del(namespace: string, key: string): void;
22
+ }
23
+ /**
24
+ * Create a `Db` instance scoped to `projectDir`.
25
+ *
26
+ * @param projectDir - root of the project (where `.claudius/` lives).
27
+ * Defaults to `"."` (current working directory).
28
+ */
29
+ export declare function createDb(projectDir?: string): Db;
30
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/lib/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,yCAAyC;AACzC,MAAM,WAAW,EAAE;IAClB,6DAA6D;IAC7D,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;IAChE,yDAAyD;IACzD,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1D,oDAAoD;IACpD,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAiCD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,UAAU,SAAM,GAAG,EAAE,CAqB7C"}
package/dist/lib/db.js ADDED
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Generic local store — Convex-ready interface.
3
+ *
4
+ * Interface mirrors Convex query/mutation shape:
5
+ * - namespace = table name
6
+ * - key = document id
7
+ *
8
+ * Backed by `.claudius/db.json` with atomic writes (tmp + rename) so the
9
+ * file is always valid JSON even if the process is killed mid-write.
10
+ *
11
+ * Swap path: replace `createDb` with a Convex adapter that implements the
12
+ * same `Db` interface — callers don't change.
13
+ */
14
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
15
+ import { dirname, resolve } from "node:path";
16
+ const DB_FILENAME = ".claudius/db.json";
17
+ function dbPath(projectDir) {
18
+ return resolve(projectDir, DB_FILENAME);
19
+ }
20
+ function read(projectDir) {
21
+ const path = dbPath(projectDir);
22
+ if (!existsSync(path))
23
+ return {};
24
+ try {
25
+ return JSON.parse(readFileSync(path, "utf-8"));
26
+ }
27
+ catch {
28
+ return {};
29
+ }
30
+ }
31
+ function write(projectDir, store) {
32
+ const path = dbPath(projectDir);
33
+ const dir = dirname(path);
34
+ if (!existsSync(dir)) {
35
+ mkdirSync(dir, { recursive: true });
36
+ }
37
+ // Atomic write: write to tmp then rename.
38
+ // pid + random suffix prevents collisions under concurrent writes.
39
+ const tmp = `${path}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`;
40
+ writeFileSync(tmp, JSON.stringify(store, null, 2));
41
+ renameSync(tmp, path);
42
+ }
43
+ /**
44
+ * Create a `Db` instance scoped to `projectDir`.
45
+ *
46
+ * @param projectDir - root of the project (where `.claudius/` lives).
47
+ * Defaults to `"."` (current working directory).
48
+ */
49
+ export function createDb(projectDir = ".") {
50
+ return {
51
+ get(namespace, key) {
52
+ const store = read(projectDir);
53
+ return store[namespace]?.[key] ?? undefined;
54
+ },
55
+ set(namespace, key, value) {
56
+ const store = read(projectDir);
57
+ if (!store[namespace])
58
+ store[namespace] = {};
59
+ store[namespace][key] = value;
60
+ write(projectDir, store);
61
+ },
62
+ del(namespace, key) {
63
+ const store = read(projectDir);
64
+ if (!store[namespace])
65
+ return;
66
+ delete store[namespace][key];
67
+ write(projectDir, store);
68
+ },
69
+ };
70
+ }
71
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/lib/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAc7C,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAExC,SAAS,MAAM,CAAC,UAAkB;IACjC,OAAO,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,IAAI,CAAC,UAAkB;IAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAU,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;AACF,CAAC;AAED,SAAS,KAAK,CAAC,UAAkB,EAAE,KAAY;IAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,0CAA0C;IAC1C,mEAAmE;IACnE,MAAM,GAAG,GAAG,GAAG,IAAI,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAChF,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACnD,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,UAAU,GAAG,GAAG;IACxC,OAAO;QACN,GAAG,CAAc,SAAiB,EAAE,GAAW;YAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,OAAQ,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAO,IAAI,SAAS,CAAC;QACpD,CAAC;QAED,GAAG,CAAC,SAAiB,EAAE,GAAW,EAAE,KAAc;YACjD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;gBAAE,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;YAC7C,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC9B,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC;QAED,GAAG,CAAC,SAAiB,EAAE,GAAW;YACjC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;gBAAE,OAAO;YAC9B,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC;YAC7B,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Slack PR notification layer.
3
+ *
4
+ * Announces PRs as channel messages and routes all follow-up activity
5
+ * (approvals, merges, CI failures) as thread replies on the original post.
6
+ *
7
+ * Thread timestamps are persisted via the `Db` store under the
8
+ * `slack_threads` namespace so they survive process restarts.
9
+ *
10
+ * Environment variables:
11
+ * SLACK_BOT_TOKEN — required; xoxb-… bot token
12
+ * SLACK_CHANNEL — required; channel ID (C123…) or name
13
+ */
14
+ import type { Db } from "./db.js";
15
+ export interface SlackNotifier {
16
+ /**
17
+ * Post a new channel message announcing PR creation.
18
+ * Stores the message timestamp in db for thread replies.
19
+ */
20
+ postPR(prNumber: number, title: string, url: string): Promise<void>;
21
+ /**
22
+ * Reply to the original PR announcement thread.
23
+ * No-ops if no thread is found in db or if Slack is unconfigured.
24
+ */
25
+ replyPR(prNumber: number, text: string): Promise<void>;
26
+ }
27
+ /**
28
+ * Create a `SlackNotifier` backed by the given `Db` instance.
29
+ *
30
+ * @param db - db instance for persisting thread timestamps.
31
+ */
32
+ export declare function createSlack(db: Db): SlackNotifier;
33
+ //# sourceMappingURL=slack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../../src/lib/slack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AA4ClC,MAAM,WAAW,aAAa;IAC7B;;;OAGG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpE;;;OAGG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,aAAa,CA+BjD"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Slack PR notification layer.
3
+ *
4
+ * Announces PRs as channel messages and routes all follow-up activity
5
+ * (approvals, merges, CI failures) as thread replies on the original post.
6
+ *
7
+ * Thread timestamps are persisted via the `Db` store under the
8
+ * `slack_threads` namespace so they survive process restarts.
9
+ *
10
+ * Environment variables:
11
+ * SLACK_BOT_TOKEN — required; xoxb-… bot token
12
+ * SLACK_CHANNEL — required; channel ID (C123…) or name
13
+ */
14
+ const SLACK_API = "https://slack.com/api/chat.postMessage";
15
+ const NAMESPACE = "slack_threads";
16
+ function getConfig() {
17
+ const token = process.env.SLACK_BOT_TOKEN;
18
+ const channel = process.env.SLACK_CHANNEL;
19
+ if (!token || !channel)
20
+ return null;
21
+ return { token, channel };
22
+ }
23
+ async function post(token, channel, text, threadTs) {
24
+ const body = { channel, text };
25
+ if (threadTs)
26
+ body.thread_ts = threadTs;
27
+ const response = await fetch(SLACK_API, {
28
+ method: "POST",
29
+ headers: {
30
+ "Content-Type": "application/json",
31
+ Authorization: `Bearer ${token}`,
32
+ },
33
+ body: JSON.stringify(body),
34
+ });
35
+ if (!response.ok) {
36
+ console.warn(`[slack] HTTP ${response.status} from Slack API`);
37
+ return { ok: false, error: `http_${response.status}` };
38
+ }
39
+ return response.json();
40
+ }
41
+ /**
42
+ * Create a `SlackNotifier` backed by the given `Db` instance.
43
+ *
44
+ * @param db - db instance for persisting thread timestamps.
45
+ */
46
+ export function createSlack(db) {
47
+ return {
48
+ async postPR(prNumber, title, url) {
49
+ const cfg = getConfig();
50
+ if (!cfg)
51
+ return;
52
+ const text = `\u{1F500} PR #${prNumber}: ${title}\n${url}`;
53
+ try {
54
+ const res = await post(cfg.token, cfg.channel, text);
55
+ if (res.ok && res.ts) {
56
+ db.set(NAMESPACE, String(prNumber), res.ts);
57
+ }
58
+ }
59
+ catch (err) {
60
+ console.warn(`[slack] postPR failed for PR #${prNumber}:`, err);
61
+ }
62
+ },
63
+ async replyPR(prNumber, text) {
64
+ const cfg = getConfig();
65
+ if (!cfg)
66
+ return;
67
+ const threadTs = db.get(NAMESPACE, String(prNumber));
68
+ if (!threadTs)
69
+ return;
70
+ try {
71
+ await post(cfg.token, cfg.channel, text, threadTs);
72
+ }
73
+ catch (err) {
74
+ console.warn(`[slack] replyPR failed for PR #${prNumber}:`, err);
75
+ }
76
+ },
77
+ };
78
+ }
79
+ //# sourceMappingURL=slack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.js","sourceRoot":"","sources":["../../src/lib/slack.ts"],"names":[],"mappings":"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"}