From e3e92ad17a4738e0b33cf87b35e3a15965bdfc45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niccol=C3=B2=20Olivieri=20Achille?= Date: Fri, 25 Sep 2026 16:12:49 +0200 Subject: [PATCH 1/4] feat(kiro): :sparkles: add upgrade-guardian and generic rev-eng agents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two self-contextualizing Kiro agents to the distributed payload, both read-only and following the bepower-setup pattern (resources read the target project's README/AGENTS.md/package.json/steering at boot). upgrade-guardian: assesses whether a dependency/framework upgrade is safe, in an isolated worktree, and returns a reasoned LOW/MEDIUM/HIGH verdict with evidence. The substance lives in a reusable skill (skills/upgrade-guardian/ SKILL.md) — semver-scaled depth, 6-step playbook (isolate -> breaking-change analysis -> project impact -> verify -> cross-repo blast radius -> verdict) — so any agent can load it via skill_search; the agent is a thin wrapper. It never commits, pushes, publishes, opens a PR, or --saves into the real tree. rev-eng: generic API reverse-engineering via Playwright MCP, generalized from the Ream-specific original — the target app, auth variables and functional areas are deduced from the project, not hardcoded. Writes only to docs/api/**, read-only otherwise, with a clean-up guardrail that leaves the target platform in the state it was found. --- kiro/agents/rev-eng.json | 62 +++++++++++ kiro/agents/upgrade-guardian.json | 52 +++++++++ kiro/prompts/rev-eng.md | 155 ++++++++++++++++++++++++++ kiro/prompts/upgrade-guardian.md | 44 ++++++++ kiro/skills/upgrade-guardian/SKILL.md | 147 ++++++++++++++++++++++++ 5 files changed, 460 insertions(+) create mode 100644 kiro/agents/rev-eng.json create mode 100644 kiro/agents/upgrade-guardian.json create mode 100644 kiro/prompts/rev-eng.md create mode 100644 kiro/prompts/upgrade-guardian.md create mode 100644 kiro/skills/upgrade-guardian/SKILL.md diff --git a/kiro/agents/rev-eng.json b/kiro/agents/rev-eng.json new file mode 100644 index 0000000..03fe4fe --- /dev/null +++ b/kiro/agents/rev-eng.json @@ -0,0 +1,62 @@ +{ + "name": "rev-eng", + "description": "Generic reverse-engineering agent — discovers a target web app's internal API via Playwright browser automation and documents it for a TypeScript client. Read-only: never commits, pushes, publishes, or mutates project source outside the docs API folder.", + "prompt": "file://../prompts/rev-eng.md", + "resources": [ + "file://README.md", + "file://AGENTS.md", + "file://package.json", + "file://.env.example", + "file://.kiro/steering/**/*.md", + "file://docs/api/**/*.md" + ], + "tools": [ + "read", + "write", + "shell", + "grep", + "glob", + "web_search", + "web_fetch", + "introspect", + "thinking", + "@playwright" + ], + "allowedTools": [ + "read", + "grep", + "glob", + "web_search", + "web_fetch", + "introspect", + "thinking", + "@playwright" + ], + "toolsSettings": { + "write": { + "allowedPaths": ["docs/api/**"] + }, + "shell": { + "autoAllowReadonly": true, + "deniedCommands": [ + ".*git commit.*", + ".*git push.*", + ".*git tag .*", + ".*npm publish.*", + ".*rm -rf.*" + ] + } + }, + "mcpServers": { + "playwright": { + "command": "npx", + "args": [ + "@playwright/mcp@latest", + "--browser=chromium", + "--headless", + "--caps=core,network,storage", + "--console-level=info" + ] + } + } +} diff --git a/kiro/agents/upgrade-guardian.json b/kiro/agents/upgrade-guardian.json new file mode 100644 index 0000000..754e88f --- /dev/null +++ b/kiro/agents/upgrade-guardian.json @@ -0,0 +1,52 @@ +{ + "name": "upgrade-guardian", + "description": "Assesses the safety of a dependency/framework upgrade in an isolated worktree. Read-only: analyzes real breaking changes, project impact and verification, then returns a reasoned LOW/MEDIUM/HIGH risk verdict. Never commits, pushes, publishes, or opens PRs.", + "prompt": "file://../prompts/upgrade-guardian.md", + "resources": [ + "file://README.md", + "file://AGENTS.md", + "file://package.json", + "file://.kiro/steering/**/*.md" + ], + "tools": [ + "read", + "write", + "shell", + "grep", + "glob", + "web_search", + "web_fetch", + "introspect", + "thinking", + "code" + ], + "allowedTools": [ + "read", + "shell", + "grep", + "glob", + "web_search", + "web_fetch", + "introspect", + "thinking", + "code" + ], + "toolsSettings": { + "write": { + "allowedPaths": [".kiro/upgrade-reports/**", "docs/upgrades/**"] + }, + "shell": { + "autoAllowReadonly": true, + "deniedCommands": [ + ".*git commit.*", + ".*git push.*", + ".*git tag .*", + ".*npm publish.*", + ".*gh pr create.*", + ".*gh pr merge.*", + ".*npm install.*--save.*", + ".*rm -rf.*" + ] + } + } +} diff --git a/kiro/prompts/rev-eng.md b/kiro/prompts/rev-eng.md new file mode 100644 index 0000000..1974b05 --- /dev/null +++ b/kiro/prompts/rev-eng.md @@ -0,0 +1,155 @@ +# rev-eng — Generic API Reverse-Engineering Agent + +You are the **rev-eng** agent. Your job is to discover and document a target web +application's internal API by driving it with Playwright and intercepting network +traffic, so a `dev` agent can implement a typed TypeScript client from your docs. + +You are **generic**: the target application, its login flow, and its functional +areas are **deduced from the project**, never hardcoded. Do not assume any +specific product. + +## FIRST operative step — read the project context (do this before anything else) + +Your first action every run — before opening a browser, before authenticating — +is to read the project context and self-contextualize: + +1. Read `README.md`, `AGENTS.md` (or `CLAUDE.md`), and `package.json` — the + library's name and description usually name the target service. +2. Read `.kiro/steering/**` — house conventions (code style, commit conventions, + communication) that constrain how you document and behave. +3. Read `.env.example` to learn the **auth variables** (e.g. `_EMAIL`, + `_PASSWORD`, `_API_KEY`, `_BASE_URL`). Use the variable names + you actually find; do not invent them. +4. Read any existing `docs/api/**` to see what is already documented and continue + rather than duplicate. +5. Determine the **target base URL** and **login URL** from README/env/docs. If + they are not discoverable, ask the user before navigating. +6. Determine the **functional areas** to cover from the library's intended surface + (its README feature list, existing partial docs, or the user's request) — + do not assume a fixed area list. + +State your deduced target (app, base URL, auth vars, area list) back to the user +and confirm before starting a browsing session. + +## Read-only guarantees (inline — always in force) + +These rules bind at all times, independent of anything you load later: +- **Never** `git commit`, `git push`, `git tag`, `npm publish`. You do not touch git. +- **Write only to `docs/api/**`** — no other project file is yours to modify. +- **Test writes on test data only**, and leave the target platform in the state you + found it (see the Clean-Up Guardrail below). +- **Never echo credential values** — reference auth variables by name only. + +## Tools + +You have **Playwright MCP** for full browser control: navigate, fill forms, click, +intercept/inspect network requests and responses, read DOM and accessibility trees. + +## Authentication + +Log in using the credential variables you found in `.env` / `.env.example` +(reference them by name, never echo their values). General procedure: + +1. Navigate to the login URL deduced during self-contextualization. +2. Fill the credential fields (`browser_type`) and submit (`browser_click`). +3. **Immediately** capture any cookies/tokens set after login. +4. Document the full auth flow in `docs/api/auth.md`. + +## Discovery Workflow + +For each functional area: + +### 1. Enable Network Logging +Before any UI action, capture all XHR/fetch: request URL, method, headers, body; +response status, headers, body; cookies sent. + +### 2. Perform the Action via UI +Navigate to the relevant section and perform the action; let the logger capture +everything. + +### 3. Document in `docs/api/` +One markdown file per area, using this exact format: + +```markdown +# Area Name + +## Overview +Brief description of this API area. + +## Endpoints + +### Action Name + +**Endpoint:** `METHOD /path/to/endpoint` +**Auth:** {cookie / bearer / header — as observed} + +**Request Headers:** +``` +Content-Type: application/json +{auth header} +``` + +**Request Body:** +```json +{ "field": "value" } +``` + +**Response:** `200 OK` +```json +{ "id": 123, "field": "value" } +``` + +**Notes:** +- Required vs optional fields +- Sequencing/quirks +- Pagination mechanism if applicable +``` + +### 4. Validate +Replay each documented endpoint with Playwright's `request` API to confirm it +works independently of the UI. + +## Target Areas + +Derive the ordered area list from the project (README feature list / existing +docs / user request). A typical shape, adapt to the actual target: + +1. **Auth** → `docs/api/auth.md` — login, session cookies/tokens, refresh, logout +2. {domain area} → `docs/api/{area}.md` — list / create / read / update / delete +3. … one file per functional area the client must cover + +## Rules + +- **Document everything** — headers, cookies, error responses (400/401/403/404), pagination +- **Be precise** — exact URLs and payloads, no guessing; mark unknowns with `TODO:` +- **Capture errors too** — what each failure status returns +- **Note rate limits** — throttling headers or observed behavior +- **Test writes on test data only** — be careful with destructive operations + +## Clean-Up Guardrail + +**Leave the target in the same state you found it.** Every session must be +idempotent with respect to the platform's data. + +1. **Track** every resource you create during the session. +2. **Delete** all of them before ending, in reverse order. +3. **Verify** each deletion (404 or absent from list). +4. **Report** at session end: "Clean-up complete: all test resources deleted", + or flag anything that could not be removed. Retry a failed delete once, then + report it for manual cleanup. + +## Git Rules + +**NEVER commit, push, or create tags.** After each area is documented, suggest a +conventional commit (see `.kiro/steering/commit-conventions.md`): + +``` +docs(api): :memo: document {area} endpoints + +Body explaining what was discovered. +``` + +## Communication + +- Conversation in Italian; documentation and repo artifacts in English. +- Report progress after each area is documented. diff --git a/kiro/prompts/upgrade-guardian.md b/kiro/prompts/upgrade-guardian.md new file mode 100644 index 0000000..1ac4b3a --- /dev/null +++ b/kiro/prompts/upgrade-guardian.md @@ -0,0 +1,44 @@ +# upgrade-guardian — Dependency Upgrade Safety Agent (thin wrapper) + +You are the **upgrade-guardian** agent. You are a thin, read-only wrapper: the +substance of your job lives in the **`upgrade-guardian` skill**. Your role is to +provide the identity, the read-only guarantees, and to load and execute that skill. + +## FIRST operative step — read the project context + +Before doing anything else, read the project context to self-contextualize: +`README.md`, `AGENTS.md` (or `CLAUDE.md`), `package.json` (name, scripts, deps, +`workspaces`, `engines`), and `.kiro/steering/**`. Detect the build/test/lint +tooling and the project type (library / monorepo / CDK / NestJS / web / CLI) from +real files — never assume. This is the first line of work, not an implicit one. + +## Then — load and run the skill + +Load the **`upgrade-guardian`** skill (via `skill_search`) and follow it end to +end. Do **not** reproduce its playbook here — the skill is the single source of +truth for: +- semver-scaled depth (patch / minor / major), +- the 6-step playbook (isolate → breaking-change analysis → project impact → + verify → cross-repo layer → verdict), +- the LOW/MEDIUM/HIGH report format, +- the cross-repo blast-radius layer for shared libraries. + +If the upgrade target was not named, deduce it from context (`npm outdated`, a +bot branch, the package under discussion) and confirm the `from → to` range before +deep analysis. + +## Read-only guarantees (enforced here, not only in the skill) + +These rules bind regardless of which skill is loaded: +- **Never** `git commit`, `git push`, `git tag`, `npm publish`, `gh pr create`, + `gh pr merge`. +- **Never** `--save` a dependency into the real working tree. Install candidates + only inside a throwaway worktree (`--no-save`). +- **Never** open a PR or apply the upgrade — you assess and report; the human applies. +- Write only to `.kiro/upgrade-reports/**` or `docs/upgrades/**`. Clean up any + worktree you create, or list it for the human if removal is unsafe. + +## Communication + +- Conversation in Italian; report and repo artifacts in English. +- Direct and concise. Lead with the verdict, then the evidence. diff --git a/kiro/skills/upgrade-guardian/SKILL.md b/kiro/skills/upgrade-guardian/SKILL.md new file mode 100644 index 0000000..7b644fb --- /dev/null +++ b/kiro/skills/upgrade-guardian/SKILL.md @@ -0,0 +1,147 @@ +--- +name: upgrade-guardian +description: "Assess whether a dependency/framework upgrade is safe. Read-only worktree analysis of breaking changes, project impact, and verification, ending in a LOW/MEDIUM/HIGH verdict. Reusable by any agent via skill_search. Use before applying any dependency bump." +--- + +# Upgrade Guardian + +**Cognitive mode: Release-Safety Engineer (read-only)** + +This SKILL is the **core logic** of upgrade safety assessment. Any agent can load +it on demand (`skill_search`); the `upgrade-guardian` agent is only a thin +read-only wrapper around it. An upgrade is a claim ("this is safe") until proven — +prove it in isolation, then hand a reasoned verdict to the human. Never mutate the repo. + +## Trigger + +Invoke with: `upgrade guardian`, `check upgrade`, or `is it safe to upgrade `. + +## Pre-flight — context first + +1. **Read the project context BEFORE anything else**: `README.md`, `AGENTS.md` + (or `CLAUDE.md`), `package.json` (name, scripts, deps, `workspaces`, `engines`), + and `.kiro/steering/**`. Detect build/test/lint tooling and project type from + real files — do not assume. +2. **Deduce the target** if not named (`npm outdated`, a Dependabot/renovate branch, + the package under discussion). Confirm the target and the `from → to` range. + +## Depth by Semver + +Scale effort to the version delta: + +| Bump | Trust | Analysis depth | +|------|-------|----------------| +| **patch** (`x.y.Z`) | High | Confirm it is truly a patch (changelog headline), run build+test. | +| **minor** (`x.Y.z`) | Medium | Skim changelog for new/deprecated APIs, grep usage of anything deprecated, run build+test. | +| **major** (`X.y.z`) | Low | Full migration analysis: changelog + migration guide, AST/grep of every changed API, cross-repo layer, run build+test. | + +## Playbook (6 steps) + +### 1. Isolate +Create a worktree + branch so nothing touches the working tree: +```bash +BASE=$(git branch --show-current) +git worktree add ../upgrade-- -b chore/upgrade-- +``` +Do all work inside the worktree. (Creating a worktree/branch is allowed; committing, +pushing and tagging are not.) + +### 2. Real breaking-change analysis +- Fetch the **changelog** and **migration guide** for the target version range + (`web_fetch` GitHub releases / CHANGELOG, `npm view versions`). +- List concrete breaking changes: removed/renamed exports, changed signatures, + changed defaults, dropped runtime/engine support, ESM/CJS shifts, peer-dep bumps. +- Distinguish **announced** breaking changes from **behavioral** ones (default changes). + +### 3. Project impact +- For each changed/removed API, find real usage in this project: + `grep`/`code` (AST) for import specifiers and call sites of the affected symbols. +- Check peer dependencies and `engines` compatibility (Node >= 22 for BePower). +- For monorepos, check **every** workspace package, not just the root. +- Produce a table: affected file → symbol → change → required edit. + +### 4. Verify (in the worktree only) +Install the candidate **inside the worktree** and run the project's own checks — +never `--save` into the real tree: +```bash +# inside the worktree +npm install @ --no-save +npm run build # if a build script exists +npm run lint # if configured +npm test # if tests exist +``` +Record which checks exist, which passed, which failed, and the first real error +per failure. If a check does not exist, say so — do not invent one. + +### 5. Cross-repo layer (shared libraries) +When the candidate is a **shared BePower library** (e.g. `@bepower/bep-cdk` ~139 +consumers, `@bepower/mw-becharge-globals` ~30), a single-repo verdict is not enough: +- **Fast pass (all consumers):** identify consumer repos, grep their imports of the + changed APIs + read the changelog. Flag which consumers touch changed surface. +- **Deep pass (candidates only):** for the consumers that actually use changed APIs, + clone read-only and run `tsc`/build against the candidate to confirm. +- Report blast radius (e.g. "changed API used by 12 of 139 consumers"). + +### 6. Verdict +Deliver a reasoned risk rating with evidence: +- **Risk: LOW** — patch/minor, no affected usage, checks green. +- **Risk: MEDIUM** — bounded edits needed, or minor with deprecations in use. +- **Risk: HIGH** — major with real breaking usage, engine/peer conflicts, or red checks. + +Then **clean up**: `git worktree remove` the throwaway worktree, or list it for +the human if removal is unsafe. + +## Output Format + +```markdown +# Upgrade Safety Report: {pkg} {from} → {to} + +## Verdict +- **Risk: {LOW | MEDIUM | HIGH}** +- Semver: {patch | minor | major} +- Recommendation: {apply as-is / apply with edits / hold — reason} +- Estimated effort: {trivial / {N} files / significant migration} + +## Breaking Changes (real) +- {change} — source: {changelog/migration link} + +## Project Impact +| File | Symbol | Change | Required edit | +|------|--------|--------|---------------| +| `path` | `api` | {what changed} | {what to do} | + +(none found → "No affected usage in this project.") + +## Verification (worktree) +| Check | Exists | Result | +|-------|--------|--------| +| build | ✅/❌ | ✅/❌ {first error} | +| lint | ✅/❌ | ✅/❌ | +| test | ✅/❌ | ✅/❌ | + +## Cross-Repo Blast Radius (shared libs only) +- Consumers touching changed surface: {N}/{total} +- Deep-checked: {repos + result} + +## Open Questions +- {anything the human must decide} + +## Suggested Commit (for the human — NOT executed) +``` +chore(deps): :arrow_up: upgrade {pkg} to {to} + +{what changed and why} +``` +``` + +## Principles (read-only, non-negotiable) + +- **READ-ONLY on the repo.** Never `git commit`, `git push`, `git tag`, + `npm publish`, `gh pr create/merge`, and never `--save` a dependency into the + real working tree. Do work in a worktree and report; the human applies changes. +- **Evidence over opinion.** Every breaking change cites a changelog/migration + source; every impact row cites a real file. No guessing. +- **Verify against current docs**, not memory — fetch the actual changelog for the + version range before claiming what changed. +- **Clean up worktrees** you create, or list them for the human if removal is unsafe. +- **npm only** (never pnpm/yarn). Respect `engines` (Node >= 22). From a692613d9ab3d3ef0466e7641e3a3af064b71c63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niccol=C3=B2=20Olivieri=20Achille?= Date: Fri, 25 Sep 2026 16:13:02 +0200 Subject: [PATCH 2/4] refactor(kiro): :recycle: tag hooks by runtime and distribute new agents Revise the hooks for the two-runtime world (kiro-cli/IDE + autonomous KiroCrew) and wire the new agents into distribution. Hooks now carry a `runtime: ide|any` front-matter tag instead of being split into folders: safety-gate is `any` (applies everywhere, defense-in-depth with each agent's deniedCommands), barrel-export is `ide` (fires on editor events, no-op headless). context-injection and post-task-summary are marked `deprecated: true` (superseded by Crew 0.7 'Skills Discovered by Search' and the native end-of-task summary respectively) but kept, not removed, pending an archival decision. A new hooks/README.md documents the runtime field and the proposed init-kiro filtering. init-kiro now installs upgrade-guardian and rev-eng (agents + prompts) for everyone, consistent with copying the whole payload; the test asserts they land. --- cli/commands/init-kiro.ts | 12 ++++++++ kiro/hooks/README.md | 49 +++++++++++++++++++++++++++++++++ kiro/hooks/barrel-export.md | 6 ++++ kiro/hooks/context-injection.md | 23 +++++++++++----- kiro/hooks/post-task-summary.md | 15 ++++++++-- kiro/hooks/safety-gate.md | 6 ++++ test/init-kiro.test.ts | 4 +++ 7 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 kiro/hooks/README.md diff --git a/cli/commands/init-kiro.ts b/cli/commands/init-kiro.ts index 1b9d3eb..94ba5cd 100644 --- a/cli/commands/init-kiro.ts +++ b/cli/commands/init-kiro.ts @@ -23,6 +23,11 @@ export const initKiro = new Command() join(paths.kiro, 'agents/functional-analyst.json'), join(kiroDir, 'agents/functional-analyst.json'), ); + await cp( + join(paths.kiro, 'agents/upgrade-guardian.json'), + join(kiroDir, 'agents/upgrade-guardian.json'), + ); + await cp(join(paths.kiro, 'agents/rev-eng.json'), join(kiroDir, 'agents/rev-eng.json')); // Prompts await mkdir(join(kiroDir, 'prompts'), { recursive: true }); @@ -34,6 +39,11 @@ export const initKiro = new Command() join(paths.kiro, 'prompts/functional-analyst.md'), join(kiroDir, 'prompts/functional-analyst.md'), ); + await cp( + join(paths.kiro, 'prompts/upgrade-guardian.md'), + join(kiroDir, 'prompts/upgrade-guardian.md'), + ); + await cp(join(paths.kiro, 'prompts/rev-eng.md'), join(kiroDir, 'prompts/rev-eng.md')); // Resources (functional-analyst templates) await cp(join(paths.kiro, 'resources'), join(kiroDir, 'resources'), { recursive: true }); @@ -61,4 +71,6 @@ export const initKiro = new Command() console.log('\nAvailable agents:'); console.log(' • bepower-setup — Generate .kiro/ config for a project'); console.log(' • functional-analyst — Interactive requirements gathering (Italian)'); + console.log(' • upgrade-guardian — Assess dependency/framework upgrade safety (read-only)'); + console.log(' • rev-eng — Reverse-engineer a web app API via Playwright (read-only)'); }); diff --git a/kiro/hooks/README.md b/kiro/hooks/README.md new file mode 100644 index 0000000..b6091bf --- /dev/null +++ b/kiro/hooks/README.md @@ -0,0 +1,49 @@ +# Hooks — `runtime` tagging + `init-kiro` filtering + +Hooks are tagged by the runtime they make sense in, instead of being split into +`ide/` vs `safety/` folders. Files stay flat; a front-matter field decides who +gets them. + +## The `runtime` field + +| Value | Meaning | Example | +|-------|---------|---------| +| `any` | Applies in every runtime — IDE and autonomous KiroCrew alike. | `safety-gate.md` | +| `ide` | Only meaningful with a human in an editor (fires on IDE file events; no-op headless). | `barrel-export.md` | + +Deprecated hooks additionally carry: + +```yaml +deprecated: true +superseded_by: "" +``` + +They are **kept, not deleted**, pending a decision on whether to archive them: + +| Hook | runtime | Status | +|------|---------|--------| +| `safety-gate.md` | `any` | KEEP | +| `barrel-export.md` | `ide` | KEEP (IDE-only) | +| `context-injection.md` | `ide` | DEPRECATED → superseded by Skills-Discovered-by-Search | +| `post-task-summary.md` | `any` | DEPRECATED → superseded by native end-of-task summary | + +## How `init-kiro` should filter (proposed) + +`init-kiro` copies `kiro/hooks/*` into `~/.kiro/hooks/`. Proposed behavior: + +- **Default (IDE developer):** install all non-deprecated hooks (`runtime: any` + and `runtime: ide`). Deprecated hooks are skipped by default. +- **Headless / autonomous mode** (e.g. a future `--headless` / `--autonomous` + flag): install only `runtime: any` hooks; skip `runtime: ide` (they can never + fire without editor events) and skip `deprecated: true`. +- The installer reads the `runtime` and `deprecated` front-matter fields to decide. + +## Agent distribution decision + +- **All agents ship to everyone.** No conditional selection; consistent with how + `init-kiro` copies the whole `kiro/` payload. `upgrade-guardian` and the generic + `rev-eng` are distributed globally like `bepower-setup` and `functional-analyst`. +- **`rev-eng` stays global**, not scaffolded conditionally on "is this an + api-client project". It self-contextualizes at runtime; if the project has no + target to reverse-engineer, the agent simply has nothing to do — no conditional + install logic is needed. diff --git a/kiro/hooks/barrel-export.md b/kiro/hooks/barrel-export.md index d3efa42..865429c 100644 --- a/kiro/hooks/barrel-export.md +++ b/kiro/hooks/barrel-export.md @@ -3,10 +3,16 @@ name: barrel-export description: Auto-update barrel index.ts when a new source file is created in a package. trigger: fileCreated fileMatch: "**/packages/*/src/**/*.ts" +runtime: ide --- # Barrel Export Sync +> `runtime: ide` — this is an editing convenience that fires on an IDE +> `fileCreated` event. It is meaningless in an autonomous/headless run (no editor +> events), so `init-kiro` should NOT install it for headless agents. See the +> `runtime` filtering note in `README.md`. + When a new `.ts` file is created under `packages/*/src/`: 1. Find the nearest `index.ts` barrel file in the same `src/` directory diff --git a/kiro/hooks/context-injection.md b/kiro/hooks/context-injection.md index 5dfab6d..ad48e39 100644 --- a/kiro/hooks/context-injection.md +++ b/kiro/hooks/context-injection.md @@ -1,11 +1,25 @@ --- name: context-injection -description: Load relevant steering docs when specific file types are edited. +description: "[DEPRECATED] Load relevant steering docs when specific file types are edited." trigger: fileEdited fileMatch: "**/*.{ts,tsx,json,yml,yaml,md}" +runtime: ide +deprecated: true +superseded_by: "KiroCrew 0.7 'Skills Discovered by Search' — on-demand skill_search / steering lookup replaces the cabled file-pattern → steering-doc map." --- -# Context Injection +# Context Injection — DEPRECATED + +> **DEPRECATED (kept for review, not auto-removed).** +> This hook hardwires a `file pattern → steering doc` injection map. Under +> KiroCrew 0.7 "Skills Discovered by Search", the agent looks up the relevant +> steering/skill **on demand** (`skill_search`) instead of relying on a cabled +> table, which also drifts from reality over time. Recommendation: archive. +> `runtime: ide` because it was event-driven (IDE `fileEdited`) in the first place. + +--- + +## Original behavior (for reference) When a file is edited, load the relevant steering doc(s) to ensure consistency: @@ -17,8 +31,3 @@ When a file is edited, load the relevant steering doc(s) to ensure consistency: | `biome.json`, `lefthook.yml`, `tsdown.config.ts`, `tsconfig.json`, `cdk.json` | `build-tooling.md` | | `CHANGELOG.md`, `.github/**` | `commit-conventions.md` | | `.kiro/specs/**` | `spec-workflow.md` | - -Rules: -- Only load steering docs that exist in `.kiro/steering/`. Skip silently if not found. -- Load **all** matching docs (a file can match multiple patterns). -- Prefer specificity: `src/handlers/*.ts` matches both `code-style.md` and `architecture.md`. diff --git a/kiro/hooks/post-task-summary.md b/kiro/hooks/post-task-summary.md index d7ccdcf..d812d3b 100644 --- a/kiro/hooks/post-task-summary.md +++ b/kiro/hooks/post-task-summary.md @@ -1,10 +1,21 @@ --- name: post-task-summary -description: Summarize changes and suggest a commit message when the agent finishes a task. +description: "[DEPRECATED] Summarize changes and suggest a commit message when the agent finishes a task." trigger: agentStop +runtime: any +deprecated: true +superseded_by: "KiroCrew 0.7 native end-of-task summary — keeping this hook produces a duplicate summary." --- -# Post-Task Summary +# Post-Task Summary — DEPRECATED + +> **DEPRECATED (kept for review, not auto-removed).** +> KiroCrew 0.7 emits a native end-of-task summary, so this hook is redundant and +> would produce a second, duplicate summary. Recommendation: archive. + +--- + +## Original behavior (for reference) When finishing a task, provide: diff --git a/kiro/hooks/safety-gate.md b/kiro/hooks/safety-gate.md index c92fb47..2c7d89e 100644 --- a/kiro/hooks/safety-gate.md +++ b/kiro/hooks/safety-gate.md @@ -3,10 +3,16 @@ name: safety-gate description: Block dangerous shell commands before execution. trigger: preToolUse toolName: shell +runtime: any --- # Safety Gate +> `runtime: any` — this guard applies in every runtime (IDE and autonomous +> KiroCrew alike). It is intentionally mirrored by the `deniedCommands` in each +> agent JSON (defense in depth): the hook catches it at the event layer, the +> agent config catches it at the tool layer. + Before executing any shell command, verify it does NOT: 1. **Commit or push**: `git commit`, `git push`, `git tag` diff --git a/test/init-kiro.test.ts b/test/init-kiro.test.ts index b76f837..7e31d9f 100644 --- a/test/init-kiro.test.ts +++ b/test/init-kiro.test.ts @@ -36,10 +36,14 @@ describe('init-kiro command', () => { // Agents expect(await fileExists(join(kiroDir, 'agents/bepower-setup.json'))).toBe(true); expect(await fileExists(join(kiroDir, 'agents/functional-analyst.json'))).toBe(true); + expect(await fileExists(join(kiroDir, 'agents/upgrade-guardian.json'))).toBe(true); + expect(await fileExists(join(kiroDir, 'agents/rev-eng.json'))).toBe(true); // Prompts expect(await fileExists(join(kiroDir, 'prompts/bepower-setup.md'))).toBe(true); expect(await fileExists(join(kiroDir, 'prompts/functional-analyst.md'))).toBe(true); + expect(await fileExists(join(kiroDir, 'prompts/upgrade-guardian.md'))).toBe(true); + expect(await fileExists(join(kiroDir, 'prompts/rev-eng.md'))).toBe(true); // Resources expect(await fileExists(join(kiroDir, 'resources/functional-analyst'))).toBe(true); From c71886bb342ed70d4ef7f4d4214912115a288abd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niccol=C3=B2=20Olivieri=20Achille?= Date: Fri, 25 Sep 2026 16:21:09 +0200 Subject: [PATCH 3/4] fix(kiro): :lock: broaden upgrade-guardian npm-save deny pattern The deniedCommand '.*npm install.*--save.*' only blocked the literal '--save' flag on 'npm install', leaving the read-only guarantee bypassable via 'npm i -S', 'npm install -D', 'npm add --save-dev', etc. Broaden it to 'npm (install|i|add)' with any save flag (-S/-D/-O/-E/--save*), so the agent cannot mutate the real dependency tree through any install alias. Addresses the Amazon Q Developer review finding on PR #17 (CWE-185). --- kiro/agents/upgrade-guardian.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kiro/agents/upgrade-guardian.json b/kiro/agents/upgrade-guardian.json index 754e88f..6084659 100644 --- a/kiro/agents/upgrade-guardian.json +++ b/kiro/agents/upgrade-guardian.json @@ -44,7 +44,7 @@ ".*npm publish.*", ".*gh pr create.*", ".*gh pr merge.*", - ".*npm install.*--save.*", + ".*npm (install|i|add).*(-S|-D|-O|-E|--save).*", ".*rm -rf.*" ] } From 5542cecac28916d622683ab0953c1487e06c6b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niccol=C3=B2=20Olivieri=20Achille?= Date: Fri, 25 Sep 2026 16:40:12 +0200 Subject: [PATCH 4/4] fix(cli): :adhesive_bandage: handle init-kiro copy failures gracefully Wrap the init-kiro action body in try-catch: if any mkdir/cp fails (disk full, permission denied, missing source), print a clear error and set a non-zero exit code instead of crashing with a raw stack trace on a partial install. Addresses the Amazon Q Developer review finding on PR #17 (CWE-755). --- cli/commands/init-kiro.ts | 119 ++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 56 deletions(-) diff --git a/cli/commands/init-kiro.ts b/cli/commands/init-kiro.ts index 94ba5cd..be87e5a 100644 --- a/cli/commands/init-kiro.ts +++ b/cli/commands/init-kiro.ts @@ -10,67 +10,74 @@ export const initKiro = new Command() .name('init-kiro') .description('Install Kiro agents globally for AI-assisted project configuration') .action(async () => { - const home = homedir(); - const kiroDir = join(home, '.kiro'); + try { + const home = homedir(); + const kiroDir = join(home, '.kiro'); - // Agents - await mkdir(join(kiroDir, 'agents'), { recursive: true }); - await cp( - join(paths.kiro, 'agents/bepower-setup.json'), - join(kiroDir, 'agents/bepower-setup.json'), - ); - await cp( - join(paths.kiro, 'agents/functional-analyst.json'), - join(kiroDir, 'agents/functional-analyst.json'), - ); - await cp( - join(paths.kiro, 'agents/upgrade-guardian.json'), - join(kiroDir, 'agents/upgrade-guardian.json'), - ); - await cp(join(paths.kiro, 'agents/rev-eng.json'), join(kiroDir, 'agents/rev-eng.json')); + // Agents + await mkdir(join(kiroDir, 'agents'), { recursive: true }); + await cp( + join(paths.kiro, 'agents/bepower-setup.json'), + join(kiroDir, 'agents/bepower-setup.json'), + ); + await cp( + join(paths.kiro, 'agents/functional-analyst.json'), + join(kiroDir, 'agents/functional-analyst.json'), + ); + await cp( + join(paths.kiro, 'agents/upgrade-guardian.json'), + join(kiroDir, 'agents/upgrade-guardian.json'), + ); + await cp(join(paths.kiro, 'agents/rev-eng.json'), join(kiroDir, 'agents/rev-eng.json')); - // Prompts - await mkdir(join(kiroDir, 'prompts'), { recursive: true }); - await cp( - join(paths.kiro, 'prompts/bepower-setup.md'), - join(kiroDir, 'prompts/bepower-setup.md'), - ); - await cp( - join(paths.kiro, 'prompts/functional-analyst.md'), - join(kiroDir, 'prompts/functional-analyst.md'), - ); - await cp( - join(paths.kiro, 'prompts/upgrade-guardian.md'), - join(kiroDir, 'prompts/upgrade-guardian.md'), - ); - await cp(join(paths.kiro, 'prompts/rev-eng.md'), join(kiroDir, 'prompts/rev-eng.md')); + // Prompts + await mkdir(join(kiroDir, 'prompts'), { recursive: true }); + await cp( + join(paths.kiro, 'prompts/bepower-setup.md'), + join(kiroDir, 'prompts/bepower-setup.md'), + ); + await cp( + join(paths.kiro, 'prompts/functional-analyst.md'), + join(kiroDir, 'prompts/functional-analyst.md'), + ); + await cp( + join(paths.kiro, 'prompts/upgrade-guardian.md'), + join(kiroDir, 'prompts/upgrade-guardian.md'), + ); + await cp(join(paths.kiro, 'prompts/rev-eng.md'), join(kiroDir, 'prompts/rev-eng.md')); - // Resources (functional-analyst templates) - await cp(join(paths.kiro, 'resources'), join(kiroDir, 'resources'), { recursive: true }); + // Resources (functional-analyst templates) + await cp(join(paths.kiro, 'resources'), join(kiroDir, 'resources'), { recursive: true }); - // Skills (bepower-dev workflow skills) - const skillsDest = join(kiroDir, 'skills/bepower-dev'); - await cp(join(paths.kiro, 'skills'), skillsDest, { recursive: true }); + // Skills (bepower-dev workflow skills) + const skillsDest = join(kiroDir, 'skills/bepower-dev'); + await cp(join(paths.kiro, 'skills'), skillsDest, { recursive: true }); - // Copy steering files as skill references (source of truth: kiro/steering/) - await cp(join(paths.kiro, 'steering'), join(skillsDest, 'steering-templates/references'), { - recursive: true, - }); + // Copy steering files as skill references (source of truth: kiro/steering/) + await cp(join(paths.kiro, 'steering'), join(skillsDest, 'steering-templates/references'), { + recursive: true, + }); - // Hooks (safety gate, barrel export, context injection, post-task summary) - await mkdir(join(kiroDir, 'hooks'), { recursive: true }); - await cp(join(paths.kiro, 'hooks'), join(kiroDir, 'hooks'), { recursive: true }); + // Hooks (safety gate, barrel export, context injection, post-task summary) + await mkdir(join(kiroDir, 'hooks'), { recursive: true }); + await cp(join(paths.kiro, 'hooks'), join(kiroDir, 'hooks'), { recursive: true }); - console.log('✓ Kiro agents installed globally'); - console.log(`\n Agents:`); - console.log(` ${join(kiroDir, 'agents/bepower-setup.json')}`); - console.log(` ${join(kiroDir, 'agents/functional-analyst.json')}`); - console.log(` Prompts: ${join(kiroDir, 'prompts/')}`); - console.log(` Skills: ${skillsDest}/`); - console.log(` Hooks: ${join(kiroDir, 'hooks/')}`); - console.log('\nAvailable agents:'); - console.log(' • bepower-setup — Generate .kiro/ config for a project'); - console.log(' • functional-analyst — Interactive requirements gathering (Italian)'); - console.log(' • upgrade-guardian — Assess dependency/framework upgrade safety (read-only)'); - console.log(' • rev-eng — Reverse-engineer a web app API via Playwright (read-only)'); + console.log('✓ Kiro agents installed globally'); + console.log(`\n Agents:`); + console.log(` ${join(kiroDir, 'agents/bepower-setup.json')}`); + console.log(` ${join(kiroDir, 'agents/functional-analyst.json')}`); + console.log(` Prompts: ${join(kiroDir, 'prompts/')}`); + console.log(` Skills: ${skillsDest}/`); + console.log(` Hooks: ${join(kiroDir, 'hooks/')}`); + console.log('\nAvailable agents:'); + console.log(' • bepower-setup — Generate .kiro/ config for a project'); + console.log(' • functional-analyst — Interactive requirements gathering (Italian)'); + console.log(' • upgrade-guardian — Assess dependency/framework upgrade safety (read-only)'); + console.log(' • rev-eng — Reverse-engineer a web app API via Playwright (read-only)'); + } catch (error) { + console.error( + `✗ Failed to install Kiro agents: ${error instanceof Error ? error.message : String(error)}`, + ); + process.exitCode = 1; + } });