-
Notifications
You must be signed in to change notification settings - Fork 3.1k
feat(slack): structured scoping-question modal for spec loop #1318
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
Changes from all commits
34c1ba2
96e2c71
37b691b
97ea2b3
1dba9e2
686d7da
28b7ad5
eccb49f
a4d7e8c
3019ace
7aa843a
453cf46
2ec6b4e
0596934
e7c30e1
bb19356
2e0f7d5
1e4f6f9
1e6c4e0
f11a43d
721b8bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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.` | ||
| 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. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
Comment on lines
+24
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fail closed when Scout input is unavailable. This runs before the interactive review gate, so “ask the user to set Suggested prompt contract-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.
+1. **MCP**: Scout tools should be available (`list_apps`, `get_app_endpoints`, `get_endpoint_metrics`, etc.). If MCP is unavailable, first check whether `$ARTIFACTS_DIR/scout-endpoints-export.json` already exists and continue from that file. If it does not exist, write `routes.json` as `[]`, write `routes-summary.md` with setup instructions, print `ERROR: Scout MCP unavailable and no endpoints export found`, and stop without inventing routes.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## 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`. | ||||||||||||||||||||||||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copying The comment explains this is needed so Scout MCP sees
🤖 Prompt for AI Agents |
||
|
|
||
| docs: | ||
| path: packages/docs-web/src/content/docs | ||
| 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(); |
| 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(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a hard guard for zero usable profiles.
If
routes.jsonis[]or everyprofile-XX.mdisSKIPPED/empty, this can still write a valid-lookingplan.mdwith0tasks, allowing the implementation pipeline to continue on an empty plan. Make that case explicit: do not produceplan.md; emit a clear failure message instead.Suggested command contract addition
## 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. +6. If there are **zero** usable profiles or `routes.json` is empty, do not write `plan.md`; print `ERROR: no Scout routes/profiles available to consolidate` and stop.📝 Committable suggestion
🤖 Prompt for AI Agents