Repository navigation
feat: recover content from closed PRs #20 and #22 #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
a093bfb
feat: recover content from closed PRs #20 and #22
ThePlenkov 1eb66bc
fix: address Amazon Q and Codacy review findings on PR #28
ThePlenkov e0e41ff
fix: address CodeRabbit and Qodo iteration-2 findings on code files
ThePlenkov 75ce5b4
fix: address CodeRabbit and Qodo doc review findings on PR #28
ThePlenkov 7e165a2
fix: scope wisp/nudge filter to bead ID prefix in watchdog
ThePlenkov 48eca56
fix: configure Codacy and SonarCloud to exclude scripts/ utility dire…
ThePlenkov 8e1834f
chore: trigger CI re-run to clear stale SonarCloud annotation
ThePlenkov 816edd6
fix: address CodeRabbit iteration-3 findings on PR #28
ThePlenkov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| --- | ||
| name: gc-watchdog | ||
| description: Use when setting up a periodic Gas City health monitor. Trigger when the user asks for a watchdog, periodic status check, or monitoring loop for gc status. Covers the check cycle, exit conditions, and reporting format. | ||
| --- | ||
|
|
||
| # GC Watchdog | ||
|
|
||
| Periodic Gas City health monitor. Checks `gc status` and `bd list` on an | ||
| interval, reports issues, and exits when there is no more open work. | ||
|
|
||
| ## When to use | ||
|
|
||
| - User asks to "watch" or "monitor" Gas City while work is in progress | ||
| - User wants periodic status reports during a long-running wave | ||
| - User wants to know when the city goes idle (all work done) | ||
|
|
||
| ## Exit conditions | ||
|
|
||
| The watchdog stops when ALL of these are true: | ||
|
|
||
| 1. No open real tasks: `bd list --status=open` returns no issues (excluding | ||
| ephemeral wisp/nudge beads) | ||
| 2. No in-progress workflows: no beads with `gc.kind: workflow` in | ||
| `in_progress` state | ||
| 3. Mayor is awake and not suspended (clean shutdown, not a crash) | ||
|
|
||
| If the mayor is down or the city is suspended, the watchdog reports the | ||
| error and keeps running (does NOT exit on failure — only on success). | ||
|
|
||
| ## Check cycle | ||
|
|
||
| Each tick: | ||
|
|
||
| 1. `gc status` — extract mayor status, sessions, suspended, controller | ||
| 2. `bd list --status=open` — count real (non-wisp, non-nudge) open issues | ||
| 3. `bd list --status=in_progress` — count real in-progress issues | ||
| 4. Report one line | ||
| 5. If no open AND no in-progress real issues → report "idle" and exit 0 | ||
|
|
||
| ## Reporting format | ||
|
|
||
| ```text | ||
| [HH:MM:SS] ✓ mayor:<status> | open:<N> in_progress:<M> | <sessions line> | ||
| [HH:MM:SS] ⚠ <issues> | open:<N> in_progress:<M> | <sessions line> | ||
| [HH:MM:SS] IDLE — no open work, no in-progress work. Watchdog exiting. | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| ### As a skill (agent-driven) | ||
|
|
||
| The agent reads this SKILL.md, runs the check script, and reports back. | ||
| Each tick is one subagent invocation: wait 60s, check, report. | ||
|
|
||
| ### As a standalone script | ||
|
|
||
| ```bash | ||
| bash .agents/skills/gc-watchdog/watchdog.sh [interval_seconds] | ||
| ``` | ||
|
|
||
| Default interval: 60 seconds. Runs until idle or interrupted. | ||
|
|
||
| ## Files | ||
|
|
||
| - `watchdog.sh` — standalone shell script implementing the check cycle | ||
| - `SKILL.md` — this file (documentation for agents) |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| #!/bin/bash | ||
| # gc-watchdog — periodic Gas City health monitor with exit condition. | ||
| # | ||
| # Checks gc status + bd ready on an interval. Reports issues. Exits when | ||
| # there is no more open real work (non-wisp, non-nudge) and no in-progress | ||
| # real work. | ||
| # | ||
| # Usage: bash watchdog.sh [interval_seconds] | ||
| # Default interval: 60 seconds. | ||
|
|
||
| # NOTE: intentionally NOT using set -e. gc status and bd list can fail | ||
| # transiently (session snapshot timeouts, store locks). We handle errors | ||
| # per-command and continue the loop. | ||
| set -uo pipefail | ||
|
|
||
| INTERVAL="${1:-60}" | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| # Validate INTERVAL is a positive integer to prevent injection. | ||
| if ! [[ "$INTERVAL" =~ ^[1-9][0-9]*$ ]]; then | ||
| echo "ERROR: interval must be a positive integer, got: $INTERVAL" >&2 | ||
| exit 2 | ||
| fi | ||
| ITER=0 | ||
|
ThePlenkov marked this conversation as resolved.
|
||
|
|
||
| # Filter out ephemeral wisp/nudge beads from bd output. | ||
| # Real issues have IDs like sv-XXXX (4+ chars after sv-). | ||
| # Wisp/nudge beads have IDs like sv-wisp-XXXX or sv-nudge-XXXX. | ||
| # Status symbols: ○ = open, ◐ = in_progress, ● = blocked, ✓ = closed | ||
| # Returns -1 on bd failure (distinct from a legitimate 0 count) so the | ||
| # caller can distinguish "no work" from "lookup failed". Adds a timeout | ||
| # to bd list so a blocked store cannot stall the watchdog. | ||
| count_real_issues() { | ||
| local status="$1" | ||
| local raw | ||
| if ! raw=$(timeout 10 bd list --status="$status" 2>/dev/null); then | ||
| printf -- '-1\n' | ||
| return 1 | ||
|
ThePlenkov marked this conversation as resolved.
|
||
| fi | ||
| # grep returns 1 when no matches; with pipefail that would fail the | ||
| # pipeline. Use `|| true` to swallow grep's no-match exit code so | ||
| # an empty result yields 0, not -1. | ||
| printf '%s\n' "$raw" \ | ||
| | { grep -E '^\s*[○◐●] sv-[a-z0-9]{4,}($| )' || true; } \ | ||
| | { grep -vE '^\s*[○◐●] sv-(wisp|nudge)' || true; } \ | ||
|
ThePlenkov marked this conversation as resolved.
|
||
| | wc -l | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } | ||
|
|
||
| while true; do | ||
| ITER=$((ITER + 1)) | ||
| TS=$(date '+%H:%M:%S') | ||
|
|
||
| # 1. gc status | ||
| STATUS=$(timeout 15 gc status 2>/dev/null || true) | ||
|
|
||
| if [ -z "$STATUS" ]; then | ||
| echo "[$TS] #$ITER ⚠ gc status timeout/error" | ||
| sleep "$INTERVAL" | ||
| continue | ||
| fi | ||
|
qodo-code-review[bot] marked this conversation as resolved.
|
||
|
|
||
| MAYOR=$(echo "$STATUS" | grep "harness.mayor" | awk '{print $2}') | ||
|
ThePlenkov marked this conversation as resolved.
|
||
| SESSIONS=$(echo "$STATUS" | grep "Sessions:" | head -1 | sed 's/^ *//') | ||
| SUSPENDED=$(echo "$STATUS" | grep "Suspended:" | awk '{print $2}') | ||
|
ThePlenkov marked this conversation as resolved.
|
||
| CONTROLLER=$(echo "$STATUS" | grep "Controller:" | grep -o "supervisor-managed\|stopped\|error" | head -1 || true) | ||
|
|
||
| # Handle transient lookup errors (mayor shows "lookup" instead of "awake") | ||
| if echo "$MAYOR" | grep -q "lookup"; then | ||
| MAYOR="lookup-error" | ||
| fi | ||
|
|
||
| # 2. bd work counts | ||
| OPEN_COUNT=$(count_real_issues "open") | ||
| OPEN_FAILED=$? | ||
| INPROG_COUNT=$(count_real_issues "in_progress") | ||
| INPROG_FAILED=$? | ||
|
|
||
| # 3. Check for issues | ||
| ISSUES="" | ||
| # bd lookup failures are hard issues — don't allow idle exit when store is unreachable | ||
| if [ "$OPEN_FAILED" -ne 0 ] || [ "$INPROG_FAILED" -ne 0 ]; then | ||
| ISSUES="$ISSUES BD_LOOKUP_FAILED" | ||
| fi | ||
| [ -z "$MAYOR" ] && ISSUES="$ISSUES MAYOR_MISSING" | ||
| if [ -n "$MAYOR" ] && [ "$MAYOR" != "awake" ] && [ "$MAYOR" != "running" ] && [ "$MAYOR" != "active" ] && [ "$MAYOR" != "lookup-error" ]; then | ||
| ISSUES="$ISSUES MAYOR($MAYOR)" | ||
| fi | ||
| # lookup-error is a transient issue, not a hard failure — report as ⚠ but don't treat as fatal | ||
| if [ "$MAYOR" = "lookup-error" ]; then | ||
| ISSUES="$ISSUES MAYOR_LOOKUP_TIMEOUT" | ||
| fi | ||
| # Treat missing status fields as unknown, not healthy defaults | ||
| if [ -z "${SUSPENDED:-}" ]; then | ||
| ISSUES="$ISSUES SUSPENDED_MISSING" | ||
| elif [ "$SUSPENDED" != "no" ]; then | ||
| ISSUES="$ISSUES SUSPENDED" | ||
| fi | ||
| if [ -z "${CONTROLLER:-}" ]; then | ||
| ISSUES="$ISSUES CONTROLLER_MISSING" | ||
| elif [ "$CONTROLLER" != "supervisor-managed" ]; then | ||
| ISSUES="$ISSUES CONTROLLER($CONTROLLER)" | ||
| fi | ||
|
|
||
| # 4. Report | ||
| if [ -n "$ISSUES" ]; then | ||
| echo "[$TS] #$ITER ⚠$ISSUES | open:$OPEN_COUNT in_progress:$INPROG_COUNT | ${SESSIONS:-no-sessions}" | ||
| else | ||
| echo "[$TS] #$ITER ✓ mayor:$MAYOR | open:$OPEN_COUNT in_progress:$INPROG_COUNT | ${SESSIONS:-no-sessions}" | ||
| fi | ||
|
|
||
| # 5. Exit condition: no open AND no in-progress real work, mayor healthy, | ||
| # and bd lookups succeeded. Soft signals (MAYOR_LOOKUP_TIMEOUT) are | ||
| # stripped; hard signals (BD_LOOKUP_FAILED) prevent idle exit. | ||
| HARD_ISSUES="${ISSUES// MAYOR_LOOKUP_TIMEOUT/}" | ||
| if [ "$OPEN_COUNT" -eq 0 ] && [ "$INPROG_COUNT" -eq 0 ] && [ -z "$HARD_ISSUES" ]; then | ||
| echo "[$TS] #$ITER IDLE — no open work, no in-progress work. Watchdog exiting." | ||
| exit 0 | ||
| fi | ||
|
|
||
| sleep "$INTERVAL" | ||
| done | ||
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| name: "Sverka CodeQL Config" | ||
|
|
||
| # Exclude non-source paths from CodeQL analysis | ||
| paths: | ||
| - packages | ||
| paths-ignore: | ||
| - packages/*/dist/** | ||
| - "**/node_modules/**" | ||
| - "**/__tests__/**" | ||
| - "**/*.test.ts" | ||
| - pack/** | ||
| - .agents/** | ||
| - .gc/** | ||
| - website/** | ||
| - engdocs/** | ||
| - specs/** | ||
|
|
||
| # Query suite: security-extended (set in workflow) | ||
| queries: | ||
| - uses: security-extended |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| # Review Policy | ||
|
|
||
| ## Two-Axis Review | ||
|
|
||
| Every change is reviewed along two independent axes: | ||
|
|
||
| 1. **Standards** — does the code follow the repo's documented coding | ||
| standards (AGENTS.md) plus a Fowler smell baseline? | ||
| 2. **Spec** — does the code faithfully implement the originating spec | ||
| in `specs/`? | ||
|
|
||
| Both axes must pass. A change that is clean code but implements the wrong | ||
| thing is rejected. A change that implements the right thing with messy code | ||
| is rejected. | ||
|
|
||
| ## Verification Bar | ||
|
|
||
| The reviewer runs all checks themselves. No trusting builder claims. | ||
|
|
||
| ```bash | ||
| bun run test # vitest via nx (NOT `bun test` — that runs Bun's runner) | ||
| bun run typecheck # tsc via nx | ||
| bun run lint # eslint via nx | ||
| bun run build # tsdown via nx | ||
| ``` | ||
|
|
||
| Run fresh with `--skip-nx-cache` to avoid cached results. | ||
|
|
||
| ## Finding Classification | ||
|
|
||
| | Class | Meaning | Action | | ||
| | ------- | ------------------------------ | --------------- | | ||
| | BLOCKING | Spec violation or broken gate | Must fix | | ||
| | NIT | Non-blocking style or edge case | Note, don't block | | ||
| | DECLINE | Reviewer disagrees with suggestion | Explain why | | ||
|
|
||
| ## Minimalism Audit | ||
|
|
||
| If the builder wrote more code than the spec requires, that's a rejection | ||
| for over-engineering. Less code = fewer bugs. The reviewer audits for: | ||
|
|
||
| - Unnecessary abstractions | ||
| - Speculative API (exports not used by spec) | ||
| - Dead code | ||
| - Premature generalization | ||
|
|
||
| ## Spec Compliance | ||
|
|
||
| Every interface, every type, every error code in the spec must be present | ||
| in the implementation. No "close enough." No "it's basically the same." | ||
|
|
||
| Exports must match spec 1:1. No extra exports beyond what the spec defines | ||
| (testability seams excepted — note them as NITs). | ||
|
|
||
| ## Error Handling | ||
|
|
||
| - Custom error classes must use `override` on `cause` (noImplicitOverride) | ||
| - No `any` types — use `unknown` and narrow | ||
| - Error codes as string unions, not enums | ||
|
|
||
| ## Scaffolding Checks | ||
|
|
||
| - `package.json`: dist outputs as `.mjs`/`.d.mts` (not `.js`/`.d.ts`) | ||
| - `project.json`: lint target without `--ext .ts` (ESLint 9 flat config) | ||
| - `project.json`: test target with `--passWithNoTests` | ||
|
|
||
| ## Commit Hygiene | ||
|
|
||
| Before committing a wave, verify: | ||
|
|
||
| - `git status --short` — every impl + test file is at least staged | ||
| - No untracked impl files (recurrence of untracked-test-helpers drill finding) | ||
| - Exclude: `city.toml`, `agents/`, `.devin/`, `.gc/`, `.beads/`, `.evidence/`, | ||
| `.opencode/`, `formulas/` (process improvement files) | ||
| - Stage only: `packages/<package>/**`, `specs/NN-<name>/`, `engdocs/`, `bun.lock` | ||
|
|
||
| ## Process | ||
|
|
||
| 1. Reviewer runs all gates fresh (not cached, not trusted from builder) | ||
| 2. Reviewer reads the diff and spec | ||
| 3. Reviewer classifies findings | ||
| 4. APPROVE or REJECT with specific, actionable feedback | ||
| 5. On REJECT: builder fixes, reviewer re-reviews |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # Security Policy | ||
|
|
||
| ## Reporting Vulnerabilities | ||
|
|
||
| Report security vulnerabilities privately. Do NOT open a public GitHub issue. | ||
|
|
||
| - Email: security@sverka.dev | ||
| - Response time: 48 hours | ||
| - Disclosure: coordinated, after fix is released | ||
|
|
||
| ## Secrets | ||
|
|
||
| - NEVER commit secrets, API keys, tokens, or passwords to the repository | ||
| - Use environment variables or secret managers | ||
| - If a secret is accidentally committed: rotate it immediately, then use | ||
| `git filter-repo` or BFG Repo-Cleaner to purge it from history, then | ||
| force-push the rewritten branch. A force-push alone does NOT remove the | ||
| secret from retained history, forks, logs, or artifacts — rotation comes first | ||
| - Reviewer must check for hardcoded secrets in every PR | ||
|
|
||
| ## Dependencies | ||
|
|
||
| - Prefer dependencies published at least 7 days ago (supply chain safety) | ||
| - Avoid floating ranges (`latest`, `*`, unbounded `>=`) that auto-resolve to | ||
| brand-new releases | ||
| - Run `bun audit` periodically | ||
| - Pin lockfile (`bun.lock`) — do not commit without it | ||
|
|
||
| ## Code Security | ||
|
|
||
| - No `any` types (use `unknown` and narrow) — prevents type confusion bugs | ||
| - Validate all external input before use | ||
| - No `eval()`, no `new Function()`, no dynamic code execution | ||
| - No `child_process.exec` with user input — use `execFile` with arg arrays | ||
| - Sanitize file paths — no path traversal via `..` in user input | ||
| - Use `spawnSync` with timeout for subprocess calls (prevent hangs) | ||
|
|
||
| ## CI/CD Security | ||
|
|
||
| - Never modify repository security policies or compliance controls to work | ||
| around CI failures | ||
| - Never disable branch protection, even temporarily | ||
| - Escalate CI/auth failures to the user instead of working around them | ||
|
|
||
| ## Agent Security | ||
|
|
||
| - Agents must not expose or log secrets | ||
| - Agents must not commit secrets | ||
| - Agents must not modify security policies | ||
| - `dangerous` permission mode is for local dev only, never for CI | ||
|
|
||
| ## Runtime Security | ||
|
|
||
| Sverka executes commands in Docker containers and host processes: | ||
|
|
||
| - Docker executor: verify image digests, no untrusted images | ||
| - Host executor: validate commands before execution, no shell injection | ||
| - Runtime args: sanitize all user-provided paths and arguments | ||
| - Credentials: pass via env vars, never log them |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.