Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 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
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

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;
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