Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
34c1ba2
Update Archon configuration and setup documentation
ibuildthings-instrumentl Apr 17, 2026
96e2c71
Merge pull request #1 from instrumentl/initial-changes
ibuildthings-instrumentl Apr 17, 2026
37b691b
docs: design for @archie Slack feature-to-review-app workflow
ibuildthings-instrumentl Apr 17, 2026
97ea2b3
docs(plans): implementation plan for @archie slack feature-to-review-app
ibuildthings-instrumentl Apr 17, 2026
1dba9e2
feat(scripts): dispatch-review-app helper for slack feature workflow
ibuildthings-instrumentl Apr 17, 2026
686d7da
feat(scripts): ci-wait helper with hard timeout
ibuildthings-instrumentl Apr 17, 2026
28b7ad5
feat(scripts): fetch-review-app-url helper
ibuildthings-instrumentl Apr 17, 2026
eccb49f
feat(workflows): archon-slack-feature-to-review-app
ibuildthings-instrumentl Apr 17, 2026
a4d7e8c
feat(workflows): register archon-slack-feature-to-review-app as bundled
ibuildthings-instrumentl Apr 17, 2026
3019ace
feat(workflows): add plan-approval gate to slack-feature-to-review-app
ibuildthings-instrumentl Apr 17, 2026
7aa843a
feat(slack): add Block Kit approve + request-changes UI for loop gates
ibuildthings-instrumentl Apr 17, 2026
453cf46
Merge pull request #2 from instrumentl/slack-yolo-integration
ibuildthings-instrumentl Apr 17, 2026
2ec6b4e
Merge pull request #3 from instrumentl/slack-gate-blockkit
ibuildthings-instrumentl Apr 17, 2026
0596934
feat(slack): ack incoming messages with :eyes: reaction immediately
ibuildthings-instrumentl Apr 17, 2026
e7c30e1
Merge pull request #4 from instrumentl/slack-receipt-ack
ibuildthings-instrumentl Apr 17, 2026
bb19356
fix(deps): bump flatted to >=3.4.2 via override (Dependabot #19)
ibuildthings-instrumentl Apr 20, 2026
2e0f7d5
Merge pull request #5 from instrumentl/fix/dependabot-flatted
ibuildthings-instrumentl Apr 20, 2026
1e4f6f9
fix(deps): bump axios to ^1.15.0 via override (#29, #30)
ibuildthings-instrumentl Apr 20, 2026
1e6c4e0
Merge pull request #9 from instrumentl/fix/dependabot-axios
ibuildthings-instrumentl Apr 20, 2026
f11a43d
feat(slack): implement Slack scoping questions modal for structured i…
ibuildthings-instrumentl Apr 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions .archon/commands/defaults/scout-consolidate-perf-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
description: Merge per-route Scout profiles into a single implementation plan (plan.md)
argument-hint: (no arguments)
---

# Consolidate Scout performance plan

**Workflow ID**: $WORKFLOW_ID
**Artifacts**: $ARTIFACTS_DIR

---

## Mission

Read:

- `$ARTIFACTS_DIR/routes.json`
- `$ARTIFACTS_DIR/routes-summary.md`
- `$ARTIFACTS_DIR/profile-00.md` … `$ARTIFACTS_DIR/profile-09.md` (include only files that exist; skipped indices may say SKIPPED)

Produce **one** implementation plan at **`$ARTIFACTS_DIR/plan.md`** that `archon-plan-setup` / `archon-confirm-plan` / `archon-implement-tasks` can consume.

---

## Plan template (required sections)

Use this structure (fill with real content from profiles):

```markdown
# Performance: Scout hot-route optimizations

## Summary
{1–2 sentences}

## Mission
{Single goal statement}

## NOT Building (Scope Limits)
- {Explicit non-goals — e.g. unrelated refactors, new features}
- Do not change behavior except latency/resource usage unless noted.

## Success Criteria
- [ ] Each targeted route has measurable improvement or documented tradeoff
- [ ] Project validation suite passes (see CLAUDE.md)
- [ ] Scout shows no new regressions for these endpoints after deploy (verification note)

## Files to Change

| File | Action |
|------|--------|
| `{path}` | UPDATE |

## Patterns to Mirror

| Pattern | Source File | Lines |
|---------|-------------|-------|
| {name} | `{path}` | {lines} |

## Task List

### Task 1: {title}
**Action**: UPDATE
**Details**: {specific changes}
**Route**: `{METHOD} {path}`
**Validate**: {command}

### Task 2: ...

(Add one or more tasks per route or grouped fix.)

## Validation Commands
1. Commands from CLAUDE.md / package.json (typecheck, lint, test).

## Risks

| Risk | Impact | Mitigation |
|------|--------|------------|
| {risk} | {H/M/L} | {mitigation} |
```

---

## Rules

1. **Deduplicate** overlapping tasks if multiple profiles touch the same file.
2. **Order** tasks by dependency (models before handlers, shared utils first).
3. **Reference** actual symbols/files from the profile markdown files.
4. If profiles disagree, prefer the most evidence-backed recommendation and note the conflict in **Risks**.
5. Ignore profiles that are SKIPPED or empty.

---

## Output

- Write **`$ARTIFACTS_DIR/plan.md`** only (plan-setup will create `plan-context.md`).
- Stdout: `Plan written to $ARTIFACTS_DIR/plan.md with {N} tasks.`
67 changes: 67 additions & 0 deletions .archon/commands/defaults/scout-discover-routes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
description: Query Scout APM for top slow + high-traffic routes and write routes.json
argument-hint: "[optional app name or app id — else first active app]"
---

# Scout route discovery

**User message**: $ARGUMENTS
**Artifacts**: $ARTIFACTS_DIR

---

## Mission

Use **Scout MCP** tools to identify **up to 10 HTTP routes** to optimize. Combine:

- **Slowest** endpoints (p95 / mean response time), and
- **Most hit** (throughput / request volume)

Dedupe by route identity (method + path). If you have fewer than 10 distinct hot/slow routes, include the next candidates by severity. If Scout returns fewer than 10, use all available.

---

## Prerequisites

1. **MCP**: Scout tools should be available (`list_apps`, `get_app_endpoints`, `get_endpoint_metrics`, etc.). If MCP is unavailable, ask the user to set `SCOUT_API_KEY`, ensure Docker can run `scoutapp/scout-mcp-local`, or paste a Scout endpoints export into `$ARTIFACTS_DIR/scout-endpoints-export.json` (array of endpoint objects) and continue from that file.

2. **App selection**: If `$ARGUMENTS` names an app or numeric id, use that. Otherwise call `list_apps` and pick the production app that matches this repo (name/hostname) or the most recently active app. State which app you chose.

---

## Steps

1. Call Scout MCP to list endpoints with metrics for the chosen app (`get_app_endpoints` or equivalent).

2. Rank and select up to **10** routes using a clear rule, e.g.:
- Take top **5** by p95 latency (or worst mean response time if p95 missing).
- Take top **5** by throughput.
- Union, dedupe, then fill remaining slots by composite score: `latency × log(throughput)` or similar.

3. Write **`$ARTIFACTS_DIR/routes.json`** — JSON array of exactly the chosen routes, each object including at least:

- `rank` (1–10)
- `method` (e.g. `GET`)
- `path` (e.g. `/api/foo`)
- `scout_name` or endpoint id if the API exposes one
- `p95_ms`, `mean_ms` (numbers or null)
- `rpm` or throughput (number or null)
- `error_rate` if available

4. Write **`$ARTIFACTS_DIR/routes-summary.md`** — human-readable table: rank, method, path, p95, throughput, notes.

5. Print a one-line stdout summary: `Discovered N routes for app {name} (id {id}).`

---

## Error handling

- If no endpoints are returned: write `routes.json` as `[]`, explain in summary, and STOP with a clear error in stdout so the workflow can fail visibly.

---

## Success criteria

- `routes.json` exists and is valid JSON.
- `routes-summary.md` exists.
- At most 10 routes; each profile step can rely on fixed indices `0..N-1`.
3 changes: 3 additions & 0 deletions .archon/config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
worktree:
baseBranch: dev
# Copy local .env into isolated worktrees so Scout MCP sees SCOUT_API_KEY when cwd is ~/.archon/workspaces/...
copyFiles:
- .env
Comment on lines +3 to +5
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid copying the entire .env into every worktree.

This duplicates all local secrets for one Scout key and broadens exposure to generated workspaces. Prefer managed env injection, or copy a least-privilege Scout-only env file and point the MCP config at that file. Based on learnings, per-project env vars are stored in database, injected into bash/script nodes, Claude/Codex AI calls, and direct chat when codebase-scoped.

🛡️ Safer direction
-  # Copy local .env into isolated worktrees so Scout MCP sees SCOUT_API_KEY when cwd is ~/.archon/workspaces/...
+  # Copy only Scout MCP env needed by isolated worktrees; do not duplicate the full repo .env.
   copyFiles:
-    - .env
+    - .env.scout

Also update the Cursor MCP envFile to read the same least-privilege file if file-based injection is still required.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.archon/config.yaml around lines 3 - 5, The config currently copies the full
local .env (copyFiles: - .env) into each worktree which duplicates secrets;
instead create a least-privilege file (e.g., scout.env) that contains only the
Scout-specific vars (SCOUT_API_KEY) and replace the .env reference in copyFiles
with that filename, or switch to managed env injection instead of file-copy;
also update the Cursor MCP's envFile setting to point to the same
least-privilege scout.env if file-based injection is still used so both MCPs
read the minimal Scout-only vars rather than the full .env.


docs:
path: packages/docs-web/src/content/docs
70 changes: 70 additions & 0 deletions .archon/scripts/ci-wait.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env bun
/**
* Wait for GitHub CI on a PR to finish, with a hard wall-clock timeout.
*
* Usage: bun .archon/scripts/ci-wait.js <pr-number-or-url> [timeout-ms]
*
* Exit codes:
* 0 — all required checks passed
* 1 — at least one required check failed
* 3 — timeout reached before CI finished
* 2 — bad args / missing gh
*
* Used by archon-slack-feature-to-review-app to gate review-app deploy.
*/
import { spawn } from 'node:child_process';

const DEFAULT_TIMEOUT_MS = 60 * 60 * 1000;

function main() {
const [pr, timeoutArg] = process.argv.slice(2);

if (!pr) {
console.error('Usage: ci-wait.js <pr-number-or-url> [timeout-ms]');
process.exit(2);
}

const timeoutMs = timeoutArg ? Number(timeoutArg) : DEFAULT_TIMEOUT_MS;
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
console.error(`Invalid timeout-ms: ${timeoutArg}`);
process.exit(2);
}

console.log(
`Waiting for CI on PR ${pr} (timeout: ${Math.round(timeoutMs / 1000)}s)...`
);

const child = spawn(
'gh',
['pr', 'checks', pr, '--watch', '--fail-fast', '--interval', '30'],
{ stdio: 'inherit' }
);

let timedOut = false;
const timer = setTimeout(() => {
timedOut = true;
console.error(`\nCI wait timed out after ${Math.round(timeoutMs / 1000)}s`);
child.kill('SIGTERM');
setTimeout(() => process.exit(3), 2000).unref();
}, timeoutMs);
timer.unref();

child.on('exit', (code, _signal) => {
clearTimeout(timer);
if (timedOut) return;
Comment on lines +43 to +54
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's find and examine the file
find . -name "ci-wait.js" -type f

Repository: coleam00/Archon

Length of output: 87


🏁 Script executed:

# Get the file content to understand context
cat -n .archon/scripts/ci-wait.js

Repository: coleam00/Archon

Length of output: 2383


Preserve the timeout exit code after killing gh.

When the timeout triggers and the child exits before the 2-second grace period, the exit handler returns early without calling process.exit(3). The grace timer on line 48 is .unref()'d and therefore does not keep the process alive—the process exits immediately with no referenced handles remaining, so the grace timer never fires. Instead of exiting with code 3 as documented, the process exits with the child's exit code or 0. Since exit code 3 is used by archon-slack-feature-to-review-app for deployment gating, fix by removing .unref() from the grace timer and calling process.exit(3) directly when timedOut in the exit handler:

Proposed fix
   let timedOut = false;
+  let timeoutExit: ReturnType<typeof setTimeout> | undefined;
   const timer = setTimeout(() => {
     timedOut = true;
     console.error(`\nCI wait timed out after ${Math.round(timeoutMs / 1000)}s`);
     child.kill('SIGTERM');
-    setTimeout(() => process.exit(3), 2000).unref();
+    timeoutExit = setTimeout(() => process.exit(3), 2000);
   }, timeoutMs);
   timer.unref();

   child.on('exit', (code, _signal) => {
     clearTimeout(timer);
-    if (timedOut) return;
+    if (timedOut) {
+      if (timeoutExit) clearTimeout(timeoutExit);
+      process.exit(3);
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.archon/scripts/ci-wait.js around lines 43 - 54, The timeout handler sets
timedOut and schedules a 2s grace timer with .unref(), but because unrefed
timers don't keep the process alive the grace timer may never run and the child
'exit' handler returns early, dropping the intended exit code; update the
timeout logic in the timeout callback to stop using .unref() on the grace
setTimeout and in the child.on('exit', ...) handler (referencing timedOut,
timer, and child) call process.exit(3) directly when timedOut is true before
returning so the process reliably exits with code 3 after a timeout.

if (code === 0) {
console.log('CI passed.');
process.exit(0);
}
console.error(`CI failed (gh exit code ${code ?? 'null'})`);
process.exit(1);
});

child.on('error', err => {
clearTimeout(timer);
console.error(`Failed to spawn gh: ${err.message}`);
process.exit(2);
});
}

main();
47 changes: 47 additions & 0 deletions .archon/scripts/dispatch-review-app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env bun
/**
* Dispatch a GitHub Actions workflow_dispatch event on the given ref.
*
* Usage: bun .archon/scripts/dispatch-review-app.js <workflow-file> <ref>
*
* Exits 0 on successful dispatch. Exits non-zero with a human-readable stderr
* message on any failure (missing args, gh not installed, gh call failed).
*
* Used by the archon-slack-feature-to-review-app workflow after CI passes
* to deploy a review app for the PR branch.
*/
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';

const execFileAsync = promisify(execFile);

async function main() {
const [workflowFile, ref] = process.argv.slice(2);

if (!workflowFile || !ref) {
console.error('Usage: dispatch-review-app.js <workflow-file> <ref>');
process.exit(2);
}

try {
const { stdout, stderr } = await execFileAsync('gh', [
'workflow',
'run',
workflowFile,
'--ref',
ref,
]);
if (stdout.trim()) console.log(stdout.trim());
if (stderr.trim()) console.log(stderr.trim());
console.log(
JSON.stringify({ dispatched: true, workflow: workflowFile, ref })
);
} catch (err) {
console.error(
`Failed to dispatch ${workflowFile} on ref ${ref}: ${err.stderr ?? err.message}`
);
process.exit(1);
}
}

void main();
Loading