-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Guidance layer: a family AGENTS.md for every family, a README for every crate, and a repo-wide stale sweep #7264
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
0c9a3dd
8b56e2d
b77fc07
4c4f4e9
783b575
4aa656c
533d095
993ec64
297d4f9
d5797ed
0c6c0cf
9e68ba3
b2ced45
ddc5dd2
bb06522
245bae3
4a65201
8d13454
864d93e
05668c9
3c646e8
022f38f
93af288
e3be23c
d55b154
5db1a3f
83f1676
85db706
5e95f76
0d3d751
c449a68
3ac3bfe
2648ed9
c58b6ca
6a4bf6c
bcaf480
ce0d1bb
777bd58
71cf60c
5c16055
0ea85ec
2581935
e76b70c
15d4c48
7d33b59
4dff436
5184b68
d865e72
a288613
cfdbe6b
c7229fe
0720766
6c3831d
5db4640
ae3492a
485a207
bf31d20
778955d
e0957f1
ef38082
b851e1b
1a88f6f
14554a7
7fd54fb
d2b589c
aeb3c20
935cbc3
667e764
8ce6fbe
f1be131
29d2934
b41b6c2
cf76f6a
f3c434d
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 |
|---|---|---|
| @@ -1,122 +1,34 @@ | ||
| --- | ||
| description: Scaffold a new SSE event end-to-end (Rust backend to web frontend) | ||
| allowed-tools: Read, Edit, Write, Glob, Grep, Bash(cargo fmt:*), Bash(cargo clippy:*), Bash(cargo test:*) | ||
| description: Retired v1 SSE scaffold — redirects to the Reborn projection/streaming path (full rewrite pending) | ||
| allowed-tools: Read, Glob, Grep | ||
| argument-hint: <event_name> [description] | ||
| model: opus | ||
| --- | ||
|
|
||
| > # ⚠ DO NOT FOLLOW THIS COMMAND — IT TARGETS A DELETED CODEBASE | ||
| > | ||
| > **Every file path in the steps below is gone.** This procedure scaffolds into | ||
| > the retired v1 gateway SSE path: `src/channels/` (Steps 1–3), | ||
| > `crates/ironclaw_gateway/static/` (Steps 4–5), and `src/agent/` / `src/worker/` | ||
| > (Step 6) — the final checklist names the same dead files. The | ||
| > `ironclaw_gateway` crate and the entire root `src/` monolith were deleted from | ||
| > the tree; none of these files exist and none should be created. Only Step 7 | ||
| > (`cargo fmt` / `clippy`) still means anything. Following this command produces | ||
| > new files in a directory layout the build does not know about. | ||
| > | ||
| > **This command needs rewriting onto the `ironclaw_webui` streaming path** — | ||
| > the Reborn projection/SSE frame served by `crates/product/ironclaw_webui`, with the | ||
| > client side in `crates/product/ironclaw_webui/frontend/`, over the event-stream | ||
| > substrate (`ironclaw_event_log` → `ironclaw_event_projections` → | ||
| > `ironclaw_event_streams`). That rewrite has not been done: the correct | ||
| > Reborn procedure is **not** written down here, and this banner deliberately | ||
| > does not guess at it. | ||
| > | ||
| > Until then, for a new user-visible event start from the `reborn-feature` | ||
| > skill and `.claude/rules/gateway-events.md` (the live Reborn events and | ||
| > transport-projection rules), not from the steps below. | ||
| > | ||
| > *Identified in PR #6944 (WS11.3 guidance drift hotfixes), which found the | ||
| > paths dead but scoped the rewrite out — replacing a scaffold procedure is new | ||
| > guidance, not a drift fix.* | ||
|
|
||
| Add a new SSE event called `$ARGUMENTS` to the IronClaw web gateway. This involves changes across 5 files in a specific order. Follow each step exactly. | ||
|
|
||
| ## Step 1: Add `StatusUpdate` variant | ||
|
|
||
| **File**: `src/channels/channel.rs` | ||
|
|
||
| Find the `StatusUpdate` enum and add a new variant. Use the event name in PascalCase. Include any fields the event needs as named fields (not a generic String). | ||
|
|
||
| Example for reference (existing variants): | ||
| ```rust | ||
| pub enum StatusUpdate { | ||
| Thinking(String), | ||
| ToolStarted { name: String }, | ||
| ToolCompleted { name: String, success: bool }, | ||
| Status(String), | ||
| ApprovalNeeded { | ||
| request_id: String, | ||
| tool_name: String, | ||
| description: String, | ||
| parameters: serde_json::Value, | ||
| }, | ||
| } | ||
| ``` | ||
|
|
||
| ## Step 2: Map to `SseEvent` in web channel | ||
|
|
||
| **File**: `src/channels/web/mod.rs` | ||
|
|
||
| Find the `send_status` method in the `Channel` impl for `WebChannel`. Add a match arm for the new `StatusUpdate` variant that maps it to an `SseEvent`. The SSE event name should be snake_case. | ||
|
|
||
| Look at existing match arms for the pattern. The event data is serialized as JSON. | ||
|
|
||
| ## Step 3: Add types if needed | ||
|
|
||
| **File**: `src/channels/web/types.rs` | ||
|
|
||
| If the event carries structured data beyond a simple string, add a serializable DTO struct here. Use `#[derive(Debug, Clone, Serialize, Deserialize)]`. Follow the existing patterns in the file. | ||
|
|
||
| ## Step 4: Add frontend handler | ||
|
|
||
| **File**: ~~`crates/ironclaw_gateway/static/js/core/sse.js`~~ — **deleted; do not create.** The Reborn client lives in `crates/product/ironclaw_webui/frontend/`. | ||
|
|
||
| In the `connectSSE()` function, add a new `eventSource.addEventListener()` for the snake_case event name. Parse the JSON data and call a handler function. | ||
|
|
||
| Create the handler function that updates the DOM. Put it in the split file that matches its surface — e.g. `js/core/onboarding.js` for auth/onboarding handlers, `js/surfaces/chat.js` for chat message handlers, `js/surfaces/jobs.js` for sandbox job events. Follow existing patterns: | ||
| - `showApproval(data)` for complex card-style UI | ||
| - `addMessage(role, content)` for simple text | ||
| - `setStatus(text, spinning)` for status bar updates | ||
|
|
||
| ## Step 5: Add CSS if needed | ||
|
|
||
| **File**: ~~`crates/ironclaw_gateway/static/styles/`~~ — **deleted; do not create.** Reborn styling lives with the SPA under `crates/product/ironclaw_webui/frontend/`. | ||
|
|
||
| If the event needs custom UI (cards, badges, etc.), add styles. Follow the existing naming conventions (`.approval-card`, `.log-entry`, etc.). | ||
|
|
||
| ## Step 6: Send the event from Rust | ||
|
|
||
| Identify where in the backend this event should be triggered. Common locations: | ||
| - `src/agent/agent_loop.rs` - During message processing or tool execution | ||
| - `src/worker/job.rs` - During job execution | ||
| - `src/agent/heartbeat.rs` - During periodic execution | ||
|
|
||
| Use the existing pattern: | ||
| ```rust | ||
| let _ = self.channels.send_status( | ||
| &message.channel, | ||
| StatusUpdate::YourNewVariant { ... }, | ||
| &message.metadata, | ||
| ).await; | ||
| ``` | ||
|
|
||
| ## Step 7: Quality gate | ||
|
|
||
| Run `cargo fmt` and `cargo clippy --all --benches --tests --examples --all-features` to verify the changes compile cleanly. | ||
|
|
||
| ## Checklist | ||
|
|
||
| Before finishing, verify: | ||
| - [ ] `StatusUpdate` variant added in `channel.rs` | ||
| - [ ] Match arm added in `web/mod.rs` `send_status` | ||
| - [ ] DTO added in `types.rs` (if needed) | ||
| - [ ] `addEventListener` added in `app.js` | ||
| - [ ] Handler function created in `app.js` | ||
| - [ ] CSS styles added (if needed) | ||
| - [ ] Event sent from appropriate backend location | ||
| - [ ] `cargo fmt` clean | ||
| - [ ] `cargo clippy` clean | ||
| - [ ] Non-web channels unaffected (they ignore unknown StatusUpdate variants) | ||
| # This command's scaffold procedure was retired with the v1 codebase | ||
|
|
||
| The step-by-step procedure this command used to carry scaffolded into the | ||
| deleted v1 gateway SSE path (`src/channels/`, `crates/ironclaw_gateway/static/`, | ||
| `src/agent/` / `src/worker/`). The `ironclaw_gateway` crate and the entire root | ||
| `src/` monolith were deleted from the tree; none of those files exist and none | ||
| should be created. The dead steps were removed rather than left behind a | ||
| warning banner (2026-08-05 stale-docs sweep; the paths were first found dead in | ||
| PR #6944, which scoped the rewrite out). | ||
|
|
||
| **The Reborn replacement procedure has not been written.** A correct rewrite | ||
| targets the `ironclaw_webui` streaming path — the Reborn projection/SSE frame | ||
| served by `crates/product/ironclaw_webui`, with the client side in | ||
| `crates/product/ironclaw_webui/frontend/`, over the event-stream substrate | ||
| (`crates/events/ironclaw_event_log` → `crates/events/ironclaw_event_projections` | ||
| → `crates/events/ironclaw_event_streams`). This stub deliberately does not | ||
| guess at the step list. | ||
|
|
||
| Until the rewrite lands, to add a new user-visible event `$ARGUMENTS`: | ||
|
|
||
| 1. Start from the `reborn-feature` skill (`.claude/skills/reborn-feature/SKILL.md`) | ||
| to wire the feature across the layers. | ||
| 2. Read `.claude/rules/gateway-events.md` — the live Reborn events and | ||
| transport-projection rules. | ||
| 3. Find the current server-side stream seam with | ||
| `grep -n "stream_events" crates/product/ironclaw_webui/src/webui_v2/handlers.rs` | ||
| and the client consumption in `crates/product/ironclaw_webui/frontend/src/`. | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -21,18 +21,19 @@ crate and skip the selection cascade in §1 — but still run the §1 Reborn/leg | |||||||||||||||||||||||||||||||
| a legitimate Reborn target. Otherwise pick one per §1. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## 0. Environment & state | ||||||||||||||||||||||||||||||||
| - **Reborn-only.** New feature and quality work targets the Reborn stack in `crates/`, never the v1 | ||||||||||||||||||||||||||||||||
| `src/` monolith (root CLAUDE.md, "Where to Build — Reborn-First"). This loop only touches `crates/` | ||||||||||||||||||||||||||||||||
| Reborn crates. It must **skip the legacy enclave** — crates that serve *only* the retiring v1 | ||||||||||||||||||||||||||||||||
| monolith. That enclave is now empty — `ironclaw_engine`, `ironclaw_tui`, `ironclaw_gateway`, and | ||||||||||||||||||||||||||||||||
| `ironclaw_oauth` have all been removed, so every crate under `crates/` that the workspace builds | ||||||||||||||||||||||||||||||||
| is a legitimate target. Two caveats you can check in the root `Cargo.toml`: `tools/ironclaw_silk_decoder` | ||||||||||||||||||||||||||||||||
| - **Reborn-only.** All work targets the Reborn stack in `crates/` (root CLAUDE.md, "Where to Build | ||||||||||||||||||||||||||||||||
| — the Reborn stack in `crates/`"). The v1 `src/` monolith and its legacy enclave | ||||||||||||||||||||||||||||||||
| (`ironclaw_engine`, `ironclaw_tui`, `ironclaw_gateway`, `ironclaw_oauth`) have all been removed, | ||||||||||||||||||||||||||||||||
| so every crate under `crates/` that the workspace builds is a legitimate target. Two caveats you can check in the root `Cargo.toml`: `tools/ironclaw_silk_decoder` | ||||||||||||||||||||||||||||||||
| is in `exclude`, so workspace-wide `cargo` commands never see it; and a crate with no consumers | ||||||||||||||||||||||||||||||||
| may be queued for deletion rather than for de-slopping (`grep -rl "<crate>" crates/*/Cargo.toml | ||||||||||||||||||||||||||||||||
| Cargo.toml`). Verify each candidate's status with the orientation recipe (§1) before picking it. | ||||||||||||||||||||||||||||||||
| may be queued for deletion rather than for de-slopping (`grep -rl --include=Cargo.toml "<crate>" | ||||||||||||||||||||||||||||||||
| crates/ Cargo.toml` — the family layout means `crates/*/Cargo.toml` matches nothing). Verify each | ||||||||||||||||||||||||||||||||
| candidate's status with the orientation recipe (§1) before picking it. | ||||||||||||||||||||||||||||||||
| - **Local gate reality.** You can prove `cargo fmt`, `cargo clippy`, per-crate `cargo test -p <crate>`, | ||||||||||||||||||||||||||||||||
| the workspace unit-test tier, and the architecture-boundary test (`cargo test -p ironclaw_architecture_tests`) | ||||||||||||||||||||||||||||||||
| locally. The **integration tier** (`cargo test --features integration`) needs a running PostgreSQL; | ||||||||||||||||||||||||||||||||
| locally. The **backend-integration tier** (crate-level feature-gated suites, e.g. | ||||||||||||||||||||||||||||||||
| `cargo test -p ironclaw_hooks --features integration` — the workspace-root `integration` feature is | ||||||||||||||||||||||||||||||||
| empty and does nothing) needs Docker for its Postgres testcontainers; | ||||||||||||||||||||||||||||||||
| the **live tier** (`-- --ignored`) needs Postgres + LLM API keys; **Reborn e2e** | ||||||||||||||||||||||||||||||||
| (`scripts/reborn-e2e-rust.sh`) may need Docker. If a fix touches those paths, implement it fully and | ||||||||||||||||||||||||||||||||
| mark the gate **"CI-deferred (needs Postgres/Docker/keys)"** in the PR body. Never weaken or delete | ||||||||||||||||||||||||||||||||
|
|
@@ -45,10 +46,12 @@ a legitimate Reborn target. Otherwise pick one per §1. | |||||||||||||||||||||||||||||||
| open PR holds. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## 1. Pick ONE un-de-slopped Reborn crate — stop at first viable | ||||||||||||||||||||||||||||||||
| List the crates (`ls crates/`). A crate is a **candidate** when ALL hold: | ||||||||||||||||||||||||||||||||
| - **it is a Reborn crate, not legacy-enclave.** Verify: `grep -rl "<crate_name>" crates/*/Cargo.toml Cargo.toml` | ||||||||||||||||||||||||||||||||
| — if the **only** consumer is the root `Cargo.toml` package, it's v1-only; skip it. When unsure, | ||||||||||||||||||||||||||||||||
| consult the `ironclaw-reborn-orientation` skill (it maps which side each crate is on). | ||||||||||||||||||||||||||||||||
| List the crates (`ls crates/*/` — the top level is the ten family directories, crates are one level | ||||||||||||||||||||||||||||||||
| down, plus `crates/extensions/packages/*`). A crate is a **candidate** when ALL hold: | ||||||||||||||||||||||||||||||||
| - **it has real consumers.** Verify: `grep -rl --include=Cargo.toml "<crate_name>" crates/ Cargo.toml` | ||||||||||||||||||||||||||||||||
| — the legacy enclave is gone (every workspace crate is Reborn), so this check now exists to catch | ||||||||||||||||||||||||||||||||
| crates with no consumers that may be queued for deletion instead. When unsure, | ||||||||||||||||||||||||||||||||
| consult the `ironclaw-reborn-orientation` skill. | ||||||||||||||||||||||||||||||||
|
Comment on lines
+49
to
+54
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. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Make the consumer check exclude the candidate's own manifest. The command searches for Use dependency metadata and exclude the package itself. Proposed validation-- **it has real consumers.** Verify: `grep -rl --include=Cargo.toml "<crate_name>" crates/ Cargo.toml`
+- **it has real consumers.** Verify that another package lists `<crate_name>` as a dependency:
+ `cargo metadata --no-deps --format-version 1 | jq -e --arg crate "<crate_name>" '
+ [.packages[] | select(.name != $crate)
+ | select(any(.dependencies[]?; .name == $crate))] | length > 0'`📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| - **not already in the ledger DESLOPPED list** (§0), | ||||||||||||||||||||||||||||||||
| - **not the hot surface of an open PR** (§0) — leave those to the build/review loops, | ||||||||||||||||||||||||||||||||
| - it has real source to review (skip thin aggregator/facade crates with ~no `src` — though their | ||||||||||||||||||||||||||||||||
|
|
@@ -267,8 +270,9 @@ cargo build --workspace --all-targets # sealing a pub can break OTHER cr | |||||||||||||||||||||||||||||||
| cargo clippy --all --benches --tests --examples --all-features | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
| Sealing a public item can break **other** crates — the workspace build/clippy catches that; fix the | ||||||||||||||||||||||||||||||||
| fallout or keep the item public with a note. If the crate has an **integration** path, run | ||||||||||||||||||||||||||||||||
| `cargo test --features integration` when Postgres is reachable; if it has a **Reborn e2e** path | ||||||||||||||||||||||||||||||||
| fallout or keep the item public with a note. If the crate has an **integration** feature, run | ||||||||||||||||||||||||||||||||
| `cargo test -p <crate> --features integration` when Docker is reachable (the workspace-root | ||||||||||||||||||||||||||||||||
| `integration` feature is empty — the flag only means something per-crate); if it has a **Reborn e2e** path | ||||||||||||||||||||||||||||||||
| (turns, runtime lanes, host services, authorization, approvals, networking, secrets, product | ||||||||||||||||||||||||||||||||
| workflow, capability dispatch), run `scripts/reborn-e2e-rust.sh`. Any tier you cannot run here (needs | ||||||||||||||||||||||||||||||||
| Postgres/Docker/keys) → note it **"CI-deferred"** in the PR body. Everything runnable must be **green | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,8 +31,12 @@ Read `.claude/skills/ironclaw-reborn-testing/SKILL.md` and | |
| 3. **Architecture:** dependency and composition boundaries — | ||
| `cargo test -p ironclaw_architecture_tests`. | ||
| 4. **Backend/runtime integration:** DB-, Docker-, or runtime-shaped behavior — | ||
| use the owning feature-gated suite and `cargo test --features integration` | ||
| when required by its guide. | ||
| use the owning crate's feature-gated suite | ||
| (`cargo test -p <owning-crate> --features integration`, e.g. | ||
| `-p ironclaw_hooks` for the Postgres/libSQL hooks parity matrix) when its | ||
| guide requires it. The workspace-root `integration` feature is empty with no | ||
| consumers, so a bare root `cargo test --features integration` adds nothing | ||
| over `cargo test`. | ||
|
Comment on lines
+34
to
+39
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. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
rg -n -C 2 -- '--features integration|test-support' \
.claude/rules/testing.md \
.claude/skills/ironclaw-reborn-testing/SKILL.md
rg -n -C 2 '^\[features\]|integration|test-support' \
crates/loop/ironclaw_hooks/Cargo.toml \
Cargo.toml \
.github/workflows/platform-and-compat.ymlRepository: nearai/ironclaw Length of output: 27853 🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
# Inspect the exact feature/test manifest for ironclaw_hooks and the two documented guidance ranges.
sed -n '1,130p' crates/loop/ironclaw_hooks/Cargo.toml
printf '\n--- .claude docs snippets ---\n'
sed -n '28,42p' .claude/rules/testing.md
sed -n '22,32p' .claude/skills/ironclaw-reborn-testing/SKILL.md
# Deterministic Cargo manifest invariant check: read package manifest text and check which features
# each [[test]] target requires without installing/making/cleaning dependencies.
python3 - <<'PY'
from pathlib import Path
p = Path("crates/loop/ironclaw_hooks/Cargo.toml")
text = p.read_text()
lines = text.splitlines()
in_test = False
test = {}
for i, line in enumerate(lines, start=1):
stripped = line.strip()
if stripped == "[[[[test]]]]:.format(7): # not valid, adjust
pass
PYRepository: nearai/ironclaw Length of output: 7768 Align the backend-integration commands with
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| 5. **Recorded model behavior:** hermetic fixtures for tool choice/request shape; | ||
| validate with `scripts/ci/check-reborn-qa-fixtures.sh`. | ||
| 6. **Browser/E2E:** user-visible WebUI flows under `tests/e2e/`. | ||
|
|
||
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.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the retired-path sentence.
Line 10 is not grammatical: “used to carry scaffolded into” is unclear. Replace it with “used to scaffold the deleted v1 gateway SSE path.”
Proposed wording fix
📝 Committable suggestion
🤖 Prompt for AI Agents