Conversation
Co-Authored-By: Claude Opus 4.5 <[email protected]>
stack72
reviewed
Jan 28, 2026
|
|
||
| ## License | ||
|
|
||
| MIT |
This was referenced Mar 3, 2026
This was referenced Mar 8, 2026
This was referenced Mar 10, 2026
stack72
added a commit
that referenced
this pull request
Mar 17, 2026
… bundling failure - Move bundleSourceFactory call inside the non-raw driver branch so raw executions never trigger self-contained bundling (HIGH #2) - Switch to promise-based memoization to avoid duplicate concurrent builds - Restore error handling: log a warning and rethrow on bundling failure, resetting the cached promise so subsequent calls can retry (HIGH #1) Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
5 tasks
stack72
added a commit
that referenced
this pull request
Mar 19, 2026
Agents now see "search before you build" as Rule #1 in every swamp-managed CLAUDE.md, prompting them to check local types and community extensions before creating custom models. Previously this guidance only appeared in the swamp-extension-model skill, which agents loaded too late — after already deciding to build from scratch. Closes #757 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
stack72
added a commit
that referenced
this pull request
Mar 19, 2026
Agents now see "search before you build" as Rule #1 in every swamp-managed CLAUDE.md, prompting them to check local types and community extensions before creating custom models. Previously this guidance only appeared in the swamp-extension-model skill, which agents loaded too late — after already deciding to build from scratch. Closes #757 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> fix: use correct command `swamp extension pull` instead of `resolve` Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
6 tasks
stack72
added a commit
that referenced
this pull request
Mar 19, 2026
Agents now see "search before you build" as Rule #1 in every swamp-managed CLAUDE.md, prompting them to check local types and community extensions before creating custom models. Previously this guidance only appeared in the swamp-extension-model skill, which agents loaded too late — after already deciding to build from scratch. Closes #757 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> fix: use correct command `swamp extension pull` instead of `resolve` Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
stack72
added a commit
that referenced
this pull request
Mar 19, 2026
feat: search community extensions before creating custom models ## Summary - Rewrites Rule #1 in the CLAUDE.md template from "Extension models for service integrations" to **"Search before you build"**, with explicit steps: search local types → search community extensions (`swamp extension pull`) → install if found → only then create custom - Adds a community search step to the `swamp-model` skill workflow - Adds Scenario 5 ("Community Extension Found") to the `swamp-extension-model` skill showing the happy path where a community extension exists ## User Impact Previously, agents only saw guidance to "create an extension model" in the CLAUDE.md Rules section. The `swamp-extension-model` skill documented the search-first flow, but agents only loaded that skill *after* deciding to create a model — too late. Now agents see the search-first guidance immediately in Rule #1, prompting them to run `swamp extension search` before building anything custom. ## Test Plan - [x] New unit test: `RepoService.init generates CLAUDE.md with extension search guidance` — asserts generated CLAUDE.md contains `extension search`, `Search before you build`, and `swamp model type search` - [x] All 78 repo service tests pass - [x] Full test suite passes - [x] `deno check`, `deno lint`, `deno fmt` all pass - [x] `deno run compile` — binary recompiled - [x] **Manual verification**: Asked an agent to "create me a model that I can use to create an aws ec2 instance" — the agent correctly ran `swamp model type search "ec2"` followed by `swamp extension search "ec2 instance"` before attempting to create anything, then found a community extension and used `swamp extension pull` to install it Closes #757 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
This was referenced Mar 22, 2026
This was referenced Mar 27, 2026
This was referenced Mar 30, 2026
9 tasks
johnrwatson
pushed a commit
that referenced
this pull request
Apr 7, 2026
## Summary Adds a GitHub Action that auto-moves every new issue filed against `systeminit/swamp` into the swamp.club lab, posts a comment on the GitHub issue linking to the new lab home, and closes the GitHub issue. Also migrates the existing `@swamp/issue-lifecycle` extension client to the numeric lab issue id contract introduced by systeminit/swamp-club#364 and #369. ## User-visible behaviour change When anyone files an issue against `systeminit/swamp`: 1. The issue body (with an `Automoved by swampadmin from GitHub issue #<n>` footer appended) is POSTed to `https://swamp.club/api/v1/lab/issues/ensure`. 2. A comment is posted on the GitHub issue that reads: > Thank you for opening an issue. This issue is now managed in the Claude lab. > > https://swamp.club/lab/<number> 3. The GitHub issue is closed. If the swamp-club call fails for any reason, the action fails and **the GitHub issue stays open** — there is no failure mode in which we close a GitHub issue without confirming the lab counterpart exists. See "Why the close is gated" below. The previous behaviour (welcome comment + `needs-triage` label, with a maintainer skip) is removed. Every new issue gets moved unconditionally — issues filed by maintainers go through the same path as community issues, by design. ## Contract change in swamp-club#369 systeminit/swamp-club#364 introduced a sequential, human-friendly `number` on every lab issue (allocated by an atomic Mongo counter) and migrated the UI route from `/lab/{uuid}` to `/lab/{number}`. systeminit/swamp-club#369 finished the job: it collapsed `/api/v1/lab/issues/{uuid}` and `/api/v1/lab/issues/by-number/{n}` into a single `/api/v1/lab/issues/{number}` tree, so every endpoint that used to take a UUID now takes the sequential number. The internal UUID is still the Mongo foreign key (comments, events, lifecycle entries reference it) but **it never appears in a URL**. Endpoints affected, all of which this client now hits via the new shape: | Endpoint | Method | |---|---| | `/api/v1/lab/issues/{number}` | `PATCH` (used by `transitionStatus`) | | `/api/v1/lab/issues/{number}/lifecycle` | `POST` (used by `postLifecycleEntry`) | | `/api/v1/lab/issues/ensure` | `POST` (unchanged — still no path id) | This client previously cached the UUID it received from `/ensure` and interpolated it into the lifecycle/PATCH paths. After #369, those calls would 400 with `\"Invalid issue number\"` because the server-side `parseLabIssueNumberParam` validator (`^\d+$` + `Number.isSafeInteger`) rejects UUIDs. The migration in this PR is necessary to keep the issue-lifecycle integration working at all. ### Tracking issue This PR closes the client-side half of the work I tracked in systeminit/swamp-club#367, which I filed when I first noticed the contract drift. The server-side half shipped as #369 (already merged). ## Safe-integer validation rationale swamp-club#369 added a strict validator `lib/lab-issue-number-param.ts` that uses `Number.isSafeInteger` instead of `Number.isInteger`. The PR description explains why: during live testing, `Number.parseInt(\"7d03f113-80a5-...\", 10)` silently truncated a UUID to `7` and routed a request meant for one issue onto issue #7, **clobbering its title**. The strict validator catches that hazard. This client doesn't parse strings (it consumes a JSON number from `/ensure` and emits it back into a URL path), so the parseInt hazard is not directly reachable. But mirroring the server's safe-integer bound is still the right call for two reasons: 1. **Contract symmetry.** If the server ever returns a value the client would happily emit but the next request would 400 on, we'd have a confusing failure mode. Validating with the same predicate the server uses means \"if the client accepts it, the server accepts it.\" 2. **Defence against upstream contract drift.** The client previously asserted the response shape with a TypeScript `as` cast — runtime-trivial. The new code reads `data?.issue?.number` defensively (typed as `unknown`) and runs it through the same `Number.isSafeInteger` + positive check. A malformed response can no longer throw a `TypeError` before we hit our validator, and a numerically-suspicious response (NaN, Infinity, fractions, anything past 2^53-1) is rejected with a structured log line. ## Why the GitHub Action close is gated on a valid lab number The action's only safety property is: **a GitHub issue must never be closed unless its lab counterpart exists.** If we close before confirming, an issue can disappear from GitHub without ever being filed in the lab — losing the report. The flow is therefore strictly sequential and short-circuits on every error: 1. POST to `/api/v1/lab/issues/ensure`. If non-2xx → `core.setFailed(...)` and `return` (issue stays open). 2. Parse JSON. If `data.issue.number` is missing or not a safe positive integer → `core.setFailed(...)` and `return` (issue stays open). 3. Post the auto-responder comment with the lab URL. 4. **Only then** close the GitHub issue. `core.setFailed` does not stop execution by itself in `actions/github-script`, so each guard is paired with an explicit `return`. Steps 3 and 4 are unreachable unless we have a confirmed `labIssueNumber`. ## Files changed ### `.github/workflows/auto-response.yml` Repurposed end-to-end: - Removed the maintainer-permission probe and the maintainer-only skip path. - Removed the `needs-triage` label step and the welcome-comment step. - Single new step (`actions/github-script@v7`, Node 20 fetch) that: - Reads the issue title, body, and author from `context.payload.issue`. - Builds the lab body: original body + `\n\n---\nAutomoved by swampadmin from GitHub issue #<n>` footer (handles empty bodies). - POSTs to `https://swamp.club/api/v1/lab/issues/ensure` with `{ githubRepoFullName, githubIssueNumber, title, body, type: \"feature\", githubAuthorLogin }`, 15s `AbortSignal.timeout`. - Validates the response: defensive `data?.issue?.number` access, `Number.isSafeInteger`, `> 0`. Mirrors swamp-club's `parseLabIssueNumberParam`. - Posts a comment on the GitHub issue: `\"Thank you for opening an issue. This issue is now managed in the Claude lab.\\n\\nhttps://swamp.club/lab/<number>\"`. - Closes the GitHub issue via `issues.update({ state: \"closed\" })`. - Reads the API key from the repo secret `SWAMP_API_KEY` (already configured). - Trigger is unchanged: `on.issues.types: [opened]`. Permissions are unchanged: `issues: write`, `contents: read`. ### `extensions/models/_lib/swamp_club.ts` - Renamed `private issueId: string | null` → `private labIssueNumber: number | null`. The cached value is now the sequential lab id, not the UUID. - `ensureIssue` now returns `Promise<number | null>` (was `Promise<string | null>`). - Reads `data?.issue?.number` with `unknown` typing (was `data.issue.id` with a `{ id: string }` cast). - Validates with `typeof === \"number\"` + `Number.isSafeInteger` + positive (was a UUID regex). Mirrors swamp-club's `parseLabIssueNumberParam`. - Logs `\"swamp-club returned invalid lab issue number: {number}\"` on validation failure (was `\"...invalid issue ID...\"`). - `postLifecycleEntry` now builds `${baseUrl}/api/v1/lab/issues/${this.labIssueNumber}/lifecycle` and gates on `this.labIssueNumber === null` (was `!this.issueId`). - `transitionStatus` now builds `${baseUrl}/api/v1/lab/issues/${this.labIssueNumber}` and gates on `this.labIssueNumber === null` (was `!this.issueId`). - New public `labUrl()` helper: returns `${baseUrl}/lab/${labIssueNumber}` if the issue has been ensured, or `null` otherwise. Lets callers display the public lab URL without re-fetching anything. - Updated `createSwampClubClient` doc comment: \"The lab issue number is resolved lazily — no extra arg needed.\" (was \"The issue ID is resolved lazily — no swampClubIssueId arg needed.\") ### `extensions/models/issue_lifecycle.ts` - `ensureSwampClub`: renamed local `id` → `labIssueNumber`, replaced `if (!id)` with `if (labIssueNumber === null)`. The strict null check guards against a future `0` being misread as missing — the server validates `> 0`, so `0` is currently unreachable, but `=== null` is the right pattern for a `number | null` return type either way. - Updated the doc comment from \"the issueId cache is lost\" to \"the lab issue number cache is lost.\" - The other `ensureIssue` call site (`triage_started` lifecycle entry, line ~435) discards the return value, so no change needed. ### `extensions/models/README.md` - Added a paragraph in the \"Swamp Club Integration / How it works\" section: > Each lab issue is assigned a sequential, human-friendly number (`#1`, `#2`, ...) that is used in every lab URL — both the dashboard and the API. After the model has run against an issue you can find it at `https://swamp.club/lab/<number>`. ## Test plan ### Local verification - [x] `deno fmt --check` — clean (1114 files) - [x] `deno lint` — clean (1008 files) - [x] `deno run test` — **4193 passed, 0 failed** (3m30s) - [x] `deno check extensions/models/_lib/swamp_club.ts extensions/models/issue_lifecycle.ts` — clean ### Client behaviour (manual / by-inspection) - [x] `ensureIssue` happy path: server returns `{ issue: { number: 42, ... }, created: true }` → cache populated, `42` returned. - [x] `ensureIssue` cache hit: second call short-circuits via `this.labIssueNumber !== null` and returns the cached number without re-fetching. - [x] `ensureIssue` rejects malformed responses without throwing: missing `issue` key, missing `number` key, `number: \"42\"` (string), `number: 0`, `number: -1`, `number: 1.5`, `number: NaN`, `number: 2 ** 53` (past safe integer). Each path logs a structured warning and returns `null`. - [x] `postLifecycleEntry` and `transitionStatus` no-op when `labIssueNumber === null` (i.e. before `ensureIssue` succeeds). - [x] `labUrl()` returns `null` before `ensureIssue`, then `${baseUrl}/lab/{number}` after. ### GitHub Action - [ ] **Smoke test:** file a throwaway issue against `systeminit/swamp` after this PR merges. Expect: - The issue closes within seconds of being filed. - A comment appears with the auto-responder text and a `https://swamp.club/lab/<n>` link. - The lab issue exists at that URL with the original body plus the `Automoved by swampadmin from GitHub issue #<n>` footer. - [ ] **Failure-mode test:** temporarily revoke the `SWAMP_API_KEY` secret value (or point at an unreachable host) and file a throwaway issue. Expect: - The action run fails with a `core.setFailed` message. - The GitHub issue stays **open**. - No auto-responder comment is posted. - Restore the secret afterwards. - [ ] **Validator test:** if a future swamp-club regression returns a non-number `id` field, expect the action to fail with `\"swamp.club ensure returned no lab issue number: ...\"` and the issue to stay open. I have not pre-merged the smoke tests because they require the workflow to be on `main` to fire on real `issues: opened` events. Suggest doing them as the first action after merge with throwaway issues. ## Related - systeminit/swamp-club#367 — issue I filed to track migrating the lab API endpoints from UUID to sequential number (closed by #369). - systeminit/swamp-club#369 — the merged server-side PR that shipped the contract this client now consumes. Adds `parseLabIssueNumberParam` and caught a real data-corruption hazard with `Number.parseInt`. - systeminit/swamp-club#364 — the original PR that introduced the sequential `number` field on lab issues and migrated the UI route to `/lab/{number}`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
This was referenced Apr 7, 2026
This was referenced Apr 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.