From 541c62b59715f7254670d97d00a238c00f638fff Mon Sep 17 00:00:00 2001 From: Jurie Smit Date: Sat, 21 Mar 2026 08:26:47 +0200 Subject: [PATCH] feat: default config (#439) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add start command: new user entry point with state detection (#387) * fix(commands): add AskUserQuestion to VALID_TOOLS and /start command The /start command session got stuck because AskUserQuestion was not included in the allowed-tools whitelist. This fix addresses three issues: 1. VALID_TOOLS in spec-validator was missing AskUserQuestion, TodoWrite, Agent, and NotebookEdit — preventing commands from declaring these Claude Code built-in tools in their allowed-tools. 2. The /start command template now explicitly includes AskUserQuestion in its allowed-tools frontmatter and instructs the agent to use it for interactive guided choices (Phase 3). 3. Added /start command spec to commands.yaml with AskUserQuestion as a declared tool dependency. Also adds a test case validating all four newly-added tools are accepted by the spec validator. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M * fix(commands): remove unrendered Handlebars comment from start.md output The generated .claude/commands/start.md contained a raw {{! ... }} Handlebars comment that was not processed by the sync engine. Remove it so the generated output is clean Markdown. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M --------- Co-authored-by: Claude * Add configurable prefix to kits commands (#388) * feat(sync): add configurable command prefix for generated slash commands Add `commandPrefix` setting to overlay settings that namespaces all generated slash commands across platforms: - Claude Code: subdirectory strategy (kits/check.md → /project:kits:check) - Cursor/Windsurf/Copilot/Codex: filename prefix (kits-check.md → /kits-check) - Team commands excluded from prefixing (already namespaced) Changes: - Add resolveCommandPath() helper with subdirectory/filename strategies - Update syncClaudeCommands, syncClaudeSkills, syncCursorCommands, syncWindsurfCommands, syncCopilotPrompts, syncCodexSkills - Add commandPrefix to vars from overlay settings - Add commandPrefixedName to buildCommandVars - Add 16 unit + integration tests (all pass, 93 existing tests unaffected) Default is null (no prefix) for full backwards compatibility. https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p * fix(sync): address review findings for command prefix - Remove unused afterAll import from test file - Add clarifying comment that non-spec command files are also prefixed - Add 2 integration tests verifying commandPrefixedName template variable renders correctly with and without prefix https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p --------- Co-authored-by: Claude * fix(ci): CI remediation — package manager, review findings, test stability (#390) * fix(ci): resolve 7 bugs from project review - BUG-001: Replace flaky discover test with controlled temp fixture - BUG-002: Run prettier --write to fix formatting drift - BUG-003: Add form-template detection skip in issue label validation - BUG-005: Change claude.yml to self-hosted runner - BUG-006: Align branch protection required status checks with project.yaml - BUG-007: Fix command injection in resolve-merge.sh (use grep -F) Co-Authored-By: Claude Opus 4.6 * docs: update changelog, add planning registry review findings - Add changelog entries for Wave 1-3 fixes (Added/Changed/Fixed/Removed) - Add Project Review Findings section to planning registry (PR-001 to PR-014) - Update planning docs after sync merge Co-Authored-By: Claude Opus 4.6 * feat(review): add --generate-plans flag to project-review command Add Phase 2.5 plan generation after project review findings. When --generate-plans is passed (default: true), scaffold plan files from critical/high findings into docs/planning/review-findings/. Also includes sync cleanup of stale cursor/windsurf settings. Co-Authored-By: Claude Opus 4.6 * chore(sync): regenerate all outputs after project review fixes Co-Authored-By: Claude Opus 4.6 * feat(cli): dynamic flag loading from commands.yaml + context-aware template hook - Replace ~200 lines of hardcoded VALID_FLAGS/FLAG_TYPES with loadCommandFlags() that reads flag definitions from commands.yaml at startup - CLI_INTERNAL_FLAGS/CLI_INTERNAL_FLAG_TYPES cover commands not in commands.yaml - Self-validation warns at startup if any flag is missing a type definition - Update cli.test.mjs to validate CLI_INTERNAL_FLAGS consistency - Fix scaffold-once orphan bug: carry forward manifest entries for files skipped by scaffold-once so orphan cleanup does not delete them - Make protect-templates hook context-aware: skip protection in the agentkit-forge source repo (detected via package.json name) so maintainer agents can edit templates; block only in downstream repos Co-Authored-By: Claude Opus 4.6 * feat(sync): add managed-mode script templates for downstream repos Add 14 script templates (.agentkit/templates/scripts/) with `managed` scaffold mode so downstream repos receive script updates via three-way merge while preserving local customizations. Templates include: create-doc, update-changelog, validate-documentation, validate-numbering, check-documentation-requirement, sync-issues, sync-split-pr, setup-agentkit-branch-governance, and resolve-merge (both .sh and .ps1 variants where applicable). Parameterized templates use {{defaultBranch}} and branch protection variables from project.yaml. Engine wired via syncScripts() under doc-scaffolding feature gate. Co-Authored-By: Claude Opus 4.6 * feat(teams): add TeamForge meta-team for agent team creation (cogmesh #130) Add the TEAMFORGE meta-team (T11) — a structured pipeline for creating, validating, and deploying new agent team specifications. Adapted from cogmesh #130 with a simplified 6-agent pipeline: - input-clarifier: assess requests, extract constraints - mission-definer: lock team definition (ID, scope, accepts) - role-architect: design agent roles and dependencies - prompt-engineer: write agent descriptions and rules - flow-designer: design team command and integration points - team-validator: quality gate for spec consistency Includes /team-forge command with --task flag (create-team, validate-team, audit-teams, update-team) and planning doc. Co-Authored-By: Claude Opus 4.6 * feat(teams): add Strategic Ops team for cross-project coordination Add the STRATEGIC OPS team (T12) — handles framework governance, portfolio analysis, adoption strategy, impact assessment, and release coordination across all repos using AgentKit Forge. 5-agent pipeline: - portfolio-analyst: inventory repos, detect drift, adoption metrics - governance-advisor: versioning strategy, breaking change protocols - adoption-strategist: onboarding, migration paths, rollout plans - impact-assessor: blast radius analysis for template/spec changes - release-coordinator: version bumps, sync waves, release comms Includes /team-strategic-ops command with --task and --scope flags. Co-Authored-By: Claude Opus 4.6 * feat(agents): add agent/team relationship matrix analysis engine + scripts Add comprehensive agent/team relationship analysis with 8 cross-reference matrices and 10 supplementary analyses (orphans, cycles, bottlenecks, reachability, critical path, notification amplifiers, etc.). - Fix YAML structure: strategic-ops agents now under own top-level key - Add explicit agents: lists to forge + strategic-ops teams in teams.yaml - Add consolidation detection responsibilities to portfolio-analyst - Create agent-analysis.mjs engine module (loadFullAgentGraph + renderers) - Wire analyze-agents CLI command with --output/--matrix/--format flags - Add managed-scaffold script templates (bash + PowerShell) - Integrate into sync pipeline (auto-regenerates matrix on spec changes) - Add 33 tests covering all matrices, analyses, and edge cases Co-Authored-By: Claude Opus 4.6 * chore: update documentation files and add plan template - Add trailing newlines to Cursor command documentation files for consistency - Add new plan template files for project planning - Improve markdown table formatting in Claude skills documentation - Remove obsolete .clinerules/testing.md file - Update various rule files with better formatting and advisory rule alignment * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance Co-Authored-By: Claude Opus 4.6 * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. Co-Authored-By: Claude Opus 4.6 * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add Cost Ops team, agents, and multi-provider cost ticket (#364) * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance Co-Authored-By: Claude Opus 4.6 * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. Co-Authored-By: Claude Opus 4.6 * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents (#365) Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs Co-authored-by: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 * fix(teams): address CodeRabbit review findings on strategic-ops PR - Lazy-load js-yaml in cli.mjs after ensureDependencies() to prevent crash when node_modules is missing - Convert YAML frontmatter to PowerShell comment blocks in all 6 PS1 templates to fix invalid PowerShell syntax - Fix protect-templates hook path: use 3 parent traversals to reach .agentkit/package.json from hooks directory - Remove schema-invalid 'phase' field from ai-cost-ops rule domain - Narrow strategic-ops scope: replace **/* catch-all with specific files - Add strategic-ops to cost-ops handoff-chain for consistency - Add Write tool to spec-compliance-auditor, vendor-arbitrage-analyst, and grant-hunter agents - Fix glob matching in resolve-merge.sh (use regex instead of broken sed strip) - Add merge failure vs conflict detection in resolve-merge.ps1 - Add branch existence check in setup-agentkit-branch-governance scripts - Add gh CLI preflight check in sync-split-pr.ps1 - Deduplicate branch protection loop when defaultBranch is 'main' - Fix applies-to glob: docs/planning/cost/** → docs/planning/cost-governance/** - Fix non-canonical doc paths in intake-agent-proposal.md - Add changelog entries for new teams, agents, and analysis engine - Resolve AGENT_TEAMS.md merge conflict (accept narrowed scope) - Run prettier on all modified files Co-Authored-By: Claude Opus 4.6 * fix(templates): add gh auth preflight and changelog divider handling - sync-split-pr.ps1: add gh auth status check before side effects - update-changelog.ps1: stop before --- divider when appending entries Addresses CodeRabbit review comments #7 and #13 on PR #356. Co-Authored-By: Claude Opus 4.6 * fix(sync): set executable permission on analyze-agents.sh Linux CI sync produces +x permissions; align local to match. Co-Authored-By: Claude Opus 4.6 * fix(templates): address CodeRabbit review round 3-4 findings - Fix YAML frontmatter in copilot agent template: use double quotes for description field to handle apostrophes (CRITICAL) - Fix protect-templates.sh/ps1 path traversal: correct parent directory count for .agentkit/package.json source repo detection - Add $PSNativeCommandUseErrorActionPreference to sync-split-pr.ps1 so native command failures (git, pnpm, gh) are treated as fatal - Replace try/catch with $LASTEXITCODE check for gh auth status - Deduplicate branch loop in setup-agentkit-branch-governance.sh when defaultBranch equals 'main' - Fix duplicate verification echo lines in governance scripts Co-Authored-By: Claude Opus 4.6 * style(docs): fix prettier formatting on planning documents Run prettier --write on web-intake-expansion.md and intake-agent-proposal.md to fix CI formatting check. Co-Authored-By: Claude Opus 4.6 * fix(tests): isolate render target gating tests with fresh temp dirs Tests in the "render target gating" describe block shared a single temp directory via beforeAll/afterAll. The first test ran --only claude (generating .claude/ files), and the second ran --only warp expecting no Claude files — but leftovers from test 1 caused the assertion to fail. Changing to beforeEach/afterEach gives each test a clean directory. Closes #377 Co-Authored-By: Claude Opus 4.6 * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(engine): add pre-sync commit guard and interactive apply mode Adds two safety features to the sync pipeline: 1. Pre-sync commit guard: Detects uncommitted changes in protected directories (.agentkit/engines, spec, overlays) before sync runs. In TTY mode, prompts to abort, stash, or continue. In non-TTY mode (CI), prints a warning and proceeds. 2. Interactive apply mode: After rendering, shows a change summary and prompts: apply all / skip all / prompt each file. Per-file prompt supports show-diff and apply-all-remaining. Default in TTY; bypassed with --yes, --no-prompt, or --force. New module: sync-guard.mjs with 4 exported functions and 7 tests. New CLI flags: --yes, --no-prompt for non-interactive sync. Co-Authored-By: Claude Opus 4.6 * chore(sync): regenerate outputs after branch merges Co-Authored-By: Claude Opus 4.6 * chore(sync): regenerate outputs after merge of new-user-entry-point Co-Authored-By: Claude Opus 4.6 * feat(engine): add configurable package manager and fix review findings - Add `stack.packageManager` field to project.yaml (pnpm | npm | yarn) - Derive helper template vars (pmInstall, pmRun, pmExec, pmLockfile, etc.) - Update CLAUDE.md template and hook/workflow templates to use {{packageManager}} - Fix sync-guard to exclude .agentkit/spec from protected dirs and add try/catch - Remove duplicate cost-ops team definition from teams.yaml - Pin all dependency versions in package.json (remove ^ prefixes) - Add vitest coverage thresholds (80% statements/branches/functions/lines) - Fix src/start/ code quality: null guards, exit delay, error boundaries - Harden consolidate-branches.sh: self-resolution guard, stash restore - Regenerate all 533 output files via agentkit sync Co-Authored-By: Claude Opus 4.6 * chore(engine): add brand color palette variables to sync vars Co-Authored-By: Claude Opus 4.6 * fix(ci): fix test race condition, workspace config, and lockfile - Fix ConversationFlow test: wait for 'Got it' before asserting hint text - Add packages field to pnpm-workspace.yaml for proper workspace resolution - Regenerate lockfile after version pinning (removed ^ prefixes) - Remove accidental .agentkit/templates/src/ artifacts Co-Authored-By: Claude Opus 4.6 * fix(start): add event loop yields to ConversationFlow tests ink-select-input needs setImmediate yields after a new menu renders before it can process ENTER keypresses. Without this, the second ENTER in leaf-selection tests was swallowed, causing intermittent failures. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 * fix(spec): correct githubSlug to phoenixvc/agentkit-forge (#391) Co-authored-by: Claude Opus 4.6 * Add entry point for new framework users (#389) * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * test(start): add coverage for result screen exit path Add App-level test that navigates through ConversationFlow to a leaf node and verifies the result screen text is rendered before exit(). Confirms the synchronous useEffect exit is safe — React commits the render (Ink captures the frame) before useEffect fires. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: update generated sync output timestamps Generated files updated with current sync date from dev merge. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW --------- Co-authored-by: Claude * fix: caldues heuristics (#398) * feat: complete revisit of agents (#399) (#400) * Add start command: new user entry point with state detection (#387) * fix(commands): add AskUserQuestion to VALID_TOOLS and /start command The /start command session got stuck because AskUserQuestion was not included in the allowed-tools whitelist. This fix addresses three issues: 1. VALID_TOOLS in spec-validator was missing AskUserQuestion, TodoWrite, Agent, and NotebookEdit — preventing commands from declaring these Claude Code built-in tools in their allowed-tools. 2. The /start command template now explicitly includes AskUserQuestion in its allowed-tools frontmatter and instructs the agent to use it for interactive guided choices (Phase 3). 3. Added /start command spec to commands.yaml with AskUserQuestion as a declared tool dependency. Also adds a test case validating all four newly-added tools are accepted by the spec validator. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M * fix(commands): remove unrendered Handlebars comment from start.md output The generated .claude/commands/start.md contained a raw {{! ... }} Handlebars comment that was not processed by the sync engine. Remove it so the generated output is clean Markdown. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M --------- * Add configurable prefix to kits commands (#388) * feat(sync): add configurable command prefix for generated slash commands Add `commandPrefix` setting to overlay settings that namespaces all generated slash commands across platforms: - Claude Code: subdirectory strategy (kits/check.md → /project:kits:check) - Cursor/Windsurf/Copilot/Codex: filename prefix (kits-check.md → /kits-check) - Team commands excluded from prefixing (already namespaced) Changes: - Add resolveCommandPath() helper with subdirectory/filename strategies - Update syncClaudeCommands, syncClaudeSkills, syncCursorCommands, syncWindsurfCommands, syncCopilotPrompts, syncCodexSkills - Add commandPrefix to vars from overlay settings - Add commandPrefixedName to buildCommandVars - Add 16 unit + integration tests (all pass, 93 existing tests unaffected) Default is null (no prefix) for full backwards compatibility. https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p * fix(sync): address review findings for command prefix - Remove unused afterAll import from test file - Add clarifying comment that non-spec command files are also prefixed - Add 2 integration tests verifying commandPrefixedName template variable renders correctly with and without prefix https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p --------- * fix(ci): CI remediation — package manager, review findings, test stability (#390) * fix(ci): resolve 7 bugs from project review - BUG-001: Replace flaky discover test with controlled temp fixture - BUG-002: Run prettier --write to fix formatting drift - BUG-003: Add form-template detection skip in issue label validation - BUG-005: Change claude.yml to self-hosted runner - BUG-006: Align branch protection required status checks with project.yaml - BUG-007: Fix command injection in resolve-merge.sh (use grep -F) * docs: update changelog, add planning registry review findings - Add changelog entries for Wave 1-3 fixes (Added/Changed/Fixed/Removed) - Add Project Review Findings section to planning registry (PR-001 to PR-014) - Update planning docs after sync merge * feat(review): add --generate-plans flag to project-review command Add Phase 2.5 plan generation after project review findings. When --generate-plans is passed (default: true), scaffold plan files from critical/high findings into docs/planning/review-findings/. Also includes sync cleanup of stale cursor/windsurf settings. * chore(sync): regenerate all outputs after project review fixes * feat(cli): dynamic flag loading from commands.yaml + context-aware template hook - Replace ~200 lines of hardcoded VALID_FLAGS/FLAG_TYPES with loadCommandFlags() that reads flag definitions from commands.yaml at startup - CLI_INTERNAL_FLAGS/CLI_INTERNAL_FLAG_TYPES cover commands not in commands.yaml - Self-validation warns at startup if any flag is missing a type definition - Update cli.test.mjs to validate CLI_INTERNAL_FLAGS consistency - Fix scaffold-once orphan bug: carry forward manifest entries for files skipped by scaffold-once so orphan cleanup does not delete them - Make protect-templates hook context-aware: skip protection in the agentkit-forge source repo (detected via package.json name) so maintainer agents can edit templates; block only in downstream repos * feat(sync): add managed-mode script templates for downstream repos Add 14 script templates (.agentkit/templates/scripts/) with `managed` scaffold mode so downstream repos receive script updates via three-way merge while preserving local customizations. Templates include: create-doc, update-changelog, validate-documentation, validate-numbering, check-documentation-requirement, sync-issues, sync-split-pr, setup-agentkit-branch-governance, and resolve-merge (both .sh and .ps1 variants where applicable). Parameterized templates use {{defaultBranch}} and branch protection variables from project.yaml. Engine wired via syncScripts() under doc-scaffolding feature gate. * feat(teams): add TeamForge meta-team for agent team creation (cogmesh #130) Add the TEAMFORGE meta-team (T11) — a structured pipeline for creating, validating, and deploying new agent team specifications. Adapted from cogmesh #130 with a simplified 6-agent pipeline: - input-clarifier: assess requests, extract constraints - mission-definer: lock team definition (ID, scope, accepts) - role-architect: design agent roles and dependencies - prompt-engineer: write agent descriptions and rules - flow-designer: design team command and integration points - team-validator: quality gate for spec consistency Includes /team-forge command with --task flag (create-team, validate-team, audit-teams, update-team) and planning doc. * feat(teams): add Strategic Ops team for cross-project coordination Add the STRATEGIC OPS team (T12) — handles framework governance, portfolio analysis, adoption strategy, impact assessment, and release coordination across all repos using AgentKit Forge. 5-agent pipeline: - portfolio-analyst: inventory repos, detect drift, adoption metrics - governance-advisor: versioning strategy, breaking change protocols - adoption-strategist: onboarding, migration paths, rollout plans - impact-assessor: blast radius analysis for template/spec changes - release-coordinator: version bumps, sync waves, release comms Includes /team-strategic-ops command with --task and --scope flags. * feat(agents): add agent/team relationship matrix analysis engine + scripts Add comprehensive agent/team relationship analysis with 8 cross-reference matrices and 10 supplementary analyses (orphans, cycles, bottlenecks, reachability, critical path, notification amplifiers, etc.). - Fix YAML structure: strategic-ops agents now under own top-level key - Add explicit agents: lists to forge + strategic-ops teams in teams.yaml - Add consolidation detection responsibilities to portfolio-analyst - Create agent-analysis.mjs engine module (loadFullAgentGraph + renderers) - Wire analyze-agents CLI command with --output/--matrix/--format flags - Add managed-scaffold script templates (bash + PowerShell) - Integrate into sync pipeline (auto-regenerates matrix on spec changes) - Add 33 tests covering all matrices, analyses, and edge cases * chore: update documentation files and add plan template - Add trailing newlines to Cursor command documentation files for consistency - Add new plan template files for project planning - Improve markdown table formatting in Claude skills documentation - Remove obsolete .clinerules/testing.md file - Update various rule files with better formatting and advisory rule alignment * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs * feat(cost-ops): add Cost Ops team, agents, and multi-provider cost ticket (#364) * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents (#365) Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs --------- * fix(teams): address CodeRabbit review findings on strategic-ops PR - Lazy-load js-yaml in cli.mjs after ensureDependencies() to prevent crash when node_modules is missing - Convert YAML frontmatter to PowerShell comment blocks in all 6 PS1 templates to fix invalid PowerShell syntax - Fix protect-templates hook path: use 3 parent traversals to reach .agentkit/package.json from hooks directory - Remove schema-invalid 'phase' field from ai-cost-ops rule domain - Narrow strategic-ops scope: replace **/* catch-all with specific files - Add strategic-ops to cost-ops handoff-chain for consistency - Add Write tool to spec-compliance-auditor, vendor-arbitrage-analyst, and grant-hunter agents - Fix glob matching in resolve-merge.sh (use regex instead of broken sed strip) - Add merge failure vs conflict detection in resolve-merge.ps1 - Add branch existence check in setup-agentkit-branch-governance scripts - Add gh CLI preflight check in sync-split-pr.ps1 - Deduplicate branch protection loop when defaultBranch is 'main' - Fix applies-to glob: docs/planning/cost/** → docs/planning/cost-governance/** - Fix non-canonical doc paths in intake-agent-proposal.md - Add changelog entries for new teams, agents, and analysis engine - Resolve AGENT_TEAMS.md merge conflict (accept narrowed scope) - Run prettier on all modified files * fix(templates): add gh auth preflight and changelog divider handling - sync-split-pr.ps1: add gh auth status check before side effects - update-changelog.ps1: stop before --- divider when appending entries Addresses CodeRabbit review comments #7 and #13 on PR #356. * fix(sync): set executable permission on analyze-agents.sh Linux CI sync produces +x permissions; align local to match. * fix(templates): address CodeRabbit review round 3-4 findings - Fix YAML frontmatter in copilot agent template: use double quotes for description field to handle apostrophes (CRITICAL) - Fix protect-templates.sh/ps1 path traversal: correct parent directory count for .agentkit/package.json source repo detection - Add $PSNativeCommandUseErrorActionPreference to sync-split-pr.ps1 so native command failures (git, pnpm, gh) are treated as fatal - Replace try/catch with $LASTEXITCODE check for gh auth status - Deduplicate branch loop in setup-agentkit-branch-governance.sh when defaultBranch equals 'main' - Fix duplicate verification echo lines in governance scripts * style(docs): fix prettier formatting on planning documents Run prettier --write on web-intake-expansion.md and intake-agent-proposal.md to fix CI formatting check. * fix(tests): isolate render target gating tests with fresh temp dirs Tests in the "render target gating" describe block shared a single temp directory via beforeAll/afterAll. The first test ran --only claude (generating .claude/ files), and the second ran --only warp expecting no Claude files — but leftovers from test 1 caused the assertion to fail. Changing to beforeEach/afterEach gives each test a clean directory. Closes #377 * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(engine): add pre-sync commit guard and interactive apply mode Adds two safety features to the sync pipeline: 1. Pre-sync commit guard: Detects uncommitted changes in protected directories (.agentkit/engines, spec, overlays) before sync runs. In TTY mode, prompts to abort, stash, or continue. In non-TTY mode (CI), prints a warning and proceeds. 2. Interactive apply mode: After rendering, shows a change summary and prompts: apply all / skip all / prompt each file. Per-file prompt supports show-diff and apply-all-remaining. Default in TTY; bypassed with --yes, --no-prompt, or --force. New module: sync-guard.mjs with 4 exported functions and 7 tests. New CLI flags: --yes, --no-prompt for non-interactive sync. * chore(sync): regenerate outputs after branch merges * chore(sync): regenerate outputs after merge of new-user-entry-point * feat(engine): add configurable package manager and fix review findings - Add `stack.packageManager` field to project.yaml (pnpm | npm | yarn) - Derive helper template vars (pmInstall, pmRun, pmExec, pmLockfile, etc.) - Update CLAUDE.md template and hook/workflow templates to use {{packageManager}} - Fix sync-guard to exclude .agentkit/spec from protected dirs and add try/catch - Remove duplicate cost-ops team definition from teams.yaml - Pin all dependency versions in package.json (remove ^ prefixes) - Add vitest coverage thresholds (80% statements/branches/functions/lines) - Fix src/start/ code quality: null guards, exit delay, error boundaries - Harden consolidate-branches.sh: self-resolution guard, stash restore - Regenerate all 533 output files via agentkit sync * chore(engine): add brand color palette variables to sync vars * fix(ci): fix test race condition, workspace config, and lockfile - Fix ConversationFlow test: wait for 'Got it' before asserting hint text - Add packages field to pnpm-workspace.yaml for proper workspace resolution - Regenerate lockfile after version pinning (removed ^ prefixes) - Remove accidental .agentkit/templates/src/ artifacts * fix(start): add event loop yields to ConversationFlow tests ink-select-input needs setImmediate yields after a new menu renders before it can process ENTER keypresses. Without this, the second ENTER in leaf-selection tests was swallowed, causing intermittent failures. --------- * fix(spec): correct githubSlug to phoenixvc/agentkit-forge (#391) * Add entry point for new framework users (#389) * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * test(start): add coverage for result screen exit path Add App-level test that navigates through ConversationFlow to a leaf node and verifies the result screen text is rendered before exit(). Confirms the synchronous useEffect exit is safe — React commits the render (Ink captures the frame) before useEffect fires. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: update generated sync output timestamps Generated files updated with current sync date from dev merge. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW --------- * fix: caldues heuristics (#398) --------- Co-authored-by: Claude * fix(quality): resolve all lint and format errors - Fix Prettier formatting across engine src and start components - Resolve 381 markdown lint errors (MD040, MD024, MD036, MD029, MD022, MD001) - Add markdownlint config rules for intentional doc patterns - Add .claude/worktrees to prettierignore to exclude external branches - Enable markdownlint MD024/MD026 for duplicate headings and trailing colons All quality checks now pass: Prettier (0 errors), Markdown lint (0 errors), Tests (111/111), Build (28.9kb) * I'll update the last_updated field in all the files from '2026-03-12' to '2026-03-13'. This appears to be a routine timestamp update across all the AgentKit Forge generated files. * docs: add AgentKit Forge sync feedback Add detailed feedback on AgentKit Forge v3.1.0 integration, focusing on: - Windows line-ending issues and multi-editor sync behavior - Documentation scaffold-once limitations and override challenges - Unresolved placeholder warnings lacking diagnostics - Windows-specific pnpm execution problems * docs: update CLAUDE.md with repository-specific editing guidelines Clarified that modifications to `.agentkit` files are permitted in the agentkit-forge repository, while upstream directories remain protected. This ensures users understand the editing boundaries for project configuration and template files. * docs(claude): allow .agentkit edits in this repo (NB for framework dev) Made-with: Cursor * chore(sync): regenerate outputs after agentkit:sync Made-with: Cursor * Fix/generated files and conflict markers (#427) * fix(infra): resolve container app fqdn attribute and format code * chore(sync): update AGENT_BACKLOG.md and other files for task management - Enhanced AGENT_BACKLOG.md with detailed task scopes for CI pipeline configuration and test framework setup. - Added new docker-compose.yml for local/staging validation of the framework. - Updated CONTRIBUTING.md to include documentation hub link in the Discovery phase. - Introduced README.md files in db, infra, and migrations directories to clarify their purpose for adopters. - Added API conventions documentation to guide adopters on structuring their APIs. - Created implementation plan for state management improvements and added relevant tests. - Regenerated outputs across various files to reflect recent changes and ensure consistency. * chore(ci): reduce CodeQL to weekly + manual only (#430) * chore(ci): reduce CodeQL to weekly schedule + manual trigger Removes push and pull_request triggers to reduce GitHub Actions costs. Scans were running on every PR including Renovate dependency updates. Co-Authored-By: Claude Opus 4.6 * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Claude Opus 4.6 Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * docs(architecture): add tool-neutral agent hub findings, ADR-10, and adoption roadmap (#428) * docs(architecture): add tool-neutral agent hub findings, ADR-10, and adoption roadmap Comparative analysis of agentkit-forge sync engine vs Mystira.workspace hand-authored .agents/ pattern. Documents 5-phase adoption roadmap to converge both approaches: .agents/ as sync target, reflective guards, .readme.yaml generation, cross-session traces, and schema formalisation. Includes regenerated sync output (updated timestamps across all tools). Co-Authored-By: Claude Opus 4.6 * docs(architecture): add competitive landscape and strategic research report Comprehensive analysis of the AI agent configuration & orchestration market: - 6 primary competitors profiled (Ruler, Agent OS, ai-rules-sync, agent-rules, Block ai-rules, AGENTS.md) - Evaluation matrix across 14 dimensions - SWOT analysis with evidence-based assessments - 12-KPI framework with baselines, targets, and scoring methodology - Tracking dashboard template and priority matrix - Market context: $8.5B market, 62% developer adoption, protocol convergence Key finding: Rules sync is commoditising; AgentKit Forge's moat is orchestration + governance + CI validation. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 * docs(history): add Linear PhoenixVC workspace setup implementation record (#431) * feat: new entry points (#426) * Add start command: new user entry point with state detection (#387) * fix(commands): add AskUserQuestion to VALID_TOOLS and /start command The /start command session got stuck because AskUserQuestion was not included in the allowed-tools whitelist. This fix addresses three issues: 1. VALID_TOOLS in spec-validator was missing AskUserQuestion, TodoWrite, Agent, and NotebookEdit — preventing commands from declaring these Claude Code built-in tools in their allowed-tools. 2. The /start command template now explicitly includes AskUserQuestion in its allowed-tools frontmatter and instructs the agent to use it for interactive guided choices (Phase 3). 3. Added /start command spec to commands.yaml with AskUserQuestion as a declared tool dependency. Also adds a test case validating all four newly-added tools are accepted by the spec validator. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M * fix(commands): remove unrendered Handlebars comment from start.md output The generated .claude/commands/start.md contained a raw {{! ... }} Handlebars comment that was not processed by the sync engine. Remove it so the generated output is clean Markdown. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M --------- Co-authored-by: Claude * Add configurable prefix to kits commands (#388) * feat(sync): add configurable command prefix for generated slash commands Add `commandPrefix` setting to overlay settings that namespaces all generated slash commands across platforms: - Claude Code: subdirectory strategy (kits/check.md → /project:kits:check) - Cursor/Windsurf/Copilot/Codex: filename prefix (kits-check.md → /kits-check) - Team commands excluded from prefixing (already namespaced) Changes: - Add resolveCommandPath() helper with subdirectory/filename strategies - Update syncClaudeCommands, syncClaudeSkills, syncCursorCommands, syncWindsurfCommands, syncCopilotPrompts, syncCodexSkills - Add commandPrefix to vars from overlay settings - Add commandPrefixedName to buildCommandVars - Add 16 unit + integration tests (all pass, 93 existing tests unaffected) Default is null (no prefix) for full backwards compatibility. https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p * fix(sync): address review findings for command prefix - Remove unused afterAll import from test file - Add clarifying comment that non-spec command files are also prefixed - Add 2 integration tests verifying commandPrefixedName template variable renders correctly with and without prefix https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p --------- Co-authored-by: Claude * fix(ci): CI remediation — package manager, review findings, test stability (#390) * fix(ci): resolve 7 bugs from project review - BUG-001: Replace flaky discover test with controlled temp fixture - BUG-002: Run prettier --write to fix formatting drift - BUG-003: Add form-template detection skip in issue label validation - BUG-005: Change claude.yml to self-hosted runner - BUG-006: Align branch protection required status checks with project.yaml - BUG-007: Fix command injection in resolve-merge.sh (use grep -F) Co-Authored-By: Claude Opus 4.6 * docs: update changelog, add planning registry review findings - Add changelog entries for Wave 1-3 fixes (Added/Changed/Fixed/Removed) - Add Project Review Findings section to planning registry (PR-001 to PR-014) - Update planning docs after sync merge Co-Authored-By: Claude Opus 4.6 * feat(review): add --generate-plans flag to project-review command Add Phase 2.5 plan generation after project review findings. When --generate-plans is passed (default: true), scaffold plan files from critical/high findings into docs/planning/review-findings/. Also includes sync cleanup of stale cursor/windsurf settings. Co-Authored-By: Claude Opus 4.6 * chore(sync): regenerate all outputs after project review fixes Co-Authored-By: Claude Opus 4.6 * feat(cli): dynamic flag loading from commands.yaml + context-aware template hook - Replace ~200 lines of hardcoded VALID_FLAGS/FLAG_TYPES with loadCommandFlags() that reads flag definitions from commands.yaml at startup - CLI_INTERNAL_FLAGS/CLI_INTERNAL_FLAG_TYPES cover commands not in commands.yaml - Self-validation warns at startup if any flag is missing a type definition - Update cli.test.mjs to validate CLI_INTERNAL_FLAGS consistency - Fix scaffold-once orphan bug: carry forward manifest entries for files skipped by scaffold-once so orphan cleanup does not delete them - Make protect-templates hook context-aware: skip protection in the agentkit-forge source repo (detected via package.json name) so maintainer agents can edit templates; block only in downstream repos Co-Authored-By: Claude Opus 4.6 * feat(sync): add managed-mode script templates for downstream repos Add 14 script templates (.agentkit/templates/scripts/) with `managed` scaffold mode so downstream repos receive script updates via three-way merge while preserving local customizations. Templates include: create-doc, update-changelog, validate-documentation, validate-numbering, check-documentation-requirement, sync-issues, sync-split-pr, setup-agentkit-branch-governance, and resolve-merge (both .sh and .ps1 variants where applicable). Parameterized templates use {{defaultBranch}} and branch protection variables from project.yaml. Engine wired via syncScripts() under doc-scaffolding feature gate. Co-Authored-By: Claude Opus 4.6 * feat(teams): add TeamForge meta-team for agent team creation (cogmesh #130) Add the TEAMFORGE meta-team (T11) — a structured pipeline for creating, validating, and deploying new agent team specifications. Adapted from cogmesh #130 with a simplified 6-agent pipeline: - input-clarifier: assess requests, extract constraints - mission-definer: lock team definition (ID, scope, accepts) - role-architect: design agent roles and dependencies - prompt-engineer: write agent descriptions and rules - flow-designer: design team command and integration points - team-validator: quality gate for spec consistency Includes /team-forge command with --task flag (create-team, validate-team, audit-teams, update-team) and planning doc. Co-Authored-By: Claude Opus 4.6 * feat(teams): add Strategic Ops team for cross-project coordination Add the STRATEGIC OPS team (T12) — handles framework governance, portfolio analysis, adoption strategy, impact assessment, and release coordination across all repos using AgentKit Forge. 5-agent pipeline: - portfolio-analyst: inventory repos, detect drift, adoption metrics - governance-advisor: versioning strategy, breaking change protocols - adoption-strategist: onboarding, migration paths, rollout plans - impact-assessor: blast radius analysis for template/spec changes - release-coordinator: version bumps, sync waves, release comms Includes /team-strategic-ops command with --task and --scope flags. Co-Authored-By: Claude Opus 4.6 * feat(agents): add agent/team relationship matrix analysis engine + scripts Add comprehensive agent/team relationship analysis with 8 cross-reference matrices and 10 supplementary analyses (orphans, cycles, bottlenecks, reachability, critical path, notification amplifiers, etc.). - Fix YAML structure: strategic-ops agents now under own top-level key - Add explicit agents: lists to forge + strategic-ops teams in teams.yaml - Add consolidation detection responsibilities to portfolio-analyst - Create agent-analysis.mjs engine module (loadFullAgentGraph + renderers) - Wire analyze-agents CLI command with --output/--matrix/--format flags - Add managed-scaffold script templates (bash + PowerShell) - Integrate into sync pipeline (auto-regenerates matrix on spec changes) - Add 33 tests covering all matrices, analyses, and edge cases Co-Authored-By: Claude Opus 4.6 * chore: update documentation files and add plan template - Add trailing newlines to Cursor command documentation files for consistency - Add new plan template files for project planning - Improve markdown table formatting in Claude skills documentation - Remove obsolete .clinerules/testing.md file - Update various rule files with better formatting and advisory rule alignment * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance Co-Authored-By: Claude Opus 4.6 * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. Co-Authored-By: Claude Opus 4.6 * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add Cost Ops team, agents, and multi-provider cost ticket (#364) * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance Co-Authored-By: Claude Opus 4.6 * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. Co-Authored-By: Claude Opus 4.6 * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents (#365) Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs Co-authored-by: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 * fix(teams): address CodeRabbit review findings on strategic-ops PR - Lazy-load js-yaml in cli.mjs after ensureDependencies() to prevent crash when node_modules is missing - Convert YAML frontmatter to PowerShell comment blocks in all 6 PS1 templates to fix invalid PowerShell syntax - Fix protect-templates hook path: use 3 parent traversals to reach .agentkit/package.json from hooks directory - Remove schema-invalid 'phase' field from ai-cost-ops rule domain - Narrow strategic-ops scope: replace **/* catch-all with specific files - Add strategic-ops to cost-ops handoff-chain for consistency - Add Write tool to spec-compliance-auditor, vendor-arbitrage-analyst, and grant-hunter agents - Fix glob matching in resolve-merge.sh (use regex instead of broken sed strip) - Add merge failure vs conflict detection in resolve-merge.ps1 - Add branch existence check in setup-agentkit-branch-governance scripts - Add gh CLI preflight check in sync-split-pr.ps1 - Deduplicate branch protection loop when defaultBranch is 'main' - Fix applies-to glob: docs/planning/cost/** → docs/planning/cost-governance/** - Fix non-canonical doc paths in intake-agent-proposal.md - Add changelog entries for new teams, agents, and analysis engine - Resolve AGENT_TEAMS.md merge conflict (accept narrowed scope) - Run prettier on all modified files Co-Authored-By: Claude Opus 4.6 * fix(templates): add gh auth preflight and changelog divider handling - sync-split-pr.ps1: add gh auth status check before side effects - update-changelog.ps1: stop before --- divider when appending entries Addresses CodeRabbit review comments #7 and #13 on PR #356. Co-Authored-By: Claude Opus 4.6 * fix(sync): set executable permission on analyze-agents.sh Linux CI sync produces +x permissions; align local to match. Co-Authored-By: Claude Opus 4.6 * fix(templates): address CodeRabbit review round 3-4 findings - Fix YAML frontmatter in copilot agent template: use double quotes for description field to handle apostrophes (CRITICAL) - Fix protect-templates.sh/ps1 path traversal: correct parent directory count for .agentkit/package.json source repo detection - Add $PSNativeCommandUseErrorActionPreference to sync-split-pr.ps1 so native command failures (git, pnpm, gh) are treated as fatal - Replace try/catch with $LASTEXITCODE check for gh auth status - Deduplicate branch loop in setup-agentkit-branch-governance.sh when defaultBranch equals 'main' - Fix duplicate verification echo lines in governance scripts Co-Authored-By: Claude Opus 4.6 * style(docs): fix prettier formatting on planning documents Run prettier --write on web-intake-expansion.md and intake-agent-proposal.md to fix CI formatting check. Co-Authored-By: Claude Opus 4.6 * fix(tests): isolate render target gating tests with fresh temp dirs Tests in the "render target gating" describe block shared a single temp directory via beforeAll/afterAll. The first test ran --only claude (generating .claude/ files), and the second ran --only warp expecting no Claude files — but leftovers from test 1 caused the assertion to fail. Changing to beforeEach/afterEach gives each test a clean directory. Closes #377 Co-Authored-By: Claude Opus 4.6 * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(engine): add pre-sync commit guard and interactive apply mode Adds two safety features to the sync pipeline: 1. Pre-sync commit guard: Detects uncommitted changes in protected directories (.agentkit/engines, spec, overlays) before sync runs. In TTY mode, prompts to abort, stash, or continue. In non-TTY mode (CI), prints a warning and proceeds. 2. Interactive apply mode: After rendering, shows a change summary and prompts: apply all / skip all / prompt each file. Per-file prompt supports show-diff and apply-all-remaining. Default in TTY; bypassed with --yes, --no-prompt, or --force. New module: sync-guard.mjs with 4 exported functions and 7 tests. New CLI flags: --yes, --no-prompt for non-interactive sync. Co-Authored-By: Claude Opus 4.6 * chore(sync): regenerate outputs after branch merges Co-Authored-By: Claude Opus 4.6 * chore(sync): regenerate outputs after merge of new-user-entry-point Co-Authored-By: Claude Opus 4.6 * feat(engine): add configurable package manager and fix review findings - Add `stack.packageManager` field to project.yaml (pnpm | npm | yarn) - Derive helper template vars (pmInstall, pmRun, pmExec, pmLockfile, etc.) - Update CLAUDE.md template and hook/workflow templates to use {{packageManager}} - Fix sync-guard to exclude .agentkit/spec from protected dirs and add try/catch - Remove duplicate cost-ops team definition from teams.yaml - Pin all dependency versions in package.json (remove ^ prefixes) - Add vitest coverage thresholds (80% statements/branches/functions/lines) - Fix src/start/ code quality: null guards, exit delay, error boundaries - Harden consolidate-branches.sh: self-resolution guard, stash restore - Regenerate all 533 output files via agentkit sync Co-Authored-By: Claude Opus 4.6 * chore(engine): add brand color palette variables to sync vars Co-Authored-By: Claude Opus 4.6 * fix(ci): fix test race condition, workspace config, and lockfile - Fix ConversationFlow test: wait for 'Got it' before asserting hint text - Add packages field to pnpm-workspace.yaml for proper workspace resolution - Regenerate lockfile after version pinning (removed ^ prefixes) - Remove accidental .agentkit/templates/src/ artifacts Co-Authored-By: Claude Opus 4.6 * fix(start): add event loop yields to ConversationFlow tests ink-select-input needs setImmediate yields after a new menu renders before it can process ENTER keypresses. Without this, the second ENTER in leaf-selection tests was swallowed, causing intermittent failures. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 * fix(spec): correct githubSlug to phoenixvc/agentkit-forge (#391) Co-authored-by: Claude Opus 4.6 * Add entry point for new framework users (#389) * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * test(start): add coverage for result screen exit path Add App-level test that navigates through ConversationFlow to a leaf node and verifies the result screen text is rendered before exit(). Confirms the synchronous useEffect exit is safe — React commits the render (Ink captures the frame) before useEffect fires. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: update generated sync output timestamps Generated files updated with current sync date from dev merge. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW --------- Co-authored-by: Claude * fix: caldues heuristics (#398) * feat: complete revisit of agents (#399) (#400) * Add start command: new user entry point with state detection (#387) * fix(commands): add AskUserQuestion to VALID_TOOLS and /start command The /start command session got stuck because AskUserQuestion was not included in the allowed-tools whitelist. This fix addresses three issues: 1. VALID_TOOLS in spec-validator was missing AskUserQuestion, TodoWrite, Agent, and NotebookEdit — preventing commands from declaring these Claude Code built-in tools in their allowed-tools. 2. The /start command template now explicitly includes AskUserQuestion in its allowed-tools frontmatter and instructs the agent to use it for interactive guided choices (Phase 3). 3. Added /start command spec to commands.yaml with AskUserQuestion as a declared tool dependency. Also adds a test case validating all four newly-added tools are accepted by the spec validator. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M * fix(commands): remove unrendered Handlebars comment from start.md output The generated .claude/commands/start.md contained a raw {{! ... }} Handlebars comment that was not processed by the sync engine. Remove it so the generated output is clean Markdown. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M --------- * Add configurable prefix to kits commands (#388) * feat(sync): add configurable command prefix for generated slash commands Add `commandPrefix` setting to overlay settings that namespaces all generated slash commands across platforms: - Claude Code: subdirectory strategy (kits/check.md → /project:kits:check) - Cursor/Windsurf/Copilot/Codex: filename prefix (kits-check.md → /kits-check) - Team commands excluded from prefixing (already namespaced) Changes: - Add resolveCommandPath() helper with subdirectory/filename strategies - Update syncClaudeCommands, syncClaudeSkills, syncCursorCommands, syncWindsurfCommands, syncCopilotPrompts, syncCodexSkills - Add commandPrefix to vars from overlay settings - Add commandPrefixedName to buildCommandVars - Add 16 unit + integration tests (all pass, 93 existing tests unaffected) Default is null (no prefix) for full backwards compatibility. https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p * fix(sync): address review findings for command prefix - Remove unused afterAll import from test file - Add clarifying comment that non-spec command files are also prefixed - Add 2 integration tests verifying commandPrefixedName template variable renders correctly with and without prefix https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p --------- * fix(ci): CI remediation — package manager, review findings, test stability (#390) * fix(ci): resolve 7 bugs from project review - BUG-001: Replace flaky discover test with controlled temp fixture - BUG-002: Run prettier --write to fix formatting drift - BUG-003: Add form-template detection skip in issue label validation - BUG-005: Change claude.yml to self-hosted runner - BUG-006: Align branch protection required status checks with project.yaml - BUG-007: Fix command injection in resolve-merge.sh (use grep -F) * docs: update changelog, add planning registry review findings - Add changelog entries for Wave 1-3 fixes (Added/Changed/Fixed/Removed) - Add Project Review Findings section to planning registry (PR-001 to PR-014) - Update planning docs after sync merge * feat(review): add --generate-plans flag to project-review command Add Phase 2.5 plan generation after project review findings. When --generate-plans is passed (default: true), scaffold plan files from critical/high findings into docs/planning/review-findings/. Also includes sync cleanup of stale cursor/windsurf settings. * chore(sync): regenerate all outputs after project review fixes * feat(cli): dynamic flag loading from commands.yaml + context-aware template hook - Replace ~200 lines of hardcoded VALID_FLAGS/FLAG_TYPES with loadCommandFlags() that reads flag definitions from commands.yaml at startup - CLI_INTERNAL_FLAGS/CLI_INTERNAL_FLAG_TYPES cover commands not in commands.yaml - Self-validation warns at startup if any flag is missing a type definition - Update cli.test.mjs to validate CLI_INTERNAL_FLAGS consistency - Fix scaffold-once orphan bug: carry forward manifest entries for files skipped by scaffold-once so orphan cleanup does not delete them - Make protect-templates hook context-aware: skip protection in the agentkit-forge source repo (detected via package.json name) so maintainer agents can edit templates; block only in downstream repos * feat(sync): add managed-mode script templates for downstream repos Add 14 script templates (.agentkit/templates/scripts/) with `managed` scaffold mode so downstream repos receive script updates via three-way merge while preserving local customizations. Templates include: create-doc, update-changelog, validate-documentation, validate-numbering, check-documentation-requirement, sync-issues, sync-split-pr, setup-agentkit-branch-governance, and resolve-merge (both .sh and .ps1 variants where applicable). Parameterized templates use {{defaultBranch}} and branch protection variables from project.yaml. Engine wired via syncScripts() under doc-scaffolding feature gate. * feat(teams): add TeamForge meta-team for agent team creation (cogmesh #130) Add the TEAMFORGE meta-team (T11) — a structured pipeline for creating, validating, and deploying new agent team specifications. Adapted from cogmesh #130 with a simplified 6-agent pipeline: - input-clarifier: assess requests, extract constraints - mission-definer: lock team definition (ID, scope, accepts) - role-architect: design agent roles and dependencies - prompt-engineer: write agent descriptions and rules - flow-designer: design team command and integration points - team-validator: quality gate for spec consistency Includes /team-forge command with --task flag (create-team, validate-team, audit-teams, update-team) and planning doc. * feat(teams): add Strategic Ops team for cross-project coordination Add the STRATEGIC OPS team (T12) — handles framework governance, portfolio analysis, adoption strategy, impact assessment, and release coordination across all repos using AgentKit Forge. 5-agent pipeline: - portfolio-analyst: inventory repos, detect drift, adoption metrics - governance-advisor: versioning strategy, breaking change protocols - adoption-strategist: onboarding, migration paths, rollout plans - impact-assessor: blast radius analysis for template/spec changes - release-coordinator: version bumps, sync waves, release comms Includes /team-strategic-ops command with --task and --scope flags. * feat(agents): add agent/team relationship matrix analysis engine + scripts Add comprehensive agent/team relationship analysis with 8 cross-reference matrices and 10 supplementary analyses (orphans, cycles, bottlenecks, reachability, critical path, notification amplifiers, etc.). - Fix YAML structure: strategic-ops agents now under own top-level key - Add explicit agents: lists to forge + strategic-ops teams in teams.yaml - Add consolidation detection responsibilities to portfolio-analyst - Create agent-analysis.mjs engine module (loadFullAgentGraph + renderers) - Wire analyze-agents CLI command with --output/--matrix/--format flags - Add managed-scaffold script templates (bash + PowerShell) - Integrate into sync pipeline (auto-regenerates matrix on spec changes) - Add 33 tests covering all matrices, analyses, and edge cases * chore: update documentation files and add plan template - Add trailing newlines to Cursor command documentation files for consistency - Add new plan template files for project planning - Improve markdown table formatting in Claude skills documentation - Remove obsolete .clinerules/testing.md file - Update various rule files with better formatting and advisory rule alignment * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs * feat(cost-ops): add Cost Ops team, agents, and multi-provider cost ticket (#364) * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents (#365) Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs --------- * fix(teams): address CodeRabbit review findings on strategic-ops PR - Lazy-load js-yaml in cli.mjs after ensureDependencies() to prevent crash when node_modules is missing - Convert YAML frontmatter to PowerShell comment blocks in all 6 PS1 templates to fix invalid PowerShell syntax - Fix protect-templates hook path: use 3 parent traversals to reach .agentkit/package.json from hooks directory - Remove schema-invalid 'phase' field from ai-cost-ops rule domain - Narrow strategic-ops scope: replace **/* catch-all with specific files - Add strategic-ops to cost-ops handoff-chain for consistency - Add Write tool to spec-compliance-auditor, vendor-arbitrage-analyst, and grant-hunter agents - Fix glob matching in resolve-merge.sh (use regex instead of broken sed strip) - Add merge failure vs conflict detection in resolve-merge.ps1 - Add branch existence check in setup-agentkit-branch-governance scripts - Add gh CLI preflight check in sync-split-pr.ps1 - Deduplicate branch protection loop when defaultBranch is 'main' - Fix applies-to glob: docs/planning/cost/** → docs/planning/cost-governance/** - Fix non-canonical doc paths in intake-agent-proposal.md - Add changelog entries for new teams, agents, and analysis engine - Resolve AGENT_TEAMS.md merge conflict (accept narrowed scope) - Run prettier on all modified files * fix(templates): add gh auth preflight and changelog divider handling - sync-split-pr.ps1: add gh auth status check before side effects - update-changelog.ps1: stop before --- divider when appending entries Addresses CodeRabbit review comments #7 and #13 on PR #356. * fix(sync): set executable permission on analyze-agents.sh Linux CI sync produces +x permissions; align local to match. * fix(templates): address CodeRabbit review round 3-4 findings - Fix YAML frontmatter in copilot agent template: use double quotes for description field to handle apostrophes (CRITICAL) - Fix protect-templates.sh/ps1 path traversal: correct parent directory count for .agentkit/package.json source repo detection - Add $PSNativeCommandUseErrorActionPreference to sync-split-pr.ps1 so native command failures (git, pnpm, gh) are treated as fatal - Replace try/catch with $LASTEXITCODE check for gh auth status - Deduplicate branch loop in setup-agentkit-branch-governance.sh when defaultBranch equals 'main' - Fix duplicate verification echo lines in governance scripts * style(docs): fix prettier formatting on planning documents Run prettier --write on web-intake-expansion.md and intake-agent-proposal.md to fix CI formatting check. * fix(tests): isolate render target gating tests with fresh temp dirs Tests in the "render target gating" describe block shared a single temp directory via beforeAll/afterAll. The first test ran --only claude (generating .claude/ files), and the second ran --only warp expecting no Claude files — but leftovers from test 1 caused the assertion to fail. Changing to beforeEach/afterEach gives each test a clean directory. Closes #377 * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(engine): add pre-sync commit guard and interactive apply mode Adds two safety features to the sync pipeline: 1. Pre-sync commit guard: Detects uncommitted changes in protected directories (.agentkit/engines, spec, overlays) before sync runs. In TTY mode, prompts to abort, stash, or continue. In non-TTY mode (CI), prints a warning and proceeds. 2. Interactive apply mode: After rendering, shows a change summary and prompts: apply all / skip all / prompt each file. Per-file prompt supports show-diff and apply-all-remaining. Default in TTY; bypassed with --yes, --no-prompt, or --force. New module: sync-guard.mjs with 4 exported functions and 7 tests. New CLI flags: --yes, --no-prompt for non-interactive sync. * chore(sync): regenerate outputs after branch merges * chore(sync): regenerate outputs after merge of new-user-entry-point * feat(engine): add configurable package manager and fix review findings - Add `stack.packageManager` field to project.yaml (pnpm | npm | yarn) - Derive helper template vars (pmInstall, pmRun, pmExec, pmLockfile, etc.) - Update CLAUDE.md template and hook/workflow templates to use {{packageManager}} - Fix sync-guard to exclude .agentkit/spec from protected dirs and add try/catch - Remove duplicate cost-ops team definition from teams.yaml - Pin all dependency versions in package.json (remove ^ prefixes) - Add vitest coverage thresholds (80% statements/branches/functions/lines) - Fix src/start/ code quality: null guards, exit delay, error boundaries - Harden consolidate-branches.sh: self-resolution guard, stash restore - Regenerate all 533 output files via agentkit sync * chore(engine): add brand color palette variables to sync vars * fix(ci): fix test race condition, workspace config, and lockfile - Fix ConversationFlow test: wait for 'Got it' before asserting hint text - Add packages field to pnpm-workspace.yaml for proper workspace resolution - Regenerate lockfile after version pinning (removed ^ prefixes) - Remove accidental .agentkit/templates/src/ artifacts * fix(start): add event loop yields to ConversationFlow tests ink-select-input needs setImmediate yields after a new menu renders before it can process ENTER keypresses. Without this, the second ENTER in leaf-selection tests was swallowed, causing intermittent failures. --------- * fix(spec): correct githubSlug to phoenixvc/agentkit-forge (#391) * Add entry point for new framework users (#389) * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * test(start): add coverage for result screen exit path Add App-level test that navigates through ConversationFlow to a leaf node and verifies the result screen text is rendered before exit(). Confirms the synchronous useEffect exit is safe — React commits the render (Ink captures the frame) before useEffect fires. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: update generated sync output timestamps Generated files updated with current sync date from dev merge. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW --------- * fix: caldues heuristics (#398) --------- Co-authored-by: Claude * fix(quality): resolve all lint and format errors - Fix Prettier formatting across engine src and start components - Resolve 381 markdown lint errors (MD040, MD024, MD036, MD029, MD022, MD001) - Add markdownlint config rules for intentional doc patterns - Add .claude/worktrees to prettierignore to exclude external branches - Enable markdownlint MD024/MD026 for duplicate headings and trailing colons All quality checks now pass: Prettier (0 errors), Markdown lint (0 errors), Tests (111/111), Build (28.9kb) * I'll update the last_updated field in all the files from '2026-03-12' to '2026-03-13'. This appears to be a routine timestamp update across all the AgentKit Forge generated files. * docs: add AgentKit Forge sync feedback Add detailed feedback on AgentKit Forge v3.1.0 integration, focusing on: - Windows line-ending issues and multi-editor sync behavior - Documentation scaffold-once limitations and override challenges - Unresolved placeholder warnings lacking diagnostics - Windows-specific pnpm execution problems * docs: update CLAUDE.md with repository-specific editing guidelines Clarified that modifications to `.agentkit` files are permitted in the agentkit-forge repository, while upstream directories remain protected. This ensures users understand the editing boundaries for project configuration and template files. * docs(claude): allow .agentkit edits in this repo (NB for framework dev) Made-with: Cursor * chore(sync): regenerate outputs after agentkit:sync Made-with: Cursor --------- Co-authored-by: Claude * chore(sync): regenerate outputs and update timestamps (#429) * Add start command: new user entry point with state detection (#387) * fix(commands): add AskUserQuestion to VALID_TOOLS and /start command The /start command session got stuck because AskUserQuestion was not included in the allowed-tools whitelist. This fix addresses three issues: 1. VALID_TOOLS in spec-validator was missing AskUserQuestion, TodoWrite, Agent, and NotebookEdit — preventing commands from declaring these Claude Code built-in tools in their allowed-tools. 2. The /start command template now explicitly includes AskUserQuestion in its allowed-tools frontmatter and instructs the agent to use it for interactive guided choices (Phase 3). 3. Added /start command spec to commands.yaml with AskUserQuestion as a declared tool dependency. Also adds a test case validating all four newly-added tools are accepted by the spec validator. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M * fix(commands): remove unrendered Handlebars comment from start.md output The generated .claude/commands/start.md contained a raw {{! ... }} Handlebars comment that was not processed by the sync engine. Remove it so the generated output is clean Markdown. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M --------- Co-authored-by: Claude * Add configurable prefix to kits commands (#388) * feat(sync): add configurable command prefix for generated slash commands Add `commandPrefix` setting to overlay settings that namespaces all generated slash commands across platforms: - Claude Code: subdirectory strategy (kits/check.md → /project:kits:check) - Cursor/Windsurf/Copilot/Codex: filename prefix (kits-check.md → /kits-check) - Team commands excluded from prefixing (already namespaced) Changes: - Add resolveCommandPath() helper with subdirectory/filename strategies - Update syncClaudeCommands, syncClaudeSkills, syncCursorCommands, syncWindsurfCommands, syncCopilotPrompts… * feat(engine): kit-based domain selection, init wizard, stop hook perf (#432) * feat: new entry points (#426) * Add start command: new user entry point with state detection (#387) * fix(commands): add AskUserQuestion to VALID_TOOLS and /start command The /start command session got stuck because AskUserQuestion was not included in the allowed-tools whitelist. This fix addresses three issues: 1. VALID_TOOLS in spec-validator was missing AskUserQuestion, TodoWrite, Agent, and NotebookEdit — preventing commands from declaring these Claude Code built-in tools in their allowed-tools. 2. The /start command template now explicitly includes AskUserQuestion in its allowed-tools frontmatter and instructs the agent to use it for interactive guided choices (Phase 3). 3. Added /start command spec to commands.yaml with AskUserQuestion as a declared tool dependency. Also adds a test case validating all four newly-added tools are accepted by the spec validator. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M * fix(commands): remove unrendered Handlebars comment from start.md output The generated .claude/commands/start.md contained a raw {{! ... }} Handlebars comment that was not processed by the sync engine. Remove it so the generated output is clean Markdown. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M --------- Co-authored-by: Claude * Add configurable prefix to kits commands (#388) * feat(sync): add configurable command prefix for generated slash commands Add `commandPrefix` setting to overlay settings that namespaces all generated slash commands across platforms: - Claude Code: subdirectory strategy (kits/check.md → /project:kits:check) - Cursor/Windsurf/Copilot/Codex: filename prefix (kits-check.md → /kits-check) - Team commands excluded from prefixing (already namespaced) Changes: - Add resolveCommandPath() helper with subdirectory/filename strategies - Update syncClaudeCommands, syncClaudeSkills, syncCursorCommands, syncWindsurfCommands, syncCopilotPrompts, syncCodexSkills - Add commandPrefix to vars from overlay settings - Add commandPrefixedName to buildCommandVars - Add 16 unit + integration tests (all pass, 93 existing tests unaffected) Default is null (no prefix) for full backwards compatibility. https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p * fix(sync): address review findings for command prefix - Remove unused afterAll import from test file - Add clarifying comment that non-spec command files are also prefixed - Add 2 integration tests verifying commandPrefixedName template variable renders correctly with and without prefix https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p --------- Co-authored-by: Claude * fix(ci): CI remediation — package manager, review findings, test stability (#390) * fix(ci): resolve 7 bugs from project review - BUG-001: Replace flaky discover test with controlled temp fixture - BUG-002: Run prettier --write to fix formatting drift - BUG-003: Add form-template detection skip in issue label validation - BUG-005: Change claude.yml to self-hosted runner - BUG-006: Align branch protection required status checks with project.yaml - BUG-007: Fix command injection in resolve-merge.sh (use grep -F) Co-Authored-By: Claude Opus 4.6 * docs: update changelog, add planning registry review findings - Add changelog entries for Wave 1-3 fixes (Added/Changed/Fixed/Removed) - Add Project Review Findings section to planning registry (PR-001 to PR-014) - Update planning docs after sync merge Co-Authored-By: Claude Opus 4.6 * feat(review): add --generate-plans flag to project-review command Add Phase 2.5 plan generation after project review findings. When --generate-plans is passed (default: true), scaffold plan files from critical/high findings into docs/planning/review-findings/. Also includes sync cleanup of stale cursor/windsurf settings. Co-Authored-By: Claude Opus 4.6 * chore(sync): regenerate all outputs after project review fixes Co-Authored-By: Claude Opus 4.6 * feat(cli): dynamic flag loading from commands.yaml + context-aware template hook - Replace ~200 lines of hardcoded VALID_FLAGS/FLAG_TYPES with loadCommandFlags() that reads flag definitions from commands.yaml at startup - CLI_INTERNAL_FLAGS/CLI_INTERNAL_FLAG_TYPES cover commands not in commands.yaml - Self-validation warns at startup if any flag is missing a type definition - Update cli.test.mjs to validate CLI_INTERNAL_FLAGS consistency - Fix scaffold-once orphan bug: carry forward manifest entries for files skipped by scaffold-once so orphan cleanup does not delete them - Make protect-templates hook context-aware: skip protection in the agentkit-forge source repo (detected via package.json name) so maintainer agents can edit templates; block only in downstream repos Co-Authored-By: Claude Opus 4.6 * feat(sync): add managed-mode script templates for downstream repos Add 14 script templates (.agentkit/templates/scripts/) with `managed` scaffold mode so downstream repos receive script updates via three-way merge while preserving local customizations. Templates include: create-doc, update-changelog, validate-documentation, validate-numbering, check-documentation-requirement, sync-issues, sync-split-pr, setup-agentkit-branch-governance, and resolve-merge (both .sh and .ps1 variants where applicable). Parameterized templates use {{defaultBranch}} and branch protection variables from project.yaml. Engine wired via syncScripts() under doc-scaffolding feature gate. Co-Authored-By: Claude Opus 4.6 * feat(teams): add TeamForge meta-team for agent team creation (cogmesh #130) Add the TEAMFORGE meta-team (T11) — a structured pipeline for creating, validating, and deploying new agent team specifications. Adapted from cogmesh #130 with a simplified 6-agent pipeline: - input-clarifier: assess requests, extract constraints - mission-definer: lock team definition (ID, scope, accepts) - role-architect: design agent roles and dependencies - prompt-engineer: write agent descriptions and rules - flow-designer: design team command and integration points - team-validator: quality gate for spec consistency Includes /team-forge command with --task flag (create-team, validate-team, audit-teams, update-team) and planning doc. Co-Authored-By: Claude Opus 4.6 * feat(teams): add Strategic Ops team for cross-project coordination Add the STRATEGIC OPS team (T12) — handles framework governance, portfolio analysis, adoption strategy, impact assessment, and release coordination across all repos using AgentKit Forge. 5-agent pipeline: - portfolio-analyst: inventory repos, detect drift, adoption metrics - governance-advisor: versioning strategy, breaking change protocols - adoption-strategist: onboarding, migration paths, rollout plans - impact-assessor: blast radius analysis for template/spec changes - release-coordinator: version bumps, sync waves, release comms Includes /team-strategic-ops command with --task and --scope flags. Co-Authored-By: Claude Opus 4.6 * feat(agents): add agent/team relationship matrix analysis engine + scripts Add comprehensive agent/team relationship analysis with 8 cross-reference matrices and 10 supplementary analyses (orphans, cycles, bottlenecks, reachability, critical path, notification amplifiers, etc.). - Fix YAML structure: strategic-ops agents now under own top-level key - Add explicit agents: lists to forge + strategic-ops teams in teams.yaml - Add consolidation detection responsibilities to portfolio-analyst - Create agent-analysis.mjs engine module (loadFullAgentGraph + renderers) - Wire analyze-agents CLI command with --output/--matrix/--format flags - Add managed-scaffold script templates (bash + PowerShell) - Integrate into sync pipeline (auto-regenerates matrix on spec changes) - Add 33 tests covering all matrices, analyses, and edge cases Co-Authored-By: Claude Opus 4.6 * chore: update documentation files and add plan template - Add trailing newlines to Cursor command documentation files for consistency - Add new plan template files for project planning - Improve markdown table formatting in Claude skills documentation - Remove obsolete .clinerules/testing.md file - Update various rule files with better formatting and advisory rule alignment * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance Co-Authored-By: Claude Opus 4.6 * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. Co-Authored-By: Claude Opus 4.6 * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add Cost Ops team, agents, and multi-provider cost ticket (#364) * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance Co-Authored-By: Claude Opus 4.6 * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. Co-Authored-By: Claude Opus 4.6 * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops Co-Authored-By: Claude Opus 4.6 * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents (#365) Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs Co-authored-by: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 * fix(teams): address CodeRabbit review findings on strategic-ops PR - Lazy-load js-yaml in cli.mjs after ensureDependencies() to prevent crash when node_modules is missing - Convert YAML frontmatter to PowerShell comment blocks in all 6 PS1 templates to fix invalid PowerShell syntax - Fix protect-templates hook path: use 3 parent traversals to reach .agentkit/package.json from hooks directory - Remove schema-invalid 'phase' field from ai-cost-ops rule domain - Narrow strategic-ops scope: replace **/* catch-all with specific files - Add strategic-ops to cost-ops handoff-chain for consistency - Add Write tool to spec-compliance-auditor, vendor-arbitrage-analyst, and grant-hunter agents - Fix glob matching in resolve-merge.sh (use regex instead of broken sed strip) - Add merge failure vs conflict detection in resolve-merge.ps1 - Add branch existence check in setup-agentkit-branch-governance scripts - Add gh CLI preflight check in sync-split-pr.ps1 - Deduplicate branch protection loop when defaultBranch is 'main' - Fix applies-to glob: docs/planning/cost/** → docs/planning/cost-governance/** - Fix non-canonical doc paths in intake-agent-proposal.md - Add changelog entries for new teams, agents, and analysis engine - Resolve AGENT_TEAMS.md merge conflict (accept narrowed scope) - Run prettier on all modified files Co-Authored-By: Claude Opus 4.6 * fix(templates): add gh auth preflight and changelog divider handling - sync-split-pr.ps1: add gh auth status check before side effects - update-changelog.ps1: stop before --- divider when appending entries Addresses CodeRabbit review comments #7 and #13 on PR #356. Co-Authored-By: Claude Opus 4.6 * fix(sync): set executable permission on analyze-agents.sh Linux CI sync produces +x permissions; align local to match. Co-Authored-By: Claude Opus 4.6 * fix(templates): address CodeRabbit review round 3-4 findings - Fix YAML frontmatter in copilot agent template: use double quotes for description field to handle apostrophes (CRITICAL) - Fix protect-templates.sh/ps1 path traversal: correct parent directory count for .agentkit/package.json source repo detection - Add $PSNativeCommandUseErrorActionPreference to sync-split-pr.ps1 so native command failures (git, pnpm, gh) are treated as fatal - Replace try/catch with $LASTEXITCODE check for gh auth status - Deduplicate branch loop in setup-agentkit-branch-governance.sh when defaultBranch equals 'main' - Fix duplicate verification echo lines in governance scripts Co-Authored-By: Claude Opus 4.6 * style(docs): fix prettier formatting on planning documents Run prettier --write on web-intake-expansion.md and intake-agent-proposal.md to fix CI formatting check. Co-Authored-By: Claude Opus 4.6 * fix(tests): isolate render target gating tests with fresh temp dirs Tests in the "render target gating" describe block shared a single temp directory via beforeAll/afterAll. The first test ran --only claude (generating .claude/ files), and the second ran --only warp expecting no Claude files — but leftovers from test 1 caused the assertion to fail. Changing to beforeEach/afterEach gives each test a clean directory. Closes #377 Co-Authored-By: Claude Opus 4.6 * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(engine): add pre-sync commit guard and interactive apply mode Adds two safety features to the sync pipeline: 1. Pre-sync commit guard: Detects uncommitted changes in protected directories (.agentkit/engines, spec, overlays) before sync runs. In TTY mode, prompts to abort, stash, or continue. In non-TTY mode (CI), prints a warning and proceeds. 2. Interactive apply mode: After rendering, shows a change summary and prompts: apply all / skip all / prompt each file. Per-file prompt supports show-diff and apply-all-remaining. Default in TTY; bypassed with --yes, --no-prompt, or --force. New module: sync-guard.mjs with 4 exported functions and 7 tests. New CLI flags: --yes, --no-prompt for non-interactive sync. Co-Authored-By: Claude Opus 4.6 * chore(sync): regenerate outputs after branch merges Co-Authored-By: Claude Opus 4.6 * chore(sync): regenerate outputs after merge of new-user-entry-point Co-Authored-By: Claude Opus 4.6 * feat(engine): add configurable package manager and fix review findings - Add `stack.packageManager` field to project.yaml (pnpm | npm | yarn) - Derive helper template vars (pmInstall, pmRun, pmExec, pmLockfile, etc.) - Update CLAUDE.md template and hook/workflow templates to use {{packageManager}} - Fix sync-guard to exclude .agentkit/spec from protected dirs and add try/catch - Remove duplicate cost-ops team definition from teams.yaml - Pin all dependency versions in package.json (remove ^ prefixes) - Add vitest coverage thresholds (80% statements/branches/functions/lines) - Fix src/start/ code quality: null guards, exit delay, error boundaries - Harden consolidate-branches.sh: self-resolution guard, stash restore - Regenerate all 533 output files via agentkit sync Co-Authored-By: Claude Opus 4.6 * chore(engine): add brand color palette variables to sync vars Co-Authored-By: Claude Opus 4.6 * fix(ci): fix test race condition, workspace config, and lockfile - Fix ConversationFlow test: wait for 'Got it' before asserting hint text - Add packages field to pnpm-workspace.yaml for proper workspace resolution - Regenerate lockfile after version pinning (removed ^ prefixes) - Remove accidental .agentkit/templates/src/ artifacts Co-Authored-By: Claude Opus 4.6 * fix(start): add event loop yields to ConversationFlow tests ink-select-input needs setImmediate yields after a new menu renders before it can process ENTER keypresses. Without this, the second ENTER in leaf-selection tests was swallowed, causing intermittent failures. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 * fix(spec): correct githubSlug to phoenixvc/agentkit-forge (#391) Co-authored-by: Claude Opus 4.6 * Add entry point for new framework users (#389) * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * test(start): add coverage for result screen exit path Add App-level test that navigates through ConversationFlow to a leaf node and verifies the result screen text is rendered before exit(). Confirms the synchronous useEffect exit is safe — React commits the render (Ink captures the frame) before useEffect fires. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: update generated sync output timestamps Generated files updated with current sync date from dev merge. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW --------- Co-authored-by: Claude * fix: caldues heuristics (#398) * feat: complete revisit of agents (#399) (#400) * Add start command: new user entry point with state detection (#387) * fix(commands): add AskUserQuestion to VALID_TOOLS and /start command The /start command session got stuck because AskUserQuestion was not included in the allowed-tools whitelist. This fix addresses three issues: 1. VALID_TOOLS in spec-validator was missing AskUserQuestion, TodoWrite, Agent, and NotebookEdit — preventing commands from declaring these Claude Code built-in tools in their allowed-tools. 2. The /start command template now explicitly includes AskUserQuestion in its allowed-tools frontmatter and instructs the agent to use it for interactive guided choices (Phase 3). 3. Added /start command spec to commands.yaml with AskUserQuestion as a declared tool dependency. Also adds a test case validating all four newly-added tools are accepted by the spec validator. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M * fix(commands): remove unrendered Handlebars comment from start.md output The generated .claude/commands/start.md contained a raw {{! ... }} Handlebars comment that was not processed by the sync engine. Remove it so the generated output is clean Markdown. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M --------- * Add configurable prefix to kits commands (#388) * feat(sync): add configurable command prefix for generated slash commands Add `commandPrefix` setting to overlay settings that namespaces all generated slash commands across platforms: - Claude Code: subdirectory strategy (kits/check.md → /project:kits:check) - Cursor/Windsurf/Copilot/Codex: filename prefix (kits-check.md → /kits-check) - Team commands excluded from prefixing (already namespaced) Changes: - Add resolveCommandPath() helper with subdirectory/filename strategies - Update syncClaudeCommands, syncClaudeSkills, syncCursorCommands, syncWindsurfCommands, syncCopilotPrompts, syncCodexSkills - Add commandPrefix to vars from overlay settings - Add commandPrefixedName to buildCommandVars - Add 16 unit + integration tests (all pass, 93 existing tests unaffected) Default is null (no prefix) for full backwards compatibility. https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p * fix(sync): address review findings for command prefix - Remove unused afterAll import from test file - Add clarifying comment that non-spec command files are also prefixed - Add 2 integration tests verifying commandPrefixedName template variable renders correctly with and without prefix https://claude.ai/code/session_01EBjmVEhi7fP2huAL3SBR6p --------- * fix(ci): CI remediation — package manager, review findings, test stability (#390) * fix(ci): resolve 7 bugs from project review - BUG-001: Replace flaky discover test with controlled temp fixture - BUG-002: Run prettier --write to fix formatting drift - BUG-003: Add form-template detection skip in issue label validation - BUG-005: Change claude.yml to self-hosted runner - BUG-006: Align branch protection required status checks with project.yaml - BUG-007: Fix command injection in resolve-merge.sh (use grep -F) * docs: update changelog, add planning registry review findings - Add changelog entries for Wave 1-3 fixes (Added/Changed/Fixed/Removed) - Add Project Review Findings section to planning registry (PR-001 to PR-014) - Update planning docs after sync merge * feat(review): add --generate-plans flag to project-review command Add Phase 2.5 plan generation after project review findings. When --generate-plans is passed (default: true), scaffold plan files from critical/high findings into docs/planning/review-findings/. Also includes sync cleanup of stale cursor/windsurf settings. * chore(sync): regenerate all outputs after project review fixes * feat(cli): dynamic flag loading from commands.yaml + context-aware template hook - Replace ~200 lines of hardcoded VALID_FLAGS/FLAG_TYPES with loadCommandFlags() that reads flag definitions from commands.yaml at startup - CLI_INTERNAL_FLAGS/CLI_INTERNAL_FLAG_TYPES cover commands not in commands.yaml - Self-validation warns at startup if any flag is missing a type definition - Update cli.test.mjs to validate CLI_INTERNAL_FLAGS consistency - Fix scaffold-once orphan bug: carry forward manifest entries for files skipped by scaffold-once so orphan cleanup does not delete them - Make protect-templates hook context-aware: skip protection in the agentkit-forge source repo (detected via package.json name) so maintainer agents can edit templates; block only in downstream repos * feat(sync): add managed-mode script templates for downstream repos Add 14 script templates (.agentkit/templates/scripts/) with `managed` scaffold mode so downstream repos receive script updates via three-way merge while preserving local customizations. Templates include: create-doc, update-changelog, validate-documentation, validate-numbering, check-documentation-requirement, sync-issues, sync-split-pr, setup-agentkit-branch-governance, and resolve-merge (both .sh and .ps1 variants where applicable). Parameterized templates use {{defaultBranch}} and branch protection variables from project.yaml. Engine wired via syncScripts() under doc-scaffolding feature gate. * feat(teams): add TeamForge meta-team for agent team creation (cogmesh #130) Add the TEAMFORGE meta-team (T11) — a structured pipeline for creating, validating, and deploying new agent team specifications. Adapted from cogmesh #130 with a simplified 6-agent pipeline: - input-clarifier: assess requests, extract constraints - mission-definer: lock team definition (ID, scope, accepts) - role-architect: design agent roles and dependencies - prompt-engineer: write agent descriptions and rules - flow-designer: design team command and integration points - team-validator: quality gate for spec consistency Includes /team-forge command with --task flag (create-team, validate-team, audit-teams, update-team) and planning doc. * feat(teams): add Strategic Ops team for cross-project coordination Add the STRATEGIC OPS team (T12) — handles framework governance, portfolio analysis, adoption strategy, impact assessment, and release coordination across all repos using AgentKit Forge. 5-agent pipeline: - portfolio-analyst: inventory repos, detect drift, adoption metrics - governance-advisor: versioning strategy, breaking change protocols - adoption-strategist: onboarding, migration paths, rollout plans - impact-assessor: blast radius analysis for template/spec changes - release-coordinator: version bumps, sync waves, release comms Includes /team-strategic-ops command with --task and --scope flags. * feat(agents): add agent/team relationship matrix analysis engine + scripts Add comprehensive agent/team relationship analysis with 8 cross-reference matrices and 10 supplementary analyses (orphans, cycles, bottlenecks, reachability, critical path, notification amplifiers, etc.). - Fix YAML structure: strategic-ops agents now under own top-level key - Add explicit agents: lists to forge + strategic-ops teams in teams.yaml - Add consolidation detection responsibilities to portfolio-analyst - Create agent-analysis.mjs engine module (loadFullAgentGraph + renderers) - Wire analyze-agents CLI command with --output/--matrix/--format flags - Add managed-scaffold script templates (bash + PowerShell) - Integrate into sync pipeline (auto-regenerates matrix on spec changes) - Add 33 tests covering all matrices, analyses, and edge cases * chore: update documentation files and add plan template - Add trailing newlines to Cursor command documentation files for consistency - Add new plan template files for project planning - Improve markdown table formatting in Claude skills documentation - Remove obsolete .clinerules/testing.md file - Update various rule files with better formatting and advisory rule alignment * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs * feat(cost-ops): add Cost Ops team, agents, and multi-provider cost ticket (#364) * feat(agents): add spec-compliance-auditor feedback loop + Cost Ops team (T14) - Add spec-compliance-auditor to operations category (quality team) — closes the feedback loop between agent specs and actual behavior - Add Cost Ops team (T14) with 5 agents: model-economist, token-efficiency-engineer, vendor-arbitrage-analyst, grant-hunter, cost-ops-monitor - Add ai-cost-ops rules domain with 6 conventions (model routing, token budgets, caching, batch APIs, vendor abstraction, credit tracking) - Add team-cost-ops command with --task, --period, --provider flags - Update notification chains: data→cost-ops-monitor, infra→model-economist, retrospective-analyst→spec-compliance-auditor - Add intake routes: cost-ops, agent-performance * fix(teams): add implement to cost-ops team accepts list Resolves agent/team accepts mismatch — token-efficiency-engineer accepts implement but the team definition only had investigate/review/plan/document. * feat(cost-ops): add multi-provider infra cost ticket to backlog Add detailed planning ticket for multi-provider infrastructure cost normalisation, routing, and cost-agent integration. Covers 9 providers (Anthropic, OpenAI, Google, Mistral, Cohere, self-hosted, Azure, AWS, GCP) with 3-phase delivery plan and cross-team dependency tracking. * fix(templates): resolve PR review comments from CodeRabbit - Fix protect-templates.sh: package name check uses correct "agentkit-forge-runtime" instead of "agentkit-forge" - Fix protect-templates.ps1: malformed path (missing separator before .agentkit) and same package name correction - Fix update-changelog.ps1: change .mjs to .cjs to match CommonJS require() syntax used in the inline Node script - Fix resolve-merge.sh: add fallback for {{defaultBranch}} placeholder - Fix AGENT_TEAMS.md: resolve three-way merge conflict markers left by sync engine, keeping user formatting + implement in cost-ops * feat(cost-ops): add WebSearch/WebFetch tools to cost-ops agents (#365) Enable web research capabilities for cost-ops team: - Add WebSearch and WebFetch to /team-cost-ops allowed-tools - Add WebSearch and WebFetch to model-economist, vendor-arbitrage-analyst, and grant-hunter agent preferred-tools - Add web intake expansion ticket (P2) for MCP crawler, Puppeteer integration, automated pricing refresh, and cross-session persistence - Regenerate sync outputs --------- * fix(teams): address CodeRabbit review findings on strategic-ops PR - Lazy-load js-yaml in cli.mjs after ensureDependencies() to prevent crash when node_modules is missing - Convert YAML frontmatter to PowerShell comment blocks in all 6 PS1 templates to fix invalid PowerShell syntax - Fix protect-templates hook path: use 3 parent traversals to reach .agentkit/package.json from hooks directory - Remove schema-invalid 'phase' field from ai-cost-ops rule domain - Narrow strategic-ops scope: replace **/* catch-all with specific files - Add strategic-ops to cost-ops handoff-chain for consistency - Add Write tool to spec-compliance-auditor, vendor-arbitrage-analyst, and grant-hunter agents - Fix glob matching in resolve-merge.sh (use regex instead of broken sed strip) - Add merge failure vs conflict detection in resolve-merge.ps1 - Add branch existence check in setup-agentkit-branch-governance scripts - Add gh CLI preflight check in sync-split-pr.ps1 - Deduplicate branch protection loop when defaultBranch is 'main' - Fix applies-to glob: docs/planning/cost/** → docs/planning/cost-governance/** - Fix non-canonical doc paths in intake-agent-proposal.md - Add changelog entries for new teams, agents, and analysis engine - Resolve AGENT_TEAMS.md merge conflict (accept narrowed scope) - Run prettier on all modified files * fix(templates): add gh auth preflight and changelog divider handling - sync-split-pr.ps1: add gh auth status check before side effects - update-changelog.ps1: stop before --- divider when appending entries Addresses CodeRabbit review comments #7 and #13 on PR #356. * fix(sync): set executable permission on analyze-agents.sh Linux CI sync produces +x permissions; align local to match. * fix(templates): address CodeRabbit review round 3-4 findings - Fix YAML frontmatter in copilot agent template: use double quotes for description field to handle apostrophes (CRITICAL) - Fix protect-templates.sh/ps1 path traversal: correct parent directory count for .agentkit/package.json source repo detection - Add $PSNativeCommandUseErrorActionPreference to sync-split-pr.ps1 so native command failures (git, pnpm, gh) are treated as fatal - Replace try/catch with $LASTEXITCODE check for gh auth status - Deduplicate branch loop in setup-agentkit-branch-governance.sh when defaultBranch equals 'main' - Fix duplicate verification echo lines in governance scripts * style(docs): fix prettier formatting on planning documents Run prettier --write on web-intake-expansion.md and intake-agent-proposal.md to fix CI formatting check. * fix(tests): isolate render target gating tests with fresh temp dirs Tests in the "render target gating" describe block shared a single temp directory via beforeAll/afterAll. The first test ran --only claude (generating .claude/ files), and the second ran --only warp expecting no Claude files — but leftovers from test 1 caused the assertion to fail. Changing to beforeEach/afterEach gives each test a clean directory. Closes #377 * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(engine): add pre-sync commit guard and interactive apply mode Adds two safety features to the sync pipeline: 1. Pre-sync commit guard: Detects uncommitted changes in protected directories (.agentkit/engines, spec, overlays) before sync runs. In TTY mode, prompts to abort, stash, or continue. In non-TTY mode (CI), prints a warning and proceeds. 2. Interactive apply mode: After rendering, shows a change summary and prompts: apply all / skip all / prompt each file. Per-file prompt supports show-diff and apply-all-remaining. Default in TTY; bypassed with --yes, --no-prompt, or --force. New module: sync-guard.mjs with 4 exported functions and 7 tests. New CLI flags: --yes, --no-prompt for non-interactive sync. * chore(sync): regenerate outputs after branch merges * chore(sync): regenerate outputs after merge of new-user-entry-point * feat(engine): add configurable package manager and fix review findings - Add `stack.packageManager` field to project.yaml (pnpm | npm | yarn) - Derive helper template vars (pmInstall, pmRun, pmExec, pmLockfile, etc.) - Update CLAUDE.md template and hook/workflow templates to use {{packageManager}} - Fix sync-guard to exclude .agentkit/spec from protected dirs and add try/catch - Remove duplicate cost-ops team definition from teams.yaml - Pin all dependency versions in package.json (remove ^ prefixes) - Add vitest coverage thresholds (80% statements/branches/functions/lines) - Fix src/start/ code quality: null guards, exit delay, error boundaries - Harden consolidate-branches.sh: self-resolution guard, stash restore - Regenerate all 533 output files via agentkit sync * chore(engine): add brand color palette variables to sync vars * fix(ci): fix test race condition, workspace config, and lockfile - Fix ConversationFlow test: wait for 'Got it' before asserting hint text - Add packages field to pnpm-workspace.yaml for proper workspace resolution - Regenerate lockfile after version pinning (removed ^ prefixes) - Remove accidental .agentkit/templates/src/ artifacts * fix(start): add event loop yields to ConversationFlow tests ink-select-input needs setImmediate yields after a new menu renders before it can process ENTER keypresses. Without this, the second ENTER in leaf-selection tests was swallowed, causing intermittent failures. --------- * fix(spec): correct githubSlug to phoenixvc/agentkit-forge (#391) * Add entry point for new framework users (#389) * feat(commands): add /start command as new user entry point Adds a context-aware triage command that detects repository state (fresh clone, post-discovery, mid-session, uncommitted work) and guides users to the right command or team for their goal. Includes team routing table, 4 contextual flows, and decision guidance for when users don't know which team to use. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * refactor(commands): add Arguments and State Management sections to /start Addresses TEAMFORGE validation findings: - Add dedicated Arguments section documenting $ARGUMENTS handling - Add State Management section (reads/writes inventory) - Fix frontmatter: remove misleading generated_by field - Add explicit "manually authored" comment header https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): add /start to spec and template for cross-repo generation Moves /start from a hand-authored command to a proper spec-driven, sync-generated command available to any repo that adopts AgentKit Forge. - Add start command definition to commands.yaml (no feature gate — always on) - Create start.md template in .agentkit/templates/claude/commands/ - Add /start to CLAUDE.md Quick Reference table template https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after adding /start command Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(commands): make /start team routing dynamic instead of hardcoded Replace the static team routing table with dynamic discovery: 1. Read AGENT_TEAMS.md (from /discover) at runtime 2. Fall back to .agentkit/spec/teams.yaml 3. Fall back to /team-* command frontmatter This ensures /start always reflects the actual teams configured in any repo, rather than a hardcoded list that could go stale. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore(sync): regenerate outputs after dynamic routing change Generated by: pnpm -C .agentkit agentkit:sync https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add interactive TUI entry point with hybrid UI Replace static markdown output with an ink-based terminal UI that combines two modes: a guided conversation flow for first-run users and a fuzzy-searchable command palette for returning users. A persistent status bar shows repo state at a glance (branch, phase, backlog count, working tree status). - Context detection module mirrors /start Phase 1 signals - ConversationFlow: branching dialogue tree (choose-your-own-adventure) - CommandPalette: fuzzy search with context-ranked star recommendations - StatusBar: tmux-style persistent strip with color-coded segments - Supports --json flag for scripting/piping https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * feat(start): add test suite, error handling, and refactor for production readiness - Add vitest test infrastructure with 102 tests across 7 files - Coverage: 95.58% statements, 90.81% branches, 96.72% functions - Extract conversation tree to separate config module for testability - Add error boundary to App component for graceful error display - Add --help flag with usage documentation - Add TTY detection with JSON fallback for non-interactive environments - Add SIGINT/SIGTERM signal handling for clean exit https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: add coverage to gitignore, include plan and workspace config https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — unused code, git cwd, magic numbers - Call exit() after command selection so Ink process terminates - Remove unused ctx prop from Header component - Fix git commands to use -C flag with root path parameter - Extract dumpContextJson() helper to deduplicate JSON output logic - Add comment explaining hardcoded team filter exclusion - Replace magic numbers with named constants (FUSE_THRESHOLD, RECOMMENDED_SCORE, MAX_BRANCH_LENGTH) - Remove unused ink-spinner dependency - Add test verifying git -C flag passes root correctly https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * fix(start): address review findings — security, correctness, test quality - CRITICAL: Replace execSync shell interpolation with execFileSync to prevent command injection via root parameter in detect.js - CRITICAL: Remove phantom --external:ink-spinner from build script and switch npx to direct esbuild invocation - HIGH: Fix exit race condition — use useEffect instead of setTimeout - HIGH: Wire up onSelect callback in ConversationFlow so Guide mode triggers the result screen in App - HIGH: Destructure and accept ctx prop in ConversationFlow - HIGH: Add back-navigation (Escape) in ConversationFlow - HIGH: Guard against undefined team.focus in commands.js tags - MEDIUM: Use functional setCursor form to avoid stale closures - MEDIUM: Key commandIndices Map by string id instead of object identity - MEDIUM: Improve parseTeams header detection (drop first row approach) - MEDIUM: Filter completed/done/closed items from backlogCount - MEDIUM: Extract shared makeCtx test utility across all test files - MEDIUM: Add null guard to StatusBar truncate helper - LOW: Validate orchestratorPhase is a number in range 1-5 - LOW: Fix pnpm-workspace.yaml list syntax - Replace all setTimeout in tests with vi.waitFor deterministic waits https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * test(start): add coverage for result screen exit path Add App-level test that navigates through ConversationFlow to a leaf node and verifies the result screen text is rendered before exit(). Confirms the synchronous useEffect exit is safe — React commits the render (Ink captures the frame) before useEffect fires. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW * chore: update generated sync output timestamps Generated files updated with current sync date from dev merge. https://claude.ai/code/session_01Gy1HvvywVe6Z2iFJ2bHYCW --------- * fix: caldues heuristics (#398) --------- Co-authored-by: Claude * fix(quality): resolve all lint and format errors - Fix Prettier formatting across engine src and start components - Resolve 381 markdown lint errors (MD040, MD024, MD036, MD029, MD022, MD001) - Add markdownlint config rules for intentional doc patterns - Add .claude/worktrees to prettierignore to exclude external branches - Enable markdownlint MD024/MD026 for duplicate headings and trailing colons All quality checks now pass: Prettier (0 errors), Markdown lint (0 errors), Tests (111/111), Build (28.9kb) * I'll update the last_updated field in all the files from '2026-03-12' to '2026-03-13'. This appears to be a routine timestamp update across all the AgentKit Forge generated files. * docs: add AgentKit Forge sync feedback Add detailed feedback on AgentKit Forge v3.1.0 integration, focusing on: - Windows line-ending issues and multi-editor sync behavior - Documentation scaffold-once limitations and override challenges - Unresolved placeholder warnings lacking diagnostics - Windows-specific pnpm execution problems * docs: update CLAUDE.md with repository-specific editing guidelines Clarified that modifications to `.agentkit` files are permitted in the agentkit-forge repository, while upstream directories remain protected. This ensures users understand the editing boundaries for project configuration and template files. * docs(claude): allow .agentkit edits in this repo (NB for framework dev) Made-with: Cursor * chore(sync): regenerate outputs after agentkit:sync Made-with: Cursor --------- Co-authored-by: Claude * chore(sync): regenerate outputs and update timestamps (#429) * Add start command: new user entry point with state detection (#387) * fix(commands): add AskUserQuestion to VALID_TOOLS and /start command The /start command session got stuck because AskUserQuestion was not included in the allowed-tools whitelist. This fix addresses three issues: 1. VALID_TOOLS in spec-validator was missing AskUserQuestion, TodoWrite, Agent, and NotebookEdit — preventing commands from declaring these Claude Code built-in tools in their allowed-tools. 2. The /start command template now explicitly includes AskUserQuestion in its allowed-tools frontmatter and instructs the agent to use it for interactive guided choices (Phase 3). 3. Added /start command spec to commands.yaml with AskUserQuestion as a declared tool dependency. Also adds a test case validating all four newly-added tools are accepted by the spec validator. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M * fix(commands): remove unrendered Handlebars comment from start.md output The generated .claude/commands/start.md contained a raw {{! ... }} Handlebars comment that was not processed by the sync engine. Remove it so the generated output is clean Markdown. https://claude.ai/code/session_01Qh3Xk3jFkVdeRAXTqLvq3M --------- Co-authored-by: Claude * Add configurable prefix to kits commands (#388) * feat(sync): add configurable command prefix for generated slash commands Add `commandPrefix` setting to overlay settings that namespaces all generated slash commands across platforms: - Claude Code: subdirectory strategy (kits/check.md → /project:kits:check) - Cursor/Windsurf/Copilot/Codex: filename prefix (kits-check.md → /kits-check) - Team commands excluded from prefixing (already namespaced) Changes: - Add resolveCommandPath() helper with subdirectory/filename strategies - Update syncClaudeCommands, syncClaudeSkills, syncCursorCommands, syncWindsurfCommands, syncCopilotPrompts, sy… --------- Co-authored-by: Claude Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../explicit-domains-project.yaml | 25 + .../__fixtures__/fullstack-project.yaml | 23 + .../__fixtures__/heuristic-project.yaml | 23 + .../__fixtures__/js-only-project.yaml | 23 + .../node/src/__tests__/generation.test.mjs | 297 ++ .../src/__tests__/sync-integration.test.mjs | 36 +- .agentkit/engines/node/src/check.mjs | 58 +- .agentkit/engines/node/src/cli.mjs | 36 +- .../engines/node/src/commands-registry.mjs | 52 + .agentkit/engines/node/src/doctor.mjs | 8 +- .agentkit/engines/node/src/init.mjs | 149 + .agentkit/engines/node/src/propose-skill.mjs | 105 + .agentkit/engines/node/src/spec-validator.mjs | 2 +- .agentkit/engines/node/src/synchronize.mjs | 213 +- .agentkit/engines/node/src/template-utils.mjs | 119 +- .agentkit/engines/node/src/validate.mjs | 61 +- .agentkit/package.json | 1 + .agentkit/spec/agents.yaml | 35 +- .agentkit/spec/aliases.yaml | 2 +- .agentkit/spec/brand.yaml | 2 +- .agentkit/spec/commands.yaml | 209 +- .agentkit/spec/docs.yaml | 2 +- .agentkit/spec/features.yaml | 2 +- .agentkit/spec/project.yaml | 18 +- .agentkit/spec/rules.yaml | 8 +- .agentkit/spec/settings.yaml | 2 +- .agentkit/spec/skills.yaml | 680 ++++ .agentkit/spec/spec-defaults.yaml | 7 +- .agentkit/spec/teams.yaml | 2 +- .../claude/commands/project-review.md | 2 +- .agentkit/templates/claude/commands/review.md | 2 +- .../claude/hooks/stop-build-check.sh | 135 +- .agents/skills/cicd-optimize/SKILL.md | 110 + .agents/skills/handoff/SKILL.md | 8 +- .agents/skills/healthcheck/SKILL.md | 8 +- .agents/skills/init/SKILL.md | 79 + .agents/skills/project-review/SKILL.md | 8 +- .ai/README.md | 4 +- .ai/continuerules | 3 + .ai/cursorrules | 3 + .ai/windsurfrules | 3 + .claude/commands/handoff.md | 6 +- .claude/commands/healthcheck.md | 6 +- .claude/commands/project-review.md | 4 +- .claude/hooks/budget-guard-check.sh | 4 +- .claude/hooks/guard-destructive-commands.ps1 | 4 +- .claude/hooks/guard-destructive-commands.sh | 4 +- .claude/hooks/pre-push-validate.sh | 4 +- .claude/hooks/protect-sensitive.ps1 | 4 +- .claude/hooks/protect-sensitive.sh | 4 +- .claude/hooks/protect-templates.ps1 | 4 +- .claude/hooks/protect-templates.sh | 4 +- .claude/hooks/session-start.ps1 | 6 +- .claude/hooks/session-start.sh | 4 +- .claude/hooks/stop-build-check.ps1 | 4 +- .claude/hooks/stop-build-check.sh | 70 +- .claude/hooks/warn-uncommitted.ps1 | 4 +- .claude/hooks/warn-uncommitted.sh | 4 +- .claude/plans/tui-entry-point.md | 2 +- .claude/skills/cicd-optimize/SKILL.md | 110 + .claude/skills/handoff/SKILL.md | 8 +- .claude/skills/healthcheck/SKILL.md | 8 +- .claude/skills/init/SKILL.md | 79 + .claude/skills/project-review/SKILL.md | 8 +- .../focused-colden/.agentkit/.manifest.json | 1873 ----------- .../.agentkit/.scaffold-cache/AGENT_TEAMS.md | 80 - .../.agentkit/.scaffold-cache/docs/README.md | 47 - .../.scaffold-cache/docs/api/README.md | 14 - .../docs/architecture/README.md | 12 - .../docs/architecture/decisions/README.md | 16 - .../docs/architecture/diagrams/README.md | 16 - .../docs/architecture/specs/README.md | 12 - .../docs/engineering/README.md | 16 - .../.scaffold-cache/docs/history/README.md | 67 - .../docs/history/bug-fixes/README.md | 8 - .../docs/history/features/README.md | 8 - .../docs/history/implementations/README.md | 8 - .../docs/history/issues/README.md | 42 - .../docs/history/lessons-learned/README.md | 11 - .../docs/history/migrations/README.md | 8 - .../docs/integrations/README.md | 11 - .../.scaffold-cache/docs/operations/README.md | 13 - .../.scaffold-cache/docs/product/README.md | 12 - .../.scaffold-cache/docs/reference/README.md | 14 - .../.scaffold-cache/scripts/analyze-agents.sh | 20 - .../check-documentation-requirement.sh | 115 - .../scripts/consolidate-branches.sh | 289 -- .../.scaffold-cache/scripts/create-doc.sh | 170 - .../.scaffold-cache/scripts/resolve-merge.sh | 162 - .../setup-agentkit-branch-governance.sh | 128 - .../.scaffold-cache/scripts/sync-issues.sh | 180 -- .../.scaffold-cache/scripts/sync-split-pr.sh | 113 - .../scripts/update-changelog.sh | 122 - .../scripts/validate-documentation.sh | 83 - .../scripts/validate-numbering.sh | 70 - .../.agentkit/logs/usage-2026-03-16.jsonl | 8 - .../.agentkit/logs/usage-2026-03-17.jsonl | 24 - .../.agentkit/package-lock.json | 2764 ----------------- .../state/orchestrator.json.template | 25 - .../.agentkit/state/schema.json | 138 - .../.claude/settings.local.json | 40 - .../focused-colden/.claude/state/events.log | 105 - .../.claude/state/orchestrator.json | 72 - .../.claude/state/orchestrator.json.template | 25 - .../focused-colden/.claude/state/schema.json | 138 - .../state/tasks/task-p0-ci-pipeline.json | 22 - .../state/tasks/task-p0-test-framework.json | 0 .../state/tasks/task-p1-api-routes.json | 24 - .../state/tasks/task-p1-db-schema.json | 25 - .../state/tasks/task-p1-health-check.json | 24 - .../tasks/task-p1-migration-tooling.json | 24 - .../state/tasks/task-p1-staging-env.json | 24 - .../focused-colden/package-lock.json | 31 - .claude/worktrees/heuristic-mendel | 1 - .../tender-margulis/.agentkit/.manifest.json | 1873 ----------- .../.agentkit/.scaffold-cache/AGENT_TEAMS.md | 80 - .../.agentkit/.scaffold-cache/docs/README.md | 47 - .../.scaffold-cache/docs/api/README.md | 14 - .../docs/architecture/README.md | 12 - .../docs/architecture/decisions/README.md | 16 - .../docs/architecture/diagrams/README.md | 16 - .../docs/architecture/specs/README.md | 12 - .../docs/engineering/README.md | 16 - .../.scaffold-cache/docs/history/README.md | 67 - .../docs/history/bug-fixes/README.md | 8 - .../docs/history/features/README.md | 8 - .../docs/history/implementations/README.md | 8 - .../docs/history/issues/README.md | 42 - .../docs/history/lessons-learned/README.md | 11 - .../docs/history/migrations/README.md | 8 - .../docs/integrations/README.md | 11 - .../.scaffold-cache/docs/operations/README.md | 13 - .../.scaffold-cache/docs/product/README.md | 12 - .../.scaffold-cache/docs/reference/README.md | 14 - .../.scaffold-cache/scripts/analyze-agents.sh | 20 - .../check-documentation-requirement.sh | 115 - .../scripts/consolidate-branches.sh | 289 -- .../.scaffold-cache/scripts/create-doc.sh | 170 - .../.scaffold-cache/scripts/resolve-merge.sh | 162 - .../setup-agentkit-branch-governance.sh | 128 - .../.scaffold-cache/scripts/sync-issues.sh | 180 -- .../.scaffold-cache/scripts/sync-split-pr.sh | 113 - .../scripts/update-changelog.sh | 122 - .../scripts/validate-documentation.sh | 83 - .../scripts/validate-numbering.sh | 70 - .../.agentkit/logs/usage-2026-03-16.jsonl | 16 - .../.agentkit/logs/usage-2026-03-17.jsonl | 32 - .../.agentkit/package-lock.json | 2764 ----------------- .../state/orchestrator.json.template | 25 - .../.agentkit/state/schema.json | 138 - .../.claude/settings.local.json | 37 - .../tender-margulis/.claude/state/events.log | 104 - .../.claude/state/orchestrator.json | 72 - .../.claude/state/orchestrator.json.template | 25 - .../tender-margulis/.claude/state/schema.json | 138 - .../state/tasks/task-p0-ci-pipeline.json | 22 - .../state/tasks/task-p0-test-framework.json | 0 .../state/tasks/task-p1-api-routes.json | 24 - .../state/tasks/task-p1-db-schema.json | 25 - .../state/tasks/task-p1-health-check.json | 24 - .../tasks/task-p1-migration-tooling.json | 24 - .../state/tasks/task-p1-staging-env.json | 24 - .../tender-margulis/package-lock.json | 31 - .cursor/commands/cicd-optimize.md | 99 + .cursor/commands/handoff.md | 10 +- .cursor/commands/healthcheck.md | 10 +- .cursor/commands/init.md | 68 + .cursor/commands/project-review.md | 10 +- .cursor/rules/orchestrate.mdc | 4 +- .cursor/rules/project-context.mdc | 5 +- .cursor/rules/security.mdc | 4 +- .cursor/settings.json | 2 +- .gemini/config.yaml | 4 +- .gitattributes | 74 +- .../002-maintenance-coordinator-agent.md | 2 +- .../ISSUES/009-doctor-presync-healthcheck.md | 2 +- .../ISSUES/013-trae-mcp-alignment-umbrella.md | 8 +- .github/ISSUES/014-trae-mcp-foundation.md | 2 +- .../ISSUES/015-priority-mcp-integrations.md | 6 +- .../016-mcp-category-browser-devtools.md | 4 +- .../017-mcp-category-repo-data-research.md | 4 +- .../018-mcp-category-desktop-collab-memory.md | 2 +- .../019-trae-memory-support-umbrella.md | 6 +- .../ISSUES/020-memory-model-and-storage.md | 2 +- .../022-memory-generated-output-support.md | 2 +- .github/ISSUES/023-trae-codebase-indexing.md | 4 +- .github/ISSUES/024-trae-context-compaction.md | 2 +- .github/ISSUES/025-trae-rules-revisit.md | 11 +- .github/ISSUES/026-trae-skills-revisit.md | 9 +- .github/ISSUES/027-trae-agents-revisit.md | 11 +- .github/ISSUES/028-trae-figma-support.md | 2 +- .../ISSUES/029-platform-support-umbrella.md | 6 +- .github/ISSUES/031-ai-aggregator-support.md | 2 +- .../032-trae-alignment-master-umbrella.md | 2 +- .../ISSUES/033-notion-mcp-client-support.md | 8 +- .github/ISSUES/034-insforge-mcp-support.md | 6 +- ...35-documentation-mcp-and-pandoc-support.md | 6 +- .../036-self-hosted-mcp-server-strategy.md | 10 +- .../037-todoist-mcp-task-integration.md | 12 +- ...038-platform-support-zed-codex-opencode.md | 2 +- ...-should-consider-architectural-elegance.md | 27 +- .github/ISSUES/agent-maintainer-proposal.md | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 4 +- .github/ISSUE_TEMPLATE/doc-audit-command.md | 4 +- .github/ISSUE_TEMPLATE/doc-audit-command.yml | 4 +- .github/ISSUE_TEMPLATE/feature_request.yml | 4 +- .github/PULL_REQUEST_TEMPLATE.md | 4 +- .github/ai-framework-ci.yml | 4 +- .github/codeql/codeql-config.yml | 2 +- .github/instructions/rust.md | 6 +- .github/prompts/cicd-optimize.prompt.md | 115 + .github/prompts/handoff.prompt.md | 10 +- .github/prompts/healthcheck.prompt.md | 10 +- .github/prompts/init.prompt.md | 84 + .github/prompts/project-review.prompt.md | 10 +- .github/scripts/README.md | 3 + .github/scripts/resolve-merge.ps1 | 3 + .github/scripts/resolve-merge.sh | 3 + .github/scripts/setup-branch-protection.ps1 | 4 +- .github/scripts/setup-branch-protection.sh | 4 +- .github/workflows/block-agentkit-changes.yml | 6 +- .github/workflows/branch-protection.yml | 12 +- .../workflows/breaking-change-detection.yml | 5 +- .github/workflows/ci.yml | 2 +- .github/workflows/codeql.yml | 10 +- .github/workflows/coverage-report.yml | 5 +- .github/workflows/dependency-audit.yml | 5 +- .github/workflows/documentation-quality.yml | 5 +- .../workflows/documentation-validation.yml | 5 +- .github/workflows/issue-label-validation.yml | 2 +- .github/workflows/pr-validation.yml | 5 +- .github/workflows/retrospective-quality.yml | 5 +- .github/workflows/template-protection.yml | 6 +- .gitignore | 1 + .gitmessage | 4 +- .roadmap.yaml | 37 + .todo.yaml | 19 + .vscode/settings.json | 2 +- .windsurf/commands/cicd-optimize.md | 99 + .windsurf/commands/handoff.md | 6 +- .windsurf/commands/healthcheck.md | 6 +- .windsurf/commands/init.md | 68 + .windsurf/commands/project-review.md | 6 +- .windsurf/settings.json | 2 +- .windsurf/workflows/full-assessment.yml | 4 +- .windsurf/workflows/phase-execution.yml | 4 +- AGENTS.md | 8 +- AGENT_TEAMS.md | 8 +- CHANGELOG.md | 11 +- COMMAND_GUIDE.md | 4 +- CONTRIBUTING.md | 6 +- MIGRATIONS.md | 14 +- QUALITY_GATES.md | 7 +- RUNBOOK_AI.md | 6 +- SECURITY.md | 10 +- UNIFIED_AGENT_TEAMS.md | 5 +- agentkit_feedback.md | 6 +- db/README.md | 6 + docs/README.md | 11 +- docs/agents/README.md | 2 +- docs/api/01_overview.md | 6 +- docs/api/02_endpoints.md | 4 +- docs/api/03_authentication.md | 6 +- docs/api/04_examples.md | 6 +- docs/api/05_errors.md | 4 +- docs/api/06_versioning.md | 4 +- docs/api/07_framework-api-conventions.md | 4 + docs/api/README.md | 4 +- docs/architecture/01_overview.md | 8 +- docs/architecture/README.md | 4 +- .../Retort System Connections.png | Bin 0 -> 356693 bytes .../02-fallback-policy-tokens-problem.md | 10 +- .../decisions/03-tooling-strategy.md | 10 +- ...-static-security-analysis-depth-tooling.md | 8 +- ...pendency-supply-chain-detection-tooling.md | 8 +- ...-quality-maintainability-signal-tooling.md | 8 +- .../decisions/07-delivery-strategy.md | 66 +- ...directive-classification-type-and-phase.md | 4 +- .../decisions/08-expansion-analyst-agent.md | 2 +- .../decisions/08-issue-sync-strategy.md | 2 +- .../decisions/10-tool-neutral-agent-hub.md | 69 + .../decisions/ADR-08-split-brain-analysis.md | 12 +- docs/architecture/decisions/README.md | 6 +- docs/architecture/diagrams/README.md | 4 +- docs/architecture/expansion-agent-analysis.md | 2 +- docs/architecture/specs/01_functional_spec.md | 6 +- docs/architecture/specs/02_technical_spec.md | 8 +- docs/architecture/specs/03_api_spec.md | 6 +- docs/architecture/specs/04_data_models.md | 6 +- .../specs/PLAN-template-variable-audit.md | 2 +- docs/architecture/specs/README.md | 4 +- .../specs/competitive-landscape-report.md | 396 +++ .../specs/tool-neutral-agent-hub-findings.md | 262 ++ docs/engineering/01_setup.md | 8 +- docs/engineering/02_coding_standards.md | 6 +- docs/engineering/03_testing.md | 6 +- docs/engineering/04_git_workflow.md | 6 +- docs/engineering/05_security.md | 6 +- docs/engineering/06_pr_documentation.md | 6 +- docs/engineering/07_changelog.md | 8 +- .../engineering/08_code_quality_assessment.md | 10 +- docs/engineering/08_scaffold_management.md | 6 +- .../09_quality_framework_expansion_plan.md | 8 +- docs/engineering/12_package_management.md | 4 +- docs/engineering/13_template_system.md | 2 +- docs/engineering/14_brand_theming.md | 2 +- docs/engineering/README.md | 4 +- .../engineering/doc-audit-command-proposal.md | 4 +- .../reviews/cicd-implementation-plan.md | 6 +- .../cicd-infrastructure-review-2026-03-04.md | 2 +- docs/history/README.md | 6 +- ...26-03-04-infra-eval-review-fixes-bugfix.md | 2 +- docs/history/bug-fixes/README.md | 4 +- docs/history/bug-fixes/TEMPLATE-bugfix.md | 4 +- docs/history/features/README.md | 4 +- docs/history/features/TEMPLATE-feature.md | 4 +- ...ain-merge-reconciliation-implementation.md | 4 +- ...-and-onboarding-redesign-implementation.md | 86 + ...erformance-stabilization-implementation.md | 2 +- ...and-config-stabilization-implementation.md | 4 +- ...val-template-integration-implementation.md | 2 +- ...-06-cost-management-plan-implementation.md | 26 +- ...tandardize-github-issues-implementation.md | 2 +- ...7-linear-workspace-setup-implementation.md | 126 + docs/history/implementations/README.md | 4 +- .../TEMPLATE-implementation.md | 4 +- docs/history/issues/README.md | 4 +- docs/history/issues/TEMPLATE-issue.md | 4 +- docs/history/lessons-learned/README.md | 4 +- .../lessons-learned/TEMPLATE-lesson.md | 4 +- docs/history/migrations/README.md | 4 +- docs/history/migrations/TEMPLATE-migration.md | 4 +- docs/integrations/01_external_apis.md | 6 +- docs/integrations/02_webhooks.md | 6 +- docs/integrations/03_sdk.md | 6 +- .../04_notion-linear-intake-agent.md | 168 + docs/integrations/README.md | 4 +- docs/integrations/cognitive-mesh-skill.md | 76 + docs/integrations/ide-settings-sync.md | 104 + docs/integrations/trae-compatibility.md | 140 + docs/operations/01_deployment.md | 6 +- docs/operations/02_monitoring.md | 6 +- docs/operations/03_incident_response.md | 6 +- docs/operations/04_troubleshooting.md | 10 +- docs/operations/05_slos_slis.md | 4 +- docs/operations/README.md | 4 +- docs/orchestration/README.md | 2 +- docs/orchestration/concurrency-protocol.md | 2 +- docs/orchestration/overview.md | 2 +- docs/orchestration/pm-guide.md | 6 +- ...-state-cleanup-validation-session-start.md | 4 + docs/planning/README.md | 8 +- docs/planning/TEMPLATE-plan.md | 4 +- .../agents-teams/finops-specialist.md | 2 +- docs/planning/agents-teams/forge-team.md | 2 +- .../agents-teams/restructuring-gaps.md | 2 +- .../agents-teams/strategic-ops-team.md | 4 +- .../archive/cost-budget-flag-duplicate.md | 2 +- docs/planning/finops/wave5-integration.md | 6 +- .../framework/docs-wiki-generation.md | 2 +- .../tool-neutral-hub-adoption-roadmap.md | 309 ++ docs/product/01_prd.md | 6 +- docs/product/02_user_stories.md | 4 +- docs/product/03_roadmap.md | 6 +- docs/product/04_personas.md | 6 +- docs/product/PRD-001-llm-decision-engine.md | 10 +- .../PRD-002-llm-selection-scorecard-guide.md | 10 +- ...ent-to-llm-weighted-matrix-config-guide.md | 8 +- .../PRD-005-mesh-native-distribution.md | 68 +- ...RD-006-pwa-desktop-visual-configuration.md | 36 +- docs/product/PRD-007-adopter-autoupdate.md | 82 +- docs/product/README.md | 4 +- docs/reference/01_glossary.md | 8 +- docs/reference/02_faq.md | 12 +- docs/reference/03_changelog.md | 4 +- docs/reference/04_contributing.md | 4 +- docs/reference/05_project_yaml_reference.md | 2 +- docs/reference/README.md | 4 +- .../agent-prompt-comparative-analysis.md | 4 +- ...kit_adopter_branch_governance_checklist.md | 16 +- .../agentkit_sync_integration_patch_plan.md | 6 +- docs/reference/analysis/README.md | 2 +- .../language-aware-hooks-phase-plan.md | 12 +- .../analysis/model-quirks-analysis.md | 2 +- .../analysis/quirks-scoring-implementation.md | 2 +- .../cli_delivery_improvements_milestone.md | 50 +- .../governance_issue_file_impact_map.md | 2 +- docs/reference/issue_170_patch_blocks.md | 2 +- docs/reference/maintainer_exception_policy.md | 4 +- .../aider-polyglot-leaderboard-2025.md | 6 +- .../best-llm-for-coding-teams-2026.md | 2 +- .../swe-bench-leaderboard-feb-2026.md | 4 +- .../router_integration_governance_rollout.md | 28 +- infra/README.md | 10 + migrations/README.md | 6 + package-lock.json | 4 +- pnpm-setup.sh | 2 +- renovate.json | 2 +- scripts/analyze-agents.ps1 | 4 +- scripts/analyze-agents.sh | 4 +- scripts/check-documentation-requirement.sh | 4 +- scripts/consolidate-branches.ps1 | 4 +- scripts/consolidate-branches.sh | 4 +- scripts/create-doc.ps1 | 4 +- scripts/create-doc.sh | 4 +- scripts/resolve-merge.ps1 | 4 +- scripts/resolve-merge.sh | 6 +- scripts/setup-agentkit-branch-governance.ps1 | 4 +- scripts/setup-agentkit-branch-governance.sh | 6 +- scripts/sync-issues.sh | 4 +- scripts/sync-split-pr.ps1 | 4 +- scripts/sync-split-pr.sh | 4 +- scripts/update-changelog.ps1 | 4 +- scripts/update-changelog.sh | 4 +- scripts/validate-documentation.sh | 4 +- scripts/validate-numbering.sh | 4 +- src/start/index.js | 4 +- 417 files changed, 5804 insertions(+), 15576 deletions(-) create mode 100644 .agentkit/engines/node/src/__tests__/__fixtures__/explicit-domains-project.yaml create mode 100644 .agentkit/engines/node/src/__tests__/__fixtures__/fullstack-project.yaml create mode 100644 .agentkit/engines/node/src/__tests__/__fixtures__/heuristic-project.yaml create mode 100644 .agentkit/engines/node/src/__tests__/__fixtures__/js-only-project.yaml create mode 100644 .agentkit/engines/node/src/__tests__/generation.test.mjs create mode 100644 .agentkit/engines/node/src/commands-registry.mjs create mode 100644 .agentkit/engines/node/src/propose-skill.mjs create mode 100644 .agentkit/spec/skills.yaml create mode 100644 .agents/skills/cicd-optimize/SKILL.md create mode 100644 .agents/skills/init/SKILL.md create mode 100644 .claude/skills/cicd-optimize/SKILL.md create mode 100644 .claude/skills/init/SKILL.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.manifest.json delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/AGENT_TEAMS.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/api/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/decisions/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/diagrams/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/specs/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/engineering/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/bug-fixes/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/features/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/implementations/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/issues/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/lessons-learned/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/migrations/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/integrations/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/operations/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/product/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/reference/README.md delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/analyze-agents.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/check-documentation-requirement.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/consolidate-branches.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/create-doc.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/resolve-merge.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/setup-agentkit-branch-governance.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/sync-issues.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/sync-split-pr.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/update-changelog.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/validate-documentation.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/validate-numbering.sh delete mode 100644 .claude/worktrees/focused-colden/.agentkit/logs/usage-2026-03-16.jsonl delete mode 100644 .claude/worktrees/focused-colden/.agentkit/logs/usage-2026-03-17.jsonl delete mode 100644 .claude/worktrees/focused-colden/.agentkit/package-lock.json delete mode 100644 .claude/worktrees/focused-colden/.agentkit/state/orchestrator.json.template delete mode 100644 .claude/worktrees/focused-colden/.agentkit/state/schema.json delete mode 100644 .claude/worktrees/focused-colden/.claude/settings.local.json delete mode 100644 .claude/worktrees/focused-colden/.claude/state/events.log delete mode 100644 .claude/worktrees/focused-colden/.claude/state/orchestrator.json delete mode 100644 .claude/worktrees/focused-colden/.claude/state/orchestrator.json.template delete mode 100644 .claude/worktrees/focused-colden/.claude/state/schema.json delete mode 100644 .claude/worktrees/focused-colden/.claude/state/tasks/task-p0-ci-pipeline.json delete mode 100644 .claude/worktrees/focused-colden/.claude/state/tasks/task-p0-test-framework.json delete mode 100644 .claude/worktrees/focused-colden/.claude/state/tasks/task-p1-api-routes.json delete mode 100644 .claude/worktrees/focused-colden/.claude/state/tasks/task-p1-db-schema.json delete mode 100644 .claude/worktrees/focused-colden/.claude/state/tasks/task-p1-health-check.json delete mode 100644 .claude/worktrees/focused-colden/.claude/state/tasks/task-p1-migration-tooling.json delete mode 100644 .claude/worktrees/focused-colden/.claude/state/tasks/task-p1-staging-env.json delete mode 100644 .claude/worktrees/focused-colden/package-lock.json delete mode 160000 .claude/worktrees/heuristic-mendel delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.manifest.json delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/AGENT_TEAMS.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/api/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/decisions/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/diagrams/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/specs/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/engineering/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/bug-fixes/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/features/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/implementations/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/issues/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/lessons-learned/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/migrations/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/integrations/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/operations/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/product/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/reference/README.md delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/analyze-agents.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/check-documentation-requirement.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/consolidate-branches.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/create-doc.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/resolve-merge.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/setup-agentkit-branch-governance.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/sync-issues.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/sync-split-pr.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/update-changelog.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/validate-documentation.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/validate-numbering.sh delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/logs/usage-2026-03-16.jsonl delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/logs/usage-2026-03-17.jsonl delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/package-lock.json delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/state/orchestrator.json.template delete mode 100644 .claude/worktrees/tender-margulis/.agentkit/state/schema.json delete mode 100644 .claude/worktrees/tender-margulis/.claude/settings.local.json delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/events.log delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/orchestrator.json delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/orchestrator.json.template delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/schema.json delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/tasks/task-p0-ci-pipeline.json delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/tasks/task-p0-test-framework.json delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-api-routes.json delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-db-schema.json delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-health-check.json delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-migration-tooling.json delete mode 100644 .claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-staging-env.json delete mode 100644 .claude/worktrees/tender-margulis/package-lock.json create mode 100644 .cursor/commands/cicd-optimize.md create mode 100644 .cursor/commands/init.md create mode 100644 .github/prompts/cicd-optimize.prompt.md create mode 100644 .github/prompts/init.prompt.md create mode 100644 .roadmap.yaml create mode 100644 .todo.yaml create mode 100644 .windsurf/commands/cicd-optimize.md create mode 100644 .windsurf/commands/init.md create mode 100644 docs/architecture/Retort System Connections.png create mode 100644 docs/architecture/decisions/10-tool-neutral-agent-hub.md create mode 100644 docs/architecture/specs/competitive-landscape-report.md create mode 100644 docs/architecture/specs/tool-neutral-agent-hub-findings.md create mode 100644 docs/history/implementations/0001-2026-03-20-kit-based-domain-selection-and-onboarding-redesign-implementation.md create mode 100644 docs/history/implementations/0008-2026-03-17-linear-workspace-setup-implementation.md create mode 100644 docs/integrations/04_notion-linear-intake-agent.md create mode 100644 docs/integrations/cognitive-mesh-skill.md create mode 100644 docs/integrations/ide-settings-sync.md create mode 100644 docs/integrations/trae-compatibility.md create mode 100644 docs/planning/framework/tool-neutral-hub-adoption-roadmap.md diff --git a/.agentkit/engines/node/src/__tests__/__fixtures__/explicit-domains-project.yaml b/.agentkit/engines/node/src/__tests__/__fixtures__/explicit-domains-project.yaml new file mode 100644 index 00000000..224f5051 --- /dev/null +++ b/.agentkit/engines/node/src/__tests__/__fixtures__/explicit-domains-project.yaml @@ -0,0 +1,25 @@ +name: explicit-domains-test +githubSlug: test-org/explicit-domains-test +description: Explicit domain override fixture for domain filtering tests. +phase: active +stack: + languages: [typescript, csharp, rust] + packageManager: pnpm + nodeVersion: lts/* + frameworks: + frontend: [] + backend: [node.js] + css: [] + orm: none + database: [none] + search: none + messaging: [none] +domains: + rules: [typescript, security] +automation: + languageProfile: + mode: configured + diagnostics: off + inferFrom: + frameworks: true + tests: true diff --git a/.agentkit/engines/node/src/__tests__/__fixtures__/fullstack-project.yaml b/.agentkit/engines/node/src/__tests__/__fixtures__/fullstack-project.yaml new file mode 100644 index 00000000..8494b7a8 --- /dev/null +++ b/.agentkit/engines/node/src/__tests__/__fixtures__/fullstack-project.yaml @@ -0,0 +1,23 @@ +name: fullstack-test +githubSlug: test-org/fullstack-test +description: Full-stack fixture for domain filtering tests. +phase: active +stack: + languages: [typescript, csharp, rust, solidity] + packageManager: pnpm + nodeVersion: lts/* + frameworks: + frontend: [] + backend: [node.js, asp.net-core, axum] + css: [] + orm: none + database: [none] + search: none + messaging: [none] +automation: + languageProfile: + mode: configured + diagnostics: off + inferFrom: + frameworks: true + tests: true diff --git a/.agentkit/engines/node/src/__tests__/__fixtures__/heuristic-project.yaml b/.agentkit/engines/node/src/__tests__/__fixtures__/heuristic-project.yaml new file mode 100644 index 00000000..7030fc1c --- /dev/null +++ b/.agentkit/engines/node/src/__tests__/__fixtures__/heuristic-project.yaml @@ -0,0 +1,23 @@ +name: heuristic-test +githubSlug: test-org/heuristic-test +description: Heuristic mode fixture — all domains should be included (backward compat). +phase: active +stack: + languages: [javascript] + packageManager: pnpm + nodeVersion: lts/* + frameworks: + frontend: [] + backend: [node.js] + css: [] + orm: none + database: [none] + search: none + messaging: [none] +automation: + languageProfile: + mode: heuristic + diagnostics: off + inferFrom: + frameworks: true + tests: true diff --git a/.agentkit/engines/node/src/__tests__/__fixtures__/js-only-project.yaml b/.agentkit/engines/node/src/__tests__/__fixtures__/js-only-project.yaml new file mode 100644 index 00000000..4db170e0 --- /dev/null +++ b/.agentkit/engines/node/src/__tests__/__fixtures__/js-only-project.yaml @@ -0,0 +1,23 @@ +name: js-only-test +githubSlug: test-org/js-only-test +description: JS-only fixture for domain filtering tests. +phase: active +stack: + languages: [javascript] + packageManager: pnpm + nodeVersion: lts/* + frameworks: + frontend: [] + backend: [node.js] + css: [] + orm: none + database: [none] + search: none + messaging: [none] +automation: + languageProfile: + mode: configured + diagnostics: off + inferFrom: + frameworks: true + tests: true diff --git a/.agentkit/engines/node/src/__tests__/generation.test.mjs b/.agentkit/engines/node/src/__tests__/generation.test.mjs new file mode 100644 index 00000000..ae902fbd --- /dev/null +++ b/.agentkit/engines/node/src/__tests__/generation.test.mjs @@ -0,0 +1,297 @@ +/** + * Phase 6 — Domain filtering tests + * + * Tests that filterDomainsByStack correctly filters rule domains based on: + * 1. js-only project (mode: configured, languages: [javascript]) + * 2. fullstack project (typescript + dotnet + rust + solidity) + * 3. explicit domains.rules override (only listed domains regardless of stack) + * 4. heuristic mode (all domains — backward compat) + */ +import { readFileSync } from 'fs'; +import yaml from 'js-yaml'; +import { dirname, resolve } from 'path'; +import { describe, expect, it } from 'vitest'; +import { filterDomainsByStack, filterTechStacks } from '../template-utils.mjs'; + +const FIXTURES_DIR = resolve(import.meta.dirname, '__fixtures__'); +const AGENTKIT_ROOT = resolve(import.meta.dirname, '..', '..', '..', '..'); + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function loadFixture(name) { + return yaml.load(readFileSync(resolve(FIXTURES_DIR, name), 'utf-8')); +} + +function loadRulesSpec() { + return yaml.load(readFileSync(resolve(AGENTKIT_ROOT, 'spec', 'rules.yaml'), 'utf-8')); +} + +/** + * Build a minimal vars object matching what flattenProjectYaml + language inference + * produces for a given project.yaml fixture. + * Only the fields used by filterDomainsByStack are populated. + */ +function buildVarsFromFixture(project) { + const langs = (project?.stack?.languages || []).map((l) => l.trim().toLowerCase()); + const mode = project?.automation?.languageProfile?.mode || 'hybrid'; + + const hasLanguageTypeScript = langs.some((l) => l === 'typescript' || l === 'ts'); + const hasLanguageJavaScript = langs.some((l) => l === 'javascript' || l === 'js'); + const hasLanguageJsLike = hasLanguageTypeScript || hasLanguageJavaScript; + const hasLanguageRust = langs.includes('rust'); + const hasLanguagePython = langs.includes('python'); + const hasLanguageDotnet = langs.some((l) => ['csharp', 'c#', 'dotnet', '.net'].includes(l)); + const hasLanguageBlockchain = langs.some((l) => ['solidity', 'blockchain'].includes(l)); + + const hasConfiguredLanguages = langs.length > 0; + + let hasLanguageJsLikeEffective; + let hasLanguagePythonEffective; + let hasLanguageDotnetEffective; + let hasLanguageRustEffective; + + if (mode === 'configured') { + hasLanguageJsLikeEffective = hasConfiguredLanguages && hasLanguageJsLike; + hasLanguagePythonEffective = hasConfiguredLanguages && hasLanguagePython; + hasLanguageDotnetEffective = hasConfiguredLanguages && hasLanguageDotnet; + hasLanguageRustEffective = hasConfiguredLanguages && hasLanguageRust; + } else if (mode === 'heuristic') { + // heuristic: inferred from frameworks/tests (we set to false for these unit tests + // since we have no framework/test signals in fixtures — real engine would infer) + hasLanguageJsLikeEffective = hasLanguageJsLike; + hasLanguagePythonEffective = hasLanguagePython; + hasLanguageDotnetEffective = hasLanguageDotnet; + hasLanguageRustEffective = hasLanguageRust; + } else { + // hybrid: use configured if present, else inferred + hasLanguageJsLikeEffective = hasConfiguredLanguages ? hasLanguageJsLike : false; + hasLanguagePythonEffective = hasConfiguredLanguages ? hasLanguagePython : false; + hasLanguageDotnetEffective = hasConfiguredLanguages ? hasLanguageDotnet : false; + hasLanguageRustEffective = hasConfiguredLanguages ? hasLanguageRust : false; + } + + return { + languageProfileMode: mode, + hasLanguageJsLikeEffective, + hasLanguagePythonEffective, + hasLanguageDotnetEffective, + hasLanguageRustEffective, + hasLanguageBlockchain, + hasInfra: false, + }; +} + +function domainNames(rules) { + return new Set(rules.map((r) => r.domain)); +} + +// Universal domains that must always be present +const UNIVERSAL_DOMAINS = [ + 'security', + 'testing', + 'git-workflow', + 'documentation', + 'ci-cd', + 'dependency-management', + 'agent-conduct', + 'template-protection', +]; + +// --------------------------------------------------------------------------- +// Scenario 1 — JS-only project (mode: configured, languages: [javascript]) +// --------------------------------------------------------------------------- +describe('filterDomainsByStack — js-only project', () => { + const project = loadFixture('js-only-project.yaml'); + const rulesSpec = loadRulesSpec(); + const vars = buildVarsFromFixture(project); + const filtered = filterDomainsByStack(rulesSpec.rules, vars, project); + const names = domainNames(filtered); + + it('includes the typescript domain for a javascript project', () => { + expect(names.has('typescript')).toBe(true); + }); + + it('includes all universal domains', () => { + for (const d of UNIVERSAL_DOMAINS) { + expect(names.has(d), `expected universal domain "${d}" to be present`).toBe(true); + } + }); + + it('excludes dotnet — not in stack', () => { + expect(names.has('dotnet')).toBe(false); + }); + + it('excludes rust — not in stack', () => { + expect(names.has('rust')).toBe(false); + }); + + it('excludes python — not in stack', () => { + expect(names.has('python')).toBe(false); + }); + + it('excludes blockchain — not in stack', () => { + expect(names.has('blockchain')).toBe(false); + }); +}); + +// --------------------------------------------------------------------------- +// Scenario 2 — Fullstack project (typescript + dotnet + rust + solidity) +// --------------------------------------------------------------------------- +describe('filterDomainsByStack — fullstack project', () => { + const project = loadFixture('fullstack-project.yaml'); + const rulesSpec = loadRulesSpec(); + const vars = buildVarsFromFixture(project); + const filtered = filterDomainsByStack(rulesSpec.rules, vars, project); + const names = domainNames(filtered); + + it('includes typescript', () => { + expect(names.has('typescript')).toBe(true); + }); + + it('includes dotnet', () => { + expect(names.has('dotnet')).toBe(true); + }); + + it('includes rust', () => { + expect(names.has('rust')).toBe(true); + }); + + it('includes blockchain', () => { + expect(names.has('blockchain')).toBe(true); + }); + + it('includes all universal domains', () => { + for (const d of UNIVERSAL_DOMAINS) { + expect(names.has(d), `expected universal domain "${d}" to be present`).toBe(true); + } + }); + + it('excludes python — not in stack', () => { + expect(names.has('python')).toBe(false); + }); +}); + +// --------------------------------------------------------------------------- +// Scenario 3 — Explicit domains.rules override (only [typescript, security]) +// --------------------------------------------------------------------------- +describe('filterDomainsByStack — explicit domains.rules override', () => { + const project = loadFixture('explicit-domains-project.yaml'); + const rulesSpec = loadRulesSpec(); + const vars = buildVarsFromFixture(project); + const filtered = filterDomainsByStack(rulesSpec.rules, vars, project); + const names = domainNames(filtered); + + it('includes typescript — in explicit list', () => { + expect(names.has('typescript')).toBe(true); + }); + + it('includes security — in explicit list', () => { + expect(names.has('security')).toBe(true); + }); + + it('excludes testing — not in explicit list even though universal', () => { + expect(names.has('testing')).toBe(false); + }); + + it('excludes dotnet — not in explicit list despite being in stack', () => { + expect(names.has('dotnet')).toBe(false); + }); + + it('excludes rust — not in explicit list despite being in stack', () => { + expect(names.has('rust')).toBe(false); + }); + + it('has exactly 2 domains', () => { + expect(filtered.length).toBe(2); + }); +}); + +// --------------------------------------------------------------------------- +// Scenario 4 — Heuristic mode (backward compat: all domains included) +// --------------------------------------------------------------------------- +describe('filterDomainsByStack — heuristic mode (backward compat)', () => { + const project = loadFixture('heuristic-project.yaml'); + const rulesSpec = loadRulesSpec(); + const vars = buildVarsFromFixture(project); + const filtered = filterDomainsByStack(rulesSpec.rules, vars, project); + const names = domainNames(filtered); + + it('returns all domains from rules.yaml (no filtering)', () => { + expect(filtered.length).toBe(rulesSpec.rules.length); + }); + + it('includes typescript', () => { + expect(names.has('typescript')).toBe(true); + }); + + it('includes rust (even though not in stack)', () => { + expect(names.has('rust')).toBe(true); + }); + + it('includes python (even though not in stack)', () => { + expect(names.has('python')).toBe(true); + }); + + it('includes dotnet (even though not in stack)', () => { + expect(names.has('dotnet')).toBe(true); + }); +}); + +// --------------------------------------------------------------------------- +// filterTechStacks — basic coverage +// --------------------------------------------------------------------------- +describe('filterTechStacks', () => { + const stacks = [ + { name: 'node' }, + { name: 'dotnet' }, + { name: 'rust' }, + { name: 'python' }, + { name: 'custom-tool' }, // unknown — always kept + ]; + + it('keeps only node stack for a JS-only project', () => { + const vars = { + languageProfileMode: 'configured', + hasLanguageJsLikeEffective: true, + hasLanguageDotnetEffective: false, + hasLanguageRustEffective: false, + hasLanguagePythonEffective: false, + }; + const result = filterTechStacks(stacks, vars); + const names = result.map((s) => s.name); + expect(names).toContain('node'); + expect(names).not.toContain('dotnet'); + expect(names).not.toContain('rust'); + expect(names).not.toContain('python'); + expect(names).toContain('custom-tool'); // unknown always kept + }); + + it('keeps all stacks in heuristic mode', () => { + const vars = { languageProfileMode: 'heuristic' }; + const result = filterTechStacks(stacks, vars); + expect(result.length).toBe(stacks.length); + }); + + it('keeps dotnet and node for a fullstack JS+dotnet project', () => { + const vars = { + languageProfileMode: 'configured', + hasLanguageJsLikeEffective: true, + hasLanguageDotnetEffective: true, + hasLanguageRustEffective: false, + hasLanguagePythonEffective: false, + }; + const result = filterTechStacks(stacks, vars); + const names = result.map((s) => s.name); + expect(names).toContain('node'); + expect(names).toContain('dotnet'); + expect(names).not.toContain('rust'); + expect(names).not.toContain('python'); + }); + + it('returns empty array when stacks is null', () => { + const vars = { languageProfileMode: 'configured' }; + expect(filterTechStacks(null, vars)).toEqual([]); + }); +}); diff --git a/.agentkit/engines/node/src/__tests__/sync-integration.test.mjs b/.agentkit/engines/node/src/__tests__/sync-integration.test.mjs index 45fb5920..fe7c532e 100644 --- a/.agentkit/engines/node/src/__tests__/sync-integration.test.mjs +++ b/.agentkit/engines/node/src/__tests__/sync-integration.test.mjs @@ -681,7 +681,7 @@ describe('--quiet, --verbose, --no-clean, --diff flags', () => { try { await runSync({ agentkitRoot: AGENTKIT_ROOT, projectRoot, flags: { diff: true } }); const out = log.join('\n'); - expect(out).toContain('[retort:sync] Diff mode'); + expect(out).toContain('[agentkit:sync] Diff mode'); expect(out).toContain('create '); expect(out).toContain('Diff:'); expect(existsSync(join(projectRoot, 'CONTRIBUTING.md'))).toBe(false); @@ -958,13 +958,16 @@ describe('syncLanguageInstructions — generic, multi-platform dynamic generatio expect(existsSync(resolve(projectRoot, '.github', 'instructions', 'languages'))).toBe(true); }); - it('generates one file per rules.yaml domain under copilot output', { timeout: 15000 }, () => { + it('generates active stack domains under copilot output', { timeout: 15000 }, () => { const files = collectFiles(resolve(projectRoot, '.github', 'instructions', 'languages')); + // Retort spec declares [javascript, yaml, markdown] with mode: configured + // typescript + all universal domains should be present expect(files.some((f) => f.endsWith('typescript.md'))).toBe(true); - expect(files.some((f) => f.endsWith('rust.md'))).toBe(true); - expect(files.some((f) => f.endsWith('python.md'))).toBe(true); expect(files.some((f) => f.endsWith('security.md'))).toBe(true); expect(files.some((f) => f.endsWith('testing.md'))).toBe(true); + // rust/python not in stack — should be absent + expect(files.some((f) => f.endsWith('rust.md'))).toBe(false); + expect(files.some((f) => f.endsWith('python.md'))).toBe(false); }); it('generates languages/README.md for copilot target', () => { @@ -982,13 +985,10 @@ describe('syncLanguageInstructions — generic, multi-platform dynamic generatio expect(content).toContain('GENERATED by Retort'); }); - it('domain-specific template is used for rust.md', () => { - const content = readFileSync( - resolve(projectRoot, '.github', 'instructions', 'languages', 'rust.md'), - 'utf-8' - ); - expect(content).toContain('Rust'); - expect(content).toContain('GENERATED by Retort'); + it('rust.md is absent for a JS-only project', () => { + expect( + existsSync(resolve(projectRoot, '.github', 'instructions', 'languages', 'rust.md')) + ).toBe(false); }); it('ruleConventions from rules.yaml are injected into domain files', () => { @@ -1055,11 +1055,13 @@ describe('syncLanguageInstructions — claude target output (.claude/rules/langu expect(existsSync(resolve(projectRoot, '.claude', 'rules', 'languages'))).toBe(true); }); - it('generates one file per rules.yaml domain under claude output', { timeout: 15000 }, () => { + it('generates active stack domains under claude output', { timeout: 15000 }, () => { const files = collectFiles(resolve(projectRoot, '.claude', 'rules', 'languages')); + // Retort spec: [javascript] → typescript + universal domains present expect(files.some((f) => f.endsWith('typescript.md'))).toBe(true); - expect(files.some((f) => f.endsWith('rust.md'))).toBe(true); expect(files.some((f) => f.endsWith('testing.md'))).toBe(true); + // rust not in stack — should be absent + expect(files.some((f) => f.endsWith('rust.md'))).toBe(false); }); it('claude language files contain GENERATED header', () => { @@ -1114,7 +1116,7 @@ describe('syncEditorTheme (brand-driven editor theme)', () => { readFileSync(resolve(projectRoot, '.vscode', 'settings.json'), 'utf-8') ); expect(settings['_agentkit_theme']).toBeDefined(); - expect(settings['_agentkit_theme'].brand).toBe('Retort'); + expect(settings['_agentkit_theme'].brand).toBe('AgentKit Forge'); expect(settings['_agentkit_theme'].mode).toBe('both'); expect(settings['_agentkit_theme'].version).toBe('1.0.0'); }); @@ -1133,7 +1135,7 @@ describe('syncEditorTheme (brand-driven editor theme)', () => { expect(existsSync(settingsPath)).toBe(true); const settings = JSON.parse(readFileSync(settingsPath, 'utf-8')); expect(settings['workbench.colorCustomizations']).toBeDefined(); - expect(settings['_agentkit_theme'].brand).toBe('Retort'); + expect(settings['_agentkit_theme'].brand).toBe('AgentKit Forge'); }); it('generates .windsurf/settings.json with theme colors', () => { @@ -1141,7 +1143,7 @@ describe('syncEditorTheme (brand-driven editor theme)', () => { expect(existsSync(settingsPath)).toBe(true); const settings = JSON.parse(readFileSync(settingsPath, 'utf-8')); expect(settings['workbench.colorCustomizations']).toBeDefined(); - expect(settings['_agentkit_theme'].brand).toBe('Retort'); + expect(settings['_agentkit_theme'].brand).toBe('AgentKit Forge'); }); it('resolved colors are valid hex values', () => { @@ -1197,7 +1199,7 @@ describe('syncEditorTheme — pre-existing settings.json merge', () => { ); expect(settings['workbench.colorCustomizations']).toBeDefined(); expect(settings['_agentkit_theme']).toBeDefined(); - expect(settings['_agentkit_theme'].brand).toBe('Retort'); + expect(settings['_agentkit_theme'].brand).toBe('AgentKit Forge'); }); it('preserves original user-defined keys after merge', () => { diff --git a/.agentkit/engines/node/src/check.mjs b/.agentkit/engines/node/src/check.mjs index f1974b21..88243763 100644 --- a/.agentkit/engines/node/src/check.mjs +++ b/.agentkit/engines/node/src/check.mjs @@ -23,27 +23,6 @@ import { commandExists, execCommand, formatDuration, isValidCommand } from './ru * @param {string} projectRoot - Project root path * @returns {string} Command to run */ -/** - * Detect the package manager in use for a project. - * Checks package.json#packageManager first, then falls back to lockfile detection. - * @param {string} projectRoot - * @param {object} [pkg] - Already-parsed package.json (optional, avoids re-read) - * @returns {'pnpm'|'yarn'|'npm'} - */ -function detectPackageManager(projectRoot, pkg) { - // 1. Explicit declaration in package.json - const pmField = pkg?.packageManager; - if (typeof pmField === 'string') { - if (pmField.startsWith('pnpm')) return 'pnpm'; - if (pmField.startsWith('yarn')) return 'yarn'; - if (pmField.startsWith('npm')) return 'npm'; - } - // 2. Lockfile heuristic - if (existsSync(resolve(projectRoot, 'pnpm-lock.yaml'))) return 'pnpm'; - if (existsSync(resolve(projectRoot, 'yarn.lock'))) return 'yarn'; - return 'npm'; -} - function resolveTypecheckCommand(stack, projectRoot) { if (stack.name !== 'node' || !stack.typecheck || !projectRoot) return stack.typecheck; try { @@ -52,10 +31,35 @@ function resolveTypecheckCommand(stack, projectRoot) { const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')); const script = pkg.scripts?.typecheck; if (typeof script !== 'string' || !script.trim()) return stack.typecheck; - if (/^node\s+-e\s+/.test(script.trim())) return script.trim(); - const pm = detectPackageManager(projectRoot, pkg); - // pnpm and yarn can run scripts without the `run` sub-command - return pm === 'npm' ? 'npm run typecheck' : `${pm} typecheck`; + const trimmed = script.trim(); + // If the script is a simple node one-liner, run it directly to avoid + // depending on a package manager binary being present. + if (/^node\s+-e\s+/.test(trimmed)) return trimmed; + + // Otherwise, prefer running the script via the project's package manager. + // Detect package manager by lockfile + available executable, then fall + // back to any available PM, and finally to the configured stack.typecheck. + let pm = null; + if (existsSync(resolve(projectRoot, 'pnpm-lock.yaml')) && commandExists('pnpm')) { + pm = 'pnpm'; + } else if (existsSync(resolve(projectRoot, 'package-lock.json')) && commandExists('npm')) { + pm = 'npm'; + } else if (existsSync(resolve(projectRoot, 'yarn.lock')) && commandExists('yarn')) { + pm = 'yarn'; + } else if (commandExists('pnpm')) { + pm = 'pnpm'; + } else if (commandExists('npm')) { + pm = 'npm'; + } else if (commandExists('yarn')) { + pm = 'yarn'; + } + + if (pm === 'yarn') return 'yarn typecheck'; + if (pm) return `${pm} run typecheck`; + + // If we can't determine a usable package manager, fall back to the + // stack-configured command, which might be a direct executable. + return stack.typecheck; } catch { /* ignore */ } @@ -112,7 +116,9 @@ function buildSteps(stack, flags, agentkitRoot, projectRoot) { if (stack.typecheck) { const typecheckCmd = resolveTypecheckCommand(stack, projectRoot); if (!isValidCommand(typecheckCmd)) { - console.warn(`[agentkit:check] Skipping invalid typecheck command: ${typecheckCmd}`); + console.warn( + `[agentkit:check] Skipping invalid typecheck command: ${typecheckCmd} (resolved from: ${stack.typecheck})` + ); } else { steps.push({ name: 'typecheck', diff --git a/.agentkit/engines/node/src/cli.mjs b/.agentkit/engines/node/src/cli.mjs index 655f344d..2f46a2d1 100644 --- a/.agentkit/engines/node/src/cli.mjs +++ b/.agentkit/engines/node/src/cli.mjs @@ -8,6 +8,7 @@ import { existsSync, readFileSync } from 'fs'; import { parseArgs } from 'node:util'; import { dirname, resolve } from 'path'; import { fileURLToPath } from 'url'; +import { VALID_COMMANDS } from './commands-registry.mjs'; // Lazy-loaded after ensureDependencies() — js-yaml may not be installed yet let yaml; @@ -26,34 +27,8 @@ try { /* fallback to 0.0.0 */ } -const VALID_COMMANDS = [ - 'init', - 'sync', - 'validate', - 'discover', - 'spec-validate', - 'orchestrate', - 'plan', - 'check', - 'review', - 'handoff', - 'healthcheck', - 'cost', - 'project-review', - 'import-issues', - 'backlog', - 'sync-backlog', - 'add', - 'remove', - 'list', - 'features', - 'tasks', - 'delegate', - 'doctor', - 'scaffold', - 'preflight', - 'analyze-agents', -]; +// Re-export for callers that import from cli.mjs directly +export { VALID_COMMANDS } from './commands-registry.mjs'; // Workflow commands with runtime handlers const WORKFLOW_COMMANDS = ['orchestrate', 'plan', 'check', 'review', 'handoff', 'healthcheck']; @@ -492,12 +467,13 @@ async function main() { process.exit(1); } - // Early --help check before dependency installation to avoid side effects. - if (commandArgs.includes('--help') || commandArgs.includes('-h')) { + // Short-circuit help for subcommands before dependency checks and dynamic imports. + if (Array.isArray(commandArgs) && commandArgs.some((arg) => arg === '--help' || arg === '-h')) { showHelp(); process.exit(0); } + if (!ensureDependencies(AGENTKIT_ROOT)) { process.exit(1); } diff --git a/.agentkit/engines/node/src/commands-registry.mjs b/.agentkit/engines/node/src/commands-registry.mjs new file mode 100644 index 00000000..288dab7c --- /dev/null +++ b/.agentkit/engines/node/src/commands-registry.mjs @@ -0,0 +1,52 @@ +/** + * Retort — Command Registry + * Single source of truth for CLI command names. + * Imported by both cli.mjs (routing) and validate.mjs (parity check). + */ + +/** All commands the CLI recognises. Keep in sync with commands.yaml. */ +export const VALID_COMMANDS = [ + 'init', + 'sync', + 'validate', + 'discover', + 'spec-validate', + 'orchestrate', + 'plan', + 'check', + 'review', + 'handoff', + 'healthcheck', + 'cost', + 'project-review', + 'import-issues', + 'backlog', + 'sync-backlog', + 'add', + 'remove', + 'list', + 'features', + 'tasks', + 'delegate', + 'doctor', + 'scaffold', + 'preflight', + 'analyze-agents', + 'cicd-optimize', +]; + +/** + * CLI-only commands intentionally absent from the user-facing commands.yaml spec. + * These are framework internals, not slash commands. + */ +export const FRAMEWORK_COMMANDS = new Set([ + 'validate', + 'spec-validate', + 'add', + 'remove', + 'list', + 'tasks', + 'delegate', + 'features', + 'init', +]); diff --git a/.agentkit/engines/node/src/doctor.mjs b/.agentkit/engines/node/src/doctor.mjs index e08093b6..a3baf93a 100644 --- a/.agentkit/engines/node/src/doctor.mjs +++ b/.agentkit/engines/node/src/doctor.mjs @@ -1,5 +1,5 @@ /** - * Retort — Doctor + * AgentKit Forge — Doctor * Repository diagnostics and setup checks. */ import { execSync } from 'child_process'; @@ -312,8 +312,10 @@ export async function runDoctor({ agentkitRoot, projectRoot, flags = {} }) { if (existsSync(gitattrsPath)) { const gitattrs = readFileSync(gitattrsPath, 'utf-8'); const hasMarkers = - gitattrs.includes('# >>> Retort merge drivers') && - gitattrs.includes('# <<< Retort merge drivers'); + (gitattrs.includes('# >>> Retort merge drivers') || + gitattrs.includes('# >>> AgentKit Forge merge drivers')) && + (gitattrs.includes('# <<< Retort merge drivers') || + gitattrs.includes('# <<< AgentKit Forge merge drivers')); const hasMergeRules = gitattrs.includes('merge=agentkit-generated'); if (!hasMergeRules) { diff --git a/.agentkit/engines/node/src/init.mjs b/.agentkit/engines/node/src/init.mjs index faa7d282..d3fb01e3 100644 --- a/.agentkit/engines/node/src/init.mjs +++ b/.agentkit/engines/node/src/init.mjs @@ -9,6 +9,7 @@ * --non-interactive Skip prompts, use auto-detected defaults * --ci Alias for --non-interactive * --preset minimal | full | team | infra + * --dry-run Show what would be generated without writing files */ import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; import yaml from 'js-yaml'; @@ -192,6 +193,7 @@ function applyExternalKnowledgeFlags(project, flags = {}) { export async function runInit({ agentkitRoot, projectRoot, flags }) { const force = flags.force || false; + const dryRun = flags['dry-run'] || false; const nonInteractive = flags['non-interactive'] || flags.ci || false; const preset = flags.preset || null; const rawRepoName = flags.repoName ?? basename(projectRoot); @@ -246,6 +248,7 @@ export async function runInit({ agentkitRoot, projectRoot, flags }) { if (nonInteractive || process.env.CI) { console.log('[agentkit:init] Non-interactive mode — using auto-detected defaults.'); applyPresetDefaults(project, preset); + applyDetectedKitDefaults(project, report); const presetDef = preset ? PRESETS[preset] : PRESETS.full; return await finalizeInit({ agentkitRoot, @@ -255,6 +258,7 @@ export async function runInit({ agentkitRoot, projectRoot, flags }) { renderTargets: presetDef.renderTargets, featurePreset: presetDef.featurePreset || 'standard', force, + dryRun, }); } @@ -262,6 +266,7 @@ export async function runInit({ agentkitRoot, projectRoot, flags }) { if (preset) { console.log(`[agentkit:init] Using preset: ${PRESETS[preset].label}`); applyPresetDefaults(project, preset); + applyDetectedKitDefaults(project, report); return await finalizeInit({ agentkitRoot, projectRoot, @@ -270,6 +275,7 @@ export async function runInit({ agentkitRoot, projectRoot, flags }) { renderTargets: PRESETS[preset].renderTargets, featurePreset: PRESETS[preset].featurePreset || 'standard', force, + dryRun, }); } @@ -281,6 +287,7 @@ export async function runInit({ agentkitRoot, projectRoot, flags }) { console.warn( '[agentkit:init] @clack/prompts not available — falling back to non-interactive mode.' ); + applyDetectedKitDefaults(project, report); return await finalizeInit({ agentkitRoot, projectRoot, @@ -289,11 +296,79 @@ export async function runInit({ agentkitRoot, projectRoot, flags }) { renderTargets: PRESETS.full.renderTargets, featurePreset: 'standard', force, + dryRun, }); } clack.intro('Retort — Project Setup'); + // --- Kit detection display --- + const STACK_TO_DOMAIN = { + javascript: 'typescript', + typescript: 'typescript', + node: 'typescript', + csharp: 'dotnet', + dotnet: 'dotnet', + rust: 'rust', + python: 'python', + solidity: 'blockchain', + blockchain: 'blockchain', + }; + const UNIVERSAL_KIT_NAMES = [ + 'security', + 'testing', + 'git-workflow', + 'documentation', + 'ci-cd', + 'dependency-management', + 'agent-conduct', + ]; + + const detectedLangDomains = new Set(); + for (const stack of report.techStacks) { + const domain = STACK_TO_DOMAIN[(stack.name || '').toLowerCase()]; + if (domain) detectedLangDomains.add(domain); + } + const iacDetectedFromReport = !!detectIacTool(report); + + const kitSummaryLines = []; + if (detectedLangDomains.size > 0) { + kitSummaryLines.push('Language kits (auto-detected from stack):'); + for (const d of detectedLangDomains) kitSummaryLines.push(` ✓ ${d}`); + } else { + kitSummaryLines.push('Language kits: none detected'); + } + kitSummaryLines.push(''); + kitSummaryLines.push('Universal kits (always included):'); + kitSummaryLines.push(` ✓ ${UNIVERSAL_KIT_NAMES.join(', ')}`); + if (iacDetectedFromReport) kitSummaryLines.push(' ✓ iac (detected from infra/)'); + clack.note(kitSummaryLines.join('\n'), 'Kit detection — nothing forced'); + + // --- Optional kit selection --- + const optionalKitChoices = await clack.multiselect({ + message: 'Additional kits to activate (space to toggle)', + options: [ + { + value: 'iac', + label: 'iac — Terraform / Bicep / Pulumi', + hint: iacDetectedFromReport ? 'auto-detected' : 'no infra/ directory found', + }, + { value: 'finops', label: 'finops — Azure cost tracking' }, + { value: 'ai-cost-ops', label: 'ai-cost-ops — LLM token budgets' }, + ], + initialValues: iacDetectedFromReport ? ['iac'] : [], + required: false, + }); + + if (clack.isCancel(optionalKitChoices)) { + clack.cancel('Init cancelled.'); + process.exit(0); + } + + const selectedOptionalKits = Array.isArray(optionalKitChoices) ? optionalKitChoices : []; + // Persist kit selections to project for sync engine consumption + applyKitSelections(project, report, selectedOptionalKits); + // --- Phase 1: Project Identity --- const identity = await clack.group({ name: () => @@ -670,6 +745,7 @@ export async function runInit({ agentkitRoot, projectRoot, flags }) { featurePreset, enabledFeatures, force, + dryRun, }); } @@ -686,7 +762,38 @@ async function finalizeInit({ featurePreset, enabledFeatures, force, + dryRun = false, }) { + // --- Dry-run: show plan without writing --- + if (dryRun) { + const langs = project.stack?.languages || []; + const mode = project.automation?.languageProfile?.mode || 'configured'; + const features = []; + if (project.features?.aiCostOps) features.push('ai-cost-ops'); + if (project.features?.finops) features.push('finops'); + const featureInfo = enabledFeatures + ? `${enabledFeatures.length} features (custom)` + : featurePreset + ? `preset: ${featurePreset}` + : 'default features'; + + console.log('\n[agentkit:init] DRY-RUN — no files will be written\n'); + console.log(` Repo name: ${repoName}`); + console.log(` Languages: ${langs.join(', ') || 'none'}`); + console.log(` Language mode: ${mode}`); + console.log( + ` Features: ${featureInfo}${features.length ? ' + ' + features.join(', ') : ''}` + ); + console.log(` Render targets: ${renderTargets.join(', ')}`); + console.log(''); + console.log(' Would write:'); + console.log(` .agentkit/overlays/${repoName}/settings.yaml`); + console.log(' .agentkit/spec/project.yaml'); + console.log(' .agentkit-repo'); + console.log(' (+ all sync outputs for configured render targets)'); + console.log('\n Run without --dry-run to generate.\n'); + return; + } // 1. Copy __TEMPLATE__ overlay const templateDir = resolve(agentkitRoot, 'overlays', '__TEMPLATE__'); const overlayDir = resolve(agentkitRoot, 'overlays', repoName); @@ -985,6 +1092,48 @@ function writeProjectYaml(filePath, project) { // Detection helpers // --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// Kit helpers +// --------------------------------------------------------------------------- + +/** + * Applies kit defaults to project based on auto-detected stack. + * Used by non-interactive / preset / fallback paths so they get the same + * language-profile configuration as the interactive wizard. + */ +function applyDetectedKitDefaults(project, report) { + project.automation = project.automation || {}; + project.automation.languageProfile = project.automation.languageProfile || {}; + // Non-interactive defaults to 'hybrid' so heuristic detection still works + if (!project.automation.languageProfile.mode) { + project.automation.languageProfile.mode = 'hybrid'; + } +} + +/** + * Persists interactive kit selections to the project object for project.yaml. + * Called after the optional-kit multiselect prompt. + */ +function applyKitSelections(project, report, selectedOptionalKits) { + project.automation = project.automation || {}; + project.automation.languageProfile = project.automation.languageProfile || {}; + project.automation.languageProfile.mode = 'configured'; + + if (selectedOptionalKits.includes('ai-cost-ops')) { + project.features = project.features || {}; + project.features.aiCostOps = true; + } + if (selectedOptionalKits.includes('finops')) { + project.features = project.features || {}; + project.features.finops = true; + } + if (selectedOptionalKits.includes('iac') && !detectIacTool(report)) { + // User explicitly opted into iac but no IaC tool was detected — default to terraform + project.deployment = project.deployment || {}; + if (!project.deployment.iacTool) project.deployment.iacTool = 'terraform'; + } +} + function detectCloudProvider(report) { if (report.infrastructure.includes('bicep')) return 'azure'; if (report.infrastructure.includes('terraform')) return null; diff --git a/.agentkit/engines/node/src/propose-skill.mjs b/.agentkit/engines/node/src/propose-skill.mjs new file mode 100644 index 00000000..867134c9 --- /dev/null +++ b/.agentkit/engines/node/src/propose-skill.mjs @@ -0,0 +1,105 @@ +/** + * AgentKit Forge — propose-skill + * + * Promotes a local skill from .agents/skills// to org-meta/skills// + * by creating a branch and copying the SKILL.md file. + * + * Usage: + * node propose-skill.mjs + * pnpm ak:propose-skill + * + * What it does: + * 1. Reads the skill from {projectRoot}/.agents/skills//SKILL.md + * 2. Resolves the org-meta path (ORG_META_PATH env var or ~/repos/org-meta) + * 3. Creates a new git branch: feat/propose-skill- + * 4. Copies the SKILL.md to org-meta/skills//SKILL.md + * 5. Prints instructions for the next steps (commit, push, PR) + */ +import { execFileSync } from 'child_process'; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; +import { dirname, join, resolve } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function log(msg) { + process.stdout.write(msg + '\n'); +} + +function err(msg) { + process.stderr.write(`[propose-skill] Error: ${msg}\n`); + process.exit(1); +} + +function resolveOrgMetaPath() { + return process.env.ORG_META_PATH + ? resolve(process.env.ORG_META_PATH) + : resolve(process.env.HOME || process.env.USERPROFILE || '~', 'repos', 'org-meta'); +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +const skillName = process.argv[2]; + +if (!skillName || skillName.startsWith('-')) { + log('Usage: pnpm ak:propose-skill '); + log(''); + log('Promotes a local skill from .agents/skills// to org-meta/skills//.'); + log('The skill must exist in the current repo and NOT already be in skills.yaml.'); + process.exit(0); +} + +const projectRoot = process.cwd(); +const localSkillPath = join(projectRoot, '.agents', 'skills', skillName, 'SKILL.md'); + +if (!existsSync(localSkillPath)) { + err(`Skill '${skillName}' not found at ${localSkillPath}`); +} + +const orgMetaRoot = resolveOrgMetaPath(); +if (!existsSync(orgMetaRoot)) { + err(`org-meta not found at ${orgMetaRoot}. Set ORG_META_PATH env var to override.`); +} + +const destDir = join(orgMetaRoot, 'skills', skillName); +const destPath = join(destDir, 'SKILL.md'); + +if (existsSync(destPath)) { + log(`[propose-skill] '${skillName}' already exists in org-meta at ${destPath}`); + log('If you want to update it, edit the file directly and open a PR in org-meta.'); + process.exit(0); +} + +// Read the local skill content +const content = readFileSync(localSkillPath, 'utf-8'); + +// Create branch in org-meta +const branchName = `feat/propose-skill-${skillName}`; +log(`[propose-skill] Creating branch '${branchName}' in org-meta...`); +try { + execFileSync('git', ['checkout', '-b', branchName], { cwd: orgMetaRoot, stdio: 'pipe' }); +} catch (e) { + err(`Failed to create branch: ${e?.message ?? e}`); +} + +// Write the skill file +mkdirSync(destDir, { recursive: true }); +writeFileSync(destPath, content, 'utf-8'); +log(`[propose-skill] Wrote ${destPath}`); + +// Print next steps +log(''); +log('Next steps:'); +log(` cd ${orgMetaRoot}`); +log(` git add skills/${skillName}/SKILL.md`); +log(` git commit -m "feat(skills): propose ${skillName} from downstream repo"`); +log(` git push -u origin ${branchName}`); +log(' # Then open a PR against org-meta main'); +log(''); +log(`Once merged, add '${skillName}' to .agentkit/spec/skills.yaml with source: org-meta.`); diff --git a/.agentkit/engines/node/src/spec-validator.mjs b/.agentkit/engines/node/src/spec-validator.mjs index bf02ad0d..7a7b644f 100644 --- a/.agentkit/engines/node/src/spec-validator.mjs +++ b/.agentkit/engines/node/src/spec-validator.mjs @@ -120,7 +120,7 @@ const agentSchema = { // --------------------------------------------------------------------------- // Schema: commands.yaml // --------------------------------------------------------------------------- -const VALID_COMMAND_TYPES = ['workflow', 'team', 'utility']; +const VALID_COMMAND_TYPES = ['workflow', 'team', 'utility', 'framework']; const VALID_TOOLS = [ 'Read', 'Write', diff --git a/.agentkit/engines/node/src/synchronize.mjs b/.agentkit/engines/node/src/synchronize.mjs index 1958b679..8cd62c65 100644 --- a/.agentkit/engines/node/src/synchronize.mjs +++ b/.agentkit/engines/node/src/synchronize.mjs @@ -29,6 +29,7 @@ import { import { categorizeFile, computeProjectCompleteness, + filterDomainsByStack, flattenProjectYaml, formatCommandFlags, insertHeader, @@ -479,6 +480,8 @@ ${GITATTR_START} # GENERATED by Retort v${version} — regenerated on every sync. # These custom merge drivers auto-resolve conflicts on framework-managed files. # Driver "agentkit-generated" accepts the incoming (upstream/theirs) version. +# Only scaffold:always files are listed — scaffold:managed files (CLAUDE.md, +# settings.json, etc.) are intentionally excluded so user edits are preserved. # # To activate locally, run: # git config merge.agentkit-generated.name "Accept upstream for generated files" @@ -486,19 +489,43 @@ ${GITATTR_START} # # Or use: scripts/resolve-merge.sh -# --- Generated agent/skill/prompt packs (always accept upstream) --- -.agents/skills/**/SKILL.md merge=agentkit-generated +# --- Claude Code: agents, commands, rules, hooks, skills --- +.claude/agents/*.md merge=agentkit-generated +.claude/commands/*.md merge=agentkit-generated +.claude/rules/**/*.md merge=agentkit-generated +.claude/hooks/*.sh merge=agentkit-generated +.claude/hooks/*.ps1 merge=agentkit-generated +.claude/skills/**/SKILL.md merge=agentkit-generated + +# --- Cursor: commands and rules --- +.cursor/commands/*.md merge=agentkit-generated +.cursor/rules/**/*.md merge=agentkit-generated + +# --- Windsurf: commands, rules, and workflows --- +.windsurf/commands/*.md merge=agentkit-generated +.windsurf/rules/**/*.md merge=agentkit-generated +.windsurf/workflows/*.yml merge=agentkit-generated + +# --- Cline rules --- +.clinerules/**/*.md merge=agentkit-generated + +# --- Roo rules --- +.roo/rules/**/*.md merge=agentkit-generated + +# --- GitHub Copilot: instructions, agents, chatmodes, prompts --- +.github/instructions/**/*.md merge=agentkit-generated .github/agents/*.agent.md merge=agentkit-generated .github/chatmodes/*.chatmode.md merge=agentkit-generated .github/prompts/*.prompt.md merge=agentkit-generated - -# --- Generated doc indexes (always accept upstream) --- -docs/*/README.md merge=agentkit-generated - -# --- Generated config files (always accept upstream) --- .github/copilot-instructions.md merge=agentkit-generated .github/PULL_REQUEST_TEMPLATE.md merge=agentkit-generated +# --- Agent skills packs --- +.agents/skills/**/SKILL.md merge=agentkit-generated + +# --- Generated doc indexes --- +docs/*/README.md merge=agentkit-generated + # --- Lock files (accept upstream, regenerate after merge) --- pnpm-lock.yaml merge=agentkit-generated .agentkit/pnpm-lock.yaml merge=agentkit-generated @@ -1280,6 +1307,124 @@ async function syncCodexSkills(templatesDir, tmpDir, vars, version, repoName, co } } +// --------------------------------------------------------------------------- +// Org-meta skill distribution + uptake detection +// --------------------------------------------------------------------------- + +/** + * Resolves the path to the org-meta skills directory. + * Priority: ORG_META_PATH env var → ~/repos/org-meta (default) + * + * @returns {string} + */ +function resolveOrgMetaSkillsDir() { + const base = process.env.ORG_META_PATH + ? resolve(process.env.ORG_META_PATH) + : resolve(process.env.HOME || process.env.USERPROFILE || '~', 'repos', 'org-meta'); + return join(base, 'skills'); +} + +/** + * Copies org-meta skills (source: org-meta) into tmpDir/.agents/skills//SKILL.md. + * Non-destructive: if the skill already exists in projectRoot with different content, + * the file is NOT written to tmpDir — the local version is preserved. + * + * @param {string} tmpDir - Temp directory for sync output + * @param {string} projectRoot - Actual project root (for diffing existing files) + * @param {object} skillsSpec - Parsed skills.yaml + * @param {function} log - Logger + */ +async function syncOrgMetaSkills(tmpDir, projectRoot, skillsSpec, log) { + const orgMetaSkillsDir = resolveOrgMetaSkillsDir(); + if (!existsSync(orgMetaSkillsDir)) { + log(`[agentkit:sync] org-meta skills: directory not found at ${orgMetaSkillsDir} — skipping`); + return; + } + + const orgMetaSkills = (skillsSpec.skills || []).filter((s) => s.source === 'org-meta'); + + for (const skill of orgMetaSkills) { + const srcPath = join(orgMetaSkillsDir, skill.name, 'SKILL.md'); + if (!existsSync(srcPath)) { + log(`[agentkit:sync] org-meta skill '${skill.name}' not found at ${srcPath} — skipping`); + continue; + } + + const destRelPath = join('.agents', 'skills', skill.name, 'SKILL.md'); + const destProjectPath = join(projectRoot, destRelPath); + + // If local version exists and differs, preserve it (non-destructive) + if (existsSync(destProjectPath)) { + const localContent = readFileSync(destProjectPath, 'utf-8'); + const srcContent = readFileSync(srcPath, 'utf-8'); + if (localContent !== srcContent) { + log( + `[agentkit:sync] org-meta skill '${skill.name}' differs from local — preserving local copy` + ); + continue; + } + } + + const content = readFileSync(srcPath, 'utf-8'); + await writeOutput(join(tmpDir, destRelPath), content); + } +} + +/** + * Scans projectRoot/.agents/skills/ for skill directories not listed in skills.yaml. + * Appends unknown skill names to .agents/skills/_unknown/report.md in tmpDir. + * This is the non-destructive uptake mechanism — unknown skills are never overwritten, + * only reported. Use `pnpm ak:propose-skill ` to promote them to org-meta. + * + * @param {string} tmpDir - Temp directory for sync output + * @param {string} projectRoot - Actual project root (for reading existing skills) + * @param {object} skillsSpec - Parsed skills.yaml + * @param {string} syncDate - ISO date string (YYYY-MM-DD) + * @param {function} log - Logger + */ +async function syncUnknownSkillsReport(tmpDir, projectRoot, skillsSpec, syncDate, log) { + const localSkillsDir = join(projectRoot, '.agents', 'skills'); + if (!existsSync(localSkillsDir)) return; + + const knownNames = new Set((skillsSpec.skills || []).map((s) => s.name)); + let entries; + try { + entries = await readdir(localSkillsDir, { withFileTypes: true }); + } catch { + return; + } + + const unknownSkills = entries + .filter((e) => e.isDirectory() && e.name !== '_unknown' && !knownNames.has(e.name)) + .map((e) => e.name); + + if (unknownSkills.length === 0) return; + + log( + `[agentkit:sync] Found ${unknownSkills.length} local skill(s) not in skills.yaml: ${unknownSkills.join(', ')}` + ); + + const reportPath = join(tmpDir, '.agents', 'skills', '_unknown', 'report.md'); + + // Read existing report from projectRoot (if any) to append rather than replace + const existingReportPath = join(projectRoot, '.agents', 'skills', '_unknown', 'report.md'); + let existingContent = ''; + if (existsSync(existingReportPath)) { + existingContent = readFileSync(existingReportPath, 'utf-8'); + } + + // Build new entries (only skills not already listed in the report) + const newEntries = unknownSkills.filter((name) => !existingContent.includes(`| \`${name}\``)); + if (newEntries.length === 0) return; + + const header = existingContent + ? '' + : `# Unknown Skills — Uptake Candidates\n\nSkills found in \`.agents/skills/\` that are not in \`skills.yaml\`.\n\nTo promote a skill: \`pnpm ak:propose-skill \`\n\n| Skill | First Seen | Action |\n|-------|------------|--------|\n`; + + const rows = newEntries.map((name) => `| \`${name}\` | ${syncDate} | pending |\n`).join(''); + await writeOutput(reportPath, existingContent + header + rows); +} + // --------------------------------------------------------------------------- // Warp sync helper // --------------------------------------------------------------------------- @@ -1777,6 +1922,7 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { const rulesSpec = readYaml(resolve(agentkitRoot, 'spec', 'rules.yaml')) || {}; const settingsSpec = readYaml(resolve(agentkitRoot, 'spec', 'settings.yaml')) || {}; const agentsSpec = readYaml(resolve(agentkitRoot, 'spec', 'agents.yaml')) || {}; + const skillsSpec = readYaml(resolve(agentkitRoot, 'spec', 'skills.yaml')) || {}; const docsSpec = readYaml(resolve(agentkitRoot, 'spec', 'docs.yaml')) || {}; const sectionsSpec = readYaml(resolve(agentkitRoot, 'spec', 'sections.yaml')) || {}; const projectSpec = readYaml(resolve(agentkitRoot, 'spec', 'project.yaml')); @@ -1864,7 +2010,7 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { commandPrefix: overlaySettings.commandPrefix || null, syncDate: new Date().toISOString().slice(0, 10), lastModel: process.env.AGENTKIT_LAST_MODEL || 'sync-engine', - lastAgent: process.env.AGENTKIT_LAST_AGENT || 'agentkit-forge', + lastAgent: process.env.AGENTKIT_LAST_AGENT || 'retort', // Branch protection defaults — ensure generated scripts produce valid // JSON even when project.yaml omits the branchProtection section. bpRequiredReviewCount: projectVars.bpRequiredReviewCount ?? '1', @@ -1935,6 +2081,15 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { vars.teamsList = buildTeamsList(rawTeams); vars.hasTeams = rawTeams.length > 0; + // Filter rule domains to those matching the active language stack. + // Universal domains (security, testing, git-workflow, etc.) are always included. + // heuristic mode keeps all domains for backward compatibility. + // An explicit `domains.rules` list in project.yaml overrides auto-detection. + const filteredRulesSpec = { + ...rulesSpec, + rules: filterDomainsByStack(rulesSpec.rules, vars, projectSpec), + }; + // Resolve render targets — determines which tool outputs to generate let targets = resolveRenderTargets(overlaySettings.renderTargets, flags); @@ -2055,7 +2210,7 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { version, headerRepoName, agentsSpec, - rulesSpec + filteredRulesSpec ), syncDirectCopy( templatesDir, @@ -2088,7 +2243,7 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { vars, version, headerRepoName, - rulesSpec, + filteredRulesSpec, '.claude/rules/languages', 'claude' ) @@ -2119,7 +2274,7 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { vars, version, headerRepoName, - rulesSpec, + filteredRulesSpec, '.cursor/rules/languages', 'cursor' ) @@ -2168,7 +2323,7 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { vars, version, headerRepoName, - rulesSpec, + filteredRulesSpec, '.windsurf/rules/languages', 'windsurf' ) @@ -2202,7 +2357,7 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { version, headerRepoName, agentsSpec, - rulesSpec + filteredRulesSpec ), syncCopilotChatModes( templatesDir, @@ -2222,7 +2377,7 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { vars, version, headerRepoName, - rulesSpec, + filteredRulesSpec, '.github/instructions/languages', 'copilot' ) @@ -2236,7 +2391,9 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { if (targets.has('codex')) { gatedTasks.push( - syncCodexSkills(templatesDir, tmpDir, vars, version, headerRepoName, commandsSpec) + syncCodexSkills(templatesDir, tmpDir, vars, version, headerRepoName, commandsSpec), + syncOrgMetaSkills(tmpDir, projectRoot, skillsSpec, log), + syncUnknownSkillsReport(tmpDir, projectRoot, skillsSpec, vars.syncDate, log) ); } @@ -2247,14 +2404,14 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { if (targets.has('cline')) { if (isFeatureEnabled('coding-rules', vars)) { gatedTasks.push( - syncClineRules(templatesDir, tmpDir, vars, version, headerRepoName, rulesSpec), + syncClineRules(templatesDir, tmpDir, vars, version, headerRepoName, filteredRulesSpec), syncLanguageInstructions( templatesDir, tmpDir, vars, version, headerRepoName, - rulesSpec, + filteredRulesSpec, '.clinerules/languages', 'cline' ) @@ -2265,14 +2422,14 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { if (targets.has('roo')) { if (isFeatureEnabled('coding-rules', vars)) { gatedTasks.push( - syncRooRules(templatesDir, tmpDir, vars, version, headerRepoName, rulesSpec), + syncRooRules(templatesDir, tmpDir, vars, version, headerRepoName, filteredRulesSpec), syncLanguageInstructions( templatesDir, tmpDir, vars, version, headerRepoName, - rulesSpec, + filteredRulesSpec, '.roo/rules/languages', 'roo' ) @@ -2598,6 +2755,24 @@ export async function runSync({ agentkitRoot, projectRoot, flags }) { } } + // Content-hash guard: skip write if content is identical to the existing file. + // This prevents mtime churn on generated files that haven't logically changed, + // reducing adopter merge-conflict counts on framework-update merges. + if (existsSync(destFile)) { + const newHash = newManifestFiles[normalizedRel]?.hash; + if (newHash) { + const existingContent = await readFile(destFile); + const existingHash = createHash('sha256') + .update(existingContent) + .digest('hex') + .slice(0, 12); + if (existingHash === newHash) { + logVerbose(` unchanged ${normalizedRel} (content identical, skipping write)`); + return; + } + } + } + try { await ensureDir(dirname(destFile)); await cp(srcFile, destFile, { force: true, recursive: false }); diff --git a/.agentkit/engines/node/src/template-utils.mjs b/.agentkit/engines/node/src/template-utils.mjs index f47b50b9..c9460b23 100644 --- a/.agentkit/engines/node/src/template-utils.mjs +++ b/.agentkit/engines/node/src/template-utils.mjs @@ -718,7 +718,22 @@ export function getCommentStyle(ext) { export function insertHeader(content, ext, version, repoName) { const header = getGeneratedHeader(version, repoName, ext); if (!header) return content; // JSON / template — no comment syntax - if (content.includes('GENERATED by Retort')) return content; // already present + if (content.includes('GENERATED by Retort')) return content; // already present (current) + + // Replace legacy AgentKit Forge header with current Retort header rather than + // prepending a second header — keeps generated files clean after the rename. + if (content.includes('GENERATED by AgentKit Forge')) { + // Strip all contiguous comment lines at the start (the old header block) + const lines = content.split('\n'); + const commentPrefixes = [' + + + +# cicd-optimize + +CI/CD pipeline and local hook optimizer. Audits GitHub Actions workflows, pre-commit/stop hooks, and test configurations for speed bottlenecks. Identifies caching gaps, sequential jobs that could parallelize, missing path filters, redundant installs, and slow hook steps. Produces a prioritized list of improvements with estimated time savings per fix. + +## Usage + +Invoke this skill when you need to perform the `cicd-optimize` operation. + +## Role + +You are the **CI/CD Optimization Agent**. Analyse this project's CI/CD pipelines and local hooks for speed bottlenecks. Produce a prioritized report with concrete, copy-paste-ready fixes. + +## Step 1 — Inventory + +Collect all CI/CD surface area: + +- `.github/workflows/*.yml` — list each workflow, its triggers, jobs, and steps +- `.claude/hooks/` — list each hook file and its purpose +- `package.json` scripts: `lint`, `test`, `build`, `typecheck` +- Test framework config: `vitest.config.*`, `jest.config.*`, `pytest.ini`, `Cargo.toml [profile.test]` +- Lock files: `pnpm-lock.yaml`, `Cargo.lock`, `poetry.lock` + +## Step 2 — Bottleneck Detection + +For each workflow, check: + +### Caching + +- [ ] Node modules cached? (`actions/cache` with `node_modules` or `pnpm store`) +- [ ] Cargo registry cached? (`~/.cargo/registry` and `target/`) +- [ ] pip/poetry cached? (`~/.cache/pip`) +- [ ] Docker layer cache used? (`cache-from: type=gha`) + +### Parallelization + +- [ ] Jobs that depend on each other but don't need to — should they be parallel? +- [ ] Test suites that could use matrix strategy or `--pool` (vitest), `pytest-xdist`, `cargo nextest` +- [ ] Lint and typecheck run sequentially when they're independent + +### Trigger efficiency + +- [ ] Workflows triggered on `push` to all branches — should use `paths:` filters +- [ ] PR workflows trigger on `push` AND `pull_request` — often redundant +- [ ] Scheduled workflows running more frequently than needed + +### Install efficiency + +- [ ] `npm install` / `pnpm install` without `--frozen-lockfile` (slower) +- [ ] Install steps duplicated across jobs (should use artifacts or caching) +- [ ] `node_modules` copied between jobs instead of restored from cache + +### Hook efficiency + +- [ ] Stop hook runs tests or full builds (should be lint-only with file-change gating) +- [ ] Pre-commit hook runs expensive operations without caching +- [ ] Hooks run regardless of which files changed + +## Step 3 — Test Suite Speed + +Check for parallelization opportunities: + +- vitest: `--pool=threads` or `--pool=forks`, `--reporter=verbose` adding noise +- pytest: `pytest-xdist` (`-n auto`), test isolation issues +- cargo: `cargo nextest` (2-3x faster than `cargo test`) +- jest: `--maxWorkers` configuration + +## Step 4 — Report + +Produce a table sorted by estimated time savings (highest first): + +| # | Area | Issue | Fix | Est. saving | +| --- | ---- | ----- | --- | ----------- | +| 1 | ... | ... | ... | ~Xs per run | + +Then provide **Ready-to-apply fixes** — code blocks for each high-impact change, in order. For workflow changes, show the exact YAML diff. For hook changes, show the exact shell change. For config changes, show the file and the new content. + +## Rules + +1. Only suggest changes with clear, measurable benefit. Skip micro-optimisations. +2. Preserve correctness — never suggest removing a cache that would break reproducibility. +3. Flag any changes that require secrets or environment variables. +4. If a fix requires a new dependency (e.g. cargo-nextest), note the install command. + +## Project Context + +- Repository: retort +- Default branch: main + - Tech stack: javascript, yaml, markdown + +## Conventions + +- Write minimal, focused changes +- Maintain backwards compatibility +- Include tests for behavioral changes +- Never expose secrets or credentials +- Follow the project's established patterns diff --git a/.agents/skills/handoff/SKILL.md b/.agents/skills/handoff/SKILL.md index 34884389..0c1bfeca 100644 --- a/.agents/skills/handoff/SKILL.md +++ b/.agents/skills/handoff/SKILL.md @@ -1,15 +1,15 @@ --- name: 'handoff' description: 'Generates a structured handoff document for the current session. Captures what was accomplished, what remains, open questions, and context needed by the next session or developer. Writes to docs/ai_handoffs/.' -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-05' # Format: YAML frontmatter + Markdown body. Codex agent skill definition. # Docs: https://developers.openai.com/codex/guides/agents-md --- - - + + # handoff @@ -45,7 +45,7 @@ Invoke this skill when you need to perform the `handoff` operation. ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.agents/skills/healthcheck/SKILL.md b/.agents/skills/healthcheck/SKILL.md index 0a1db9f6..4215b488 100644 --- a/.agents/skills/healthcheck/SKILL.md +++ b/.agents/skills/healthcheck/SKILL.md @@ -1,15 +1,15 @@ --- name: 'healthcheck' description: 'Performs a comprehensive health check of the repository: validates builds, runs tests, checks linting, verifies configuration files, and reports on the overall state of the codebase across all detected tech stacks.' -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-05' # Format: YAML frontmatter + Markdown body. Codex agent skill definition. # Docs: https://developers.openai.com/codex/guides/agents-md --- - - + + # healthcheck @@ -45,7 +45,7 @@ Invoke this skill when you need to perform the `healthcheck` operation. ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.agents/skills/init/SKILL.md b/.agents/skills/init/SKILL.md new file mode 100644 index 00000000..220ddb3b --- /dev/null +++ b/.agents/skills/init/SKILL.md @@ -0,0 +1,79 @@ +--- +name: 'init' +description: 'Initialise the current repository as a Retort project. Runs the interactive setup wizard to detect the tech stack, select language kits, choose AI tools, and generate the initial project.yaml and overlay configuration. Supports --dry-run to preview without writing.' +generated_by: 'retort' +last_model: 'sync-engine' +last_updated: '2026-03-20' +# Format: YAML frontmatter + Markdown body. Codex agent skill definition. +# Docs: https://developers.openai.com/codex/guides/agents-md +--- + + + + + +# init + +Initialise the current repository as a Retort project. Runs the interactive setup wizard to detect the tech stack, select language kits, choose AI tools, and generate the initial project.yaml and overlay configuration. Supports --dry-run to preview without writing. + +## Usage + +Invoke this skill when you need to perform the `init` operation. + +## Role + +You are the **Init Agent**. Guide users through initialising a new Retort project in the current repository. + +## How to Initialise + +Run the init command from the repository root: + +```bash +node .agentkit/engines/node/src/cli.mjs init +``` + +Or if pnpm is available: + +```bash +pnpm -C .agentkit agentkit:init +``` + +## Flags + +| Flag | Effect | +| ------------------- | ------------------------------------------------------ | +| `--dry-run` | Show what would be generated without writing any files | +| `--non-interactive` | Skip prompts, use auto-detected defaults | +| `--preset ` | Use a preset: minimal, full, team, infra | +| `--force` | Overwrite existing overlay configuration | +| `--repoName ` | Override the detected repository name | + +## Kit Selection + +During interactive init, Retort detects your tech stack and shows which +language kits will be activated (typescript, dotnet, rust, python, blockchain). +Universal kits (security, testing, git-workflow, documentation, ci-cd, +dependency-management, agent-conduct) are always included. + +Optional kits (iac, finops, ai-cost-ops) are presented for explicit opt-in. + +## Post-Init + +1. Review the generated `spec/project.yaml` — fill in any `null` fields +2. Run `/sync` to regenerate all AI tool configurations +3. Run `/validate` to verify generated outputs are well-formed +4. Commit both the spec and generated outputs together + +## Project Context + +- Repository: retort +- Default branch: main + - Tech stack: javascript, yaml, markdown + +## Conventions + +- Write minimal, focused changes +- Maintain backwards compatibility +- Include tests for behavioral changes +- Never expose secrets or credentials +- Follow the project's established patterns diff --git a/.agents/skills/project-review/SKILL.md b/.agents/skills/project-review/SKILL.md index 97427cb9..754900aa 100644 --- a/.agents/skills/project-review/SKILL.md +++ b/.agents/skills/project-review/SKILL.md @@ -1,15 +1,15 @@ --- name: 'project-review' description: 'Comprehensive production-grade project review and assessment. Systematically analyzes code quality, architecture, security, UX, performance, documentation, and feature completeness. Produces structured findings with a prioritized roadmap organized into implementation waves.' -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-05' # Format: YAML frontmatter + Markdown body. Codex agent skill definition. # Docs: https://developers.openai.com/codex/guides/agents-md --- - - + + # project-review @@ -44,7 +44,7 @@ Invoke this skill when you need to perform the `project-review` operation. ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.ai/README.md b/.ai/README.md index 82fc9d29..2efc7b79 100644 --- a/.ai/README.md +++ b/.ai/README.md @@ -1,5 +1,5 @@ - - + + # .ai — Tool-Agnostic AI Rules diff --git a/.ai/continuerules b/.ai/continuerules index 4581b275..0a7b7d68 100644 --- a/.ai/continuerules +++ b/.ai/continuerules @@ -1,3 +1,6 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync Follow UNIFIED_AGENT_TEAMS.md and CLAUDE.md. Use /discover → /healthcheck → /plan → implement → /check → /review. Never modify .env, secrets, or credential files. diff --git a/.ai/cursorrules b/.ai/cursorrules index d5e79dbd..1eab0fe5 100644 --- a/.ai/cursorrules +++ b/.ai/cursorrules @@ -1,3 +1,6 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync Follow UNIFIED_AGENT_TEAMS.md and CLAUDE.md. Use /discover → /healthcheck → /plan → implement → /check → /review. Never modify .env, secrets, or credential files. diff --git a/.ai/windsurfrules b/.ai/windsurfrules index 4581b275..0a7b7d68 100644 --- a/.ai/windsurfrules +++ b/.ai/windsurfrules @@ -1,3 +1,6 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync Follow UNIFIED_AGENT_TEAMS.md and CLAUDE.md. Use /discover → /healthcheck → /plan → implement → /check → /review. Never modify .env, secrets, or credential files. diff --git a/.claude/commands/handoff.md b/.claude/commands/handoff.md index 735d32e5..132f0247 100644 --- a/.claude/commands/handoff.md +++ b/.claude/commands/handoff.md @@ -1,15 +1,15 @@ --- description: 'Write a session handoff summary for continuity between sessions' allowed-tools: Bash(git *), Bash(mkdir *) -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-05' # Format: YAML frontmatter + Markdown body. Claude slash command. # Docs: https://docs.anthropic.com/en/docs/claude-code/memory#slash-commands --- - - + + # Session Handoff diff --git a/.claude/commands/healthcheck.md b/.claude/commands/healthcheck.md index fce20fb7..28fda0a2 100644 --- a/.claude/commands/healthcheck.md +++ b/.claude/commands/healthcheck.md @@ -1,15 +1,15 @@ --- description: 'Pre-flight validation — verify build, lint, typecheck, and tests all pass' allowed-tools: Bash(git *), Bash(npm *), Bash(pnpm *), Bash(npx *), Bash(dotnet *), Bash(cargo *), Bash(python *), Bash(pip *), Bash(pytest *), Bash(go *) -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-05' # Format: YAML frontmatter + Markdown body. Claude slash command. # Docs: https://docs.anthropic.com/en/docs/claude-code/memory#slash-commands --- - - + + # Healthcheck diff --git a/.claude/commands/project-review.md b/.claude/commands/project-review.md index 5dc66183..a1c976ab 100644 --- a/.claude/commands/project-review.md +++ b/.claude/commands/project-review.md @@ -1,7 +1,7 @@ --- description: 'Comprehensive production-grade project review and assessment' allowed-tools: Read, Glob, Grep, Bash, Bash(gh issue create*), Bash(gh issue list*), Bash(gh issue view*), Bash(linear *), WebSearch, WebFetch -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-05' # Format: YAML frontmatter + Markdown body. Claude slash command. @@ -123,7 +123,7 @@ Propose updates to: ## Template & Generated-Format Issue Filing -During Phase 1c analysis, any finding that targets a **generated file** (contains ` + + + +# cicd-optimize + +CI/CD pipeline and local hook optimizer. Audits GitHub Actions workflows, pre-commit/stop hooks, and test configurations for speed bottlenecks. Identifies caching gaps, sequential jobs that could parallelize, missing path filters, redundant installs, and slow hook steps. Produces a prioritized list of improvements with estimated time savings per fix. + +## Usage + +Invoke this skill when you need to perform the `cicd-optimize` operation. + +## Role + +You are the **CI/CD Optimization Agent**. Analyse this project's CI/CD pipelines and local hooks for speed bottlenecks. Produce a prioritized report with concrete, copy-paste-ready fixes. + +## Step 1 — Inventory + +Collect all CI/CD surface area: + +- `.github/workflows/*.yml` — list each workflow, its triggers, jobs, and steps +- `.claude/hooks/` — list each hook file and its purpose +- `package.json` scripts: `lint`, `test`, `build`, `typecheck` +- Test framework config: `vitest.config.*`, `jest.config.*`, `pytest.ini`, `Cargo.toml [profile.test]` +- Lock files: `pnpm-lock.yaml`, `Cargo.lock`, `poetry.lock` + +## Step 2 — Bottleneck Detection + +For each workflow, check: + +### Caching + +- [ ] Node modules cached? (`actions/cache` with `node_modules` or `pnpm store`) +- [ ] Cargo registry cached? (`~/.cargo/registry` and `target/`) +- [ ] pip/poetry cached? (`~/.cache/pip`) +- [ ] Docker layer cache used? (`cache-from: type=gha`) + +### Parallelization + +- [ ] Jobs that depend on each other but don't need to — should they be parallel? +- [ ] Test suites that could use matrix strategy or `--pool` (vitest), `pytest-xdist`, `cargo nextest` +- [ ] Lint and typecheck run sequentially when they're independent + +### Trigger efficiency + +- [ ] Workflows triggered on `push` to all branches — should use `paths:` filters +- [ ] PR workflows trigger on `push` AND `pull_request` — often redundant +- [ ] Scheduled workflows running more frequently than needed + +### Install efficiency + +- [ ] `npm install` / `pnpm install` without `--frozen-lockfile` (slower) +- [ ] Install steps duplicated across jobs (should use artifacts or caching) +- [ ] `node_modules` copied between jobs instead of restored from cache + +### Hook efficiency + +- [ ] Stop hook runs tests or full builds (should be lint-only with file-change gating) +- [ ] Pre-commit hook runs expensive operations without caching +- [ ] Hooks run regardless of which files changed + +## Step 3 — Test Suite Speed + +Check for parallelization opportunities: + +- vitest: `--pool=threads` or `--pool=forks`, `--reporter=verbose` adding noise +- pytest: `pytest-xdist` (`-n auto`), test isolation issues +- cargo: `cargo nextest` (2-3x faster than `cargo test`) +- jest: `--maxWorkers` configuration + +## Step 4 — Report + +Produce a table sorted by estimated time savings (highest first): + +| # | Area | Issue | Fix | Est. saving | +| --- | ---- | ----- | --- | ----------- | +| 1 | ... | ... | ... | ~Xs per run | + +Then provide **Ready-to-apply fixes** — code blocks for each high-impact change, in order. For workflow changes, show the exact YAML diff. For hook changes, show the exact shell change. For config changes, show the file and the new content. + +## Rules + +1. Only suggest changes with clear, measurable benefit. Skip micro-optimisations. +2. Preserve correctness — never suggest removing a cache that would break reproducibility. +3. Flag any changes that require secrets or environment variables. +4. If a fix requires a new dependency (e.g. cargo-nextest), note the install command. + +## Project Context + +- Repository: retort +- Default branch: main + - Tech stack: javascript, yaml, markdown + +## Conventions + +- Write minimal, focused changes +- Maintain backwards compatibility +- Include tests for behavioral changes +- Never expose secrets or credentials +- Follow the project's established patterns diff --git a/.claude/skills/handoff/SKILL.md b/.claude/skills/handoff/SKILL.md index 1dbda2d0..d26953cc 100644 --- a/.claude/skills/handoff/SKILL.md +++ b/.claude/skills/handoff/SKILL.md @@ -1,15 +1,15 @@ --- name: 'handoff' description: 'Generates a structured handoff document for the current session. Captures what was accomplished, what remains, open questions, and context needed by the next session or developer. Writes to docs/ai_handoffs/.' -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-05' # Format: YAML frontmatter + Markdown body. Claude skill definition. # Docs: https://docs.anthropic.com/en/docs/claude-code/memory --- - - + + # handoff @@ -54,7 +54,7 @@ what has been reviewed or executed. ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.claude/skills/healthcheck/SKILL.md b/.claude/skills/healthcheck/SKILL.md index 8450e481..3d1f86d2 100644 --- a/.claude/skills/healthcheck/SKILL.md +++ b/.claude/skills/healthcheck/SKILL.md @@ -1,15 +1,15 @@ --- name: 'healthcheck' description: 'Performs a comprehensive health check of the repository: validates builds, runs tests, checks linting, verifies configuration files, and reports on the overall state of the codebase across all detected tech stacks.' -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-05' # Format: YAML frontmatter + Markdown body. Claude skill definition. # Docs: https://docs.anthropic.com/en/docs/claude-code/memory --- - - + + # healthcheck @@ -54,7 +54,7 @@ what has been reviewed or executed. ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.claude/skills/init/SKILL.md b/.claude/skills/init/SKILL.md new file mode 100644 index 00000000..10b3cb4d --- /dev/null +++ b/.claude/skills/init/SKILL.md @@ -0,0 +1,79 @@ +--- +name: 'init' +description: 'Initialise the current repository as a Retort project. Runs the interactive setup wizard to detect the tech stack, select language kits, choose AI tools, and generate the initial project.yaml and overlay configuration. Supports --dry-run to preview without writing.' +generated_by: 'retort' +last_model: 'sync-engine' +last_updated: '2026-03-20' +# Format: YAML frontmatter + Markdown body. Claude skill definition. +# Docs: https://docs.anthropic.com/en/docs/claude-code/memory +--- + + + + + +# init + +Initialise the current repository as a Retort project. Runs the interactive setup wizard to detect the tech stack, select language kits, choose AI tools, and generate the initial project.yaml and overlay configuration. Supports --dry-run to preview without writing. + +## Usage + +Invoke this skill when you need to perform the `init` operation. + +## Role + +You are the **Init Agent**. Guide users through initialising a new Retort project in the current repository. + +## How to Initialise + +Run the init command from the repository root: + +```bash +node .agentkit/engines/node/src/cli.mjs init +``` + +Or if pnpm is available: + +```bash +pnpm -C .agentkit agentkit:init +``` + +## Flags + +| Flag | Effect | +| ------------------- | ------------------------------------------------------ | +| `--dry-run` | Show what would be generated without writing any files | +| `--non-interactive` | Skip prompts, use auto-detected defaults | +| `--preset ` | Use a preset: minimal, full, team, infra | +| `--force` | Overwrite existing overlay configuration | +| `--repoName ` | Override the detected repository name | + +## Kit Selection + +During interactive init, Retort detects your tech stack and shows which +language kits will be activated (typescript, dotnet, rust, python, blockchain). +Universal kits (security, testing, git-workflow, documentation, ci-cd, +dependency-management, agent-conduct) are always included. + +Optional kits (iac, finops, ai-cost-ops) are presented for explicit opt-in. + +## Post-Init + +1. Review the generated `spec/project.yaml` — fill in any `null` fields +2. Run `/sync` to regenerate all AI tool configurations +3. Run `/validate` to verify generated outputs are well-formed +4. Commit both the spec and generated outputs together + +## Project Context + +- Repository: retort +- Default branch: main + - Tech stack: javascript, yaml, markdown + +## Conventions + +- Write minimal, focused changes +- Maintain backwards compatibility +- Include tests for behavioral changes +- Never expose secrets or credentials +- Follow the project's established patterns diff --git a/.claude/skills/project-review/SKILL.md b/.claude/skills/project-review/SKILL.md index 8c07d74d..0d800ee4 100644 --- a/.claude/skills/project-review/SKILL.md +++ b/.claude/skills/project-review/SKILL.md @@ -1,15 +1,15 @@ --- name: 'project-review' description: 'Comprehensive production-grade project review and assessment. Systematically analyzes code quality, architecture, security, UX, performance, documentation, and feature completeness. Produces structured findings with a prioritized roadmap organized into implementation waves.' -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-05' # Format: YAML frontmatter + Markdown body. Claude skill definition. # Docs: https://docs.anthropic.com/en/docs/claude-code/memory --- - - + + # project-review @@ -53,7 +53,7 @@ what has been reviewed or executed. ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.claude/worktrees/focused-colden/.agentkit/.manifest.json b/.claude/worktrees/focused-colden/.agentkit/.manifest.json deleted file mode 100644 index 3fb43dd8..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.manifest.json +++ /dev/null @@ -1,1873 +0,0 @@ -{ - "generatedAt": "2026-03-17T06:36:41.261Z", - "version": "3.1.0", - "repoName": "agentkit-forge", - "files": { - ".agents/skills/analyze-agents/SKILL.md": { - "hash": "e42eee25c9fd" - }, - ".agents/skills/brand/SKILL.md": { - "hash": "4f819e2e0d69" - }, - ".agents/skills/cost-centres/SKILL.md": { - "hash": "3140d48f16b0" - }, - ".agentkit/state/orchestrator.json.template": { - "hash": "b70e87b7211b" - }, - ".agents/skills/deploy/SKILL.md": { - "hash": "2e1330fd693e" - }, - ".agentkit/state/schema.json": { - "hash": "b47a7efcd922" - }, - ".agents/skills/build/SKILL.md": { - "hash": "d325dae8f934" - }, - ".agents/skills/backlog/SKILL.md": { - "hash": "2dc8e5c1d39b" - }, - ".agents/skills/check/SKILL.md": { - "hash": "fc46476bca7b" - }, - ".agents/skills/feature-flow/SKILL.md": { - "hash": "ec9b155a84e6" - }, - ".agents/skills/expand/SKILL.md": { - "hash": "d9883bcc8f88" - }, - ".agents/skills/discover/SKILL.md": { - "hash": "9ac71caf6992" - }, - ".agents/skills/cost/SKILL.md": { - "hash": "834badf6646b" - }, - ".agents/skills/document-history/SKILL.md": { - "hash": "e82dbff8c514" - }, - ".agents/skills/import-issues/SKILL.md": { - "hash": "e2d105f8b201" - }, - ".agents/skills/orchestrate/SKILL.md": { - "hash": "2b6c677c66a3" - }, - ".agents/skills/feature-configure/SKILL.md": { - "hash": "c11f2cc3273b" - }, - ".agents/skills/infra-eval/SKILL.md": { - "hash": "37505d91a1c5" - }, - ".agents/skills/feature-review/SKILL.md": { - "hash": "da38a280ec45" - }, - ".agents/skills/doctor/SKILL.md": { - "hash": "9d9e7ffcaf71" - }, - ".agents/skills/project-status/SKILL.md": { - "hash": "9a47cc64914b" - }, - ".agents/skills/format/SKILL.md": { - "hash": "0cdb87886f36" - }, - ".agents/skills/preflight/SKILL.md": { - "hash": "85c05dc2c072" - }, - ".agents/skills/plan/SKILL.md": { - "hash": "71c44b0ef7b1" - }, - ".agents/skills/review/SKILL.md": { - "hash": "00b236ee680f" - }, - ".agents/skills/security/SKILL.md": { - "hash": "3127f1e216c9" - }, - ".agents/skills/start/SKILL.md": { - "hash": "f0cd8fd39b4a" - }, - ".agents/skills/scaffold/SKILL.md": { - "hash": "ff8fb03eecd2" - }, - ".agents/skills/validate/SKILL.md": { - "hash": "30bc2a0427be" - }, - ".agents/skills/test/SKILL.md": { - "hash": "3c02bdac8593" - }, - ".agents/skills/sync-backlog/SKILL.md": { - "hash": "6a3ad80bff8d" - }, - ".claude/agents/adoption-strategist.md": { - "hash": "e0f5197c5140" - }, - ".ai/continuerules": { - "hash": "2d40023b7c45" - }, - ".agents/skills/sync/SKILL.md": { - "hash": "c25161dc8913" - }, - ".claude/agents/backend.md": { - "hash": "738bca85b556" - }, - ".ai/cursorrules": { - "hash": "32f8f48220f6" - }, - ".claude/agents/cost-ops-monitor.md": { - "hash": "9f195cfb5ab3" - }, - ".ai/README.md": { - "hash": "608c681edb4e" - }, - ".claude/agents/content-strategist.md": { - "hash": "bdea95fbdc97" - }, - ".claude/agents/brand-guardian.md": { - "hash": "06321324ad8c" - }, - ".claude/agents/coverage-tracker.md": { - "hash": "faf2173529c5" - }, - ".claude/agents/devops.md": { - "hash": "8623979399e3" - }, - ".claude/agents/dependency-watcher.md": { - "hash": "1317fdcdbdc6" - }, - ".claude/agents/environment-manager.md": { - "hash": "7630c0856682" - }, - ".claude/agents/data.md": { - "hash": "95222b841a68" - }, - ".ai/windsurfrules": { - "hash": "2d40023b7c45" - }, - ".claude/agents/expansion-analyst.md": { - "hash": "1acec03026a0" - }, - ".claude/agents/feature-ops.md": { - "hash": "f7a55b2e0a57" - }, - ".claude/agents/frontend.md": { - "hash": "2e553b7926ef" - }, - ".claude/agents/flow-designer.md": { - "hash": "0e0423753fd8" - }, - ".claude/agents/growth-analyst.md": { - "hash": "f8eec3b1e625" - }, - ".claude/agents/impact-assessor.md": { - "hash": "86fdde8309c2" - }, - ".claude/agents/input-clarifier.md": { - "hash": "10e22accb2c0" - }, - ".claude/agents/infra.md": { - "hash": "49829cf96e63" - }, - ".claude/agents/model-economist.md": { - "hash": "87e470197ac4" - }, - ".claude/agents/integration-tester.md": { - "hash": "9c537deec75e" - }, - ".claude/agents/governance-advisor.md": { - "hash": "6fde5c50bf67" - }, - ".claude/agents/grant-hunter.md": { - "hash": "906ddfa7eeb1" - }, - ".claude/agents/mission-definer.md": { - "hash": "530ef4249f0b" - }, - ".claude/agents/portfolio-analyst.md": { - "hash": "b85f4d82d325" - }, - ".claude/agents/prompt-engineer.md": { - "hash": "3f98b589828e" - }, - ".claude/agents/release-manager.md": { - "hash": "74293815fa62" - }, - ".claude/agents/product-manager.md": { - "hash": "ae255ee14143" - }, - ".claude/agents/project-shipper.md": { - "hash": "627257130af4" - }, - ".claude/agents/release-coordinator.md": { - "hash": "df573b60959d" - }, - ".claude/agents/roadmap-tracker.md": { - "hash": "89ddfff0b104" - }, - ".claude/agents/role-architect.md": { - "hash": "ff8dfe28ea56" - }, - ".claude/agents/retrospective-analyst.md": { - "hash": "ee7cdb422865" - }, - ".claude/agents/security-auditor.md": { - "hash": "1cbf3ad0f91d" - }, - ".claude/agents/spec-compliance-auditor.md": { - "hash": "177cc631b0a2" - }, - ".claude/agents/team-validator.md": { - "hash": "bee9c68baeac" - }, - ".claude/agents/test-lead.md": { - "hash": "45e8abd92aaf" - }, - ".claude/agents/token-efficiency-engineer.md": { - "hash": "c5e07b99dbc3" - }, - ".claude/commands/backlog.md": { - "hash": "22a8d07575b3" - }, - ".claude/agents/vendor-arbitrage-analyst.md": { - "hash": "48daa9f47218" - }, - ".claude/agents/ui-designer.md": { - "hash": "a3e99552415f" - }, - ".claude/commands/brand.md": { - "hash": "472c7438a795" - }, - ".claude/commands/check.md": { - "hash": "ca6dd1de5d9a" - }, - ".claude/commands/cost-centres.md": { - "hash": "07ead7d1c63f" - }, - ".claude/commands/build.md": { - "hash": "fee9680802e1" - }, - ".claude/commands/cost.md": { - "hash": "2392989dddaa" - }, - ".claude/commands/doctor.md": { - "hash": "8fa0fd26e893" - }, - ".claude/commands/deploy.md": { - "hash": "adc2c2629b09" - }, - ".claude/commands/discover.md": { - "hash": "8fe679961a27" - }, - ".claude/commands/expand.md": { - "hash": "f3b8f79ccd05" - }, - ".claude/commands/document-history.md": { - "hash": "c99673f9ae3c" - }, - ".claude/commands/feature-configure.md": { - "hash": "ee21aacdcd29" - }, - ".claude/commands/feature-flow.md": { - "hash": "d1b8207a2a5a" - }, - ".claude/commands/feature-review.md": { - "hash": "fced358b99eb" - }, - ".claude/commands/import-issues.md": { - "hash": "6331f512f2b8" - }, - ".claude/commands/infra-eval.md": { - "hash": "8a58ea808952" - }, - ".claude/commands/format.md": { - "hash": "a3f0eee9b52e" - }, - ".claude/commands/orchestrate.md": { - "hash": "574c6938b38d" - }, - ".claude/commands/plan.md": { - "hash": "0eca590818b3" - }, - ".claude/commands/project-status.md": { - "hash": "0565edacffae" - }, - ".claude/commands/preflight.md": { - "hash": "4a65b6271bd6" - }, - ".claude/commands/scaffold.md": { - "hash": "4b3cd870e0fc" - }, - ".claude/commands/security.md": { - "hash": "5efa63762b04" - }, - ".claude/commands/review.md": { - "hash": "e32bc6f663ab" - }, - ".claude/commands/start.md": { - "hash": "d172290d22db" - }, - ".claude/commands/sync-backlog.md": { - "hash": "2352a7d04323" - }, - ".claude/commands/sync.md": { - "hash": "efd3cfb56eed" - }, - ".claude/commands/team-cost-ops.md": { - "hash": "812a2d58a81e" - }, - ".claude/commands/team-backend.md": { - "hash": "f7e4f2d9d9b7" - }, - ".claude/commands/team-devops.md": { - "hash": "715a51cc4892" - }, - ".claude/commands/team-data.md": { - "hash": "ac4681cf9293" - }, - ".claude/commands/team-docs.md": { - "hash": "3deff18a07e9" - }, - ".claude/commands/team-infra.md": { - "hash": "436ecc831ca4" - }, - ".claude/commands/team-forge.md": { - "hash": "ff14d00c8c6c" - }, - ".claude/commands/team-frontend.md": { - "hash": "93f516367115" - }, - ".claude/commands/team-security.md": { - "hash": "39f9d0c7d438" - }, - ".claude/commands/team-quality.md": { - "hash": "201199588ab2" - }, - ".claude/commands/team-testing.md": { - "hash": "0d04836de633" - }, - ".claude/commands/team-strategic-ops.md": { - "hash": "5c65b47e2d4f" - }, - ".claude/hooks/budget-guard-check.sh": { - "hash": "4fabe38fe963" - }, - ".claude/commands/validate.md": { - "hash": "db126df15cad" - }, - ".claude/commands/team-product.md": { - "hash": "d0388844667d" - }, - ".claude/hooks/guard-destructive-commands.ps1": { - "hash": "55a58d211c2c" - }, - ".claude/hooks/guard-destructive-commands.sh": { - "hash": "155b707b2af0" - }, - ".claude/commands/test.md": { - "hash": "dff6e64066e4" - }, - ".claude/hooks/pre-push-validate.sh": { - "hash": "86db6d107d60" - }, - ".claude/hooks/protect-sensitive.ps1": { - "hash": "59c32beeb28b" - }, - ".claude/hooks/protect-sensitive.sh": { - "hash": "f064ddda7879" - }, - ".claude/hooks/protect-templates.sh": { - "hash": "04a1d69ea578" - }, - ".claude/hooks/protect-templates.ps1": { - "hash": "0b14c70ee6ef" - }, - ".claude/hooks/session-start.sh": { - "hash": "bf976e3ffb1a" - }, - ".claude/hooks/stop-build-check.ps1": { - "hash": "16d00d311940" - }, - ".claude/hooks/warn-uncommitted.ps1": { - "hash": "e01cd78b2c17" - }, - ".claude/hooks/stop-build-check.sh": { - "hash": "8aecebcef7b7" - }, - ".claude/hooks/warn-uncommitted.sh": { - "hash": "b224fa6b1b1f" - }, - ".claude/rules/blockchain.md": { - "hash": "6ebb3c6166c1" - }, - ".claude/hooks/session-start.ps1": { - "hash": "7d50dcf043f4" - }, - ".claude/rules/documentation.md": { - "hash": "041b08cabcc0" - }, - ".claude/rules/agent-conduct.md": { - "hash": "a9204d8e7dc4" - }, - ".claude/rules/ci-cd.md": { - "hash": "4eb972787de8" - }, - ".claude/rules/git-workflow.md": { - "hash": "16df971f4442" - }, - ".claude/rules/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".claude/rules/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".claude/rules/dependency-management.md": { - "hash": "d0089754e232" - }, - ".claude/rules/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".claude/rules/dotnet.md": { - "hash": "afd3bc539ab3" - }, - ".claude/rules/iac.md": { - "hash": "7389f06f50fe" - }, - ".claude/rules/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".claude/rules/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".claude/rules/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".claude/rules/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".claude/rules/languages/python.md": { - "hash": "63b439981bbc" - }, - ".claude/rules/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".claude/rules/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".claude/rules/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".claude/rules/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".claude/rules/languages/security.md": { - "hash": "1c73e7635578" - }, - ".claude/rules/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".claude/rules/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".claude/rules/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".claude/rules/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".claude/rules/quality.md": { - "hash": "478859ffbb93" - }, - ".claude/rules/rust.md": { - "hash": "653b8dfb73b5" - }, - ".claude/rules/template-protection.md": { - "hash": "e0eca318e94b" - }, - ".claude/rules/testing.md": { - "hash": "3e7853b624e1" - }, - ".claude/skills/brand/SKILL.md": { - "hash": "b4de2f51b106" - }, - ".claude/settings.json": { - "hash": "b5f6aee20306" - }, - ".claude/skills/backlog/SKILL.md": { - "hash": "de8c81512467" - }, - ".claude/rules/typescript.md": { - "hash": "1b050804b6ef" - }, - ".claude/skills/analyze-agents/SKILL.md": { - "hash": "3d77831e022a" - }, - ".claude/skills/cost/SKILL.md": { - "hash": "7276c4052975" - }, - ".claude/rules/python.md": { - "hash": "842f7d201c27" - }, - ".claude/skills/build/SKILL.md": { - "hash": "77448a90e59b" - }, - ".claude/skills/check/SKILL.md": { - "hash": "6d7d38148af5" - }, - ".claude/skills/deploy/SKILL.md": { - "hash": "f5cbd6d04c02" - }, - ".claude/rules/security.md": { - "hash": "3ed7f09d1ad0" - }, - ".claude/skills/cost-centres/SKILL.md": { - "hash": "738667d8716f" - }, - ".claude/skills/discover/SKILL.md": { - "hash": "ef2e7d50b511" - }, - ".claude/skills/expand/SKILL.md": { - "hash": "fd58b1775fd1" - }, - ".claude/skills/doctor/SKILL.md": { - "hash": "310dce98d8f4" - }, - ".claude/skills/feature-configure/SKILL.md": { - "hash": "4320cc00be36" - }, - ".claude/skills/feature-flow/SKILL.md": { - "hash": "cd75ad612f63" - }, - ".claude/skills/document-history/SKILL.md": { - "hash": "074d8a3cab21" - }, - ".claude/skills/format/SKILL.md": { - "hash": "3f2951d68edf" - }, - ".claude/skills/import-issues/SKILL.md": { - "hash": "7fb72bc4c4a2" - }, - ".claude/skills/plan/SKILL.md": { - "hash": "28fd3cc22953" - }, - ".claude/skills/orchestrate/SKILL.md": { - "hash": "8950d5dbb641" - }, - ".claude/skills/preflight/SKILL.md": { - "hash": "b6ad1a083bac" - }, - ".claude/skills/project-status/SKILL.md": { - "hash": "8df33d0cb8c9" - }, - ".claude/skills/infra-eval/SKILL.md": { - "hash": "7a4eedae11b3" - }, - ".claude/skills/review/SKILL.md": { - "hash": "8386eb6c97ee" - }, - ".claude/skills/start/SKILL.md": { - "hash": "a987a611b567" - }, - ".claude/skills/scaffold/SKILL.md": { - "hash": "9291d71bc86b" - }, - ".claude/skills/security/SKILL.md": { - "hash": "1520feb2bf97" - }, - ".claude/skills/feature-review/SKILL.md": { - "hash": "b556218af259" - }, - ".claude/skills/sync/SKILL.md": { - "hash": "19de7f1cc4cb" - }, - ".claude/skills/test/SKILL.md": { - "hash": "21da74147f13" - }, - ".claude/skills/sync-backlog/SKILL.md": { - "hash": "cea14e0c67fc" - }, - ".clinerules/agent-conduct.md": { - "hash": "58310e525ade" - }, - ".claude/skills/validate/SKILL.md": { - "hash": "112b57703063" - }, - ".clinerules/ai-cost-ops.md": { - "hash": "464c1fde7714" - }, - ".clinerules/blockchain.md": { - "hash": "21750f5c565c" - }, - ".clinerules/ci-cd.md": { - "hash": "d6b6698178f3" - }, - ".clinerules/dependency-management.md": { - "hash": "909464fb0495" - }, - ".clinerules/documentation.md": { - "hash": "a947fca57aca" - }, - ".clinerules/dotnet.md": { - "hash": "d978b656d898" - }, - ".clinerules/finops.md": { - "hash": "c02b0486012f" - }, - ".clinerules/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".clinerules/git-workflow.md": { - "hash": "0ce8ea97c321" - }, - ".clinerules/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".clinerules/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".clinerules/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".clinerules/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".clinerules/iac.md": { - "hash": "12318597c6ca" - }, - ".clinerules/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".clinerules/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".clinerules/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".clinerules/languages/python.md": { - "hash": "63b439981bbc" - }, - ".clinerules/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".clinerules/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".clinerules/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".clinerules/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".clinerules/languages/security.md": { - "hash": "1c73e7635578" - }, - ".clinerules/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".clinerules/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".clinerules/python.md": { - "hash": "0d1ed61bb8dc" - }, - ".clinerules/rust.md": { - "hash": "dc2f173fa092" - }, - ".clinerules/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".clinerules/security.md": { - "hash": "9cefb19e63e5" - }, - ".clinerules/testing.md": { - "hash": "fba2f07c5a5b" - }, - ".clinerules/template-protection.md": { - "hash": "ea83904b6713" - }, - ".cursor/commands/analyze-agents.md": { - "hash": "024e3cec1f56" - }, - ".cursor/commands/backlog.md": { - "hash": "c6b5aa7de695" - }, - ".cursor/commands/brand.md": { - "hash": "63960929d9fc" - }, - ".cursor/commands/build.md": { - "hash": "74cc820e6fc1" - }, - ".clinerules/typescript.md": { - "hash": "c77f9043197a" - }, - ".cursor/commands/check.md": { - "hash": "9373b3fca5ff" - }, - ".cursor/commands/cost-centres.md": { - "hash": "143856799eda" - }, - ".cursor/commands/cost.md": { - "hash": "9c338e5f33b1" - }, - ".cursor/commands/deploy.md": { - "hash": "cd5b2f461cd7" - }, - ".cursor/commands/document-history.md": { - "hash": "975b4458c2c1" - }, - ".cursor/commands/feature-configure.md": { - "hash": "9b071a084415" - }, - ".cursor/commands/expand.md": { - "hash": "089462f22f52" - }, - ".cursor/commands/doctor.md": { - "hash": "c619f9e3b1e6" - }, - ".cursor/commands/feature-flow.md": { - "hash": "7d7a302552c6" - }, - ".cursor/commands/discover.md": { - "hash": "60be19c91420" - }, - ".cursor/commands/feature-review.md": { - "hash": "021c98874605" - }, - ".cursor/commands/format.md": { - "hash": "5be0e24ce07a" - }, - ".cursor/commands/import-issues.md": { - "hash": "2acded7ac4fa" - }, - ".cursor/commands/infra-eval.md": { - "hash": "313ed28d7c7f" - }, - ".cursor/commands/orchestrate.md": { - "hash": "e2f5928cdb2f" - }, - ".cursor/commands/plan.md": { - "hash": "0af99fb78d12" - }, - ".cursor/commands/preflight.md": { - "hash": "6d1a97bd57d5" - }, - ".cursor/commands/project-status.md": { - "hash": "7a0056181045" - }, - ".cursor/commands/review.md": { - "hash": "e1853e4abdb9" - }, - ".cursor/commands/scaffold.md": { - "hash": "69986b1530cf" - }, - ".cursor/commands/sync-backlog.md": { - "hash": "a6282eab6689" - }, - ".cursor/commands/sync.md": { - "hash": "513bea4ea974" - }, - ".cursor/commands/test.md": { - "hash": "0f83a2bdea71" - }, - ".cursor/commands/security.md": { - "hash": "1a4e4a4d8cf6" - }, - ".cursor/commands/start.md": { - "hash": "a72ec5c139fe" - }, - ".cursor/commands/validate.md": { - "hash": "5bc457b26628" - }, - ".cursor/rules/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".cursor/rules/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".cursor/rules/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".cursor/rules/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".cursor/rules/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".cursor/rules/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".cursor/rules/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".cursor/rules/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".cursor/rules/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".cursor/rules/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".cursor/rules/languages/python.md": { - "hash": "63b439981bbc" - }, - ".cursor/rules/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".cursor/rules/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".cursor/rules/languages/security.md": { - "hash": "1c73e7635578" - }, - ".cursor/rules/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".cursor/rules/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".cursor/rules/orchestrate.mdc": { - "hash": "9853913b4857" - }, - ".cursor/rules/project-context.mdc": { - "hash": "dd6859b78404" - }, - ".cursor/rules/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".cursor/rules/security.mdc": { - "hash": "24c286e725a3" - }, - ".cursor/rules/team-backend.mdc": { - "hash": "66c7510720e1" - }, - ".cursor/rules/team-cost-ops.mdc": { - "hash": "545aecedca0b" - }, - ".cursor/rules/team-data.mdc": { - "hash": "412987c5fb0e" - }, - ".cursor/rules/team-devops.mdc": { - "hash": "0fe62d640199" - }, - ".cursor/rules/team-forge.mdc": { - "hash": "a238f2cc330b" - }, - ".cursor/rules/team-frontend.mdc": { - "hash": "82a998fe0de5" - }, - ".cursor/rules/team-docs.mdc": { - "hash": "b0ccc30e6b77" - }, - ".cursor/rules/team-infra.mdc": { - "hash": "d5f6f094dc30" - }, - ".cursor/rules/team-product.mdc": { - "hash": "153f579d8b04" - }, - ".cursor/rules/team-security.mdc": { - "hash": "9778f59babaa" - }, - ".cursor/rules/team-quality.mdc": { - "hash": "f70002d21c69" - }, - ".cursor/rules/team-testing.mdc": { - "hash": "e5e949b5a9ad" - }, - ".editorconfig": { - "hash": "fa09dda3d2e2" - }, - ".cursor/rules/team-strategic-ops.mdc": { - "hash": "00d0e2e368e4" - }, - ".gemini/styleguide.md": { - "hash": "b3f330f5df8f" - }, - ".gemini/config.yaml": { - "hash": "8f50c65f25fb" - }, - ".github/agents/adoption-strategist.agent.md": { - "hash": "5d2836dcb475" - }, - ".gitattributes": { - "hash": "90af26762384" - }, - ".github/agents/brand-guardian.agent.md": { - "hash": "c2461a9a8466" - }, - ".github/agents/content-strategist.agent.md": { - "hash": "c2544a299b60" - }, - ".github/agents/backend.agent.md": { - "hash": "0d127baccf58" - }, - ".github/agents/cost-ops-monitor.agent.md": { - "hash": "4188ea493644" - }, - ".github/agents/coverage-tracker.agent.md": { - "hash": "0ec9cd09509b" - }, - ".github/agents/dependency-watcher.agent.md": { - "hash": "e85baf4d0d46" - }, - ".github/agents/environment-manager.agent.md": { - "hash": "d2e9a801a5e5" - }, - ".github/agents/devops.agent.md": { - "hash": "ffe4f3317ec8" - }, - ".github/agents/flow-designer.agent.md": { - "hash": "d09c5f1d7cd2" - }, - ".github/agents/expansion-analyst.agent.md": { - "hash": "45e7e34e7877" - }, - ".github/agents/data.agent.md": { - "hash": "a55f855de262" - }, - ".github/agents/feature-ops.agent.md": { - "hash": "c4ba3dc907f6" - }, - ".github/agents/frontend.agent.md": { - "hash": "778677e3a2f1" - }, - ".github/agents/grant-hunter.agent.md": { - "hash": "7d849df31023" - }, - ".github/agents/governance-advisor.agent.md": { - "hash": "35e92bcae9d0" - }, - ".github/agents/infra.agent.md": { - "hash": "8c8d3a4f1adf" - }, - ".github/agents/input-clarifier.agent.md": { - "hash": "63f969a72bc4" - }, - ".github/agents/growth-analyst.agent.md": { - "hash": "25e3b42da3aa" - }, - ".github/agents/mission-definer.agent.md": { - "hash": "4ba6262d5eb8" - }, - ".github/agents/portfolio-analyst.agent.md": { - "hash": "fa3fe9e48a52" - }, - ".github/agents/integration-tester.agent.md": { - "hash": "b34beafad1bd" - }, - ".github/agents/impact-assessor.agent.md": { - "hash": "98a4559e208d" - }, - ".github/agents/model-economist.agent.md": { - "hash": "b3ea5f80581d" - }, - ".github/agents/project-shipper.agent.md": { - "hash": "93e8ef14bb8f" - }, - ".github/agents/product-manager.agent.md": { - "hash": "9d3da17ae6f3" - }, - ".github/agents/prompt-engineer.agent.md": { - "hash": "778f224899a3" - }, - ".github/agents/release-coordinator.agent.md": { - "hash": "dfa94cb6ff6f" - }, - ".github/agents/release-manager.agent.md": { - "hash": "e58484632ca0" - }, - ".github/agents/retrospective-analyst.agent.md": { - "hash": "143b2fd6c727" - }, - ".github/agents/spec-compliance-auditor.agent.md": { - "hash": "e2b66fe05d2b" - }, - ".github/agents/roadmap-tracker.agent.md": { - "hash": "0fdd8e9b7985" - }, - ".github/agents/role-architect.agent.md": { - "hash": "217b0f7d6bc5" - }, - ".github/agents/security-auditor.agent.md": { - "hash": "1f8a11a72b17" - }, - ".github/agents/team-validator.agent.md": { - "hash": "046b30086c5b" - }, - ".github/agents/token-efficiency-engineer.agent.md": { - "hash": "12997f39f2cb" - }, - ".github/agents/test-lead.agent.md": { - "hash": "6561c9a0a1c2" - }, - ".github/agents/vendor-arbitrage-analyst.agent.md": { - "hash": "627c29b70357" - }, - ".github/ai-framework-ci.yml": { - "hash": "d33ebabcb073" - }, - ".github/agents/ui-designer.agent.md": { - "hash": "337cddf83447" - }, - ".github/chatmodes/team-backend.chatmode.md": { - "hash": "ac8f69b82220" - }, - ".github/chatmodes/team-data.chatmode.md": { - "hash": "0afb7a28f351" - }, - ".github/chatmodes/team-cost-ops.chatmode.md": { - "hash": "121bbf207ca4" - }, - ".github/chatmodes/team-frontend.chatmode.md": { - "hash": "cce72ab3a795" - }, - ".github/chatmodes/team-devops.chatmode.md": { - "hash": "978de914aab8" - }, - ".github/chatmodes/team-docs.chatmode.md": { - "hash": "c204bd1f1788" - }, - ".github/chatmodes/team-forge.chatmode.md": { - "hash": "b04f7d8a9d9a" - }, - ".github/chatmodes/team-product.chatmode.md": { - "hash": "03428a19c477" - }, - ".github/chatmodes/team-quality.chatmode.md": { - "hash": "7bc2b2f277e1" - }, - ".github/chatmodes/team-infra.chatmode.md": { - "hash": "5850b3a37256" - }, - ".github/chatmodes/team-strategic-ops.chatmode.md": { - "hash": "8b337da42662" - }, - ".github/chatmodes/team-security.chatmode.md": { - "hash": "09342e8fc4bc" - }, - ".github/chatmodes/team-testing.chatmode.md": { - "hash": "074a36442ca2" - }, - ".github/CODEOWNERS": { - "hash": "ccf003556232" - }, - ".github/instructions/code-verify.md": { - "hash": "f82d9d55fc86" - }, - ".github/copilot-instructions.md": { - "hash": "c8bb26bb2cba" - }, - ".github/instructions/docs.md": { - "hash": "dca898c99b6c" - }, - ".github/instructions/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".github/instructions/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".github/instructions/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".github/instructions/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".github/instructions/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".github/instructions/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".github/instructions/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".github/instructions/languages/python.md": { - "hash": "63b439981bbc" - }, - ".github/instructions/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".github/instructions/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".github/instructions/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".github/instructions/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".github/instructions/languages/security.md": { - "hash": "1c73e7635578" - }, - ".github/instructions/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".github/instructions/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".github/instructions/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".github/instructions/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".github/instructions/marketing.md": { - "hash": "84860c42a466" - }, - ".github/instructions/quality.md": { - "hash": "d2d93df02537" - }, - ".github/instructions/performance.md": { - "hash": "4f8cd32aeb7e" - }, - ".github/ISSUE_TEMPLATE/bug_report.yml": { - "hash": "0b7c12b0e1bb" - }, - ".github/instructions/testing.md": { - "hash": "ee3e0d11b01b" - }, - ".github/instructions/README.md": { - "hash": "a79739379379" - }, - ".github/prompts/analyze-agents.prompt.md": { - "hash": "19e1dc8432f0" - }, - ".github/prompts/backlog.prompt.md": { - "hash": "45f1abd24d72" - }, - ".github/ISSUE_TEMPLATE/config.yml": { - "hash": "47344ff5c32c" - }, - ".github/prompts/brand.prompt.md": { - "hash": "0c6c0002f942" - }, - ".github/ISSUE_TEMPLATE/feature_request.yml": { - "hash": "79e7e3da99d0" - }, - ".github/prompts/check.prompt.md": { - "hash": "cc0bdba2f08f" - }, - ".github/prompts/cost-centres.prompt.md": { - "hash": "6baa174774e6" - }, - ".github/prompts/build.prompt.md": { - "hash": "046bffc8791e" - }, - ".github/prompts/cost.prompt.md": { - "hash": "8d2d9868723a" - }, - ".github/prompts/discover.prompt.md": { - "hash": "e04bdf639b4a" - }, - ".github/prompts/doctor.prompt.md": { - "hash": "1dad8d876f62" - }, - ".github/prompts/deploy.prompt.md": { - "hash": "fc9569e74c5d" - }, - ".github/prompts/document-history.prompt.md": { - "hash": "d9f170e31ace" - }, - ".github/prompts/feature-configure.prompt.md": { - "hash": "ce35b4c465e6" - }, - ".github/prompts/feature-review.prompt.md": { - "hash": "cf81881f51f5" - }, - ".github/prompts/format.prompt.md": { - "hash": "94a0505df23e" - }, - ".github/prompts/expand.prompt.md": { - "hash": "ff9445bec477" - }, - ".github/prompts/feature-flow.prompt.md": { - "hash": "b82d78500eb3" - }, - ".github/prompts/import-issues.prompt.md": { - "hash": "4b2701705479" - }, - ".github/prompts/infra-eval.prompt.md": { - "hash": "a8b15916f960" - }, - ".github/prompts/orchestrate.prompt.md": { - "hash": "63451784c289" - }, - ".github/prompts/preflight.prompt.md": { - "hash": "52dcd9cbf075" - }, - ".github/prompts/project-status.prompt.md": { - "hash": "328769323130" - }, - ".github/prompts/review.prompt.md": { - "hash": "94016ba6950b" - }, - ".github/prompts/scaffold.prompt.md": { - "hash": "22240d89615d" - }, - ".github/prompts/plan.prompt.md": { - "hash": "69797faa11a4" - }, - ".github/prompts/security.prompt.md": { - "hash": "953693049d80" - }, - ".github/prompts/start.prompt.md": { - "hash": "97357c17d8fe" - }, - ".github/prompts/test.prompt.md": { - "hash": "871f38d6af82" - }, - ".github/PULL_REQUEST_TEMPLATE.md": { - "hash": "10b91e98a082" - }, - ".github/prompts/sync-backlog.prompt.md": { - "hash": "9cea7fd68060" - }, - ".github/prompts/validate.prompt.md": { - "hash": "028479c6d2e2" - }, - ".github/scripts/README.md": { - "hash": "3124e25a7cfa" - }, - ".github/prompts/sync.prompt.md": { - "hash": "7e7773332996" - }, - ".github/scripts/resolve-merge.ps1": { - "hash": "0cd5d9407b89" - }, - ".github/scripts/setup-branch-protection.ps1": { - "hash": "160cb7bb55b1" - }, - ".github/scripts/resolve-merge.sh": { - "hash": "7ce68cb84a3a" - }, - ".github/scripts/setup-branch-protection.sh": { - "hash": "6eb664b21ee4" - }, - ".github/workflows/coverage-report.yml": { - "hash": "80dafccc5b8f" - }, - ".github/workflows/breaking-change-detection.yml": { - "hash": "bcd2f5c2e450" - }, - ".github/workflows/documentation-validation.yml": { - "hash": "01abb4c23ec9" - }, - ".github/workflows/documentation-quality.yml": { - "hash": "6088b2095f59" - }, - ".github/workflows/dependency-audit.yml": { - "hash": "fc376b5eef06" - }, - ".github/workflows/pr-validation.yml": { - "hash": "2c316a51ea66" - }, - ".github/workflows/retrospective-quality.yml": { - "hash": "74474e570115" - }, - ".gitmessage": { - "hash": "3f5666033096" - }, - ".markdownlint.json": { - "hash": "afe70a444035" - }, - ".prettierrc": { - "hash": "7288d28eacd8" - }, - ".roo/rules/ai-cost-ops.md": { - "hash": "2c38e075d4db" - }, - ".roo/rules/agent-conduct.md": { - "hash": "1f4b060a86eb" - }, - ".roo/rules/blockchain.md": { - "hash": "205b3ca13935" - }, - ".roo/rules/ci-cd.md": { - "hash": "56d669134c88" - }, - ".roo/rules/dependency-management.md": { - "hash": "10ec56bb6292" - }, - ".roo/rules/documentation.md": { - "hash": "ff90f251ce71" - }, - ".roo/rules/dotnet.md": { - "hash": "8b8461bcf286" - }, - ".roo/rules/finops.md": { - "hash": "17a63264e7b1" - }, - ".roo/rules/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".roo/rules/iac.md": { - "hash": "2024c73bc61a" - }, - ".roo/rules/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".roo/rules/git-workflow.md": { - "hash": "ae185cb50c40" - }, - ".roo/rules/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".roo/rules/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".roo/rules/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".roo/rules/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".roo/rules/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".roo/rules/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".roo/rules/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".roo/rules/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".roo/rules/languages/python.md": { - "hash": "63b439981bbc" - }, - ".roo/rules/languages/security.md": { - "hash": "1c73e7635578" - }, - ".roo/rules/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".roo/rules/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".roo/rules/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".roo/rules/python.md": { - "hash": "7b9a642b9197" - }, - ".roo/rules/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".roo/rules/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".roo/rules/rust.md": { - "hash": "f68627a539a3" - }, - ".roo/rules/security.md": { - "hash": "a05714124061" - }, - ".roo/rules/testing.md": { - "hash": "f420798449b7" - }, - ".roo/rules/typescript.md": { - "hash": "5bff848ce5b6" - }, - ".vscode/settings.json": { - "hash": "4af945c89151" - }, - ".roo/rules/template-protection.md": { - "hash": "2097e8899fab" - }, - ".windsurf/commands/backlog.md": { - "hash": "68b4263fc444" - }, - ".vscode/extensions.json": { - "hash": "dd20fd0751ba" - }, - ".windsurf/commands/analyze-agents.md": { - "hash": "371f6c3bd7d5" - }, - ".windsurf/commands/brand.md": { - "hash": "1eb99e2c4883" - }, - ".windsurf/commands/build.md": { - "hash": "7fc64a835712" - }, - ".windsurf/commands/check.md": { - "hash": "780d7cb5ba53" - }, - ".windsurf/commands/cost-centres.md": { - "hash": "16f70ee610a8" - }, - ".windsurf/commands/cost.md": { - "hash": "6b9a7ee00d03" - }, - ".windsurf/commands/deploy.md": { - "hash": "bb64704796af" - }, - ".windsurf/commands/discover.md": { - "hash": "438676ab6872" - }, - ".windsurf/commands/document-history.md": { - "hash": "57554e0ae8d7" - }, - ".windsurf/commands/doctor.md": { - "hash": "e40703581729" - }, - ".windsurf/commands/format.md": { - "hash": "10cda487929d" - }, - ".windsurf/commands/expand.md": { - "hash": "62310f81603e" - }, - ".windsurf/commands/feature-configure.md": { - "hash": "31f4a7a16fe7" - }, - ".windsurf/commands/feature-review.md": { - "hash": "9c212c4c7afe" - }, - ".windsurf/commands/infra-eval.md": { - "hash": "359a364a00e5" - }, - ".windsurf/commands/feature-flow.md": { - "hash": "840122cc19aa" - }, - ".windsurf/commands/import-issues.md": { - "hash": "9b714f3d4b02" - }, - ".windsurf/commands/orchestrate.md": { - "hash": "1d9602ce2908" - }, - ".windsurf/commands/preflight.md": { - "hash": "2d35df2ccd8e" - }, - ".windsurf/commands/plan.md": { - "hash": "0bf8e69458de" - }, - ".windsurf/commands/security.md": { - "hash": "4878d4daa234" - }, - ".windsurf/commands/project-status.md": { - "hash": "a85e72f6794e" - }, - ".windsurf/commands/review.md": { - "hash": "ebd187ab3d06" - }, - ".windsurf/commands/start.md": { - "hash": "7cc5267d9274" - }, - ".windsurf/commands/scaffold.md": { - "hash": "c57cd1471acf" - }, - ".windsurf/commands/sync-backlog.md": { - "hash": "bf720daf3704" - }, - ".windsurf/commands/sync.md": { - "hash": "d4678bf06724" - }, - ".windsurf/commands/validate.md": { - "hash": "02d1c93720c5" - }, - ".windsurf/commands/test.md": { - "hash": "73463ed24c36" - }, - ".windsurf/rules/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".windsurf/rules/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".windsurf/rules/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".windsurf/rules/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".windsurf/rules/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".windsurf/rules/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".windsurf/rules/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".windsurf/rules/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".windsurf/rules/languages/python.md": { - "hash": "63b439981bbc" - }, - ".windsurf/rules/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".windsurf/rules/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".windsurf/rules/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".windsurf/rules/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".windsurf/rules/languages/security.md": { - "hash": "1c73e7635578" - }, - ".windsurf/rules/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".windsurf/rules/project.md": { - "hash": "cc8ae6d95221" - }, - ".windsurf/rules/orchestrate.md": { - "hash": "0eea9715c9db" - }, - ".windsurf/rules/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".windsurf/rules/security.md": { - "hash": "6a39548b2255" - }, - ".windsurf/rules/team-backend.md": { - "hash": "ec288e9b54ce" - }, - ".windsurf/rules/team-cost-ops.md": { - "hash": "69db0e22010d" - }, - ".windsurf/rules/team-devops.md": { - "hash": "06c93f75dcd3" - }, - ".windsurf/rules/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".windsurf/rules/team-data.md": { - "hash": "2fa55fd04223" - }, - ".windsurf/rules/team-frontend.md": { - "hash": "e9a5f425646d" - }, - ".windsurf/rules/team-docs.md": { - "hash": "f019d83abc58" - }, - ".windsurf/rules/team-forge.md": { - "hash": "13f5fa696b1d" - }, - ".windsurf/rules/team-infra.md": { - "hash": "fb977ea917c1" - }, - ".windsurf/rules/team-quality.md": { - "hash": "afb908c98b76" - }, - ".windsurf/rules/team-product.md": { - "hash": "81f4929e42f3" - }, - ".windsurf/rules/team-security.md": { - "hash": "a7c778d35665" - }, - ".windsurf/rules/team-testing.md": { - "hash": "505b7caae49d" - }, - ".windsurf/rules/team-strategic-ops.md": { - "hash": "c1d8c4f33abe" - }, - "AGENTS.md": { - "hash": "911950e72f75" - }, - ".windsurf/workflows/full-assessment.yml": { - "hash": "57d1220ee8ac" - }, - "CHANGELOG.md": { - "hash": "8cb5a19628b1" - }, - ".windsurf/workflows/phase-execution.yml": { - "hash": "81054e1a3272" - }, - "AGENT_TEAMS.md": { - "hash": "725ada7d289f" - }, - "CONTRIBUTING.md": { - "hash": "afd7d3c16416" - }, - "AGENT_BACKLOG.md": { - "hash": "8eecc5cbe45f" - }, - "docs/api/01_overview.md": { - "hash": "342e9d07b13f" - }, - "docs/api/03_authentication.md": { - "hash": "26ef4da3ef56" - }, - "CLAUDE.md": { - "hash": "4e7b5fb72c4c" - }, - "docs/api/02_endpoints.md": { - "hash": "43eb1cc5a21f" - }, - "docs/api/04_examples.md": { - "hash": "7c21b7bcf311" - }, - "COMMAND_GUIDE.md": { - "hash": "4600c6725f0d" - }, - "docs/api/05_errors.md": { - "hash": "ed2e5a6e94ed" - }, - "docs/api/06_versioning.md": { - "hash": "bd878ba8a2f6" - }, - "docs/agents/agent-team-matrix.md": { - "hash": "09345b713ca1" - }, - "docs/api/README.md": { - "hash": "5a266ea2df82" - }, - "docs/architecture/01_overview.md": { - "hash": "df6efc6fda78" - }, - "docs/architecture/decisions/01-adopt-agentkit-forge.md": { - "hash": "552c1023dcf2" - }, - "docs/architecture/decisions/02-fallback-policy-tokens-problem.md": { - "hash": "31295d24794e" - }, - "docs/architecture/decisions/05-dependency-supply-chain-detection-tooling.md": { - "hash": "6ccff01874c7" - }, - "docs/architecture/decisions/06-code-quality-maintainability-signal-tooling.md": { - "hash": "3fb3fc9fd6ff" - }, - "docs/architecture/decisions/03-tooling-strategy.md": { - "hash": "b2700e569966" - }, - "docs/architecture/decisions/04-static-security-analysis-depth-tooling.md": { - "hash": "998c41843f21" - }, - "docs/architecture/decisions/README.md": { - "hash": "28b5d189b354" - }, - "docs/architecture/diagrams/.gitkeep": { - "hash": "64edc5f9f589" - }, - "docs/architecture/diagrams/README.md": { - "hash": "782485a4f5ef" - }, - "docs/architecture/README.md": { - "hash": "a867a017c8a0" - }, - "docs/architecture/specs/01_functional_spec.md": { - "hash": "cb36564f8ddd" - }, - "docs/architecture/specs/02_technical_spec.md": { - "hash": "b603c83e06d5" - }, - "docs/architecture/specs/03_api_spec.md": { - "hash": "d5a1811ddc75" - }, - "docs/engineering/02_coding_standards.md": { - "hash": "cf4473c84515" - }, - "docs/architecture/specs/README.md": { - "hash": "7c4e52efbd0d" - }, - "docs/engineering/01_setup.md": { - "hash": "225879d37c28" - }, - "docs/engineering/03_testing.md": { - "hash": "7cbc67b07b25" - }, - "docs/architecture/specs/04_data_models.md": { - "hash": "a77400c5387c" - }, - "docs/engineering/06_pr_documentation.md": { - "hash": "74d9c99fc82a" - }, - "docs/history/.index.json": { - "hash": "7beb781687f2" - }, - "docs/engineering/04_git_workflow.md": { - "hash": "8621780ffdcb" - }, - "docs/engineering/05_security.md": { - "hash": "b2fd1574733d" - }, - "docs/engineering/07_changelog.md": { - "hash": "945e28ab8b34" - }, - "docs/history/bug-fixes/README.md": { - "hash": "78dcabc86f74" - }, - "docs/history/bug-fixes/TEMPLATE-bugfix.md": { - "hash": "7873d84034ec" - }, - "docs/history/features/README.md": { - "hash": "7a6b10981688" - }, - "docs/history/implementations/README.md": { - "hash": "938114ecc966" - }, - "docs/engineering/README.md": { - "hash": "35afee261b38" - }, - "docs/history/issues/TEMPLATE-issue.md": { - "hash": "b133cb73cdc5" - }, - "docs/history/issues/README.md": { - "hash": "3e5d149f1a6c" - }, - "docs/history/implementations/TEMPLATE-implementation.md": { - "hash": "d4b4ad9bf6cc" - }, - "docs/history/features/TEMPLATE-feature.md": { - "hash": "c704b2662b57" - }, - "docs/history/migrations/README.md": { - "hash": "7b023cecc53d" - }, - "docs/history/lessons-learned/TEMPLATE-lesson.md": { - "hash": "810fcf97423b" - }, - "docs/history/lessons-learned/README.md": { - "hash": "b21e63388be4" - }, - "docs/history/migrations/TEMPLATE-migration.md": { - "hash": "97272242bd4e" - }, - "docs/history/README.md": { - "hash": "8feb37cbe0c0" - }, - "docs/integrations/01_external_apis.md": { - "hash": "17bc92567b46" - }, - "docs/integrations/02_webhooks.md": { - "hash": "b9e1b977bf00" - }, - "docs/operations/01_deployment.md": { - "hash": "8fc948f3e280" - }, - "docs/integrations/03_sdk.md": { - "hash": "c05a8a69392d" - }, - "docs/operations/02_monitoring.md": { - "hash": "0d1c7d4a021e" - }, - "docs/integrations/README.md": { - "hash": "105308932223" - }, - "docs/operations/04_troubleshooting.md": { - "hash": "a8c0364e80c9" - }, - "docs/operations/05_slos_slis.md": { - "hash": "2cbf5f2188dd" - }, - "docs/product/01_prd.md": { - "hash": "80c041b82e0d" - }, - "docs/planning/TEMPLATE-plan.md": { - "hash": "305534965f0e" - }, - "docs/operations/03_incident_response.md": { - "hash": "549b6f418202" - }, - "docs/operations/README.md": { - "hash": "62c405f25743" - }, - "docs/product/02_user_stories.md": { - "hash": "fce181fc7087" - }, - "docs/product/04_personas.md": { - "hash": "609113c06c69" - }, - "docs/product/03_roadmap.md": { - "hash": "c24ab738099b" - }, - "docs/product/README.md": { - "hash": "43db13443d26" - }, - "docs/README.md": { - "hash": "0a5900bf46af" - }, - "docs/reference/03_changelog.md": { - "hash": "4bd7c9e727aa" - }, - "docs/reference/04_contributing.md": { - "hash": "b33e1d721718" - }, - "MIGRATIONS.md": { - "hash": "e880b3edb24c" - }, - "docs/reference/02_faq.md": { - "hash": "ac95d6fb41ec" - }, - "docs/reference/01_glossary.md": { - "hash": "2f571539f2ff" - }, - "GEMINI.md": { - "hash": "a59e2d67b8dd" - }, - "docs/reference/README.md": { - "hash": "c09171b9b8a1" - }, - "QUALITY_GATES.md": { - "hash": "e3158c924e6e" - }, - "RUNBOOK_AI.md": { - "hash": "2a0d351455dc" - }, - "scripts/consolidate-branches.sh": { - "hash": "f345de274644" - }, - "scripts/create-doc.ps1": { - "hash": "207501b71fe6" - }, - "scripts/resolve-merge.ps1": { - "hash": "1ae33673ef63" - }, - "scripts/consolidate-branches.ps1": { - "hash": "767265430308" - }, - "scripts/analyze-agents.sh": { - "hash": "dfd5f15e5267" - }, - "scripts/analyze-agents.ps1": { - "hash": "e66c881de65a" - }, - "scripts/resolve-merge.sh": { - "hash": "29048f9dc59d" - }, - "scripts/setup-agentkit-branch-governance.ps1": { - "hash": "ac356d29ce05" - }, - "scripts/check-documentation-requirement.sh": { - "hash": "0604d65be8db" - }, - "scripts/setup-agentkit-branch-governance.sh": { - "hash": "cecf99c1c59a" - }, - "scripts/sync-issues.sh": { - "hash": "5728f842fda3" - }, - "scripts/create-doc.sh": { - "hash": "c170336b69e0" - }, - "scripts/sync-split-pr.sh": { - "hash": "169e29683f7b" - }, - "scripts/validate-numbering.sh": { - "hash": "d78c153d05ee" - }, - "scripts/update-changelog.sh": { - "hash": "146f6934a4ee" - }, - "scripts/validate-documentation.sh": { - "hash": "c00c47269a24" - }, - "scripts/update-changelog.ps1": { - "hash": "3b64bfbcfc25" - }, - "scripts/sync-split-pr.ps1": { - "hash": "199b5056c32e" - }, - "UNIFIED_AGENT_TEAMS.md": { - "hash": "506e38f9e21c" - }, - "WARP.md": { - "hash": "24ca1510e68e" - }, - "SECURITY.md": { - "hash": "a926751bc190" - } - } -} diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/AGENT_TEAMS.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/AGENT_TEAMS.md deleted file mode 100644 index ed649683..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/AGENT_TEAMS.md +++ /dev/null @@ -1,80 +0,0 @@ - - - -# Agent Teams — agentkit-forge - -> Repo-local team mapping derived from `.agentkit/spec/teams.yaml`. -> Customize the **Status**, **Primary Scope**, **Tech Stack**, and **Lead Agent** -> columns for your repository. The orchestrator uses this file for task dispatch. - ---- - -## Overview - -This document maps the canonical AgentKit team definitions (see -[UNIFIED_AGENT_TEAMS.md](./UNIFIED_AGENT_TEAMS.md)) to the concrete structure -of this repository. Not all teams may be active — mark inactive teams so the -orchestrator skips them during dispatch. - ---- - -## Team Roster - -| Team | ID | Focus | Scope | Accepts | Handoff Chain | Status | Lead Agent | -| ---- | -- | ----- | ----- | ------- | ------------- | ------ | ---------- | -| BACKEND | backend | API, services, core logic | `apps/api/**`, `services/**`, `src/server/**`, `controllers/**` | implement, review, plan | testing → docs | Active | — | -| FRONTEND | frontend | UI, components, PWA | `apps/web/**`, `apps/marketing/**`, `src/client/**`, `components/**` | implement, review, plan | testing → docs | Active | — | -| DATA | data | Database, models, migrations | `db/**`, `migrations/**`, `models/**`, `prisma/**` | implement, review, plan | backend → testing | Active | — | -| INFRA | infra | IaC, cloud, Terraform/Bicep | `infra/**`, `terraform/**`, `bicep/**`, `pulumi/**` | implement, review, plan, investigate | devops → security | Active | — | -| DEVOPS | devops | CI/CD, pipelines, automation | `.github/workflows/**`, `scripts/**`, `docker/**`, `**/Dockerfile*` | implement, review, plan | testing → security | Active | — | -| TESTING | testing | Unit, E2E, integration tests | `**/*.test.*`, `**/*.spec.*`, `tests/**`, `e2e/**`, `playwright/**` | implement, review, test | quality | Active | — | -| SECURITY | security | Auth, compliance, audit | `auth/**`, `security/**`, `middleware/auth*` | review, investigate | — | Active | — | -| DOCUMENTATION | docs | Docs, ADRs, guides | `docs/**`, `docs/architecture/decisions/**`, `.github/**`, `README.md`, `CHANGELOG.md`, `CONTRIBUTING.md` | implement, review, document | — | Active | — | -| PRODUCT | product | Features, PRDs, roadmap | `docs/product/**`, `docs/prd/**` | plan, review | backend → frontend | Active | — | -| QUALITY | quality | Code review, refactoring, bugs, reliability, session retrospectives | `**/*` | review, investigate | — | Active | — | -| TEAMFORGE | forge | Meta-team — creates, validates, and deploys new agent team specifications | `.agentkit/spec/**`, `docs/planning/agents-teams/**`, `docs/architecture/**` | plan, review, investigate, document | quality → docs | Active | — | -| STRATEGIC OPS | strategic-ops | Cross-project coordination, framework governance, portfolio-level planning | `docs/planning/**`, `docs/architecture/**`, `.agentkit/spec/**`, `AGENT_BACKLOG.md`, `UNIFIED_AGENT_TEAMS.md`, `AGENT_TEAMS.md` | plan, review, investigate, document | product → quality | Active | — | -| COST OPS | cost-ops | AI infrastructure cost reduction, vendor optimization, token efficiency | `docs/cost-ops/**`, `docs/planning/cost/**`, `config/models/**`, `config/pricing/**` | investigate, review, plan, document, implement | infra → product → strategic-ops | Active | — | - ---- - -## How to Customize - -### Activating / Deactivating a Team - -1. Change the **Status** column from `Inactive` to `Active` (or vice versa). -2. Fill in the **Primary Scope** with actual directory paths in this repo. -3. Set the **Tech Stack** to reflect the tools and frameworks used. -4. Assign a **Lead Agent** identifier (used for mentions and escalation). -5. Add any relevant notes about the team's role. - -The orchestrator will skip inactive teams during `/orchestrate` dispatch. - -### Adding Custom Scope Patterns - -Each team's scope patterns determine which files the orchestrator will assign -to that team. Use glob patterns: - -``` -src/server/** — all files under src/server/ -src/api/*.ts — TypeScript files directly in src/api/ -tests/unit/server/* — server unit tests -``` - ---- - -## Scope Overlap Resolution - -When multiple teams have overlapping scope patterns, the orchestrator uses -these priority rules: - -1. **Most specific pattern wins.** A deeper path match takes precedence. -2. **Explicit assignment overrides.** A task explicitly assigned to a team - via `--teams` flag takes precedence over pattern matching. -3. **Primary scope takes priority.** The team whose scope lists the most - specific matching directory owns the file. - ---- - -_Customize this file for your repository. User edits are preserved across syncs._ -_Canonical team definitions: [UNIFIED_AGENT_TEAMS.md](./UNIFIED_AGENT_TEAMS.md)_ diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/README.md deleted file mode 100644 index 9484b549..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/README.md +++ /dev/null @@ -1,47 +0,0 @@ - - - - -# agentkit-forge — Documentation - -Welcome to the agentkit-forge documentation hub. This index links to every -documentation category maintained by this repository. - -## Categories - -| Category | Description | -| -------------------------------------- | ----------------------------------------------------- | -| [Product](./product/) | Product vision, strategy, personas, PRDs | -| [Architecture](./architecture/) | Specs, ADRs, diagrams, tech stack decisions | -| [Orchestration](./orchestration/) | Orchestration guide, PM guide, concurrency protocol | -| [Agents](./agents/) | Agent catalog, roles, team mappings | -| [API](./api/) | API reference, authentication, versioning, and errors | -| [Operations](./operations/) | CI/CD, deployments, monitoring, and troubleshooting | -| [Engineering](./engineering/) | Setup, coding standards, testing, and contributing | -| [Integrations](./integrations/) | External APIs, webhooks, and SDK | -| [Reference](./reference/) | Glossary, acronyms, FAQ, and tool config | -| [Handoffs](./handoffs/) | AI session handoff documents | -| [History](./history/) | Bug fixes, features, implementations, lessons | - -## Quick Links - -- [Architecture Overview](./architecture/01_overview.md) -- [Orchestration Guide](./orchestration/overview.md) -- [PM Guide](./orchestration/pm-guide.md) -- [Agent Catalog](./agents/catalog.md) -- [API Overview](./api/01_overview.md) -- [Getting Started](./engineering/01_setup.md) -- [Changelog](./reference/03_changelog.md) - -- [PRD Library](./product/prd/README.md) - - -## Conventions - -- Placeholder tokens `agentkit-forge` and `3.1.0` are replaced at sync time. -- Do **not** edit generated files directly — run `pnpm -C .agentkit agentkit:sync` - to regenerate them from the AgentKit Forge spec and overlays. - ---- - -Generated by AgentKit Forge v3.1.0 diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/api/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/api/README.md deleted file mode 100644 index e91f44ae..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/api/README.md +++ /dev/null @@ -1,14 +0,0 @@ - - - - -# API Docs Index - -## Contents - -- [01_overview.md](./01_overview.md) -- [02_endpoints.md](./02_endpoints.md) -- [03_authentication.md](./03_authentication.md) -- [04_examples.md](./04_examples.md) -- [05_errors.md](./05_errors.md) -- [06_versioning.md](./06_versioning.md) diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/README.md deleted file mode 100644 index de2050fe..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/README.md +++ /dev/null @@ -1,12 +0,0 @@ - - - - -# Architecture Docs Index - -## Contents - -- [01_overview.md](./01_overview.md) — Architecture overview and entry point -- [specs/](./specs/) — Functional, technical, and API specifications -- [diagrams/](./diagrams/) — Architecture diagrams -- [decisions/](./decisions/) — Architecture Decision Records (ADRs) diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/decisions/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/decisions/README.md deleted file mode 100644 index e488986f..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/decisions/README.md +++ /dev/null @@ -1,16 +0,0 @@ - - - - -# ADR Index - -## Decision Records - -- [01-adopt-agentkit-forge.md](./01-adopt-agentkit-forge.md) -- [02-fallback-policy-tokens-problem.md](./02-fallback-policy-tokens-problem.md) -- [03-tooling-strategy.md](./03-tooling-strategy.md) -- [04-static-security-analysis-depth-tooling.md](./04-static-security-analysis-depth-tooling.md) -- [05-dependency-supply-chain-detection-tooling.md](./05-dependency-supply-chain-detection-tooling.md) -- [06-code-quality-maintainability-signal-tooling.md](./06-code-quality-maintainability-signal-tooling.md) -- [07-delivery-strategy.md](./07-delivery-strategy.md) -- [08-issue-sync-strategy.md](./08-issue-sync-strategy.md) diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/diagrams/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/diagrams/README.md deleted file mode 100644 index f93d1b98..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/diagrams/README.md +++ /dev/null @@ -1,16 +0,0 @@ - - - - -# Architecture Diagrams Index - -## Contents - -- Add C4 and deployment diagrams in this folder. -- Keep diagram files named with ordered prefixes when sequence matters (`01_`, `02_`, ...). - -## Recommended Diagrams - -- `01_system-context.mmd` (C4 L1) -- `02_container-view.mmd` (C4 L2) -- `03_deployment-view.mmd` (runtime/deployment) diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/specs/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/specs/README.md deleted file mode 100644 index abdab96a..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/architecture/specs/README.md +++ /dev/null @@ -1,12 +0,0 @@ - - - - -# Specs Docs Index - -## Contents - -- [01_functional_spec.md](./01_functional_spec.md) -- [02_technical_spec.md](./02_technical_spec.md) -- [03_api_spec.md](./03_api_spec.md) -- [04_data_models.md](./04_data_models.md) diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/engineering/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/engineering/README.md deleted file mode 100644 index 9deaffc9..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/engineering/README.md +++ /dev/null @@ -1,16 +0,0 @@ - - - - -# Engineering Docs Index - -## Contents - -- [01_setup.md](./01_setup.md) -- [02_coding_standards.md](./02_coding_standards.md) -- [03_testing.md](./03_testing.md) -- [04_git_workflow.md](./04_git_workflow.md) -- [05_security.md](./05_security.md) -- [06_pr_documentation.md](./06_pr_documentation.md) -- [07_changelog.md](./07_changelog.md) -- [08_scaffold_management.md](./08_scaffold_management.md) diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/README.md deleted file mode 100644 index ecab947d..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/README.md +++ /dev/null @@ -1,67 +0,0 @@ - - - - -# History - -Historical documentation for significant PRs and implementations in agentkit-forge. - -## Directory Structure - -| Directory | Description | -| -------------------------------------- | ---------------------------------------------- | -| [implementations/](./implementations/) | Major implementations and architecture changes | -| [bug-fixes/](./bug-fixes/) | Complex or critical bug resolutions | -| [features/](./features/) | New feature launches | -| [migrations/](./migrations/) | Major migrations and upgrades | -| [issues/](./issues/) | Issues encountered during development sessions | -| [lessons-learned/](./lessons-learned/) | Lessons learned from retrospectives | - -## Naming Convention - -Files use the format: `XXXX-YYYY-MM-DD-[title]-[type].md` - -- `XXXX` — sequential 4-digit number (maintained in [.index.json](./.index.json)) -- `YYYY-MM-DD` — completion date -- `[title]` — kebab-case title -- `[type]` — `implementation`, `bugfix`, `feature`, `migration`, `issue`, or `lesson` - -## Creating New Documentation - -Use the provided script to generate a new document from the correct template: - -```bash -# Bash -./scripts/create-doc.sh implementation "Feature Name" -./scripts/create-doc.sh bugfix "Bug Description" -./scripts/create-doc.sh feature "Feature Name" -./scripts/create-doc.sh migration "Migration Name" -./scripts/create-doc.sh issue "Issue Title" -./scripts/create-doc.sh lesson "Lesson Title" -``` - -> **Note:** Issue and lesson records are created automatically via -> `/review --focus=retrospective`, not through the create-doc script. -> -> **Fallback:** When `gh` CLI is unavailable (proxy failures, air-gapped -> environments), use `./scripts/create-doc.sh issue "Title"` to record issues -> locally, then run `./scripts/sync-issues.sh --apply` once access is restored. - -The `/review` command with `--focus=retrospective` automates issue and lesson -creation at end-of-session (non-blocking — never gates delivery): - -```bash -# Via agent command -/review --focus=retrospective # Full retrospective: issues + lessons -/review --focus=retrospective --dry-run # Preview without writing -/review --focus=retrospective --open-issues # Also create GitHub issues for unresolved problems -``` - -```powershell -# PowerShell -./scripts/create-doc.ps1 implementation "Feature Name" -``` - -Or use the `/document-history` slash command for auto-detection of type and title from session context. - -See [docs/engineering/06_pr_documentation.md](../engineering/06_pr_documentation.md) for the full documentation strategy. diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/bug-fixes/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/bug-fixes/README.md deleted file mode 100644 index 011ae350..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/bug-fixes/README.md +++ /dev/null @@ -1,8 +0,0 @@ - - - -# Bug Fixes - -Historical records of complex or critical bug resolutions. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/features/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/features/README.md deleted file mode 100644 index 4e4a4c82..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/features/README.md +++ /dev/null @@ -1,8 +0,0 @@ - - - -# Features - -Historical records of new feature launches. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/implementations/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/implementations/README.md deleted file mode 100644 index afc0d54d..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/implementations/README.md +++ /dev/null @@ -1,8 +0,0 @@ - - - -# Implementations - -Historical records of major implementations, architecture changes, and significant refactoring. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/issues/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/issues/README.md deleted file mode 100644 index 53ac6b6a..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/issues/README.md +++ /dev/null @@ -1,42 +0,0 @@ - - - -# Issues - -Historical records of issues encountered during development sessions. - -## Creating Issue Records - -### Preferred: GitHub Issues via `gh` - -When the GitHub CLI is available and authenticated, create issues directly: - -```bash -gh issue create --title "Issue Title" --body "Description" -``` - -### Fallback: Local Issue Docs - -When `gh` is unavailable (no CLI installed, proxy/auth failures, air-gapped -environments), record issues locally as structured markdown: - -```bash -./scripts/create-doc.sh issue "Issue Title" -``` - -Issues are also logged automatically by `/review --focus=retrospective` at the -end of a session. - -### Syncing Local Issues to GitHub - -Once `gh` access is restored, sync local issue docs to GitHub Issues: - -```bash -./scripts/sync-issues.sh # Dry-run by default -./scripts/sync-issues.sh --apply # Create GitHub Issues and mark synced -``` - -See [ADR-08](../../architecture/decisions/08-issue-sync-strategy.md) for -the sync strategy and automation decisions. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/lessons-learned/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/lessons-learned/README.md deleted file mode 100644 index 5acf19fb..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/lessons-learned/README.md +++ /dev/null @@ -1,11 +0,0 @@ - - - -# Lessons Learned - -Historical records of lessons learned during development sessions. - -Lessons are logged automatically by `/review --focus=retrospective` at the end of -a session, or manually via `scripts/create-doc.sh lesson "Lesson Title"`. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/migrations/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/migrations/README.md deleted file mode 100644 index 672df4f0..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/history/migrations/README.md +++ /dev/null @@ -1,8 +0,0 @@ - - - -# Migrations - -Historical records of major migrations and upgrades. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/integrations/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/integrations/README.md deleted file mode 100644 index 48aa94c7..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/integrations/README.md +++ /dev/null @@ -1,11 +0,0 @@ - - - - -# Integrations Docs Index - -## Contents - -- [01_external_apis.md](./01_external_apis.md) -- [02_webhooks.md](./02_webhooks.md) -- [03_sdk.md](./03_sdk.md) diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/operations/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/operations/README.md deleted file mode 100644 index 5918083e..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/operations/README.md +++ /dev/null @@ -1,13 +0,0 @@ - - - - -# Operations Docs Index - -## Contents - -- [01_deployment.md](./01_deployment.md) -- [02_monitoring.md](./02_monitoring.md) -- [03_incident_response.md](./03_incident_response.md) -- [04_troubleshooting.md](./04_troubleshooting.md) -- [05_slos_slis.md](./05_slos_slis.md) diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/product/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/product/README.md deleted file mode 100644 index ce11aaf5..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/product/README.md +++ /dev/null @@ -1,12 +0,0 @@ - - - - -# Product Docs Index - -## Contents - -- [01_prd.md](./01_prd.md) -- [02_user_stories.md](./02_user_stories.md) -- [03_roadmap.md](./03_roadmap.md) -- [04_personas.md](./04_personas.md) diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/reference/README.md b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/reference/README.md deleted file mode 100644 index 3921959d..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/docs/reference/README.md +++ /dev/null @@ -1,14 +0,0 @@ - - - - -# Reference Docs Index - -## Contents - -- [01_glossary.md](./01_glossary.md) -- [02_faq.md](./02_faq.md) -- [03_changelog.md](./03_changelog.md) -- [04_contributing.md](./04_contributing.md) -- [05_project_yaml_reference.md](./05_project_yaml_reference.md) -- [ai_handoffs/](./ai_handoffs/) diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/analyze-agents.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/analyze-agents.sh deleted file mode 100644 index fd5324d6..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/analyze-agents.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/analyze-agents.sh -# Generates agent/team relationship matrices from spec files. -# -# Usage: -# ./scripts/analyze-agents.sh [--output ] [--matrix ] [--format ] -# -# Options: -# --output Output file (default: docs/agents/agent-team-matrix.md) -# --matrix Specific matrix: 1-8, supplementary, all (default: all) -# --format Output format: markdown, json (default: markdown) - -set -euo pipefail -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -node "$PROJECT_ROOT/.agentkit/engines/node/src/cli.mjs" analyze-agents "$@" diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/check-documentation-requirement.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/check-documentation-requirement.sh deleted file mode 100644 index 944d7501..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/check-documentation-requirement.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/check-documentation-requirement.sh -# Analyzes staged or changed files to determine whether PR documentation is required. -# -# Usage (pre-commit hook): -# ./scripts/check-documentation-requirement.sh -# -# Exit codes: -# 0 — documentation not required or already present -# 1 — documentation required but not present (when --strict is passed) -# -# Environment variables: -# GITHUB_BASE_REF — set automatically in GitHub Actions PR workflows -# STRICT — set to "true" to exit 1 when documentation is required - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -HISTORY_DIR="$REPO_ROOT/docs/history" -STRICT="${STRICT:-false}" - -# --------------------------------------------------------------------------- -# Collect changed files -# --------------------------------------------------------------------------- - -if [[ -n "${GITHUB_BASE_REF:-}" ]]; then - # Running inside GitHub Actions pull_request event - CHANGED_FILES=$(git diff --name-only "origin/${GITHUB_BASE_REF}" HEAD 2>/dev/null || git diff --name-only HEAD~1 HEAD) -else - # Running locally — inspect staged files, fall back to last commit - CHANGED_FILES=$(git diff --cached --name-only 2>/dev/null) - if [[ -z "$CHANGED_FILES" ]]; then - CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || true) - fi -fi - -if [[ -z "$CHANGED_FILES" ]]; then - echo "ℹ️ No changed files detected." - exit 0 -fi - -# --------------------------------------------------------------------------- -# Impact assessment -# --------------------------------------------------------------------------- - -IMPACT_HIGH=false -IMPACT_MEDIUM=false - -while IFS= read -r file; do - # High impact: project files, CI, security configs, infrastructure - if [[ "$file" == *.csproj || "$file" == package.json || "$file" == Cargo.toml || \ - "$file" == go.mod || "$file" == pyproject.toml || "$file" == build.gradle || \ - "$file" == .github/workflows/*.yml || "$file" == .github/workflows/*.yaml || \ - "$file" == Dockerfile* || "$file" == docker-compose*.yml || \ - "$file" == **/terraform/**/*.tf || "$file" == **/infra/**/*.tf ]]; then - IMPACT_HIGH=true - # Medium impact: source code files - elif [[ "$file" == src/**/*.cs || "$file" == src/**/*.ts || "$file" == src/**/*.tsx || \ - "$file" == src/**/*.py || "$file" == src/**/*.rs || "$file" == src/**/*.go || \ - "$file" == lib/**/*.* || "$file" == packages/**/*.* ]]; then - IMPACT_MEDIUM=true - fi -done <<< "$CHANGED_FILES" - -# --------------------------------------------------------------------------- -# Count changed files -# --------------------------------------------------------------------------- - -CHANGED_COUNT=$(echo "$CHANGED_FILES" | wc -l | tr -d ' ') - -if [[ "$CHANGED_COUNT" -gt 50 ]]; then - IMPACT_HIGH=true -fi - -# --------------------------------------------------------------------------- -# Check if documentation already exists for this branch/PR -# --------------------------------------------------------------------------- - -# Count history docs that have been staged or added in this branch -HISTORY_DOCS=0 -if [[ -n "${GITHUB_BASE_REF:-}" ]]; then - HISTORY_DOCS=$(git diff --name-only "origin/${GITHUB_BASE_REF}" HEAD -- 'docs/history/**/*.md' 2>/dev/null | grep -v 'README\.md\|TEMPLATE-' | wc -l | tr -d ' ' || echo 0) -else - HISTORY_DOCS=$(git diff --cached --name-only -- 'docs/history/*.md' 'docs/history/**/*.md' 2>/dev/null | grep -v 'README\.md\|TEMPLATE-' | wc -l | tr -d ' ' || echo 0) -fi - -# --------------------------------------------------------------------------- -# Output assessment -# --------------------------------------------------------------------------- - -if [[ "$IMPACT_HIGH" == true ]]; then - echo "⚠️ HIGH IMPACT change detected — documentation required" - echo " Changed files: $CHANGED_COUNT" - if [[ "$HISTORY_DOCS" -gt 0 ]]; then - echo "✅ Documentation found ($HISTORY_DOCS new doc(s) in docs/history/)" - exit 0 - else - echo " Run: ./scripts/create-doc.sh \"\" <pr-number>" - echo " See: docs/engineering/06_pr_documentation.md" - if [[ "$STRICT" == "true" ]]; then - exit 1 - fi - fi -elif [[ "$IMPACT_MEDIUM" == true ]]; then - echo "ℹ️ MEDIUM IMPACT change detected — documentation recommended" - echo " Run: ./scripts/create-doc.sh <type> \"<title>\" <pr-number>" -else - echo "✅ LOW IMPACT change — documentation optional" -fi - -exit 0 diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/consolidate-branches.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/consolidate-branches.sh deleted file mode 100644 index 9aa9b746..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/consolidate-branches.sh +++ /dev/null @@ -1,289 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# ============================================================================= -# consolidate-branches.sh — Merge all unmerged feature branches into one -# ============================================================================= -# Usage: scripts/consolidate-branches.sh [base-branch] [--dry-run] [--skip=branch1,branch2] -# -# Discovers all local and remote branches not yet merged into <base-branch>, -# filters out protected branches, and merges them one by one into the current -# branch. Uses resolve-merge.sh for auto-resolution of generated files. -# -# Arguments: -# base-branch Branch to check "merged" status against (default: main) -# --dry-run List branches that would be merged without doing anything -# --skip=X,Y Comma-separated list of branch names to skip -# -# Examples: -# scripts/consolidate-branches.sh # merge all into current -# scripts/consolidate-branches.sh dev --dry-run # preview what would merge -# scripts/consolidate-branches.sh main --skip=wip/experiment -# ============================================================================= -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -# Colours (disabled when piped) -if [ -t 1 ]; then - GREEN='\033[0;32m' - YELLOW='\033[1;33m' - RED='\033[0;31m' - CYAN='\033[0;36m' - BOLD='\033[1m' - NC='\033[0m' -else - GREEN='' YELLOW='' RED='' CYAN='' BOLD='' NC='' -fi - -info() { echo -e "${CYAN}[info]${NC} $*"; } -ok() { echo -e "${GREEN}[ok]${NC} $*"; } -warn() { echo -e "${YELLOW}[warn]${NC} $*"; } -err() { echo -e "${RED}[error]${NC} $*"; } - -# --------------------------------------------------------------------------- -# Parse arguments -# --------------------------------------------------------------------------- -BASE_BRANCH="main" -DRY_RUN=false -SKIP_BRANCHES="" - -for arg in "$@"; do - case "$arg" in - --dry-run) DRY_RUN=true ;; - --skip=*) SKIP_BRANCHES="${arg#--skip=}" ;; - -*) err "Unknown flag: $arg"; exit 1 ;; - *) BASE_BRANCH="$arg" ;; - esac -done - -cd "$REPO_ROOT" - -CURRENT_BRANCH="$(git branch --show-current)" -if [ -z "$CURRENT_BRANCH" ]; then - err "Not on a branch (detached HEAD). Checkout a branch first." - exit 1 -fi - -# --------------------------------------------------------------------------- -# Protected branches — never auto-merge these -# --------------------------------------------------------------------------- -PROTECTED_BRANCHES="main master develop release" - -is_protected() { - local branch="$1" - for p in $PROTECTED_BRANCHES; do - [ "$branch" = "$p" ] && return 0 - done - return 1 -} - -is_skipped() { - local branch="$1" - if [ -n "$SKIP_BRANCHES" ]; then - IFS=',' read -ra SKIPS <<< "$SKIP_BRANCHES" - for s in "${SKIPS[@]}"; do - [ "$branch" = "$s" ] && return 0 - done - fi - return 1 -} - -# --------------------------------------------------------------------------- -# 1. Fetch all remotes -# --------------------------------------------------------------------------- -info "Fetching all remotes..." -git fetch --all --prune 2>/dev/null || warn "Fetch failed — continuing with local state" - -# --------------------------------------------------------------------------- -# 2. Discover unmerged branches -# --------------------------------------------------------------------------- -info "Finding branches not merged into ${BASE_BRANCH}..." - -# Get all remote branches not merged into base -UNMERGED=() -while IFS= read -r ref; do - [ -z "$ref" ] && continue - # Strip 'origin/' prefix for display - branch="${ref#origin/}" - - # Skip current branch, base branch, HEAD pointer - [ "$branch" = "$CURRENT_BRANCH" ] && continue - [ "$branch" = "$BASE_BRANCH" ] && continue - [ "$branch" = "HEAD" ] && continue - - # Skip protected branches - is_protected "$branch" && continue - - # Skip user-specified branches - is_skipped "$branch" && continue - - UNMERGED+=("$branch") -done < <(git branch -r --no-merged "origin/${BASE_BRANCH}" 2>/dev/null | sed 's/^[* ]*//' | sort) - -# Also check local-only branches (not on remote) -while IFS= read -r branch; do - [ -z "$branch" ] && continue - [ "$branch" = "$CURRENT_BRANCH" ] && continue - [ "$branch" = "$BASE_BRANCH" ] && continue - is_protected "$branch" && continue - is_skipped "$branch" && continue - - # Check if already in UNMERGED list - already=false - for u in "${UNMERGED[@]+"${UNMERGED[@]}"}"; do - [ "$u" = "$branch" ] && already=true && break - done - $already && continue - - UNMERGED+=("$branch") -done < <(git branch --no-merged "$BASE_BRANCH" 2>/dev/null | sed 's/^[* ]*//' | sort) - -if [ ${#UNMERGED[@]} -eq 0 ]; then - ok "No unmerged branches found. Everything is up to date with ${BASE_BRANCH}." - exit 0 -fi - -# --------------------------------------------------------------------------- -# 3. Display plan -# --------------------------------------------------------------------------- -echo "" -echo -e "${BOLD}Branch Consolidation Plan${NC}" -echo -e "${BOLD}========================${NC}" -echo "" -echo -e " Current branch: ${GREEN}${CURRENT_BRANCH}${NC}" -echo -e " Base branch: ${CYAN}${BASE_BRANCH}${NC}" -echo -e " Branches to merge: ${#UNMERGED[@]}" -echo "" - -for i in "${!UNMERGED[@]}"; do - branch="${UNMERGED[$i]}" - # Get commit count ahead of base - ahead=$(git rev-list --count "origin/${BASE_BRANCH}..origin/${branch}" 2>/dev/null || echo "?") - echo -e " $((i + 1)). ${YELLOW}${branch}${NC} (${ahead} commits ahead)" -done - -echo "" - -if $DRY_RUN; then - info "Dry run — no changes made." - exit 0 -fi - -# --------------------------------------------------------------------------- -# 4. Merge each branch -# --------------------------------------------------------------------------- -MERGED=() -FAILED=() -SKIPPED_DIRTY=() - -for branch in "${UNMERGED[@]}"; do - echo "" - echo -e "${BOLD}─────────────────────────────────────────${NC}" - info "Merging ${branch} ($(( ${#MERGED[@]} + ${#FAILED[@]} + 1 ))/${#UNMERGED[@]})..." - - # Check for uncommitted changes before each merge - if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then - warn "Uncommitted changes detected. Stashing before merge..." - git stash push -m "consolidate-branches: before merging ${branch}" 2>/dev/null - fi - - # Try merging from remote first, fall back to local - merge_ref="origin/${branch}" - if ! git rev-parse --verify "$merge_ref" &>/dev/null; then - merge_ref="$branch" - fi - - merge_output=$(git merge "$merge_ref" --no-edit 2>&1) && { - ok "Merged ${branch} cleanly." - MERGED+=("$branch") - continue - } - - # Check if it's a conflict or other error - if echo "$merge_output" | grep -qF "CONFLICT"; then - warn "Conflicts merging ${branch}. Attempting auto-resolution..." - - # Use resolve-merge logic inline (auto-resolve generated files) - auto_resolved=0 - while IFS= read -r file; do - [ -z "$file" ] && continue - case "$file" in - .claude/*|.cursor/*|.windsurf/*|.roo/*|.clinerules/*|.github/instructions/*|\ - .github/copilot-instructions.md|.github/PULL_REQUEST_TEMPLATE.md|\ - .github/agents/*|.github/chatmodes/*|.github/prompts/*|\ - .agents/*|.gemini/*|docs/*/README.md|scripts/*.sh|scripts/*.ps1|\ - AGENTS.md|UNIFIED_AGENT_TEAMS.md|COMMAND_GUIDE.md|QUALITY_GATES.md|\ - RUNBOOK_AI.md|CONTRIBUTING.md) - git checkout --theirs -- "$file" 2>/dev/null && git add "$file" 2>/dev/null - ok " Auto-resolved: $file" - auto_resolved=$((auto_resolved + 1)) - ;; - pnpm-lock.yaml|.agentkit/pnpm-lock.yaml|package-lock.json|yarn.lock|.agentkit/yarn.lock) - git checkout --theirs -- "$file" 2>/dev/null && git add "$file" 2>/dev/null - ok " Auto-resolved (lockfile): $file" - auto_resolved=$((auto_resolved + 1)) - ;; - esac - done < <(git diff --name-only --diff-filter=U 2>/dev/null) - - # Check if any conflicts remain - remaining=$(git diff --name-only --diff-filter=U 2>/dev/null || true) - if [ -z "$remaining" ]; then - git commit --no-edit 2>/dev/null - ok "Merged ${branch} (${auto_resolved} auto-resolved)." - MERGED+=("$branch") - else - err "Unresolved conflicts merging ${branch}:" - echo "$remaining" | while IFS= read -r f; do - echo -e " ${RED}✗${NC} $f" - done - warn "Aborting merge of ${branch}. Resolve manually or re-run with --skip=${branch}" - git merge --abort 2>/dev/null || true - FAILED+=("$branch") - fi - else - err "Merge of ${branch} failed (not a conflict):" - echo " $merge_output" - git merge --abort 2>/dev/null || true - FAILED+=("$branch") - fi -done - -# --------------------------------------------------------------------------- -# 5. Summary -# --------------------------------------------------------------------------- -echo "" -echo -e "${BOLD}═══════════════════════════════════════════${NC}" -echo -e "${BOLD}Consolidation Summary${NC}" -echo -e "${BOLD}═══════════════════════════════════════════${NC}" -echo "" -echo -e " ${GREEN}Merged:${NC} ${#MERGED[@]}/${#UNMERGED[@]}" - -if [ ${#MERGED[@]} -gt 0 ]; then - for b in "${MERGED[@]}"; do - echo -e " ${GREEN}✓${NC} $b" - done -fi - -if [ ${#FAILED[@]} -gt 0 ]; then - echo "" - echo -e " ${RED}Failed:${NC} ${#FAILED[@]}/${#UNMERGED[@]}" - for b in "${FAILED[@]}"; do - echo -e " ${RED}✗${NC} $b" - done - echo "" - warn "Re-run with: scripts/consolidate-branches.sh ${BASE_BRANCH} --skip=$(IFS=,; echo "${MERGED[*]}")" -fi - -echo "" -if [ ${#MERGED[@]} -gt 0 ]; then - info "Next steps:" - echo " 1. Run: pnpm -C .agentkit agentkit:sync" - echo " 2. Run: pnpm test" - echo " 3. Review with: git log --oneline -20" -fi - -exit ${#FAILED[@]} diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/create-doc.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/create-doc.sh deleted file mode 100644 index 318e7fe7..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/create-doc.sh +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/create-doc.sh -# Creates a new history document from the appropriate template. -# -# Usage: -# ./scripts/create-doc.sh <type> "<title>" [pr-number] -# -# Arguments: -# type Document type: implementation | bugfix | feature | migration -# title Human-readable title for the document -# pr-number Optional PR number to include in the document -# -# Examples: -# ./scripts/create-doc.sh implementation "TreatWarningsAsErrors" 42 -# ./scripts/create-doc.sh bugfix "Null Reference in Auth" 43 -# ./scripts/create-doc.sh feature "User Authentication" 44 -# ./scripts/create-doc.sh migration "Upgrade to Node 22" 45 - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -HISTORY_DIR="$REPO_ROOT/docs/history" -INDEX_FILE="$HISTORY_DIR/.index.json" - -# --------------------------------------------------------------------------- -# Argument validation -# --------------------------------------------------------------------------- - -usage() { - echo "Usage: $0 <type> \"<title>\" [pr-number]" - echo " type: implementation | bugfix | feature | migration | issue | lesson" - exit 1 -} - -if [[ $# -lt 2 ]]; then - usage -fi - -TYPE="$1" -TITLE="$2" -PR_NUMBER="${3:-}" - -case "$TYPE" in - implementation|bugfix|feature|migration|issue|lesson) ;; - *) echo "Error: unknown type '$TYPE'. Must be one of: implementation, bugfix, feature, migration, issue, lesson"; exit 1 ;; -esac - -# --------------------------------------------------------------------------- -# Determine subdirectory from type -# --------------------------------------------------------------------------- - -case "$TYPE" in - implementation) SUBDIR="implementations" ;; - bugfix) SUBDIR="bug-fixes" ;; - feature) SUBDIR="features" ;; - migration) SUBDIR="migrations" ;; - issue) SUBDIR="issues" ;; - lesson) SUBDIR="lessons-learned" ;; -esac - -# --------------------------------------------------------------------------- -# Read and update the sequential index -# --------------------------------------------------------------------------- - -if [[ ! -f "$INDEX_FILE" ]]; then - echo '{"sequences":{"implementation":1,"bugfix":1,"feature":1,"migration":1,"issue":1,"lesson":1},"entries":[]}' > "$INDEX_FILE" -fi - -# Use node to read the current sequence number safely (no user input interpolated) -SEQ_NUM=$(node - "$INDEX_FILE" "$TYPE" << 'NODEEOF' - const [,, indexFile, type] = process.argv; - const fs = require('fs'); - const idx = JSON.parse(fs.readFileSync(indexFile, 'utf8')); - process.stdout.write(String(idx.sequences[type] || 1)); -NODEEOF -) - -PADDED=$(printf "%04d" "$SEQ_NUM") -DATE=$(date +%Y-%m-%d) - -# Sanitize title: lowercase, spaces to hyphens, remove non-alphanumeric except hyphens -SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-\|-$//g') - -FILENAME="${PADDED}-${DATE}-${SLUG}-${TYPE}.md" -DEST_DIR="$HISTORY_DIR/$SUBDIR" -DEST_FILE="$DEST_DIR/$FILENAME" - -mkdir -p "$DEST_DIR" - -# --------------------------------------------------------------------------- -# Copy template and substitute placeholders -# --------------------------------------------------------------------------- - -TEMPLATE_SRC="$REPO_ROOT/.agentkit/templates/docs/history/$SUBDIR/TEMPLATE-${TYPE}.md" - -if [[ ! -f "$TEMPLATE_SRC" ]]; then - echo "Error: template not found at $TEMPLATE_SRC" - exit 1 -fi - -PR_REF="${PR_NUMBER:+#${PR_NUMBER}}" - -# Perform literal replacements using Node.js to avoid sed injection -TITLE_VAL="$TITLE" DATE_VAL="$DATE" PR_REF_VAL="${PR_REF:-[#PR-Number]}" \ -node - "$TEMPLATE_SRC" "$DEST_FILE" << 'NODEEOF' - const fs = require('fs'); - const [,, src, dest] = process.argv; - let content = fs.readFileSync(src, 'utf8'); - - const replacements = { - '[Feature/Change Name]': process.env.TITLE_VAL, - '[Bug Description]': process.env.TITLE_VAL, - '[Feature Name]': process.env.TITLE_VAL, - '[Migration Name]': process.env.TITLE_VAL, - '[Issue Title]': process.env.TITLE_VAL, - '[Lesson Title]': process.env.TITLE_VAL, - '[YYYY-MM-DD]': process.env.DATE_VAL, - '[#PR-Number]': process.env.PR_REF_VAL - }; - - for (const [placeholder, value] of Object.entries(replacements)) { - content = content.split(placeholder).join(value); - } - - fs.writeFileSync(dest, content, 'utf8'); -NODEEOF - -# --------------------------------------------------------------------------- -# Update index -# --------------------------------------------------------------------------- - -node - "$INDEX_FILE" "$TYPE" "$SEQ_NUM" "$TITLE" "$DATE" "${PR_NUMBER:-}" "$SUBDIR/$FILENAME" << 'NODEEOF' - const [,, indexFile, type, seqNum, title, date, pr, file] = process.argv; - const fs = require('fs'); - const idx = JSON.parse(fs.readFileSync(indexFile, 'utf8')); - idx.sequences[type] = (idx.sequences[type] || 1) + 1; - idx.entries = idx.entries || []; - idx.entries.push({ number: Number(seqNum), type, title, date, pr, file }); - fs.writeFileSync(indexFile, JSON.stringify(idx, null, 2) + '\n'); -NODEEOF - -echo "Created: $DEST_FILE" - -# --------------------------------------------------------------------------- -# Update CHANGELOG.md -# --------------------------------------------------------------------------- - -# Map history doc type to changelog section -case "$TYPE" in - feature) CHANGELOG_SECTION="Added" ;; - implementation) CHANGELOG_SECTION="Added" ;; - bugfix) CHANGELOG_SECTION="Fixed" ;; - migration) CHANGELOG_SECTION="Changed" ;; - issue) CHANGELOG_SECTION="" ;; # Issues don't go in changelog - lesson) CHANGELOG_SECTION="" ;; # Lessons don't go in changelog -esac - -UPDATE_CHANGELOG="$SCRIPT_DIR/update-changelog.sh" -if [[ -z "$CHANGELOG_SECTION" ]]; then - echo "ℹ️ ${TYPE} records are not added to CHANGELOG.md — skipping changelog update." -elif [[ -f "$UPDATE_CHANGELOG" ]]; then - bash "$UPDATE_CHANGELOG" "$CHANGELOG_SECTION" "$TITLE" "${PR_NUMBER:-}" "$SUBDIR/$FILENAME" || \ - echo "⚠️ Could not update CHANGELOG.md — please add the entry manually." -else - echo "ℹ️ update-changelog.sh not found — skipping changelog update." -fi diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/resolve-merge.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/resolve-merge.sh deleted file mode 100644 index a3daecff..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/resolve-merge.sh +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# ============================================================================= -# resolve-merge.sh — Apply standard merge conflict resolutions -# ============================================================================= -# Usage: scripts/resolve-merge.sh [target-branch] -# -# Merges origin/<target-branch> into the current branch and auto-resolves -# generated/framework-managed files per the AgentKit merge resolution matrix. -# Remaining conflicts (engine source, spec files) are listed for manual review. -# ============================================================================= -set -euo pipefail - -TARGET="${1:-main}" -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -# Colours (disabled when piped) -if [ -t 1 ]; then - GREEN='\033[0;32m' - YELLOW='\033[1;33m' - RED='\033[0;31m' - CYAN='\033[0;36m' - NC='\033[0m' -else - GREEN='' YELLOW='' RED='' CYAN='' NC='' -fi - -info() { echo -e "${CYAN}[info]${NC} $*"; } -ok() { echo -e "${GREEN}[ok]${NC} $*"; } -warn() { echo -e "${YELLOW}[warn]${NC} $*"; } -err() { echo -e "${RED}[error]${NC} $*"; } - -cd "$REPO_ROOT" - -# --------------------------------------------------------------------------- -# 1. Fetch and attempt merge -# --------------------------------------------------------------------------- -info "Fetching origin/${TARGET}..." -git fetch origin "$TARGET" 2>/dev/null || { - err "Failed to fetch origin/${TARGET}. Check your remote." - exit 1 -} - -CURRENT_BRANCH="$(git branch --show-current)" -info "Merging origin/${TARGET} into ${CURRENT_BRANCH}..." - -merge_output=$(git merge "origin/${TARGET}" --no-edit 2>&1) && { - ok "Merge completed cleanly — no conflicts." - exit 0 -} - -# Distinguish real merge conflicts from other failures -if ! echo "$merge_output" | grep -qF "CONFLICT"; then - err "Merge failed for a reason other than conflicts:" - echo "$merge_output" - exit 1 -fi - -info "Merge conflicts detected. Applying resolution matrix..." - -# --------------------------------------------------------------------------- -# 2. Auto-resolve generated files (KEEP_THEIRS — accept upstream) -# --------------------------------------------------------------------------- -GENERATED_PATTERNS=( - '.agents/skills/*/SKILL.md' - '.github/agents/*.agent.md' - '.github/chatmodes/*.chatmode.md' - '.github/prompts/*.prompt.md' - 'docs/*/README.md' - '.github/copilot-instructions.md' - '.github/PULL_REQUEST_TEMPLATE.md' -) - -auto_resolved=0 -for pattern in "${GENERATED_PATTERNS[@]}"; do - # Find conflicted files matching this pattern - while IFS= read -r file; do - [ -z "$file" ] && continue - if git checkout --theirs -- "$file" 2>/dev/null; then - git add "$file" 2>/dev/null - ok "Auto-resolved (accept upstream): $file" - auto_resolved=$((auto_resolved + 1)) - fi - done < <(git diff --name-only --diff-filter=U | grep -E "$pattern" 2>/dev/null || true) -done - -# --------------------------------------------------------------------------- -# 3. Auto-resolve lockfiles (KEEP_THEIRS — accept upstream, regenerate later) -# --------------------------------------------------------------------------- -LOCKFILE_PATTERNS=( - 'pnpm-lock.yaml' - '.agentkit/pnpm-lock.yaml' - 'package-lock.json' - '.agentkit/package-lock.json' -) - -for lockfile in "${LOCKFILE_PATTERNS[@]}"; do - if git diff --name-only --diff-filter=U | grep -qx "$lockfile" 2>/dev/null; then - if git checkout --theirs -- "$lockfile" 2>/dev/null; then - git add "$lockfile" 2>/dev/null - ok "Auto-resolved (accept upstream): $lockfile" - auto_resolved=$((auto_resolved + 1)) - fi - fi -done - -# --------------------------------------------------------------------------- -# 4. Auto-resolve generated config (KEEP_THEIRS) -# --------------------------------------------------------------------------- -GENERATED_CONFIGS=( - '.gemini/config.yaml' -) - -for config in "${GENERATED_CONFIGS[@]}"; do - if git diff --name-only --diff-filter=U | grep -qx "$config" 2>/dev/null; then - if git checkout --theirs -- "$config" 2>/dev/null; then - git add "$config" 2>/dev/null - ok "Auto-resolved (accept upstream): $config" - auto_resolved=$((auto_resolved + 1)) - fi - fi -done - -# --------------------------------------------------------------------------- -# 5. Report remaining conflicts -# --------------------------------------------------------------------------- -REMAINING="$(git diff --name-only --diff-filter=U 2>/dev/null || true)" - -echo "" -info "Auto-resolved: ${auto_resolved} file(s)" - -if [ -n "$REMAINING" ]; then - echo "" - warn "Manual merge required for the following file(s):" - echo "" - while IFS= read -r file; do - [ -z "$file" ] && continue - # Categorise for the developer - case "$file" in - .agentkit/engines/*) echo -e " ${RED}[engine]${NC} $file — semantic merge required (runtime logic)" ;; - .agentkit/spec/*) echo -e " ${YELLOW}[spec]${NC} $file — preserve both intents" ;; - *) echo -e " ${CYAN}[source]${NC} $file" ;; - esac - done <<< "$REMAINING" - echo "" - info "Resolve the files above, then run: git add -A && git commit" - exit 1 -else - ok "All conflicts resolved automatically." - info "Committing merge..." - git commit --no-edit - ok "Merge committed successfully." - - # Suggest lockfile regeneration - if git diff --name-only "HEAD~1..HEAD" | grep -q "lock\.\(yaml\|json\)$" 2>/dev/null; then - echo "" - warn "Lockfiles were updated. Consider running: pnpm install" - fi -fi diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/setup-agentkit-branch-governance.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/setup-agentkit-branch-governance.sh deleted file mode 100644 index f955e11b..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/setup-agentkit-branch-governance.sh +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -set -euo pipefail - -REPO="" -DRY_RUN=false -SKIP_DEFAULT_BRANCH=false -SKIP_PROTECTION=false - -while [[ $# -gt 0 ]]; do - case "$1" in - --repo) - if [[ $# -lt 2 || -z "${2:-}" || "${2:-}" == -* ]]; then - echo "Error: --repo requires a value in the form owner/name" - exit 1 - fi - REPO="$2" - shift 2 - ;; - --dry-run) - DRY_RUN=true - shift - ;; - --skip-default-branch) - SKIP_DEFAULT_BRANCH=true - shift - ;; - --skip-protection) - SKIP_PROTECTION=true - shift - ;; - --help|-h) - echo "Usage: $(basename "$0") [--repo owner/name] [--dry-run] [--skip-default-branch] [--skip-protection]" - exit 0 - ;; - *) - echo "Unknown option: $1" - exit 1 - ;; - esac -done - -if ! command -v gh >/dev/null 2>&1; then - echo "gh CLI is not installed. Install from https://cli.github.com/" - exit 1 -fi - -if ! gh auth status >/dev/null 2>&1; then - echo "gh CLI is not authenticated. Run 'gh auth login' first." - exit 1 -fi - -if [[ -z "$REPO" ]]; then - REPO=$(gh repo view --json nameWithOwner -q '.nameWithOwner' 2>/dev/null || true) -fi - -if [[ -z "$REPO" ]]; then - echo "Could not determine repository. Pass --repo <owner/name>." - exit 1 -fi - -echo "=== AgentKit Branch Governance Setup ===" -echo "Repository: $REPO" -echo "DryRun: $DRY_RUN" -echo - -if [[ "$SKIP_DEFAULT_BRANCH" == false ]]; then - if [[ "$DRY_RUN" == true ]]; then - echo "[dry-run] Would set default branch to 'main' for $REPO" - else - gh api --method PATCH "/repos/$REPO" -f default_branch='main' >/dev/null - echo "Default branch set to 'main'." - fi -fi - -PAYLOAD=$(cat <<'JSON' -{ - "required_status_checks": { - "strict": true, - "contexts": [ - "Test", - "Validate", - "Branch Protection / branch-rules" - ] - }, - "enforce_admins": false, - "required_pull_request_reviews": { - "required_approving_review_count": 1, - "dismiss_stale_reviews": true, - "require_code_owner_reviews": true, - "require_last_push_approval": false - }, - "restrictions": null, - "required_linear_history": true, - "allow_force_pushes": false, - "allow_deletions": false, - "block_creations": false, - "required_conversation_resolution": true -} -JSON -) - -if [[ "$SKIP_PROTECTION" == false ]]; then - # Deduplicate: if defaultBranch is 'main', don't apply twice - for BRANCH in $(echo "main main" | tr ' ' '\n' | awk '!seen[$0]++'); do - # Skip if the branch does not exist on the remote - if ! gh api "/repos/$REPO/branches/$BRANCH" --silent 2>/dev/null; then - echo "[skip] Branch '$BRANCH' does not exist on $REPO — skipping protection." - continue - fi - - if [[ "$DRY_RUN" == true ]]; then - echo "[dry-run] Would apply branch protection to $REPO/$BRANCH" - continue - fi - - gh api --method PUT "/repos/$REPO/branches/$BRANCH/protection" --input - <<< "$PAYLOAD" >/dev/null - echo "Branch protection applied to $BRANCH." - done -fi - -echo -echo "Done." -for BRANCH in $(echo "main main" | tr ' ' '\n' | awk '!seen[$0]++'); do - echo "Verify with: gh api /repos/$REPO/branches/$BRANCH/protection" -done diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/sync-issues.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/sync-issues.sh deleted file mode 100644 index 9ace772a..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/sync-issues.sh +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/sync-issues.sh -# Syncs local issue docs (docs/history/issues/) to GitHub Issues. -# -# Local issue markdown files that have "gh_synced: false" are candidates for -# sync. In dry-run mode (default) the script prints what would be created. -# With --apply it creates GitHub Issues via `gh` and stamps the file with the -# resulting issue number. -# -# Usage: -# ./scripts/sync-issues.sh # Dry-run — preview only -# ./scripts/sync-issues.sh --apply # Create GitHub Issues -# ./scripts/sync-issues.sh --apply --label "from-local" # Add extra label -# -# Requirements: -# - gh CLI installed and authenticated -# - Current directory inside the git repository - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -ISSUES_DIR="$REPO_ROOT/docs/history/issues" - -APPLY=false -EXTRA_LABEL="" - -while [[ $# -gt 0 ]]; do - case "$1" in - --apply) APPLY=true; shift ;; - --label) - [[ $# -ge 2 ]] || { echo "Error: --label requires a value"; exit 1; } - EXTRA_LABEL="$2"; shift 2 ;; - -h|--help) - echo "Usage: $0 [--apply] [--label <label>]" - echo " --apply Create GitHub Issues (default is dry-run)" - echo " --label Extra label to add to created issues" - exit 0 - ;; - *) echo "Unknown option: $1"; exit 1 ;; - esac -done - -# --------------------------------------------------------------------------- -# Preflight checks (only needed when actually creating issues) -# --------------------------------------------------------------------------- - -if [[ "$APPLY" == true ]]; then - if ! command -v gh &>/dev/null; then - echo "Error: gh CLI is not installed. Install it from https://cli.github.com/" - exit 1 - fi - - if ! gh auth status &>/dev/null; then - echo "Error: gh is not authenticated. Run 'gh auth login' first." - exit 1 - fi -fi - -# --------------------------------------------------------------------------- -# Discover unsynced issue files -# --------------------------------------------------------------------------- - -CANDIDATES=0 -SKIPPED=0 -FAILED=0 - -# Glob matches the enforced naming convention: XXXX-YYYY-MM-DD-slug-issue.md -# Files created outside create-doc.sh without the -issue suffix are not picked up. -for issue_file in "$ISSUES_DIR"/*-issue.md; do - [[ -f "$issue_file" ]] || continue - - basename_file="$(basename "$issue_file")" - - # Skip templates - if [[ "$basename_file" == TEMPLATE-* ]]; then - continue - fi - - # Check sync status - if ! grep -q 'gh_synced.*false' "$issue_file" 2>/dev/null; then - SKIPPED=$((SKIPPED + 1)) - continue - fi - - # Extract title from first H1 (|| true prevents set -e exit on no match) - TITLE="$(grep -m1 '^# ' "$issue_file" | sed 's/^# //' | sed 's/ - Issue Record$//')" || true - if [[ -z "$TITLE" ]]; then - TITLE="$basename_file" - fi - - # Extract severity for labeling - SEVERITY="$(grep -m1 '^\*\*Severity\*\*:' "$issue_file" | sed 's/.*: *//' | tr '[:upper:]' '[:lower:]')" || true - if [[ -z "$SEVERITY" ]]; then - echo " [warn] No severity found in $basename_file — defaulting to unlabelled" - fi - - # Extract summary section as the issue body - BODY="$(sed -n '/^## Summary$/,/^## /{/^## Summary$/d;/^## /d;p}' "$issue_file" | sed '/^$/N;/^\n$/d')" - if [[ -z "$BODY" ]]; then - echo " [warn] No ## Summary section found in $basename_file — using fallback body" - BODY="Synced from local issue doc: $basename_file" - fi - - # Append a link back to the local file - BODY="$BODY - ---- -_Synced from \`docs/history/issues/$basename_file\`_" - - # Build labels - LABELS="synced-from-local" - if [[ -n "$SEVERITY" && "$SEVERITY" != *"["* ]]; then - LABELS="$LABELS,severity:$SEVERITY" - fi - if [[ -n "$EXTRA_LABEL" ]]; then - LABELS="$LABELS,$EXTRA_LABEL" - fi - - if [[ "$APPLY" == false ]]; then - echo "[dry-run] Would create issue: \"$TITLE\"" - echo " Labels: $LABELS" - echo " Source: $basename_file" - echo "" - CANDIDATES=$((CANDIDATES + 1)) - continue - fi - - # Create the GitHub Issue — capture stderr separately so it can be surfaced - # on failure without polluting the URL on success. - echo "Creating issue: \"$TITLE\" ..." - GH_STDERR_FILE="$(mktemp)" - ISSUE_URL="$(gh issue create \ - --title "$TITLE" \ - --body "$BODY" \ - --label "$LABELS" 2>"$GH_STDERR_FILE")" || { - echo " FAILED to create issue: \"$TITLE\"" - echo " gh stderr: $(cat "$GH_STDERR_FILE")" - rm -f "$GH_STDERR_FILE" - FAILED=$((FAILED + 1)) - continue - } - rm -f "$GH_STDERR_FILE" - - # Extract issue number from URL (https://github.com/owner/repo/issues/123) - ISSUE_NUMBER="${ISSUE_URL##*/}" - if [[ ! "$ISSUE_NUMBER" =~ ^[0-9]+$ ]]; then - ISSUE_NUMBER="$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')" || true - [[ -z "$ISSUE_NUMBER" ]] && ISSUE_NUMBER="unknown" - fi - - echo " Created: $ISSUE_URL (#$ISSUE_NUMBER)" - - # Stamp the local file with sync metadata (portable: temp file instead of sed -i). - SYNC_DATE="$(date +%Y-%m-%d)" - TMPFILE="$(mktemp)" - sed \ - -e "s/^\(- \*\*gh_synced\*\*:\) .*/\1 true/" \ - -e "s/^\(- \*\*gh_issue_number\*\*:\) .*/\1 #$ISSUE_NUMBER/" \ - -e "s/^\(- \*\*gh_synced_at\*\*:\) .*/\1 $SYNC_DATE/" \ - -e "s|\(- \*\*Issue tracker\*\*:\) \[GitHub Issue.*\]|\1 $ISSUE_URL|" \ - "$issue_file" > "$TMPFILE" && mv "$TMPFILE" "$issue_file" - - CANDIDATES=$((CANDIDATES + 1)) -done - -# --------------------------------------------------------------------------- -# Summary -# --------------------------------------------------------------------------- - -echo "---" -if [[ "$APPLY" == false ]]; then - echo "Dry-run complete. $CANDIDATES issue(s) would be created, $SKIPPED already synced." - echo "Run with --apply to create GitHub Issues." -else - echo "Sync complete. $CANDIDATES created, $SKIPPED already synced, $FAILED failed." -fi diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/sync-split-pr.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/sync-split-pr.sh deleted file mode 100644 index 1bbf61ac..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/sync-split-pr.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -set -euo pipefail - -BASE_BRANCH="" -NEW_BRANCH="" -COMMIT_MESSAGE="chore(sync): regenerate generated outputs" -PR_TITLE="chore(sync): regenerate generated outputs" -DRY_RUN=0 - -while [[ $# -gt 0 ]]; do - case "$1" in - --base) - BASE_BRANCH="${2:-}" - shift 2 - ;; - --branch) - NEW_BRANCH="${2:-}" - shift 2 - ;; - --commit-message) - COMMIT_MESSAGE="${2:-}" - shift 2 - ;; - --pr-title) - PR_TITLE="${2:-}" - shift 2 - ;; - --dry-run) - DRY_RUN=1 - shift - ;; - -h|--help) - cat <<'EOF' -Usage: scripts/sync-split-pr.sh [options] - -Creates a dedicated branch + commit + PR for files produced by `agentkit:sync`. - -Options: - --base <branch> PR base branch (default: current branch) - --branch <name> Branch name for sync commit (default: chore/sync-generated-<utc>) - --commit-message <msg> Commit message - --pr-title <title> PR title - --dry-run Run sync and report changes without creating branch/commit/PR - -h, --help Show help -EOF - exit 0 - ;; - *) - echo "Unknown option: $1" >&2 - exit 1 - ;; - esac -done - -if [[ -n "$(git status --porcelain)" ]]; then - echo "Working tree is not clean. Commit/stash/discard changes before running sync split." >&2 - exit 1 -fi - -CURRENT_BRANCH="$(git branch --show-current)" -if [[ -z "$BASE_BRANCH" ]]; then - BASE_BRANCH="$CURRENT_BRANCH" -fi - -if [[ -z "$NEW_BRANCH" ]]; then - TS="$(date -u +%Y%m%d-%H%M%S)" - NEW_BRANCH="chore/sync-generated-$TS" -fi - -echo "Running sync..." -pnpm -C .agentkit agentkit:sync - -CHANGED_FILES="$(git status --porcelain)" -if [[ -z "$CHANGED_FILES" ]]; then - echo "No sync-generated changes detected." - mkdir -p .agentkit/logs - printf '{"timestamp":"%s","tool":"sync-split-pr","outcome":"no_changes","base":"%s","branch":"%s"}\n' \ - "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$BASE_BRANCH" "$CURRENT_BRANCH" >> .agentkit/logs/tool-usage.jsonl - exit 0 -fi - -FILES_COUNT="$(git status --porcelain | wc -l | tr -d ' ')" -echo "Detected $FILES_COUNT changed file(s) from sync." - -if [[ "$DRY_RUN" -eq 1 ]]; then - echo "Dry run enabled; not creating branch/commit/PR." - git status --short - mkdir -p .agentkit/logs - printf '{"timestamp":"%s","tool":"sync-split-pr","outcome":"dry_run","files":%s,"base":"%s","branch":"%s"}\n' \ - "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$FILES_COUNT" "$BASE_BRANCH" "$CURRENT_BRANCH" >> .agentkit/logs/tool-usage.jsonl - exit 0 -fi - -git checkout -b "$NEW_BRANCH" -git add -A -git commit -m "$COMMIT_MESSAGE" -git push -u origin "$NEW_BRANCH" - -PR_BODY="Automated sync-only PR. - -- Source branch: $CURRENT_BRANCH -- Sync command: pnpm -C .agentkit agentkit:sync -- Changed files: $FILES_COUNT" - -PR_URL="$(gh pr create --base "$BASE_BRANCH" --head "$NEW_BRANCH" --title "$PR_TITLE" --body "$PR_BODY")" -echo "Created PR: $PR_URL" - -mkdir -p .agentkit/logs -printf '{"timestamp":"%s","tool":"sync-split-pr","outcome":"pr_created","files":%s,"base":"%s","source":"%s","syncBranch":"%s","prUrl":"%s"}\n' \ - "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$FILES_COUNT" "$BASE_BRANCH" "$CURRENT_BRANCH" "$NEW_BRANCH" "$PR_URL" >> .agentkit/logs/tool-usage.jsonl diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/update-changelog.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/update-changelog.sh deleted file mode 100644 index e5693e00..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/update-changelog.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/update-changelog.sh -# Inserts an entry into the [Unreleased] section of CHANGELOG.md. -# -# Usage: -# ./scripts/update-changelog.sh <section> "<description>" [pr-number] [history-doc-path] -# -# Arguments: -# section Changelog section: Added | Fixed | Changed | Removed | Security | Deprecated -# description Human-readable description of the change -# pr-number Optional PR number (e.g. 42) -# history-doc-path Optional relative path to the history document -# -# Examples: -# ./scripts/update-changelog.sh Added "New user auth feature" 44 -# ./scripts/update-changelog.sh Fixed "Null reference in login flow" 43 \ -# "docs/history/bug-fixes/0001-2026-03-01-null-reference-bugfix.md" - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -CHANGELOG="$REPO_ROOT/CHANGELOG.md" - -# --------------------------------------------------------------------------- -# Argument validation -# --------------------------------------------------------------------------- - -usage() { - echo "Usage: $0 <section> \"<description>\" [pr-number] [history-doc-path]" - echo " section: Added | Fixed | Changed | Removed | Security | Deprecated" - exit 1 -} - -if [[ $# -lt 2 ]]; then - usage -fi - -SECTION="$1" -DESCRIPTION="$2" -PR_NUMBER="${3:-}" -HISTORY_DOC="${4:-}" - -case "$SECTION" in - Added|Fixed|Changed|Removed|Security|Deprecated) ;; - *) echo "Error: unknown section '$SECTION'. Must be one of: Added, Fixed, Changed, Removed, Security, Deprecated"; exit 1 ;; -esac - -if [[ ! -f "$CHANGELOG" ]]; then - echo "Error: CHANGELOG.md not found at $CHANGELOG" - exit 1 -fi - -# --------------------------------------------------------------------------- -# Build the entry line -# --------------------------------------------------------------------------- - -ENTRY="- $DESCRIPTION" - -if [[ -n "$PR_NUMBER" && -n "$HISTORY_DOC" ]]; then - ENTRY="$ENTRY ([#${PR_NUMBER}](../../pull/${PR_NUMBER}), [history](${HISTORY_DOC}))" -elif [[ -n "$PR_NUMBER" ]]; then - ENTRY="$ENTRY ([#${PR_NUMBER}](../../pull/${PR_NUMBER}))" -elif [[ -n "$HISTORY_DOC" ]]; then - ENTRY="$ENTRY ([history](${HISTORY_DOC}))" -fi - -# --------------------------------------------------------------------------- -# Insert entry into CHANGELOG.md using Node.js for reliable multiline editing -# --------------------------------------------------------------------------- - -node - "$CHANGELOG" "$SECTION" "$ENTRY" << 'NODEEOF' -const [,, changelogPath, section, entry] = process.argv; -const fs = require('fs'); -const content = fs.readFileSync(changelogPath, 'utf8'); -const lines = content.split('\n'); - -// Find the [Unreleased] section -const unreleasedIdx = lines.findIndex(l => /^## \[Unreleased\]/i.test(l)); -if (unreleasedIdx === -1) { - console.error('Error: could not find ## [Unreleased] section in CHANGELOG.md'); - process.exit(1); -} - -// Find or create the target ### section within [Unreleased] -// The [Unreleased] block ends at the next ## line -let blockEnd = lines.findIndex((l, i) => i > unreleasedIdx && /^## /.test(l)); -if (blockEnd === -1) blockEnd = lines.length; - -const sectionHeader = `### ${section}`; -let sectionIdx = lines.findIndex((l, i) => i > unreleasedIdx && i < blockEnd && l.trim() === sectionHeader); - -if (sectionIdx === -1) { - // Section doesn't exist — insert before blockEnd (or before the next ---/## delimiter) - let insertAt = blockEnd; - // Look for a trailing --- separator just before blockEnd - for (let i = blockEnd - 1; i > unreleasedIdx; i--) { - if (lines[i].trim() === '---') { insertAt = i; break; } - if (lines[i].trim() !== '') break; - } - lines.splice(insertAt, 0, '', sectionHeader, entry); -} else { - // Section exists — insert after the header line (and any existing entries) - let insertAt = sectionIdx + 1; - // Find the end of this section's entries (next ### or ## or blank+##/###) - while ( - insertAt < blockEnd && - lines[insertAt].trim() !== '' && - !lines[insertAt].startsWith('###') && - !lines[insertAt].startsWith('##') - ) { - insertAt++; - } - lines.splice(insertAt, 0, entry); -} - -fs.writeFileSync(changelogPath, lines.join('\n'), 'utf8'); -console.log(`Updated CHANGELOG.md — ${section}: ${entry}`); -NODEEOF diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/validate-documentation.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/validate-documentation.sh deleted file mode 100644 index e5a60220..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/validate-documentation.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/validate-documentation.sh -# Validates that history documents meet structural requirements. -# -# Usage: -# ./scripts/validate-documentation.sh [file...] -# -# If no files are given, validates all markdown files under docs/history/. - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -HISTORY_DIR="$REPO_ROOT/docs/history" - -ERRORS=0 - -validate_file() { - local file="$1" - local base - base="$(basename "$file")" - - # Skip template and README files - if [[ "$base" == TEMPLATE-* || "$base" == README.md ]]; then - return 0 - fi - - # Validate naming convention: XXXX-YYYY-MM-DD-*-{type}.md - if ! [[ "$base" =~ ^[0-9]{4}-[0-9]{4}-[0-9]{2}-[0-9]{2}-.+-(implementation|bugfix|feature|migration)\.md$ ]]; then - echo "❌ $file" - echo " Invalid filename format. Expected: XXXX-YYYY-MM-DD-[title]-[type].md" - ERRORS=$((ERRORS + 1)) - return 0 - fi - - # Check that required placeholder sections have been filled in - if grep -q '\[YYYY-MM-DD\]' "$file"; then - echo "❌ $file" - echo " Unfilled placeholder: [YYYY-MM-DD]" - ERRORS=$((ERRORS + 1)) - fi - - if grep -q '\[#PR-Number\]' "$file"; then - echo "⚠️ $file" - echo " Missing PR number: [#PR-Number] not replaced" - fi - - # Check that file is non-empty beyond the title line - local line_count - line_count=$(wc -l < "$file") - if [[ "$line_count" -lt 10 ]]; then - echo "❌ $file" - echo " Document too short ($line_count lines). Please fill in the template." - ERRORS=$((ERRORS + 1)) - fi -} - -# Determine files to validate -if [[ $# -gt 0 ]]; then - FILES=("$@") -else - mapfile -t FILES < <(find "$HISTORY_DIR" -name "*.md" -not -name "README.md" -not -name "TEMPLATE-*" 2>/dev/null || true) -fi - -if [[ ${#FILES[@]} -eq 0 ]]; then - echo "ℹ️ No history documents found to validate." - exit 0 -fi - -for f in "${FILES[@]}"; do - validate_file "$f" -done - -if [[ "$ERRORS" -gt 0 ]]; then - echo "" - echo "Found $ERRORS validation error(s)." - exit 1 -else - echo "✅ All history documents are valid." -fi diff --git a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/validate-numbering.sh b/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/validate-numbering.sh deleted file mode 100644 index 00c2a506..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/.scaffold-cache/scripts/validate-numbering.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/validate-numbering.sh -# Validates the sequential numbering of history documents against .index.json. -# -# Usage: -# ./scripts/validate-numbering.sh - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -HISTORY_DIR="$REPO_ROOT/docs/history" -INDEX_FILE="$HISTORY_DIR/.index.json" - -ERRORS=0 - -if [[ ! -f "$INDEX_FILE" ]]; then - echo "ℹ️ No .index.json found at $INDEX_FILE — skipping numbering validation." - exit 0 -fi - -# Check for duplicate sequence numbers per type -for subdir in implementations bug-fixes features migrations; do - case "$subdir" in - implementations) TYPE="implementation" ;; - bug-fixes) TYPE="bugfix" ;; - features) TYPE="feature" ;; - migrations) TYPE="migration" ;; - esac - - DIR="$HISTORY_DIR/$subdir" - if [[ ! -d "$DIR" ]]; then - continue - fi - - declare -A seen_numbers=() - - while IFS= read -r -d '' file; do - base="$(basename "$file")" - # Skip templates and READMEs - if [[ "$base" == TEMPLATE-* || "$base" == README.md ]]; then - continue - fi - # Extract leading 4-digit number - if [[ "$base" =~ ^([0-9]{4})- ]]; then - num="${BASH_REMATCH[1]}" - if [[ -n "${seen_numbers[$num]+x}" ]]; then - echo "❌ Duplicate number $num in $subdir/:" - echo " ${seen_numbers[$num]}" - echo " $base" - ERRORS=$((ERRORS + 1)) - else - seen_numbers[$num]="$base" - fi - fi - done < <(find "$DIR" -maxdepth 1 -name "*.md" -print0 2>/dev/null || true) - - unset seen_numbers -done - -if [[ "$ERRORS" -gt 0 ]]; then - echo "" - echo "Found $ERRORS numbering error(s)." - exit 1 -else - echo "✅ Sequential numbering is valid." -fi diff --git a/.claude/worktrees/focused-colden/.agentkit/logs/usage-2026-03-16.jsonl b/.claude/worktrees/focused-colden/.agentkit/logs/usage-2026-03-16.jsonl deleted file mode 100644 index 1406244c..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/logs/usage-2026-03-16.jsonl +++ /dev/null @@ -1,8 +0,0 @@ -{ - "timestamp": "2026-03-16T21:11:08.000Z", - "event": "session_start", - "sessionId": "ee01d53c-5eba-4fc9-9de2-73b21ff7a6b9", - "user": "6d0e0d6bc477", - "branch": "claude/focused-colden", - "cwd": "C:\\Users\\smitj\\repos\\agentkit-forge\\.claude\\worktrees\\focused-colden" -} diff --git a/.claude/worktrees/focused-colden/.agentkit/logs/usage-2026-03-17.jsonl b/.claude/worktrees/focused-colden/.agentkit/logs/usage-2026-03-17.jsonl deleted file mode 100644 index 14ae0190..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/logs/usage-2026-03-17.jsonl +++ /dev/null @@ -1,24 +0,0 @@ -{ - "timestamp": "2026-03-17T02:10:54.000Z", - "event": "session_start", - "sessionId": "ee01d53c-5eba-4fc9-9de2-73b21ff7a6b9", - "user": "6d0e0d6bc477", - "branch": "claude/focused-colden", - "cwd": "C:\\Users\\smitj\\repos\\agentkit-forge\\.claude\\worktrees\\focused-colden" -} -{ - "timestamp": "2026-03-17T03:55:20.000Z", - "event": "session_start", - "sessionId": "ee01d53c-5eba-4fc9-9de2-73b21ff7a6b9", - "user": "6d0e0d6bc477", - "branch": "claude/focused-colden", - "cwd": "C:\\Users\\smitj\\repos\\agentkit-forge\\.claude\\worktrees\\focused-colden" -} -{ - "timestamp": "2026-03-17T06:54:30.000Z", - "event": "session_start", - "sessionId": "ee01d53c-5eba-4fc9-9de2-73b21ff7a6b9", - "user": "6d0e0d6bc477", - "branch": "claude/focused-colden", - "cwd": "C:\\Users\\smitj\\repos\\agentkit-forge\\.claude\\worktrees\\focused-colden" -} diff --git a/.claude/worktrees/focused-colden/.agentkit/package-lock.json b/.claude/worktrees/focused-colden/.agentkit/package-lock.json deleted file mode 100644 index 0ecd531d..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/package-lock.json +++ /dev/null @@ -1,2764 +0,0 @@ -{ - "name": "agentkit-forge-runtime", - "version": "3.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "agentkit-forge-runtime", - "version": "3.1.0", - "dependencies": { - "@clack/prompts": "^1.0.1", - "js-yaml": "^4.1.0" - }, - "devDependencies": { - "markdownlint-cli2": "^0.18.1", - "prettier": "^3.5.3", - "vitest": "^4.0.18" - }, - "engines": { - "node": ">=22.0.0" - } - }, - "node_modules/@clack/core": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.0.1.tgz", - "integrity": "sha512-WKeyK3NOBwDOzagPR5H08rFk9D/WuN705yEbuZvKqlkmoLM2woKtXb10OO2k1NoSU4SFG947i2/SCYh+2u5e4g==", - "license": "MIT", - "dependencies": { - "picocolors": "^1.0.0", - "sisteransi": "^1.0.5" - } - }, - "node_modules/@clack/prompts": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.0.1.tgz", - "integrity": "sha512-/42G73JkuYdyWZ6m8d/CJtBrGl1Hegyc7Fy78m5Ob+jF85TOUmLR5XLce/U3LxYAw0kJ8CT5aI99RIvPHcGp/Q==", - "license": "MIT", - "dependencies": { - "@clack/core": "1.0.1", - "picocolors": "^1.0.0", - "sisteransi": "^1.0.5" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/chai": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/katex": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz", - "integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "4.0.18", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "4.0.18", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chai": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decode-named-character-reference": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", - "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", - "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/katex": { - "version": "0.16.33", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.33.tgz", - "integrity": "sha512-q3N5u+1sY9Bu7T4nlXoiRBXWfwSefNGoKeOwekV+gw0cAXQlz2Ww6BLcmBxVDeXBMUDQv6fK5bcNaJLxob3ZQA==", - "dev": true, - "funding": [ - "https://opencollective.com/katex", - "https://github.com/sponsors/katex" - ], - "license": "MIT", - "dependencies": { - "commander": "^8.3.0" - }, - "bin": { - "katex": "cli.js" - } - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/markdownlint": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.38.0.tgz", - "integrity": "sha512-xaSxkaU7wY/0852zGApM8LdlIfGCW8ETZ0Rr62IQtAnUMlMuifsg09vWJcNYeL4f0anvr8Vo4ZQar8jGpV0btQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark": "4.0.2", - "micromark-core-commonmark": "2.0.3", - "micromark-extension-directive": "4.0.0", - "micromark-extension-gfm-autolink-literal": "2.1.0", - "micromark-extension-gfm-footnote": "2.1.0", - "micromark-extension-gfm-table": "2.1.1", - "micromark-extension-math": "3.1.0", - "micromark-util-types": "2.0.2" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/DavidAnson" - } - }, - "node_modules/markdownlint-cli2": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.18.1.tgz", - "integrity": "sha512-/4Osri9QFGCZOCTkfA8qJF+XGjKYERSHkXzxSyS1hd3ZERJGjvsUao2h4wdnvpHp6Tu2Jh/bPHM0FE9JJza6ng==", - "dev": true, - "license": "MIT", - "dependencies": { - "globby": "14.1.0", - "js-yaml": "4.1.0", - "jsonc-parser": "3.3.1", - "markdown-it": "14.1.0", - "markdownlint": "0.38.0", - "markdownlint-cli2-formatter-default": "0.0.5", - "micromatch": "4.0.8" - }, - "bin": { - "markdownlint-cli2": "markdownlint-cli2-bin.mjs" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/DavidAnson" - } - }, - "node_modules/markdownlint-cli2-formatter-default": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.5.tgz", - "integrity": "sha512-4XKTwQ5m1+Txo2kuQ3Jgpo/KmnG+X90dWt4acufg6HVGadTUG5hzHF/wssp9b5MBYOMCnZ9RMPaU//uHsszF8Q==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/DavidAnson" - }, - "peerDependencies": { - "markdownlint-cli2": ">=0.0.4" - } - }, - "node_modules/markdownlint-cli2/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-directive": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-4.0.0.tgz", - "integrity": "sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "parse-entities": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-math": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", - "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/katex": "^0.16.0", - "devlop": "^1.0.0", - "katex": "^0.16.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/sxzz", - "https://opencollective.com/debug" - ], - "license": "MIT" - }, - "node_modules/parse-entities": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prettier": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "license": "MIT" - }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyrainbow": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", - "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", - "magic-string": "^0.30.21", - "obug": "^2.1.1", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^3.10.0", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@opentelemetry/api": "^1.9.0", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser-playwright": { - "optional": true - }, - "@vitest/browser-preview": { - "optional": true - }, - "@vitest/browser-webdriverio": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - } - } -} diff --git a/.claude/worktrees/focused-colden/.agentkit/state/orchestrator.json.template b/.claude/worktrees/focused-colden/.agentkit/state/orchestrator.json.template deleted file mode 100644 index 076c20ed..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/state/orchestrator.json.template +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": "1.0.0", - "repo_id": "agentkit-forge", - "branch": "main", - "session_id": "", - "current_phase": 1, - "phase_name": "Discovery", - "last_phase_completed": 0, - "next_action": "Run /orchestrate to begin project assessment", - "team_progress": { - "team-backend": { "status": "idle", "notes": "" }, - "team-frontend": { "status": "idle", "notes": "" }, - "team-data": { "status": "idle", "notes": "" }, - "team-infra": { "status": "idle", "notes": "" }, - "team-devops": { "status": "idle", "notes": "" }, - "team-testing": { "status": "idle", "notes": "" }, - "team-security": { "status": "idle", "notes": "" }, - "team-docs": { "status": "idle", "notes": "" }, - "team-product": { "status": "idle", "notes": "" }, - "team-quality": { "status": "idle", "notes": "" } - }, - "todo_items": [], - "recent_results": [], - "completed": false -} diff --git a/.claude/worktrees/focused-colden/.agentkit/state/schema.json b/.claude/worktrees/focused-colden/.agentkit/state/schema.json deleted file mode 100644 index 7bfdc405..00000000 --- a/.claude/worktrees/focused-colden/.agentkit/state/schema.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "AgentKit Forge Orchestrator State", - "description": "Schema for the orchestrator state file managed by /orchestrate", - "type": "object", - "required": ["schema_version", "repo_id", "current_phase", "phase_name", "team_progress"], - "properties": { - "schema_version": { - "type": "string", - "const": "1.0.0", - "description": "Schema version for forward compatibility" - }, - "repo_id": { - "type": "string", - "description": "Repository identifier (from .agentkit-repo)" - }, - "branch": { - "type": "string", - "description": "Current git branch" - }, - "session_id": { - "type": "string", - "description": "Current session identifier" - }, - "current_phase": { - "type": "integer", - "minimum": 1, - "maximum": 5, - "description": "Current lifecycle phase (1-5)" - }, - "phase_name": { - "type": "string", - "enum": ["Discovery", "Planning", "Implementation", "Validation", "Ship"], - "description": "Human-readable phase name" - }, - "last_phase_completed": { - "type": "integer", - "minimum": 0, - "maximum": 5, - "description": "Last fully completed phase (0 = none)" - }, - "next_action": { - "type": "string", - "description": "Recommended next action" - }, - "team_progress": { - "type": "object", - "description": "Per-team status tracking", - "patternProperties": { - "^team-": { - "type": "object", - "required": ["status"], - "properties": { - "status": { - "type": "string", - "enum": ["idle", "in_progress", "blocked", "done"] - }, - "notes": { - "type": "string" - }, - "last_updated": { - "type": "string", - "format": "date-time" - }, - "assigned_to": { - "type": "string" - } - } - } - } - }, - "todo_items": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "title", "status"], - "properties": { - "id": { "type": "string" }, - "title": { "type": "string" }, - "status": { - "type": "string", - "enum": ["pending", "in_progress", "done", "blocked"] - }, - "team": { "type": "string" }, - "priority": { - "type": "string", - "enum": ["critical", "high", "medium", "low"] - } - } - } - }, - "recent_results": { - "type": "array", - "items": { - "type": "object", - "properties": { - "timestamp": { "type": "string", "format": "date-time" }, - "action": { "type": "string" }, - "result": { "type": "string" }, - "team": { "type": "string" } - } - } - }, - "completed": { - "type": "boolean", - "description": "Whether all phases are complete" - }, - "last_healthcheck": { - "type": "string", - "format": "date-time", - "description": "Timestamp of last healthcheck run" - }, - "health_status": { - "type": "string", - "enum": ["HEALTHY", "UNHEALTHY"], - "description": "Overall health status from last healthcheck" - }, - "session_metrics": { - "type": "object", - "description": "Cost tracking session metrics", - "properties": { - "current_session_id": { - "type": "string", - "description": "Active session ID for cost tracking" - }, - "total_sessions": { - "type": "integer", - "description": "Total sessions recorded" - }, - "last_session_end": { - "type": "string", - "format": "date-time", - "description": "When the last session ended" - } - } - } - } -} diff --git a/.claude/worktrees/focused-colden/.claude/settings.local.json b/.claude/worktrees/focused-colden/.claude/settings.local.json deleted file mode 100644 index db9b92be..00000000 --- a/.claude/worktrees/focused-colden/.claude/settings.local.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(git ls-remote https://github.com/actions/checkout.git refs/tags/v4.2.2)", - "Bash(git ls-remote https://github.com/anthropics/claude-code-action.git refs/tags/v1)", - "Bash(git ls-remote https://github.com/actions/github-script.git refs/tags/v7)", - "Bash(pnpm -C .agentkit test)", - "Bash(pnpm -C .agentkit vitest run src/__tests__/prettier.test.mjs src/__tests__/expansion-analyzer.test.mjs src/__tests__/budget-guard.test.mjs src/__tests__/feature-manager.test.mjs src/__tests__/backlog-store.test.mjs src/__tests__/discover.test.mjs)", - "Bash(pnpm -C .agentkit agentkit:sync)", - "Bash(grep -rn 'uses:' .agentkit/templates/github/workflows/*.yml)", - "Bash(grep -rn 'uses:.*@[a-f0-9]\\\\{40\\\\}' .agentkit/templates/github/workflows/*.yml)", - "Bash(grep -rn 'uses:.*@v[0-9]' .agentkit/templates/github/workflows/*.yml)", - "Bash(git ls-remote https://github.com/pnpm/action-setup.git refs/tags/v4.2.0)", - "Bash(git ls-remote https://github.com/actions/setup-node.git refs/tags/v4.4.0)", - "Bash(git ls-remote https://github.com/actions/setup-python.git refs/tags/v5.6.0)", - "Bash(git ls-remote https://github.com/pnpm/action-setup.git refs/tags/v4)", - "Bash(git checkout -- AGENT_TEAMS.md .clinerules/git-workflow.md)", - "Bash(for branch in dev chore/merge-all-open-branches ci/enforce-sha-pinning-and-templates claude/fix-full-tier-black-elements-gkgln docs/consolidate-pending-items docs/restructure-agentkit-docs fix/review-findings-round1 fix/template-numbered-paths refactor/remove-team-prefix)", - "Bash(do echo \"=== $branch ===\")", - "Bash(git checkout -- .)", - "Bash(git pull)", - "Bash(git cherry-pick 097e0cc --no-edit)", - "Bash(git remote prune origin)", - "Bash(pnpm -C /c/Users/smitj/repos/retort/.agentkit test)", - "Bash(gh repo list JustAGhosT --limit 50)", - "Bash(gh label create \"priority:P3\" --repo phoenixvc/cognitive-mesh --color \"0E8A16\" --description \"Priority 3 - Nice to have\")", - "Bash(git add -A)", - "Bash(gh label list --repo phoenixvc/cognitive-mesh --json name,description,color --limit 100)", - "Bash(gh label list --repo JustAGhosT/retort --json name,description,color --limit 100)", - "mcp__filesystem__read_multiple_files", - "Bash(grep -E \"\\\\.\\(yml|yaml|json|ts|js\\)$\")", - "Bash(gh label:*)", - "Bash(git add:*)", - "Bash(gh api:*)", - "WebSearch", - "WebFetch(domain:buildermethods.com)", - "WebFetch(domain:github.com)" - ] - } -} diff --git a/.claude/worktrees/focused-colden/.claude/state/events.log b/.claude/worktrees/focused-colden/.claude/state/events.log deleted file mode 100644 index 48ed9c92..00000000 --- a/.claude/worktrees/focused-colden/.claude/state/events.log +++ /dev/null @@ -1,105 +0,0 @@ -{"timestamp":"2026-02-26T17:31:21.524Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":92388},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1253},{"step":"build","status":"FAIL","durationMs":2299}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T17:32:22.387Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":57877},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1756}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T17:40:11.462Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":300556},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":12726},{"step":"build","status":"FAIL","durationMs":4619}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T17:44:14.114Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":236951},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":2693}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T17:57:01.313Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":54449},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1488},{"step":"build","status":"FAIL","durationMs":1535}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T17:57:39.437Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":35135},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1489}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T18:00:44.882Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":18855},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":599},{"step":"build","status":"FAIL","durationMs":755}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T18:00:57.395Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":11525},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":587}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T22:50:22.150Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":43407},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1370},{"step":"build","status":"FAIL","durationMs":1982}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T22:50:57.402Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":34361},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":485}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T22:59:44.909Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":72662},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1055},{"step":"build","status":"FAIL","durationMs":1767}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T23:00:12.840Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":26869},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":598}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T23:27:21.525Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":54059},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1538},{"step":"build","status":"FAIL","durationMs":2558}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T23:27:55.191Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":31691},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1126}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T23:47:11.830Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":54257},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":2146},{"step":"build","status":"FAIL","durationMs":3389}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T23:47:43.881Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":30944},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":619}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-28T15:41:34.550Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":118},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":15063},{"step":"build","status":"FAIL","durationMs":4029}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-28T15:41:38.884Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":29},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":3080}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-01T04:51:06.914Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":43},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":9}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-01T04:51:08.526Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":19},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-01T04:54:06.715Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":53},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":28}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-01T04:54:08.867Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":75},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-01T05:10:28.549Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":106},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":22},{"step":"build","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-01T05:10:30.610Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":19},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T14:57:27.967Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":158},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":7}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T14:57:29.567Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":22},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T15:01:59.380Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":30},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T15:02:00.404Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":20},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:05:27.157Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":20},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1913},{"step":"build","status":"FAIL","durationMs":3071}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:05:57.398Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":22},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":8}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:05:59.276Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":16},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:14:48.130Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":26},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":8},{"step":"build","status":"FAIL","durationMs":153}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:14:55.776Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":438},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":35}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:16:15.728Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":46},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":101184},{"step":"build","status":"FAIL","durationMs":9256}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:19:12.380Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":29},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":7},{"step":"build","status":"FAIL","durationMs":11}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:19:14.119Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":21},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:25:42.885Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":27},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":8},{"step":"build","status":"FAIL","durationMs":160}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:25:46.626Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":181},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":26}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:27:05.654Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":18},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"PASS","durationMs":95529},{"step":"build","status":"PASS","durationMs":7674}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:32:51.735Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":252},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":75},{"step":"build","status":"FAIL","durationMs":42}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:32:55.553Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":192},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":22}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:34:25.998Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":23},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":120925},{"step":"build","status":"PASS","durationMs":7972}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:36:16.808Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":109},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":10},{"step":"build","status":"FAIL","durationMs":9}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:36:19.087Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":51},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":8}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:39:23.323Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":269},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":37},{"step":"build","status":"FAIL","durationMs":46}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:39:26.597Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":142},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":27}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:41:21.411Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":262},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":138},{"step":"build","status":"FAIL","durationMs":74}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:41:25.946Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":179},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":68}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:42:47.046Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":16},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":92882},{"step":"build","status":"PASS","durationMs":10552}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:43:49.613Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":250},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":81},{"step":"build","status":"FAIL","durationMs":105}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:43:53.957Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":444},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":19}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T18:57:58.751Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":64},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":7},{"step":"build","status":"FAIL","durationMs":7}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T18:58:00.655Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":40},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":8}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T18:58:46.509Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":24},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":60941},{"step":"build","status":"PASS","durationMs":3076}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T19:00:40.415Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":83},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":97},{"step":"build","status":"FAIL","durationMs":171}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T19:00:50.568Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":562},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":58}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T19:15:27.769Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":48},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":7}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T19:15:29.811Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":19},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T19:18:40.784Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":56},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":8}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T19:18:42.732Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":21},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T19:36:57.250Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":25},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":9}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T19:36:58.289Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":17},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:14:44.559Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":45},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":11}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:14:46.176Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":40},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:20:45.419Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":72},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4},{"step":"build","status":"FAIL","durationMs":8}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:20:46.671Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":17},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:21:33.859Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":21},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":9}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:21:35.551Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":24},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:22:37.730Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":36},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":7}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:22:39.534Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":16},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:23:58.276Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":56},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":9}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:23:59.332Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":17},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:27:17.403Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":231},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":17},{"step":"build","status":"FAIL","durationMs":15}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:27:19.502Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":75},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":14}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-04T10:20:44.292Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":15},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":3},{"step":"build","status":"FAIL","durationMs":3}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T11:40:03.234Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":12},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":3},{"step":"build","status":"FAIL","durationMs":3}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T11:40:14.944Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":24},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T11:40:16.696Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":20},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-04T13:37:02.860Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":37},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T13:37:04.586Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":18},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-04T14:57:52.992Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"PASS","durationMs":12865},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-04T16:26:18.432Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"PASS","durationMs":8533},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":3},{"step":"build","status":"FAIL","durationMs":3}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T18:50:47.548Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":10054},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4},{"step":"build","status":"FAIL","durationMs":3}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T18:53:17.017Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":9339},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":3},{"step":"build","status":"FAIL","durationMs":3}]}],"flags":{"fix":false,"fast":false,"stack":null}} -[2026-03-11T03:17:17.000Z] [HANDOFF] [ORCHESTRATOR] Session complete. Done: 6 items. Blockers: 0. Next: "Start Phase 1 cost-provider-schema on feat/cost-provider-schema branch". -[2026-03-11T17:00:03Z] [ORCHESTRATE] [W1] Phase 5 Ship. Tests: 110/110. Sync: clean. Branch: fix/ci-remediation. Commits ahead: 51. Ready for PR to main. -[2026-03-15T07:06:00Z] [ORCHESTRATE] [W1] Phase 5 Ship. Branch: feat/source-code-conventions. Build: pass. agentkit:check fails (Duplicate export auditUnresolvedPlaceholders). orchestrator.test.mjs: 22 failed. Health: at_risk. Next: fix test/check then PR. -[2026-03-15T07:13:00Z] [ORCHESTRATE] [W1] Phase 5 Ship. Branch: feat/source-code-conventions. Build: pass. No lock. Validation: build re-run PASS. Tests running in background. Health: at_risk (check CLI + orchestrator tests). Next: fix then PR to main. -[2026-03-15T07:16:00Z] [ORCHESTRATE] [W1] Fixed check.mjs duplicate export (auditUnresolvedPlaceholders). agentkit:check runs; format PASS. NB added to CLAUDE.md: this repo may modify .agentkit files. Next: orchestrator.test.mjs fixes then PR. -[2026-03-15T09:25:00Z] [ORCHESTRATE] [W1] Phase 5 Ship. Fixed orchestrator.test.mjs: unique temp dir per test (TEST_BASE/run-id), removed afterEach rmSync. 39/39 orchestrator tests pass. Health: healthy. Next: Create PR to main. -[2026-03-15T11:30:00Z] [ORCHESTRATE] [W1] Phase 2 Planning. Scope: all P0 and P1. Discovery: AGENT_TEAMS.md present; CI workflows present (ci.yml, branch-protection, etc.). Healthcheck: UNHEALTHY (typecheck/test/build fail in agentkit:check). Created 7 task files in .claude/state/tasks/ for P0 (2) and P1 (5). Next: teams implement then Phase 4 Validation. -[2026-03-15T12:05:00Z] [ORCHESTRATE] [W1] Assess-only run. Branch: fix/generated-files-and-conflict-markers. Phase 2. Tasks: 7 submitted, 0 in progress, 0 completed. Health: UNHEALTHY. Check: format PASS; typecheck/test/build FAIL. Next: run /team-infra, /team-quality, /team-backend, /team-data to implement tasks; then re-run /orchestrate for Validation. -[2026-03-15T12:15:00Z] [TEAM] [backend] Completed 2 items. Changes: 1 file (docs/api/07_framework-api-conventions.md). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T12:25:00Z] [TEAM] [infra] Rejected task-p0-ci-pipeline (out of scope; suggested team-devops). Completed 1 item (task-p1-staging-env). Changes: infra/README.md, docker-compose.yml. Tests: 0 added, 0 modified. Gate: N/A. -[2026-03-15T12:35:00Z] [TEAM] [data] Completed 2 items. Changes: db/README.md, migrations/README.md. Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T12:45:00Z] [TEAM] [product] Completed 1 item. Changes: docs/product/prd/README.md (PRD index). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T13:00:00Z] [TEAM] [product] Completed 1 item. Changes: docs/product/prd/README.md (P1 backlog section). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T13:10:00Z] [ORCHESTRATE] [W1] Assess. Branch: fix/generated-files-and-conflict-markers. Phase 2. Tasks: 5 completed, 1 rejected (P0 CI → devops), 1 submitted (P0 test-framework). Health: UNHEALTHY (format/typecheck/test/build FAIL). Next: /team-quality for task-p0-test-framework; reassign P0 CI to DevOps; then Phase 4 Validation. -[2026-03-15T13:15:00Z] [TEAM] [product] Completed 1 item. Changes: docs/product/prd/README.md (link to PLAN-gh371). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T13:20:00Z] [ORCHESTRATE] [W1] Assess-only. Branch: fix/generated-files-and-conflict-markers. Phase 2. Tasks: 5 completed, 1 rejected, 1 submitted (task-p0-test-framework). Health: UNHEALTHY. Next: /team-quality; reassign P0 CI to DevOps; Phase 4 Validation. -[2026-03-15T13:25:00Z] [TEAM] [product] Completed 1 item. Changes: docs/product/prd/README.md (GH#328 plan note, link to implementation plans). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T13:30:00Z] [TEAM] [product] Completed 1 item. Changes: docs/product/prd/README.md (next PRD number 008 in Creating a New PRD). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T13:35:00Z] [TEAM] [product] No delegated tasks; no additional backlog items completed (P1/P2 require plans or implementation). Scope: docs/product/**, docs/prd/**. -[2026-03-15T13:40:00Z] [TEAM] [docs] Completed 1 item. Changes: CONTRIBUTING.md (link to docs hub in Discovery phase). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-17T04:35:00Z] [HANDOFF] [ORCHESTRATOR] Session complete. Done: 6 items (findings report, ADR-10, adoption roadmap, competitive landscape, PR review responses, merge conflict resolution). Blockers: 0. Next: "Review and merge PR #428, then begin Phase 1 implementation of ADR-10 (.agents/ sync target)". diff --git a/.claude/worktrees/focused-colden/.claude/state/orchestrator.json b/.claude/worktrees/focused-colden/.claude/state/orchestrator.json deleted file mode 100644 index ad4dd611..00000000 --- a/.claude/worktrees/focused-colden/.claude/state/orchestrator.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "schema_version": "1.0.0", - "repo_id": "JustAGhosT/retort", - "branch": "fix/generated-files-and-conflict-markers", - "session_id": "2026-03-15", - "current_phase": 2, - "phase_name": "Planning", - "last_phase_completed": 1, - "next_action": "Complete task-p0-test-framework (team-quality). Reassign P0 CI to DevOps. Then run Phase 4 Validation.", - "lastHealthcheck": "2026-03-15T13:10:00Z", - "healthStatus": "unhealthy", - "healthDetails": { - "dependencies": "pass", - "format": "FAIL", - "lint": "SKIP (eslint not found)", - "typecheck": "FAIL", - "tests": "FAIL", - "build": "FAIL", - "syncDrift": "not run" - }, - "taskSummary": { - "total": 7, - "completed": 5, - "rejected": 1, - "submitted": 1 - }, - "backlogSnapshot": [ - {"priority": "P0", "team": "T4-Infrastructure", "task": "Configure CI pipeline for main branch"}, - {"priority": "P0", "team": "T10-Quality", "task": "Set up test framework and coverage thresholds"}, - {"priority": "P1", "team": "T1-Backend", "task": "Define core API route structure"}, - {"priority": "P1", "team": "T3-Data", "task": "Design initial database schema"}, - {"priority": "P1", "team": "T1-Backend", "task": "Implement health check endpoint"}, - {"priority": "P1", "team": "T3-Data", "task": "Create migration tooling setup"}, - {"priority": "P1", "team": "T4-Infrastructure", "task": "Set up staging environment"} - ], - "team_progress": { - "backend": { "status": "idle", "notes": "Completed task-p1-api-routes, task-p1-health-check (docs/api/07_framework-api-conventions.md)." }, - "frontend": { "status": "idle", "notes": "start TUI component merged and tested" }, - "data": { "status": "idle", "notes": "Completed task-p1-db-schema, task-p1-migration-tooling (db/README.md, migrations/README.md; repo has no DB, adopters own schema and migrations)." }, - "infra": { "status": "idle", "notes": "Rejected P0 CI (DevOps scope). Completed P1 staging: infra/README.md, docker-compose.yml." }, - "devops": { "status": "idle", "notes": "Configurable package manager implemented" }, - "testing": { "status": "complete", "notes": "110 tests green, ConversationFlow flakiness fixed" }, - "security": { "status": "idle", "notes": "" }, - "docs": { "status": "idle", "notes": "CONTRIBUTING.md: link to docs hub (docs/README.md) in Discovery phase." }, - "product": { "status": "idle", "notes": "PRD index, P1 backlog, PLAN-gh371 link, docs/planning link, next PRD number (008) in Creating a New PRD." }, - "quality": { "status": "complete", "notes": "Review findings addressed, sync drift clean" } - }, - "todo_items": [], - "recent_results": [ - { - "date": "2026-03-11", - "action": "Fixed ConversationFlow test flakiness (ink-select-input event loop yields)", - "status": "done" - }, - { - "date": "2026-03-11", - "action": "Added pnpm-workspace.yaml packages field", - "status": "done" - }, - { - "date": "2026-03-11", - "action": "Regenerated lockfile after version pinning", - "status": "done" - }, - { - "date": "2026-03-11", - "action": "Verified sync drift clean (533 files, 0 changes)", - "status": "done" - } - ], - "completed": false -} diff --git a/.claude/worktrees/focused-colden/.claude/state/orchestrator.json.template b/.claude/worktrees/focused-colden/.claude/state/orchestrator.json.template deleted file mode 100644 index 076c20ed..00000000 --- a/.claude/worktrees/focused-colden/.claude/state/orchestrator.json.template +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": "1.0.0", - "repo_id": "agentkit-forge", - "branch": "main", - "session_id": "", - "current_phase": 1, - "phase_name": "Discovery", - "last_phase_completed": 0, - "next_action": "Run /orchestrate to begin project assessment", - "team_progress": { - "team-backend": { "status": "idle", "notes": "" }, - "team-frontend": { "status": "idle", "notes": "" }, - "team-data": { "status": "idle", "notes": "" }, - "team-infra": { "status": "idle", "notes": "" }, - "team-devops": { "status": "idle", "notes": "" }, - "team-testing": { "status": "idle", "notes": "" }, - "team-security": { "status": "idle", "notes": "" }, - "team-docs": { "status": "idle", "notes": "" }, - "team-product": { "status": "idle", "notes": "" }, - "team-quality": { "status": "idle", "notes": "" } - }, - "todo_items": [], - "recent_results": [], - "completed": false -} diff --git a/.claude/worktrees/focused-colden/.claude/state/schema.json b/.claude/worktrees/focused-colden/.claude/state/schema.json deleted file mode 100644 index 5206822c..00000000 --- a/.claude/worktrees/focused-colden/.claude/state/schema.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Retort Orchestrator State", - "description": "Schema for the orchestrator state file managed by /orchestrate", - "type": "object", - "required": ["schema_version", "repo_id", "current_phase", "phase_name", "team_progress"], - "properties": { - "schema_version": { - "type": "string", - "const": "1.0.0", - "description": "Schema version for forward compatibility" - }, - "repo_id": { - "type": "string", - "description": "Repository identifier (from .agentkit-repo)" - }, - "branch": { - "type": "string", - "description": "Current git branch" - }, - "session_id": { - "type": "string", - "description": "Current session identifier" - }, - "current_phase": { - "type": "integer", - "minimum": 1, - "maximum": 5, - "description": "Current lifecycle phase (1-5)" - }, - "phase_name": { - "type": "string", - "enum": ["Discovery", "Planning", "Implementation", "Validation", "Ship"], - "description": "Human-readable phase name" - }, - "last_phase_completed": { - "type": "integer", - "minimum": 0, - "maximum": 5, - "description": "Last fully completed phase (0 = none)" - }, - "next_action": { - "type": "string", - "description": "Recommended next action" - }, - "team_progress": { - "type": "object", - "description": "Per-team status tracking", - "patternProperties": { - "^team-": { - "type": "object", - "required": ["status"], - "properties": { - "status": { - "type": "string", - "enum": ["idle", "in_progress", "blocked", "done"] - }, - "notes": { - "type": "string" - }, - "last_updated": { - "type": "string", - "format": "date-time" - }, - "assigned_to": { - "type": "string" - } - } - } - } - }, - "todo_items": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "title", "status"], - "properties": { - "id": { "type": "string" }, - "title": { "type": "string" }, - "status": { - "type": "string", - "enum": ["pending", "in_progress", "done", "blocked"] - }, - "team": { "type": "string" }, - "priority": { - "type": "string", - "enum": ["critical", "high", "medium", "low"] - } - } - } - }, - "recent_results": { - "type": "array", - "items": { - "type": "object", - "properties": { - "timestamp": { "type": "string", "format": "date-time" }, - "action": { "type": "string" }, - "result": { "type": "string" }, - "team": { "type": "string" } - } - } - }, - "completed": { - "type": "boolean", - "description": "Whether all phases are complete" - }, - "last_healthcheck": { - "type": "string", - "format": "date-time", - "description": "Timestamp of last healthcheck run" - }, - "health_status": { - "type": "string", - "enum": ["HEALTHY", "UNHEALTHY"], - "description": "Overall health status from last healthcheck" - }, - "session_metrics": { - "type": "object", - "description": "Cost tracking session metrics", - "properties": { - "current_session_id": { - "type": "string", - "description": "Active session ID for cost tracking" - }, - "total_sessions": { - "type": "integer", - "description": "Total sessions recorded" - }, - "last_session_end": { - "type": "string", - "format": "date-time", - "description": "When the last session ended" - } - } - } - } -} diff --git a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p0-ci-pipeline.json b/.claude/worktrees/focused-colden/.claude/state/tasks/task-p0-ci-pipeline.json deleted file mode 100644 index e656cf8b..00000000 --- a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p0-ci-pipeline.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "id": "task-p0-ci-pipeline", - "type": "implement", - "status": "rejected", - "priority": "P0", - "delegator": "orchestrator", - "assignees": ["team-infra"], - "title": "Configure CI pipeline for main branch", - "description": "GitHub Actions workflow; scope: branch-protection, drift check, quality gates on main. Ensure required status checks align with ci.yml, branch-protection.yml, and drift/sync validation.", - "acceptanceCriteria": [ - "Workflow runs on push/PR to main (and dev per existing)", - "Drift check (sync then git diff) runs and is required for main", - "Quality gates (test, validate) are required; branch protection documented or enforced" - ], - "scope": [".github/workflows/**", "docs/operations/**"], - "backlogItemId": "P0-T4-CI-pipeline", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P0: Configure CI pipeline for main. See AGENT_BACKLOG.md Active Sprint." }, - { "role": "executor", "from": "infra", "timestamp": "2026-03-15T12:25:00Z", "content": "Rejected: task scope is .github/workflows/** and docs/operations/**, which is DevOps (CI/CD, pipelines), not Infra (IaC, terraform, bicep, pulumi). Suggested team: team-devops." } - ], - "artifacts": [] -} diff --git a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p0-test-framework.json b/.claude/worktrees/focused-colden/.claude/state/tasks/task-p0-test-framework.json deleted file mode 100644 index e69de29b..00000000 diff --git a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-api-routes.json b/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-api-routes.json deleted file mode 100644 index b76ef61f..00000000 --- a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-api-routes.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "task-p1-api-routes", - "type": "implement", - "status": "completed", - "priority": "P1", - "delegator": "orchestrator", - "assignees": ["team-backend"], - "title": "Define core API route structure", - "description": "REST endpoints for v1. Define route layout and conventions for the project (or document that this repo is framework-only and adopters define routes).", - "acceptanceCriteria": [ - "API route structure documented or implemented per project conventions", - "REST v1 layout clear for downstream adopters or for this repo if applicable" - ], - "scope": ["apps/api/**", "services/**", "docs/api/**"], - "backlogItemId": "P1-T1-api-routes", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P1: Define core API route structure. See AGENT_BACKLOG.md." }, - { "role": "executor", "from": "backend", "timestamp": "2026-03-15T12:15:00Z", "content": "Completed. Repo is framework-only (no apps/api or services). Added docs/api/07_framework-api-conventions.md documenting recommended route structure (base /api, url-segment versioning, envelope, cursor pagination) for adopters." } - ], - "artifacts": [ - { "type": "files-changed", "paths": ["docs/api/07_framework-api-conventions.md"] }, - { "type": "test-results", "passed": 0, "failed": 0, "testsAdded": 0, "testsModified": 0 } - ] -} diff --git a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-db-schema.json b/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-db-schema.json deleted file mode 100644 index b52354a2..00000000 --- a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-db-schema.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "id": "task-p1-db-schema", - "type": "implement", - "status": "completed", - "priority": "P1", - "delegator": "orchestrator", - "assignees": ["team-data"], - "title": "Design initial database schema", - "description": "Depends on T1 API design. Design initial schema for the project (or document that this repo has no DB and adopters own schema).", - "acceptanceCriteria": [ - "Schema design or decision documented", - "Dependencies on API design acknowledged" - ], - "scope": ["db/**", "migrations/**", "prisma/**", "docs/architecture/**"], - "dependsOn": ["task-p1-api-routes"], - "backlogItemId": "P1-T3-db-schema", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P1: Design initial database schema. Depends on T1." }, - { "role": "executor", "from": "data", "timestamp": "2026-03-15T12:35:00Z", "content": "Completed. Repo has no database (CLAUDE.md: Database none, ORM none). Added db/README.md documenting that adopters own schema and referencing API conventions; dependency on API design acknowledged." } - ], - "artifacts": [ - { "type": "files-changed", "paths": ["db/README.md"] }, - { "type": "test-results", "passed": 0, "failed": 0, "testsAdded": 0, "testsModified": 0 } - ] -} diff --git a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-health-check.json b/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-health-check.json deleted file mode 100644 index 10b652ef..00000000 --- a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-health-check.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "task-p1-health-check", - "type": "implement", - "status": "completed", - "priority": "P1", - "delegator": "orchestrator", - "assignees": ["team-backend"], - "title": "Implement health check endpoint", - "description": "Implement /api/health (or equivalent) for the application.", - "acceptanceCriteria": [ - "Health check endpoint implemented and documented", - "Returns appropriate status for load balancers or readiness probes" - ], - "scope": ["apps/api/**", "services/**", "docs/api/**"], - "backlogItemId": "P1-T1-health-check", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P1: Implement health check endpoint. See Backlog." }, - { "role": "executor", "from": "backend", "timestamp": "2026-03-15T12:15:00Z", "content": "Completed. No application server in this repo (framework-only). Documented health check convention in docs/api/07_framework-api-conventions.md: GET /api/health or GET /health, 200 + { status: ok } for adopters." } - ], - "artifacts": [ - { "type": "files-changed", "paths": ["docs/api/07_framework-api-conventions.md"] }, - { "type": "test-results", "passed": 0, "failed": 0, "testsAdded": 0, "testsModified": 0 } - ] -} diff --git a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-migration-tooling.json b/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-migration-tooling.json deleted file mode 100644 index 4e72185f..00000000 --- a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-migration-tooling.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "task-p1-migration-tooling", - "type": "implement", - "status": "completed", - "priority": "P1", - "delegator": "orchestrator", - "assignees": ["team-data"], - "title": "Create migration tooling setup", - "description": "Prisma or Drizzle (or document choice). Set up migration tooling for the project.", - "acceptanceCriteria": [ - "Migration tooling chosen and documented or implemented", - "Basic migration workflow documented" - ], - "scope": ["db/**", "migrations/**", "prisma/**", "package.json"], - "backlogItemId": "P1-T3-migration-tooling", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P1: Create migration tooling setup. See Backlog." }, - { "role": "executor", "from": "data", "timestamp": "2026-03-15T12:35:00Z", "content": "Completed. Repo has no DB. Added migrations/README.md documenting that adopters choose Prisma or Drizzle and documenting basic migration workflow (define schema, generate migration, run migrations)." } - ], - "artifacts": [ - { "type": "files-changed", "paths": ["migrations/README.md"] }, - { "type": "test-results", "passed": 0, "failed": 0, "testsAdded": 0, "testsModified": 0 } - ] -} diff --git a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-staging-env.json b/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-staging-env.json deleted file mode 100644 index 19f40686..00000000 --- a/.claude/worktrees/focused-colden/.claude/state/tasks/task-p1-staging-env.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "task-p1-staging-env", - "type": "implement", - "status": "completed", - "priority": "P1", - "delegator": "orchestrator", - "assignees": ["team-infra"], - "title": "Set up staging environment", - "description": "Docker Compose (or equivalent) for staging. Set up staging environment for the project.", - "acceptanceCriteria": [ - "Staging environment defined (e.g. docker-compose or IaC)", - "Documented how to run and deploy to staging" - ], - "scope": ["infra/**", "docker/**", "docker-compose*.yml", "docs/operations/**"], - "backlogItemId": "P1-T4-staging", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P1: Set up staging environment. See Backlog." }, - { "role": "executor", "from": "infra", "timestamp": "2026-03-15T12:25:00Z", "content": "Completed. Added infra/README.md (staging and local validation; adopters define their own staging). Added docker-compose.yml at repo root with profile 'sync' to run pnpm install + agentkit:sync in a container for staging-like validation." } - ], - "artifacts": [ - { "type": "files-changed", "paths": ["infra/README.md", "docker-compose.yml"] }, - { "type": "test-results", "passed": 0, "failed": 0, "testsAdded": 0, "testsModified": 0 } - ] -} diff --git a/.claude/worktrees/focused-colden/package-lock.json b/.claude/worktrees/focused-colden/package-lock.json deleted file mode 100644 index 24372cf6..00000000 --- a/.claude/worktrees/focused-colden/package-lock.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "retort-root", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "retort-root", - "dependencies": { - "js-yaml": "^4.1.1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - } - } -} diff --git a/.claude/worktrees/heuristic-mendel b/.claude/worktrees/heuristic-mendel deleted file mode 160000 index b65743f9..00000000 --- a/.claude/worktrees/heuristic-mendel +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b65743f9d6f48c99cdb078fce8bedf2d5d88b653 diff --git a/.claude/worktrees/tender-margulis/.agentkit/.manifest.json b/.claude/worktrees/tender-margulis/.agentkit/.manifest.json deleted file mode 100644 index f044e15e..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.manifest.json +++ /dev/null @@ -1,1873 +0,0 @@ -{ - "generatedAt": "2026-03-17T07:03:33.588Z", - "version": "3.1.0", - "repoName": "agentkit-forge", - "files": { - ".agentkit/state/orchestrator.json.template": { - "hash": "b70e87b7211b" - }, - ".agents/skills/analyze-agents/SKILL.md": { - "hash": "e42eee25c9fd" - }, - ".agents/skills/brand/SKILL.md": { - "hash": "4f819e2e0d69" - }, - ".agents/skills/build/SKILL.md": { - "hash": "d325dae8f934" - }, - ".agents/skills/check/SKILL.md": { - "hash": "fc46476bca7b" - }, - ".agents/skills/cost/SKILL.md": { - "hash": "834badf6646b" - }, - ".agents/skills/cost-centres/SKILL.md": { - "hash": "3140d48f16b0" - }, - ".agents/skills/deploy/SKILL.md": { - "hash": "2e1330fd693e" - }, - ".agents/skills/discover/SKILL.md": { - "hash": "9ac71caf6992" - }, - ".agents/skills/doctor/SKILL.md": { - "hash": "9d9e7ffcaf71" - }, - ".agents/skills/document-history/SKILL.md": { - "hash": "e82dbff8c514" - }, - ".agentkit/state/schema.json": { - "hash": "b47a7efcd922" - }, - ".agents/skills/expand/SKILL.md": { - "hash": "d9883bcc8f88" - }, - ".agents/skills/feature-flow/SKILL.md": { - "hash": "ec9b155a84e6" - }, - ".agents/skills/feature-configure/SKILL.md": { - "hash": "c11f2cc3273b" - }, - ".agents/skills/feature-review/SKILL.md": { - "hash": "da38a280ec45" - }, - ".agents/skills/format/SKILL.md": { - "hash": "0cdb87886f36" - }, - ".agents/skills/backlog/SKILL.md": { - "hash": "2dc8e5c1d39b" - }, - ".agents/skills/import-issues/SKILL.md": { - "hash": "e2d105f8b201" - }, - ".agents/skills/infra-eval/SKILL.md": { - "hash": "37505d91a1c5" - }, - ".agents/skills/plan/SKILL.md": { - "hash": "71c44b0ef7b1" - }, - ".agents/skills/preflight/SKILL.md": { - "hash": "85c05dc2c072" - }, - ".agents/skills/review/SKILL.md": { - "hash": "00b236ee680f" - }, - ".agents/skills/project-status/SKILL.md": { - "hash": "9a47cc64914b" - }, - ".agents/skills/orchestrate/SKILL.md": { - "hash": "2b6c677c66a3" - }, - ".agents/skills/scaffold/SKILL.md": { - "hash": "ff8fb03eecd2" - }, - ".agents/skills/security/SKILL.md": { - "hash": "3127f1e216c9" - }, - ".agents/skills/start/SKILL.md": { - "hash": "f0cd8fd39b4a" - }, - ".agents/skills/sync-backlog/SKILL.md": { - "hash": "6a3ad80bff8d" - }, - ".agents/skills/sync/SKILL.md": { - "hash": "c25161dc8913" - }, - ".agents/skills/test/SKILL.md": { - "hash": "3c02bdac8593" - }, - ".agents/skills/validate/SKILL.md": { - "hash": "30bc2a0427be" - }, - ".ai/cursorrules": { - "hash": "32f8f48220f6" - }, - ".ai/README.md": { - "hash": "608c681edb4e" - }, - ".ai/continuerules": { - "hash": "2d40023b7c45" - }, - ".ai/windsurfrules": { - "hash": "2d40023b7c45" - }, - ".claude/agents/adoption-strategist.md": { - "hash": "e0f5197c5140" - }, - ".claude/agents/brand-guardian.md": { - "hash": "06321324ad8c" - }, - ".claude/agents/backend.md": { - "hash": "738bca85b556" - }, - ".claude/agents/content-strategist.md": { - "hash": "bdea95fbdc97" - }, - ".claude/agents/cost-ops-monitor.md": { - "hash": "9f195cfb5ab3" - }, - ".claude/agents/data.md": { - "hash": "95222b841a68" - }, - ".claude/agents/dependency-watcher.md": { - "hash": "1317fdcdbdc6" - }, - ".claude/agents/coverage-tracker.md": { - "hash": "faf2173529c5" - }, - ".claude/agents/devops.md": { - "hash": "8623979399e3" - }, - ".claude/agents/expansion-analyst.md": { - "hash": "1acec03026a0" - }, - ".claude/agents/frontend.md": { - "hash": "2e553b7926ef" - }, - ".claude/agents/flow-designer.md": { - "hash": "0e0423753fd8" - }, - ".claude/agents/feature-ops.md": { - "hash": "f7a55b2e0a57" - }, - ".claude/agents/environment-manager.md": { - "hash": "7630c0856682" - }, - ".claude/agents/governance-advisor.md": { - "hash": "6fde5c50bf67" - }, - ".claude/agents/grant-hunter.md": { - "hash": "906ddfa7eeb1" - }, - ".claude/agents/infra.md": { - "hash": "49829cf96e63" - }, - ".claude/agents/input-clarifier.md": { - "hash": "10e22accb2c0" - }, - ".claude/agents/integration-tester.md": { - "hash": "9c537deec75e" - }, - ".claude/agents/mission-definer.md": { - "hash": "530ef4249f0b" - }, - ".claude/agents/impact-assessor.md": { - "hash": "86fdde8309c2" - }, - ".claude/agents/portfolio-analyst.md": { - "hash": "b85f4d82d325" - }, - ".claude/agents/product-manager.md": { - "hash": "ae255ee14143" - }, - ".claude/agents/model-economist.md": { - "hash": "87e470197ac4" - }, - ".claude/agents/project-shipper.md": { - "hash": "627257130af4" - }, - ".claude/agents/prompt-engineer.md": { - "hash": "3f98b589828e" - }, - ".claude/agents/release-manager.md": { - "hash": "74293815fa62" - }, - ".claude/agents/retrospective-analyst.md": { - "hash": "ee7cdb422865" - }, - ".claude/agents/roadmap-tracker.md": { - "hash": "89ddfff0b104" - }, - ".claude/agents/role-architect.md": { - "hash": "ff8dfe28ea56" - }, - ".claude/agents/growth-analyst.md": { - "hash": "f8eec3b1e625" - }, - ".claude/agents/security-auditor.md": { - "hash": "1cbf3ad0f91d" - }, - ".claude/agents/spec-compliance-auditor.md": { - "hash": "177cc631b0a2" - }, - ".claude/agents/team-validator.md": { - "hash": "bee9c68baeac" - }, - ".claude/agents/ui-designer.md": { - "hash": "a3e99552415f" - }, - ".claude/agents/release-coordinator.md": { - "hash": "df573b60959d" - }, - ".claude/agents/vendor-arbitrage-analyst.md": { - "hash": "48daa9f47218" - }, - ".claude/commands/backlog.md": { - "hash": "22a8d07575b3" - }, - ".claude/agents/test-lead.md": { - "hash": "45e8abd92aaf" - }, - ".claude/commands/check.md": { - "hash": "ca6dd1de5d9a" - }, - ".claude/commands/cost.md": { - "hash": "2392989dddaa" - }, - ".claude/commands/deploy.md": { - "hash": "adc2c2629b09" - }, - ".claude/commands/brand.md": { - "hash": "472c7438a795" - }, - ".claude/agents/token-efficiency-engineer.md": { - "hash": "c5e07b99dbc3" - }, - ".claude/commands/discover.md": { - "hash": "8fe679961a27" - }, - ".claude/commands/build.md": { - "hash": "fee9680802e1" - }, - ".claude/commands/cost-centres.md": { - "hash": "07ead7d1c63f" - }, - ".claude/commands/expand.md": { - "hash": "f3b8f79ccd05" - }, - ".claude/commands/document-history.md": { - "hash": "c99673f9ae3c" - }, - ".claude/commands/feature-flow.md": { - "hash": "d1b8207a2a5a" - }, - ".claude/commands/feature-configure.md": { - "hash": "ee21aacdcd29" - }, - ".claude/commands/format.md": { - "hash": "a3f0eee9b52e" - }, - ".claude/commands/import-issues.md": { - "hash": "6331f512f2b8" - }, - ".claude/commands/feature-review.md": { - "hash": "fced358b99eb" - }, - ".claude/commands/infra-eval.md": { - "hash": "8a58ea808952" - }, - ".claude/commands/doctor.md": { - "hash": "8fa0fd26e893" - }, - ".claude/commands/project-status.md": { - "hash": "0565edacffae" - }, - ".claude/commands/plan.md": { - "hash": "0eca590818b3" - }, - ".claude/commands/scaffold.md": { - "hash": "4b3cd870e0fc" - }, - ".claude/commands/review.md": { - "hash": "e32bc6f663ab" - }, - ".claude/commands/orchestrate.md": { - "hash": "574c6938b38d" - }, - ".claude/commands/start.md": { - "hash": "d172290d22db" - }, - ".claude/commands/security.md": { - "hash": "5efa63762b04" - }, - ".claude/commands/preflight.md": { - "hash": "4a65b6271bd6" - }, - ".claude/commands/sync.md": { - "hash": "efd3cfb56eed" - }, - ".claude/commands/sync-backlog.md": { - "hash": "2352a7d04323" - }, - ".claude/commands/team-backend.md": { - "hash": "f7e4f2d9d9b7" - }, - ".claude/commands/team-cost-ops.md": { - "hash": "812a2d58a81e" - }, - ".claude/commands/team-data.md": { - "hash": "ac4681cf9293" - }, - ".claude/commands/team-devops.md": { - "hash": "715a51cc4892" - }, - ".claude/commands/team-forge.md": { - "hash": "ff14d00c8c6c" - }, - ".claude/commands/team-frontend.md": { - "hash": "93f516367115" - }, - ".claude/commands/team-docs.md": { - "hash": "3deff18a07e9" - }, - ".claude/commands/team-infra.md": { - "hash": "436ecc831ca4" - }, - ".claude/commands/team-quality.md": { - "hash": "201199588ab2" - }, - ".claude/commands/team-product.md": { - "hash": "d0388844667d" - }, - ".claude/commands/team-strategic-ops.md": { - "hash": "5c65b47e2d4f" - }, - ".claude/commands/team-testing.md": { - "hash": "0d04836de633" - }, - ".claude/commands/test.md": { - "hash": "dff6e64066e4" - }, - ".claude/commands/team-security.md": { - "hash": "39f9d0c7d438" - }, - ".claude/commands/validate.md": { - "hash": "db126df15cad" - }, - ".claude/hooks/budget-guard-check.sh": { - "hash": "4fabe38fe963" - }, - ".claude/hooks/guard-destructive-commands.ps1": { - "hash": "55a58d211c2c" - }, - ".claude/hooks/pre-push-validate.sh": { - "hash": "86db6d107d60" - }, - ".claude/hooks/protect-sensitive.ps1": { - "hash": "59c32beeb28b" - }, - ".claude/hooks/protect-sensitive.sh": { - "hash": "f064ddda7879" - }, - ".claude/hooks/guard-destructive-commands.sh": { - "hash": "155b707b2af0" - }, - ".claude/hooks/protect-templates.ps1": { - "hash": "0b14c70ee6ef" - }, - ".claude/hooks/session-start.sh": { - "hash": "bf976e3ffb1a" - }, - ".claude/hooks/protect-templates.sh": { - "hash": "04a1d69ea578" - }, - ".claude/hooks/session-start.ps1": { - "hash": "7d50dcf043f4" - }, - ".claude/hooks/stop-build-check.sh": { - "hash": "8aecebcef7b7" - }, - ".claude/hooks/warn-uncommitted.ps1": { - "hash": "e01cd78b2c17" - }, - ".claude/hooks/warn-uncommitted.sh": { - "hash": "b224fa6b1b1f" - }, - ".claude/rules/blockchain.md": { - "hash": "6ebb3c6166c1" - }, - ".claude/rules/agent-conduct.md": { - "hash": "a9204d8e7dc4" - }, - ".claude/hooks/stop-build-check.ps1": { - "hash": "16d00d311940" - }, - ".claude/rules/dependency-management.md": { - "hash": "d0089754e232" - }, - ".claude/rules/ci-cd.md": { - "hash": "4eb972787de8" - }, - ".claude/rules/dotnet.md": { - "hash": "afd3bc539ab3" - }, - ".claude/rules/git-workflow.md": { - "hash": "16df971f4442" - }, - ".claude/rules/iac.md": { - "hash": "7389f06f50fe" - }, - ".claude/rules/documentation.md": { - "hash": "041b08cabcc0" - }, - ".claude/rules/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".claude/rules/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".claude/rules/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".claude/rules/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".claude/rules/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".claude/rules/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".claude/rules/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".claude/rules/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".claude/rules/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".claude/rules/languages/python.md": { - "hash": "63b439981bbc" - }, - ".claude/rules/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".claude/rules/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".claude/rules/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".claude/rules/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".claude/rules/languages/security.md": { - "hash": "1c73e7635578" - }, - ".claude/rules/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".claude/rules/python.md": { - "hash": "842f7d201c27" - }, - ".claude/rules/quality.md": { - "hash": "478859ffbb93" - }, - ".claude/rules/rust.md": { - "hash": "653b8dfb73b5" - }, - ".claude/rules/template-protection.md": { - "hash": "e0eca318e94b" - }, - ".claude/rules/testing.md": { - "hash": "3e7853b624e1" - }, - ".claude/rules/typescript.md": { - "hash": "1b050804b6ef" - }, - ".claude/settings.json": { - "hash": "b5f6aee20306" - }, - ".claude/skills/analyze-agents/SKILL.md": { - "hash": "3d77831e022a" - }, - ".claude/rules/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".claude/rules/security.md": { - "hash": "3ed7f09d1ad0" - }, - ".claude/skills/backlog/SKILL.md": { - "hash": "de8c81512467" - }, - ".claude/skills/brand/SKILL.md": { - "hash": "b4de2f51b106" - }, - ".claude/skills/cost/SKILL.md": { - "hash": "7276c4052975" - }, - ".claude/skills/check/SKILL.md": { - "hash": "6d7d38148af5" - }, - ".claude/skills/cost-centres/SKILL.md": { - "hash": "738667d8716f" - }, - ".claude/skills/deploy/SKILL.md": { - "hash": "f5cbd6d04c02" - }, - ".claude/skills/doctor/SKILL.md": { - "hash": "310dce98d8f4" - }, - ".claude/skills/document-history/SKILL.md": { - "hash": "074d8a3cab21" - }, - ".claude/skills/build/SKILL.md": { - "hash": "77448a90e59b" - }, - ".claude/skills/discover/SKILL.md": { - "hash": "ef2e7d50b511" - }, - ".claude/skills/expand/SKILL.md": { - "hash": "fd58b1775fd1" - }, - ".claude/skills/feature-flow/SKILL.md": { - "hash": "cd75ad612f63" - }, - ".claude/skills/format/SKILL.md": { - "hash": "3f2951d68edf" - }, - ".claude/skills/import-issues/SKILL.md": { - "hash": "7fb72bc4c4a2" - }, - ".claude/skills/infra-eval/SKILL.md": { - "hash": "7a4eedae11b3" - }, - ".claude/skills/orchestrate/SKILL.md": { - "hash": "8950d5dbb641" - }, - ".claude/skills/feature-review/SKILL.md": { - "hash": "b556218af259" - }, - ".claude/skills/feature-configure/SKILL.md": { - "hash": "4320cc00be36" - }, - ".claude/skills/plan/SKILL.md": { - "hash": "28fd3cc22953" - }, - ".claude/skills/scaffold/SKILL.md": { - "hash": "9291d71bc86b" - }, - ".claude/skills/security/SKILL.md": { - "hash": "1520feb2bf97" - }, - ".claude/skills/start/SKILL.md": { - "hash": "a987a611b567" - }, - ".claude/skills/preflight/SKILL.md": { - "hash": "b6ad1a083bac" - }, - ".claude/skills/project-status/SKILL.md": { - "hash": "8df33d0cb8c9" - }, - ".claude/skills/sync/SKILL.md": { - "hash": "19de7f1cc4cb" - }, - ".claude/skills/review/SKILL.md": { - "hash": "8386eb6c97ee" - }, - ".claude/skills/sync-backlog/SKILL.md": { - "hash": "cea14e0c67fc" - }, - ".claude/skills/validate/SKILL.md": { - "hash": "112b57703063" - }, - ".clinerules/agent-conduct.md": { - "hash": "58310e525ade" - }, - ".clinerules/ai-cost-ops.md": { - "hash": "464c1fde7714" - }, - ".claude/skills/test/SKILL.md": { - "hash": "21da74147f13" - }, - ".clinerules/ci-cd.md": { - "hash": "d6b6698178f3" - }, - ".clinerules/blockchain.md": { - "hash": "21750f5c565c" - }, - ".clinerules/dependency-management.md": { - "hash": "909464fb0495" - }, - ".clinerules/documentation.md": { - "hash": "a947fca57aca" - }, - ".clinerules/iac.md": { - "hash": "12318597c6ca" - }, - ".clinerules/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".clinerules/dotnet.md": { - "hash": "d978b656d898" - }, - ".clinerules/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".clinerules/finops.md": { - "hash": "c02b0486012f" - }, - ".clinerules/git-workflow.md": { - "hash": "0ce8ea97c321" - }, - ".clinerules/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".clinerules/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".clinerules/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".clinerules/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".clinerules/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".clinerules/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".clinerules/languages/python.md": { - "hash": "63b439981bbc" - }, - ".clinerules/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".clinerules/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".clinerules/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".clinerules/languages/security.md": { - "hash": "1c73e7635578" - }, - ".clinerules/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".clinerules/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".clinerules/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".clinerules/rust.md": { - "hash": "dc2f173fa092" - }, - ".clinerules/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".clinerules/security.md": { - "hash": "9cefb19e63e5" - }, - ".clinerules/python.md": { - "hash": "0d1ed61bb8dc" - }, - ".clinerules/template-protection.md": { - "hash": "ea83904b6713" - }, - ".cursor/commands/analyze-agents.md": { - "hash": "024e3cec1f56" - }, - ".cursor/commands/brand.md": { - "hash": "63960929d9fc" - }, - ".cursor/commands/backlog.md": { - "hash": "c6b5aa7de695" - }, - ".clinerules/typescript.md": { - "hash": "c77f9043197a" - }, - ".clinerules/testing.md": { - "hash": "fba2f07c5a5b" - }, - ".cursor/commands/build.md": { - "hash": "74cc820e6fc1" - }, - ".cursor/commands/cost-centres.md": { - "hash": "143856799eda" - }, - ".cursor/commands/check.md": { - "hash": "9373b3fca5ff" - }, - ".cursor/commands/deploy.md": { - "hash": "cd5b2f461cd7" - }, - ".cursor/commands/discover.md": { - "hash": "60be19c91420" - }, - ".cursor/commands/cost.md": { - "hash": "9c338e5f33b1" - }, - ".cursor/commands/doctor.md": { - "hash": "c619f9e3b1e6" - }, - ".cursor/commands/expand.md": { - "hash": "089462f22f52" - }, - ".cursor/commands/document-history.md": { - "hash": "975b4458c2c1" - }, - ".cursor/commands/feature-flow.md": { - "hash": "7d7a302552c6" - }, - ".cursor/commands/feature-review.md": { - "hash": "021c98874605" - }, - ".cursor/commands/format.md": { - "hash": "5be0e24ce07a" - }, - ".cursor/commands/feature-configure.md": { - "hash": "9b071a084415" - }, - ".cursor/commands/import-issues.md": { - "hash": "2acded7ac4fa" - }, - ".cursor/commands/infra-eval.md": { - "hash": "313ed28d7c7f" - }, - ".cursor/commands/orchestrate.md": { - "hash": "e2f5928cdb2f" - }, - ".cursor/commands/plan.md": { - "hash": "0af99fb78d12" - }, - ".cursor/commands/project-status.md": { - "hash": "7a0056181045" - }, - ".cursor/commands/review.md": { - "hash": "e1853e4abdb9" - }, - ".cursor/commands/preflight.md": { - "hash": "6d1a97bd57d5" - }, - ".cursor/commands/scaffold.md": { - "hash": "69986b1530cf" - }, - ".cursor/commands/sync.md": { - "hash": "513bea4ea974" - }, - ".cursor/commands/security.md": { - "hash": "1a4e4a4d8cf6" - }, - ".cursor/commands/sync-backlog.md": { - "hash": "a6282eab6689" - }, - ".cursor/commands/validate.md": { - "hash": "5bc457b26628" - }, - ".cursor/rules/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".cursor/rules/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".cursor/rules/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".cursor/rules/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".cursor/rules/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".cursor/commands/test.md": { - "hash": "0f83a2bdea71" - }, - ".cursor/rules/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".cursor/commands/start.md": { - "hash": "a72ec5c139fe" - }, - ".cursor/rules/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".cursor/rules/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".cursor/rules/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".cursor/rules/languages/python.md": { - "hash": "63b439981bbc" - }, - ".cursor/rules/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".cursor/rules/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".cursor/rules/languages/security.md": { - "hash": "1c73e7635578" - }, - ".cursor/rules/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".cursor/rules/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".cursor/rules/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".cursor/rules/orchestrate.mdc": { - "hash": "9853913b4857" - }, - ".cursor/rules/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".cursor/rules/security.mdc": { - "hash": "24c286e725a3" - }, - ".cursor/rules/project-context.mdc": { - "hash": "dd6859b78404" - }, - ".cursor/rules/team-backend.mdc": { - "hash": "66c7510720e1" - }, - ".cursor/rules/team-data.mdc": { - "hash": "412987c5fb0e" - }, - ".cursor/rules/team-docs.mdc": { - "hash": "b0ccc30e6b77" - }, - ".cursor/rules/team-cost-ops.mdc": { - "hash": "545aecedca0b" - }, - ".cursor/rules/team-forge.mdc": { - "hash": "a238f2cc330b" - }, - ".cursor/rules/team-infra.mdc": { - "hash": "d5f6f094dc30" - }, - ".cursor/rules/team-frontend.mdc": { - "hash": "82a998fe0de5" - }, - ".cursor/rules/team-product.mdc": { - "hash": "153f579d8b04" - }, - ".cursor/rules/team-security.mdc": { - "hash": "9778f59babaa" - }, - ".cursor/rules/team-devops.mdc": { - "hash": "0fe62d640199" - }, - ".cursor/rules/team-quality.mdc": { - "hash": "f70002d21c69" - }, - ".cursor/rules/team-strategic-ops.mdc": { - "hash": "00d0e2e368e4" - }, - ".cursor/rules/team-testing.mdc": { - "hash": "e5e949b5a9ad" - }, - ".gemini/config.yaml": { - "hash": "8f50c65f25fb" - }, - ".editorconfig": { - "hash": "fa09dda3d2e2" - }, - ".github/agents/adoption-strategist.agent.md": { - "hash": "5d2836dcb475" - }, - ".github/agents/backend.agent.md": { - "hash": "0d127baccf58" - }, - ".github/agents/content-strategist.agent.md": { - "hash": "c2544a299b60" - }, - ".gitattributes": { - "hash": "90af26762384" - }, - ".github/agents/brand-guardian.agent.md": { - "hash": "c2461a9a8466" - }, - ".github/agents/cost-ops-monitor.agent.md": { - "hash": "4188ea493644" - }, - ".github/agents/coverage-tracker.agent.md": { - "hash": "0ec9cd09509b" - }, - ".gemini/styleguide.md": { - "hash": "b3f330f5df8f" - }, - ".github/agents/data.agent.md": { - "hash": "a55f855de262" - }, - ".github/agents/expansion-analyst.agent.md": { - "hash": "45e7e34e7877" - }, - ".github/agents/devops.agent.md": { - "hash": "ffe4f3317ec8" - }, - ".github/agents/dependency-watcher.agent.md": { - "hash": "e85baf4d0d46" - }, - ".github/agents/environment-manager.agent.md": { - "hash": "d2e9a801a5e5" - }, - ".github/agents/flow-designer.agent.md": { - "hash": "d09c5f1d7cd2" - }, - ".github/agents/feature-ops.agent.md": { - "hash": "c4ba3dc907f6" - }, - ".github/agents/governance-advisor.agent.md": { - "hash": "35e92bcae9d0" - }, - ".github/agents/frontend.agent.md": { - "hash": "778677e3a2f1" - }, - ".github/agents/grant-hunter.agent.md": { - "hash": "7d849df31023" - }, - ".github/agents/impact-assessor.agent.md": { - "hash": "98a4559e208d" - }, - ".github/agents/infra.agent.md": { - "hash": "8c8d3a4f1adf" - }, - ".github/agents/input-clarifier.agent.md": { - "hash": "63f969a72bc4" - }, - ".github/agents/mission-definer.agent.md": { - "hash": "4ba6262d5eb8" - }, - ".github/agents/integration-tester.agent.md": { - "hash": "b34beafad1bd" - }, - ".github/agents/model-economist.agent.md": { - "hash": "b3ea5f80581d" - }, - ".github/agents/portfolio-analyst.agent.md": { - "hash": "fa3fe9e48a52" - }, - ".github/agents/product-manager.agent.md": { - "hash": "9d3da17ae6f3" - }, - ".github/agents/project-shipper.agent.md": { - "hash": "93e8ef14bb8f" - }, - ".github/agents/prompt-engineer.agent.md": { - "hash": "778f224899a3" - }, - ".github/agents/retrospective-analyst.agent.md": { - "hash": "143b2fd6c727" - }, - ".github/agents/roadmap-tracker.agent.md": { - "hash": "0fdd8e9b7985" - }, - ".github/agents/role-architect.agent.md": { - "hash": "217b0f7d6bc5" - }, - ".github/agents/security-auditor.agent.md": { - "hash": "1f8a11a72b17" - }, - ".github/agents/spec-compliance-auditor.agent.md": { - "hash": "e2b66fe05d2b" - }, - ".github/agents/team-validator.agent.md": { - "hash": "046b30086c5b" - }, - ".github/agents/test-lead.agent.md": { - "hash": "6561c9a0a1c2" - }, - ".github/agents/token-efficiency-engineer.agent.md": { - "hash": "12997f39f2cb" - }, - ".github/agents/ui-designer.agent.md": { - "hash": "337cddf83447" - }, - ".github/agents/vendor-arbitrage-analyst.agent.md": { - "hash": "627c29b70357" - }, - ".github/agents/growth-analyst.agent.md": { - "hash": "25e3b42da3aa" - }, - ".github/agents/release-coordinator.agent.md": { - "hash": "dfa94cb6ff6f" - }, - ".github/agents/release-manager.agent.md": { - "hash": "e58484632ca0" - }, - ".github/chatmodes/team-backend.chatmode.md": { - "hash": "ac8f69b82220" - }, - ".github/chatmodes/team-cost-ops.chatmode.md": { - "hash": "121bbf207ca4" - }, - ".github/chatmodes/team-devops.chatmode.md": { - "hash": "978de914aab8" - }, - ".github/chatmodes/team-data.chatmode.md": { - "hash": "0afb7a28f351" - }, - ".github/chatmodes/team-forge.chatmode.md": { - "hash": "b04f7d8a9d9a" - }, - ".github/chatmodes/team-frontend.chatmode.md": { - "hash": "cce72ab3a795" - }, - ".github/chatmodes/team-infra.chatmode.md": { - "hash": "5850b3a37256" - }, - ".github/chatmodes/team-docs.chatmode.md": { - "hash": "c204bd1f1788" - }, - ".github/chatmodes/team-product.chatmode.md": { - "hash": "03428a19c477" - }, - ".github/chatmodes/team-quality.chatmode.md": { - "hash": "7bc2b2f277e1" - }, - ".github/chatmodes/team-strategic-ops.chatmode.md": { - "hash": "8b337da42662" - }, - ".github/ai-framework-ci.yml": { - "hash": "d33ebabcb073" - }, - ".github/chatmodes/team-testing.chatmode.md": { - "hash": "074a36442ca2" - }, - ".github/CODEOWNERS": { - "hash": "ccf003556232" - }, - ".github/chatmodes/team-security.chatmode.md": { - "hash": "09342e8fc4bc" - }, - ".github/copilot-instructions.md": { - "hash": "c8bb26bb2cba" - }, - ".github/instructions/code-verify.md": { - "hash": "f82d9d55fc86" - }, - ".github/instructions/docs.md": { - "hash": "dca898c99b6c" - }, - ".github/instructions/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".github/instructions/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".github/instructions/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".github/instructions/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".github/instructions/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".github/instructions/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".github/instructions/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".github/instructions/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".github/instructions/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".github/instructions/languages/python.md": { - "hash": "63b439981bbc" - }, - ".github/instructions/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".github/instructions/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".github/instructions/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".github/instructions/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".github/instructions/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".github/instructions/marketing.md": { - "hash": "84860c42a466" - }, - ".github/instructions/performance.md": { - "hash": "4f8cd32aeb7e" - }, - ".github/instructions/quality.md": { - "hash": "d2d93df02537" - }, - ".github/instructions/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".github/instructions/languages/security.md": { - "hash": "1c73e7635578" - }, - ".github/instructions/testing.md": { - "hash": "ee3e0d11b01b" - }, - ".github/instructions/README.md": { - "hash": "a79739379379" - }, - ".github/ISSUE_TEMPLATE/feature_request.yml": { - "hash": "79e7e3da99d0" - }, - ".github/ISSUE_TEMPLATE/bug_report.yml": { - "hash": "0b7c12b0e1bb" - }, - ".github/prompts/backlog.prompt.md": { - "hash": "45f1abd24d72" - }, - ".github/ISSUE_TEMPLATE/config.yml": { - "hash": "47344ff5c32c" - }, - ".github/prompts/brand.prompt.md": { - "hash": "0c6c0002f942" - }, - ".github/prompts/build.prompt.md": { - "hash": "046bffc8791e" - }, - ".github/prompts/check.prompt.md": { - "hash": "cc0bdba2f08f" - }, - ".github/prompts/cost.prompt.md": { - "hash": "8d2d9868723a" - }, - ".github/prompts/deploy.prompt.md": { - "hash": "fc9569e74c5d" - }, - ".github/prompts/discover.prompt.md": { - "hash": "e04bdf639b4a" - }, - ".github/prompts/analyze-agents.prompt.md": { - "hash": "19e1dc8432f0" - }, - ".github/prompts/document-history.prompt.md": { - "hash": "d9f170e31ace" - }, - ".github/prompts/doctor.prompt.md": { - "hash": "1dad8d876f62" - }, - ".github/prompts/expand.prompt.md": { - "hash": "ff9445bec477" - }, - ".github/prompts/feature-review.prompt.md": { - "hash": "cf81881f51f5" - }, - ".github/prompts/feature-configure.prompt.md": { - "hash": "ce35b4c465e6" - }, - ".github/prompts/format.prompt.md": { - "hash": "94a0505df23e" - }, - ".github/prompts/cost-centres.prompt.md": { - "hash": "6baa174774e6" - }, - ".github/prompts/import-issues.prompt.md": { - "hash": "4b2701705479" - }, - ".github/prompts/infra-eval.prompt.md": { - "hash": "a8b15916f960" - }, - ".github/prompts/orchestrate.prompt.md": { - "hash": "63451784c289" - }, - ".github/prompts/preflight.prompt.md": { - "hash": "52dcd9cbf075" - }, - ".github/prompts/feature-flow.prompt.md": { - "hash": "b82d78500eb3" - }, - ".github/prompts/review.prompt.md": { - "hash": "94016ba6950b" - }, - ".github/prompts/plan.prompt.md": { - "hash": "69797faa11a4" - }, - ".github/prompts/project-status.prompt.md": { - "hash": "328769323130" - }, - ".github/prompts/scaffold.prompt.md": { - "hash": "22240d89615d" - }, - ".github/prompts/security.prompt.md": { - "hash": "953693049d80" - }, - ".github/prompts/start.prompt.md": { - "hash": "97357c17d8fe" - }, - ".github/prompts/sync-backlog.prompt.md": { - "hash": "9cea7fd68060" - }, - ".github/prompts/sync.prompt.md": { - "hash": "7e7773332996" - }, - ".github/prompts/test.prompt.md": { - "hash": "871f38d6af82" - }, - ".github/prompts/validate.prompt.md": { - "hash": "028479c6d2e2" - }, - ".github/scripts/resolve-merge.ps1": { - "hash": "0cd5d9407b89" - }, - ".github/scripts/resolve-merge.sh": { - "hash": "7ce68cb84a3a" - }, - ".github/scripts/setup-branch-protection.ps1": { - "hash": "160cb7bb55b1" - }, - ".github/scripts/setup-branch-protection.sh": { - "hash": "6eb664b21ee4" - }, - ".github/workflows/breaking-change-detection.yml": { - "hash": "bcd2f5c2e450" - }, - ".github/scripts/README.md": { - "hash": "3124e25a7cfa" - }, - ".github/workflows/coverage-report.yml": { - "hash": "80dafccc5b8f" - }, - ".github/workflows/dependency-audit.yml": { - "hash": "fc376b5eef06" - }, - ".github/workflows/documentation-quality.yml": { - "hash": "6088b2095f59" - }, - ".github/workflows/documentation-validation.yml": { - "hash": "01abb4c23ec9" - }, - ".github/workflows/pr-validation.yml": { - "hash": "2c316a51ea66" - }, - ".github/workflows/retrospective-quality.yml": { - "hash": "74474e570115" - }, - ".gitmessage": { - "hash": "3f5666033096" - }, - ".markdownlint.json": { - "hash": "afe70a444035" - }, - ".prettierrc": { - "hash": "7288d28eacd8" - }, - ".roo/rules/agent-conduct.md": { - "hash": "1f4b060a86eb" - }, - ".github/PULL_REQUEST_TEMPLATE.md": { - "hash": "10b91e98a082" - }, - ".roo/rules/ci-cd.md": { - "hash": "56d669134c88" - }, - ".roo/rules/ai-cost-ops.md": { - "hash": "2c38e075d4db" - }, - ".roo/rules/dependency-management.md": { - "hash": "10ec56bb6292" - }, - ".roo/rules/blockchain.md": { - "hash": "205b3ca13935" - }, - ".roo/rules/finops.md": { - "hash": "17a63264e7b1" - }, - ".roo/rules/documentation.md": { - "hash": "ff90f251ce71" - }, - ".roo/rules/git-workflow.md": { - "hash": "ae185cb50c40" - }, - ".roo/rules/iac.md": { - "hash": "2024c73bc61a" - }, - ".roo/rules/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".roo/rules/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".roo/rules/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".roo/rules/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".roo/rules/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".roo/rules/dotnet.md": { - "hash": "8b8461bcf286" - }, - ".roo/rules/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".roo/rules/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".roo/rules/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".roo/rules/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".roo/rules/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".roo/rules/languages/security.md": { - "hash": "1c73e7635578" - }, - ".roo/rules/languages/python.md": { - "hash": "63b439981bbc" - }, - ".roo/rules/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".roo/rules/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".roo/rules/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".roo/rules/python.md": { - "hash": "7b9a642b9197" - }, - ".roo/rules/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".roo/rules/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".roo/rules/template-protection.md": { - "hash": "2097e8899fab" - }, - ".roo/rules/security.md": { - "hash": "a05714124061" - }, - ".roo/rules/typescript.md": { - "hash": "5bff848ce5b6" - }, - ".roo/rules/testing.md": { - "hash": "f420798449b7" - }, - ".vscode/settings.json": { - "hash": "4af945c89151" - }, - ".windsurf/commands/analyze-agents.md": { - "hash": "371f6c3bd7d5" - }, - ".windsurf/commands/backlog.md": { - "hash": "68b4263fc444" - }, - ".windsurf/commands/build.md": { - "hash": "7fc64a835712" - }, - ".windsurf/commands/brand.md": { - "hash": "1eb99e2c4883" - }, - ".roo/rules/rust.md": { - "hash": "f68627a539a3" - }, - ".windsurf/commands/check.md": { - "hash": "780d7cb5ba53" - }, - ".windsurf/commands/cost-centres.md": { - "hash": "16f70ee610a8" - }, - ".windsurf/commands/cost.md": { - "hash": "6b9a7ee00d03" - }, - ".windsurf/commands/discover.md": { - "hash": "438676ab6872" - }, - ".windsurf/commands/doctor.md": { - "hash": "e40703581729" - }, - ".windsurf/commands/document-history.md": { - "hash": "57554e0ae8d7" - }, - ".windsurf/commands/expand.md": { - "hash": "62310f81603e" - }, - ".windsurf/commands/deploy.md": { - "hash": "bb64704796af" - }, - ".windsurf/commands/feature-configure.md": { - "hash": "31f4a7a16fe7" - }, - ".windsurf/commands/feature-review.md": { - "hash": "9c212c4c7afe" - }, - ".windsurf/commands/feature-flow.md": { - "hash": "840122cc19aa" - }, - ".windsurf/commands/infra-eval.md": { - "hash": "359a364a00e5" - }, - ".windsurf/commands/orchestrate.md": { - "hash": "1d9602ce2908" - }, - ".windsurf/commands/plan.md": { - "hash": "0bf8e69458de" - }, - ".windsurf/commands/preflight.md": { - "hash": "2d35df2ccd8e" - }, - ".vscode/extensions.json": { - "hash": "dd20fd0751ba" - }, - ".windsurf/commands/format.md": { - "hash": "10cda487929d" - }, - ".windsurf/commands/project-status.md": { - "hash": "a85e72f6794e" - }, - ".windsurf/commands/review.md": { - "hash": "ebd187ab3d06" - }, - ".windsurf/commands/security.md": { - "hash": "4878d4daa234" - }, - ".windsurf/commands/import-issues.md": { - "hash": "9b714f3d4b02" - }, - ".windsurf/commands/sync.md": { - "hash": "d4678bf06724" - }, - ".windsurf/commands/sync-backlog.md": { - "hash": "bf720daf3704" - }, - ".windsurf/commands/test.md": { - "hash": "73463ed24c36" - }, - ".windsurf/commands/validate.md": { - "hash": "02d1c93720c5" - }, - ".windsurf/commands/scaffold.md": { - "hash": "c57cd1471acf" - }, - ".windsurf/commands/start.md": { - "hash": "7cc5267d9274" - }, - ".windsurf/rules/languages/agent-conduct.md": { - "hash": "dfa139fec0e9" - }, - ".windsurf/rules/languages/blockchain.md": { - "hash": "7fc6185f787c" - }, - ".windsurf/rules/languages/documentation.md": { - "hash": "1987c9f42ff1" - }, - ".windsurf/rules/languages/ai-cost-ops.md": { - "hash": "a1ae9bf2bed7" - }, - ".windsurf/rules/languages/dotnet.md": { - "hash": "d32abad9b778" - }, - ".windsurf/rules/languages/ci-cd.md": { - "hash": "ee4914ac0781" - }, - ".windsurf/rules/languages/finops.md": { - "hash": "26ed29eca172" - }, - ".windsurf/rules/languages/dependency-management.md": { - "hash": "e03ef3668bb4" - }, - ".windsurf/rules/languages/git-workflow.md": { - "hash": "1fdb78c70ab0" - }, - ".windsurf/rules/languages/README.md": { - "hash": "1525f51b3b52" - }, - ".windsurf/rules/languages/rust.md": { - "hash": "4d57482d5c8b" - }, - ".windsurf/rules/languages/python.md": { - "hash": "63b439981bbc" - }, - ".windsurf/rules/languages/iac.md": { - "hash": "8e3e330610df" - }, - ".windsurf/rules/languages/template-protection.md": { - "hash": "da0cc75841da" - }, - ".windsurf/rules/languages/typescript.md": { - "hash": "02ce5a9b6f2f" - }, - ".windsurf/rules/languages/testing.md": { - "hash": "2e8c3bd2fd50" - }, - ".windsurf/rules/orchestrate.md": { - "hash": "0eea9715c9db" - }, - ".windsurf/rules/security.md": { - "hash": "6a39548b2255" - }, - ".windsurf/rules/team-cost-ops.md": { - "hash": "69db0e22010d" - }, - ".windsurf/rules/team-data.md": { - "hash": "2fa55fd04223" - }, - ".windsurf/rules/team-devops.md": { - "hash": "06c93f75dcd3" - }, - ".windsurf/rules/team-forge.md": { - "hash": "13f5fa696b1d" - }, - ".windsurf/rules/team-backend.md": { - "hash": "ec288e9b54ce" - }, - ".windsurf/rules/team-docs.md": { - "hash": "f019d83abc58" - }, - ".windsurf/rules/team-frontend.md": { - "hash": "e9a5f425646d" - }, - ".windsurf/rules/languages/security.md": { - "hash": "1c73e7635578" - }, - ".windsurf/rules/team-product.md": { - "hash": "81f4929e42f3" - }, - ".windsurf/rules/project.md": { - "hash": "cc8ae6d95221" - }, - ".windsurf/rules/team-testing.md": { - "hash": "505b7caae49d" - }, - ".windsurf/rules/team-security.md": { - "hash": "a7c778d35665" - }, - ".windsurf/workflows/phase-execution.yml": { - "hash": "81054e1a3272" - }, - "AGENTS.md": { - "hash": "911950e72f75" - }, - ".windsurf/workflows/full-assessment.yml": { - "hash": "57d1220ee8ac" - }, - "AGENT_BACKLOG.md": { - "hash": "f45282123027" - }, - "CHANGELOG.md": { - "hash": "8cb5a19628b1" - }, - "AGENT_TEAMS.md": { - "hash": "725ada7d289f" - }, - ".windsurf/rules/team-strategic-ops.md": { - "hash": "c1d8c4f33abe" - }, - "CLAUDE.md": { - "hash": "4e7b5fb72c4c" - }, - ".windsurf/rules/team-quality.md": { - "hash": "afb908c98b76" - }, - ".windsurf/rules/team-infra.md": { - "hash": "fb977ea917c1" - }, - "docs/api/01_overview.md": { - "hash": "342e9d07b13f" - }, - "docs/api/02_endpoints.md": { - "hash": "43eb1cc5a21f" - }, - "CONTRIBUTING.md": { - "hash": "afd7d3c16416" - }, - "docs/api/04_examples.md": { - "hash": "7c21b7bcf311" - }, - "docs/api/03_authentication.md": { - "hash": "26ef4da3ef56" - }, - "docs/api/05_errors.md": { - "hash": "ed2e5a6e94ed" - }, - "docs/api/06_versioning.md": { - "hash": "bd878ba8a2f6" - }, - "COMMAND_GUIDE.md": { - "hash": "4600c6725f0d" - }, - "docs/architecture/01_overview.md": { - "hash": "df6efc6fda78" - }, - "docs/architecture/decisions/01-adopt-agentkit-forge.md": { - "hash": "552c1023dcf2" - }, - "docs/api/README.md": { - "hash": "5a266ea2df82" - }, - "docs/agents/agent-team-matrix.md": { - "hash": "09345b713ca1" - }, - "docs/architecture/decisions/03-tooling-strategy.md": { - "hash": "b2700e569966" - }, - "docs/architecture/decisions/05-dependency-supply-chain-detection-tooling.md": { - "hash": "6ccff01874c7" - }, - "docs/architecture/decisions/06-code-quality-maintainability-signal-tooling.md": { - "hash": "3fb3fc9fd6ff" - }, - "docs/architecture/decisions/04-static-security-analysis-depth-tooling.md": { - "hash": "998c41843f21" - }, - "docs/architecture/decisions/02-fallback-policy-tokens-problem.md": { - "hash": "31295d24794e" - }, - "docs/architecture/decisions/README.md": { - "hash": "28b5d189b354" - }, - "docs/architecture/diagrams/.gitkeep": { - "hash": "64edc5f9f589" - }, - "docs/architecture/README.md": { - "hash": "a867a017c8a0" - }, - "docs/architecture/specs/02_technical_spec.md": { - "hash": "b603c83e06d5" - }, - "docs/architecture/diagrams/README.md": { - "hash": "782485a4f5ef" - }, - "docs/architecture/specs/01_functional_spec.md": { - "hash": "cb36564f8ddd" - }, - "docs/architecture/specs/03_api_spec.md": { - "hash": "d5a1811ddc75" - }, - "docs/architecture/specs/README.md": { - "hash": "7c4e52efbd0d" - }, - "docs/architecture/specs/04_data_models.md": { - "hash": "a77400c5387c" - }, - "docs/engineering/02_coding_standards.md": { - "hash": "cf4473c84515" - }, - "docs/engineering/03_testing.md": { - "hash": "7cbc67b07b25" - }, - "docs/engineering/04_git_workflow.md": { - "hash": "8621780ffdcb" - }, - "docs/engineering/05_security.md": { - "hash": "b2fd1574733d" - }, - "docs/engineering/06_pr_documentation.md": { - "hash": "74d9c99fc82a" - }, - "docs/engineering/README.md": { - "hash": "35afee261b38" - }, - "docs/engineering/07_changelog.md": { - "hash": "945e28ab8b34" - }, - "docs/history/.index.json": { - "hash": "7beb781687f2" - }, - "docs/history/bug-fixes/README.md": { - "hash": "78dcabc86f74" - }, - "docs/history/bug-fixes/TEMPLATE-bugfix.md": { - "hash": "7873d84034ec" - }, - "docs/history/features/README.md": { - "hash": "7a6b10981688" - }, - "docs/history/features/TEMPLATE-feature.md": { - "hash": "c704b2662b57" - }, - "docs/history/implementations/README.md": { - "hash": "938114ecc966" - }, - "docs/history/implementations/TEMPLATE-implementation.md": { - "hash": "d4b4ad9bf6cc" - }, - "docs/history/issues/README.md": { - "hash": "3e5d149f1a6c" - }, - "docs/history/issues/TEMPLATE-issue.md": { - "hash": "b133cb73cdc5" - }, - "docs/history/lessons-learned/README.md": { - "hash": "b21e63388be4" - }, - "docs/history/lessons-learned/TEMPLATE-lesson.md": { - "hash": "810fcf97423b" - }, - "docs/engineering/01_setup.md": { - "hash": "225879d37c28" - }, - "docs/history/migrations/README.md": { - "hash": "7b023cecc53d" - }, - "docs/history/migrations/TEMPLATE-migration.md": { - "hash": "97272242bd4e" - }, - "docs/history/README.md": { - "hash": "8feb37cbe0c0" - }, - "docs/integrations/02_webhooks.md": { - "hash": "b9e1b977bf00" - }, - "docs/integrations/README.md": { - "hash": "105308932223" - }, - "docs/operations/01_deployment.md": { - "hash": "8fc948f3e280" - }, - "docs/operations/02_monitoring.md": { - "hash": "0d1c7d4a021e" - }, - "docs/operations/03_incident_response.md": { - "hash": "549b6f418202" - }, - "docs/operations/04_troubleshooting.md": { - "hash": "a8c0364e80c9" - }, - "docs/operations/05_slos_slis.md": { - "hash": "2cbf5f2188dd" - }, - "docs/operations/README.md": { - "hash": "62c405f25743" - }, - "docs/planning/TEMPLATE-plan.md": { - "hash": "305534965f0e" - }, - "docs/product/01_prd.md": { - "hash": "80c041b82e0d" - }, - "docs/integrations/01_external_apis.md": { - "hash": "17bc92567b46" - }, - "docs/integrations/03_sdk.md": { - "hash": "c05a8a69392d" - }, - "docs/product/02_user_stories.md": { - "hash": "fce181fc7087" - }, - "docs/product/03_roadmap.md": { - "hash": "c24ab738099b" - }, - "docs/product/README.md": { - "hash": "43db13443d26" - }, - "docs/reference/03_changelog.md": { - "hash": "4bd7c9e727aa" - }, - "docs/reference/02_faq.md": { - "hash": "ac95d6fb41ec" - }, - "docs/reference/04_contributing.md": { - "hash": "b33e1d721718" - }, - "docs/reference/README.md": { - "hash": "c09171b9b8a1" - }, - "GEMINI.md": { - "hash": "a59e2d67b8dd" - }, - "MIGRATIONS.md": { - "hash": "e880b3edb24c" - }, - "docs/product/04_personas.md": { - "hash": "609113c06c69" - }, - "QUALITY_GATES.md": { - "hash": "e3158c924e6e" - }, - "docs/README.md": { - "hash": "0a5900bf46af" - }, - "docs/reference/01_glossary.md": { - "hash": "2f571539f2ff" - }, - "scripts/analyze-agents.sh": { - "hash": "dfd5f15e5267" - }, - "scripts/analyze-agents.ps1": { - "hash": "e66c881de65a" - }, - "scripts/check-documentation-requirement.sh": { - "hash": "0604d65be8db" - }, - "scripts/consolidate-branches.sh": { - "hash": "f345de274644" - }, - "scripts/create-doc.sh": { - "hash": "c170336b69e0" - }, - "scripts/create-doc.ps1": { - "hash": "207501b71fe6" - }, - "scripts/resolve-merge.ps1": { - "hash": "1ae33673ef63" - }, - "scripts/resolve-merge.sh": { - "hash": "29048f9dc59d" - }, - "scripts/setup-agentkit-branch-governance.ps1": { - "hash": "ac356d29ce05" - }, - "scripts/setup-agentkit-branch-governance.sh": { - "hash": "cecf99c1c59a" - }, - "RUNBOOK_AI.md": { - "hash": "2a0d351455dc" - }, - "scripts/sync-issues.sh": { - "hash": "5728f842fda3" - }, - "scripts/sync-split-pr.ps1": { - "hash": "199b5056c32e" - }, - "scripts/sync-split-pr.sh": { - "hash": "169e29683f7b" - }, - "scripts/update-changelog.sh": { - "hash": "146f6934a4ee" - }, - "scripts/consolidate-branches.ps1": { - "hash": "767265430308" - }, - "scripts/validate-documentation.sh": { - "hash": "c00c47269a24" - }, - "scripts/validate-numbering.sh": { - "hash": "d78c153d05ee" - }, - "UNIFIED_AGENT_TEAMS.md": { - "hash": "506e38f9e21c" - }, - "SECURITY.md": { - "hash": "a926751bc190" - }, - "WARP.md": { - "hash": "24ca1510e68e" - }, - "scripts/update-changelog.ps1": { - "hash": "3b64bfbcfc25" - } - } -} diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/AGENT_TEAMS.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/AGENT_TEAMS.md deleted file mode 100644 index ed649683..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/AGENT_TEAMS.md +++ /dev/null @@ -1,80 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Agent Teams — agentkit-forge - -> Repo-local team mapping derived from `.agentkit/spec/teams.yaml`. -> Customize the **Status**, **Primary Scope**, **Tech Stack**, and **Lead Agent** -> columns for your repository. The orchestrator uses this file for task dispatch. - ---- - -## Overview - -This document maps the canonical AgentKit team definitions (see -[UNIFIED_AGENT_TEAMS.md](./UNIFIED_AGENT_TEAMS.md)) to the concrete structure -of this repository. Not all teams may be active — mark inactive teams so the -orchestrator skips them during dispatch. - ---- - -## Team Roster - -| Team | ID | Focus | Scope | Accepts | Handoff Chain | Status | Lead Agent | -| ---- | -- | ----- | ----- | ------- | ------------- | ------ | ---------- | -| BACKEND | backend | API, services, core logic | `apps/api/**`, `services/**`, `src/server/**`, `controllers/**` | implement, review, plan | testing → docs | Active | — | -| FRONTEND | frontend | UI, components, PWA | `apps/web/**`, `apps/marketing/**`, `src/client/**`, `components/**` | implement, review, plan | testing → docs | Active | — | -| DATA | data | Database, models, migrations | `db/**`, `migrations/**`, `models/**`, `prisma/**` | implement, review, plan | backend → testing | Active | — | -| INFRA | infra | IaC, cloud, Terraform/Bicep | `infra/**`, `terraform/**`, `bicep/**`, `pulumi/**` | implement, review, plan, investigate | devops → security | Active | — | -| DEVOPS | devops | CI/CD, pipelines, automation | `.github/workflows/**`, `scripts/**`, `docker/**`, `**/Dockerfile*` | implement, review, plan | testing → security | Active | — | -| TESTING | testing | Unit, E2E, integration tests | `**/*.test.*`, `**/*.spec.*`, `tests/**`, `e2e/**`, `playwright/**` | implement, review, test | quality | Active | — | -| SECURITY | security | Auth, compliance, audit | `auth/**`, `security/**`, `middleware/auth*` | review, investigate | — | Active | — | -| DOCUMENTATION | docs | Docs, ADRs, guides | `docs/**`, `docs/architecture/decisions/**`, `.github/**`, `README.md`, `CHANGELOG.md`, `CONTRIBUTING.md` | implement, review, document | — | Active | — | -| PRODUCT | product | Features, PRDs, roadmap | `docs/product/**`, `docs/prd/**` | plan, review | backend → frontend | Active | — | -| QUALITY | quality | Code review, refactoring, bugs, reliability, session retrospectives | `**/*` | review, investigate | — | Active | — | -| TEAMFORGE | forge | Meta-team — creates, validates, and deploys new agent team specifications | `.agentkit/spec/**`, `docs/planning/agents-teams/**`, `docs/architecture/**` | plan, review, investigate, document | quality → docs | Active | — | -| STRATEGIC OPS | strategic-ops | Cross-project coordination, framework governance, portfolio-level planning | `docs/planning/**`, `docs/architecture/**`, `.agentkit/spec/**`, `AGENT_BACKLOG.md`, `UNIFIED_AGENT_TEAMS.md`, `AGENT_TEAMS.md` | plan, review, investigate, document | product → quality | Active | — | -| COST OPS | cost-ops | AI infrastructure cost reduction, vendor optimization, token efficiency | `docs/cost-ops/**`, `docs/planning/cost/**`, `config/models/**`, `config/pricing/**` | investigate, review, plan, document, implement | infra → product → strategic-ops | Active | — | - ---- - -## How to Customize - -### Activating / Deactivating a Team - -1. Change the **Status** column from `Inactive` to `Active` (or vice versa). -2. Fill in the **Primary Scope** with actual directory paths in this repo. -3. Set the **Tech Stack** to reflect the tools and frameworks used. -4. Assign a **Lead Agent** identifier (used for mentions and escalation). -5. Add any relevant notes about the team's role. - -The orchestrator will skip inactive teams during `/orchestrate` dispatch. - -### Adding Custom Scope Patterns - -Each team's scope patterns determine which files the orchestrator will assign -to that team. Use glob patterns: - -``` -src/server/** — all files under src/server/ -src/api/*.ts — TypeScript files directly in src/api/ -tests/unit/server/* — server unit tests -``` - ---- - -## Scope Overlap Resolution - -When multiple teams have overlapping scope patterns, the orchestrator uses -these priority rules: - -1. **Most specific pattern wins.** A deeper path match takes precedence. -2. **Explicit assignment overrides.** A task explicitly assigned to a team - via `--teams` flag takes precedence over pattern matching. -3. **Primary scope takes priority.** The team whose scope lists the most - specific matching directory owns the file. - ---- - -_Customize this file for your repository. User edits are preserved across syncs._ -_Canonical team definitions: [UNIFIED_AGENT_TEAMS.md](./UNIFIED_AGENT_TEAMS.md)_ diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/README.md deleted file mode 100644 index 9484b549..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/README.md +++ /dev/null @@ -1,47 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# agentkit-forge — Documentation - -Welcome to the agentkit-forge documentation hub. This index links to every -documentation category maintained by this repository. - -## Categories - -| Category | Description | -| -------------------------------------- | ----------------------------------------------------- | -| [Product](./product/) | Product vision, strategy, personas, PRDs | -| [Architecture](./architecture/) | Specs, ADRs, diagrams, tech stack decisions | -| [Orchestration](./orchestration/) | Orchestration guide, PM guide, concurrency protocol | -| [Agents](./agents/) | Agent catalog, roles, team mappings | -| [API](./api/) | API reference, authentication, versioning, and errors | -| [Operations](./operations/) | CI/CD, deployments, monitoring, and troubleshooting | -| [Engineering](./engineering/) | Setup, coding standards, testing, and contributing | -| [Integrations](./integrations/) | External APIs, webhooks, and SDK | -| [Reference](./reference/) | Glossary, acronyms, FAQ, and tool config | -| [Handoffs](./handoffs/) | AI session handoff documents | -| [History](./history/) | Bug fixes, features, implementations, lessons | - -## Quick Links - -- [Architecture Overview](./architecture/01_overview.md) -- [Orchestration Guide](./orchestration/overview.md) -- [PM Guide](./orchestration/pm-guide.md) -- [Agent Catalog](./agents/catalog.md) -- [API Overview](./api/01_overview.md) -- [Getting Started](./engineering/01_setup.md) -- [Changelog](./reference/03_changelog.md) - -- [PRD Library](./product/prd/README.md) - - -## Conventions - -- Placeholder tokens `agentkit-forge` and `3.1.0` are replaced at sync time. -- Do **not** edit generated files directly — run `pnpm -C .agentkit agentkit:sync` - to regenerate them from the AgentKit Forge spec and overlays. - ---- - -Generated by AgentKit Forge v3.1.0 diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/api/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/api/README.md deleted file mode 100644 index e91f44ae..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/api/README.md +++ /dev/null @@ -1,14 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# API Docs Index - -## Contents - -- [01_overview.md](./01_overview.md) -- [02_endpoints.md](./02_endpoints.md) -- [03_authentication.md](./03_authentication.md) -- [04_examples.md](./04_examples.md) -- [05_errors.md](./05_errors.md) -- [06_versioning.md](./06_versioning.md) diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/README.md deleted file mode 100644 index de2050fe..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/README.md +++ /dev/null @@ -1,12 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# Architecture Docs Index - -## Contents - -- [01_overview.md](./01_overview.md) — Architecture overview and entry point -- [specs/](./specs/) — Functional, technical, and API specifications -- [diagrams/](./diagrams/) — Architecture diagrams -- [decisions/](./decisions/) — Architecture Decision Records (ADRs) diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/decisions/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/decisions/README.md deleted file mode 100644 index e488986f..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/decisions/README.md +++ /dev/null @@ -1,16 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# ADR Index - -## Decision Records - -- [01-adopt-agentkit-forge.md](./01-adopt-agentkit-forge.md) -- [02-fallback-policy-tokens-problem.md](./02-fallback-policy-tokens-problem.md) -- [03-tooling-strategy.md](./03-tooling-strategy.md) -- [04-static-security-analysis-depth-tooling.md](./04-static-security-analysis-depth-tooling.md) -- [05-dependency-supply-chain-detection-tooling.md](./05-dependency-supply-chain-detection-tooling.md) -- [06-code-quality-maintainability-signal-tooling.md](./06-code-quality-maintainability-signal-tooling.md) -- [07-delivery-strategy.md](./07-delivery-strategy.md) -- [08-issue-sync-strategy.md](./08-issue-sync-strategy.md) diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/diagrams/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/diagrams/README.md deleted file mode 100644 index f93d1b98..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/diagrams/README.md +++ /dev/null @@ -1,16 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# Architecture Diagrams Index - -## Contents - -- Add C4 and deployment diagrams in this folder. -- Keep diagram files named with ordered prefixes when sequence matters (`01_`, `02_`, ...). - -## Recommended Diagrams - -- `01_system-context.mmd` (C4 L1) -- `02_container-view.mmd` (C4 L2) -- `03_deployment-view.mmd` (runtime/deployment) diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/specs/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/specs/README.md deleted file mode 100644 index abdab96a..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/architecture/specs/README.md +++ /dev/null @@ -1,12 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# Specs Docs Index - -## Contents - -- [01_functional_spec.md](./01_functional_spec.md) -- [02_technical_spec.md](./02_technical_spec.md) -- [03_api_spec.md](./03_api_spec.md) -- [04_data_models.md](./04_data_models.md) diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/engineering/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/engineering/README.md deleted file mode 100644 index 9deaffc9..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/engineering/README.md +++ /dev/null @@ -1,16 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# Engineering Docs Index - -## Contents - -- [01_setup.md](./01_setup.md) -- [02_coding_standards.md](./02_coding_standards.md) -- [03_testing.md](./03_testing.md) -- [04_git_workflow.md](./04_git_workflow.md) -- [05_security.md](./05_security.md) -- [06_pr_documentation.md](./06_pr_documentation.md) -- [07_changelog.md](./07_changelog.md) -- [08_scaffold_management.md](./08_scaffold_management.md) diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/README.md deleted file mode 100644 index ecab947d..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/README.md +++ /dev/null @@ -1,67 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# History - -Historical documentation for significant PRs and implementations in agentkit-forge. - -## Directory Structure - -| Directory | Description | -| -------------------------------------- | ---------------------------------------------- | -| [implementations/](./implementations/) | Major implementations and architecture changes | -| [bug-fixes/](./bug-fixes/) | Complex or critical bug resolutions | -| [features/](./features/) | New feature launches | -| [migrations/](./migrations/) | Major migrations and upgrades | -| [issues/](./issues/) | Issues encountered during development sessions | -| [lessons-learned/](./lessons-learned/) | Lessons learned from retrospectives | - -## Naming Convention - -Files use the format: `XXXX-YYYY-MM-DD-[title]-[type].md` - -- `XXXX` — sequential 4-digit number (maintained in [.index.json](./.index.json)) -- `YYYY-MM-DD` — completion date -- `[title]` — kebab-case title -- `[type]` — `implementation`, `bugfix`, `feature`, `migration`, `issue`, or `lesson` - -## Creating New Documentation - -Use the provided script to generate a new document from the correct template: - -```bash -# Bash -./scripts/create-doc.sh implementation "Feature Name" <pr-number> -./scripts/create-doc.sh bugfix "Bug Description" <pr-number> -./scripts/create-doc.sh feature "Feature Name" <pr-number> -./scripts/create-doc.sh migration "Migration Name" <pr-number> -./scripts/create-doc.sh issue "Issue Title" -./scripts/create-doc.sh lesson "Lesson Title" -``` - -> **Note:** Issue and lesson records are created automatically via -> `/review --focus=retrospective`, not through the create-doc script. -> -> **Fallback:** When `gh` CLI is unavailable (proxy failures, air-gapped -> environments), use `./scripts/create-doc.sh issue "Title"` to record issues -> locally, then run `./scripts/sync-issues.sh --apply` once access is restored. - -The `/review` command with `--focus=retrospective` automates issue and lesson -creation at end-of-session (non-blocking — never gates delivery): - -```bash -# Via agent command -/review --focus=retrospective # Full retrospective: issues + lessons -/review --focus=retrospective --dry-run # Preview without writing -/review --focus=retrospective --open-issues # Also create GitHub issues for unresolved problems -``` - -```powershell -# PowerShell -./scripts/create-doc.ps1 implementation "Feature Name" <pr-number> -``` - -Or use the `/document-history` slash command for auto-detection of type and title from session context. - -See [docs/engineering/06_pr_documentation.md](../engineering/06_pr_documentation.md) for the full documentation strategy. diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/bug-fixes/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/bug-fixes/README.md deleted file mode 100644 index 011ae350..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/bug-fixes/README.md +++ /dev/null @@ -1,8 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Bug Fixes - -Historical records of complex or critical bug resolutions. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/features/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/features/README.md deleted file mode 100644 index 4e4a4c82..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/features/README.md +++ /dev/null @@ -1,8 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Features - -Historical records of new feature launches. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/implementations/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/implementations/README.md deleted file mode 100644 index afc0d54d..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/implementations/README.md +++ /dev/null @@ -1,8 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Implementations - -Historical records of major implementations, architecture changes, and significant refactoring. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/issues/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/issues/README.md deleted file mode 100644 index 53ac6b6a..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/issues/README.md +++ /dev/null @@ -1,42 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Issues - -Historical records of issues encountered during development sessions. - -## Creating Issue Records - -### Preferred: GitHub Issues via `gh` - -When the GitHub CLI is available and authenticated, create issues directly: - -```bash -gh issue create --title "Issue Title" --body "Description" -``` - -### Fallback: Local Issue Docs - -When `gh` is unavailable (no CLI installed, proxy/auth failures, air-gapped -environments), record issues locally as structured markdown: - -```bash -./scripts/create-doc.sh issue "Issue Title" -``` - -Issues are also logged automatically by `/review --focus=retrospective` at the -end of a session. - -### Syncing Local Issues to GitHub - -Once `gh` access is restored, sync local issue docs to GitHub Issues: - -```bash -./scripts/sync-issues.sh # Dry-run by default -./scripts/sync-issues.sh --apply # Create GitHub Issues and mark synced -``` - -See [ADR-08](../../architecture/decisions/08-issue-sync-strategy.md) for -the sync strategy and automation decisions. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/lessons-learned/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/lessons-learned/README.md deleted file mode 100644 index 5acf19fb..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/lessons-learned/README.md +++ /dev/null @@ -1,11 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Lessons Learned - -Historical records of lessons learned during development sessions. - -Lessons are logged automatically by `/review --focus=retrospective` at the end of -a session, or manually via `scripts/create-doc.sh lesson "Lesson Title"`. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/migrations/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/migrations/README.md deleted file mode 100644 index 672df4f0..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/history/migrations/README.md +++ /dev/null @@ -1,8 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Migrations - -Historical records of major migrations and upgrades. - -See [docs/history/README.md](../README.md) for naming conventions and usage. diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/integrations/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/integrations/README.md deleted file mode 100644 index 48aa94c7..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/integrations/README.md +++ /dev/null @@ -1,11 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# Integrations Docs Index - -## Contents - -- [01_external_apis.md](./01_external_apis.md) -- [02_webhooks.md](./02_webhooks.md) -- [03_sdk.md](./03_sdk.md) diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/operations/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/operations/README.md deleted file mode 100644 index 5918083e..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/operations/README.md +++ /dev/null @@ -1,13 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# Operations Docs Index - -## Contents - -- [01_deployment.md](./01_deployment.md) -- [02_monitoring.md](./02_monitoring.md) -- [03_incident_response.md](./03_incident_response.md) -- [04_troubleshooting.md](./04_troubleshooting.md) -- [05_slos_slis.md](./05_slos_slis.md) diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/product/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/product/README.md deleted file mode 100644 index ce11aaf5..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/product/README.md +++ /dev/null @@ -1,12 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# Product Docs Index - -## Contents - -- [01_prd.md](./01_prd.md) -- [02_user_stories.md](./02_user_stories.md) -- [03_roadmap.md](./03_roadmap.md) -- [04_personas.md](./04_personas.md) diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/reference/README.md b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/reference/README.md deleted file mode 100644 index 3921959d..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/docs/reference/README.md +++ /dev/null @@ -1,14 +0,0 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> -<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> - -# Reference Docs Index - -## Contents - -- [01_glossary.md](./01_glossary.md) -- [02_faq.md](./02_faq.md) -- [03_changelog.md](./03_changelog.md) -- [04_contributing.md](./04_contributing.md) -- [05_project_yaml_reference.md](./05_project_yaml_reference.md) -- [ai_handoffs/](./ai_handoffs/) diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/analyze-agents.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/analyze-agents.sh deleted file mode 100644 index fd5324d6..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/analyze-agents.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/analyze-agents.sh -# Generates agent/team relationship matrices from spec files. -# -# Usage: -# ./scripts/analyze-agents.sh [--output <path>] [--matrix <n>] [--format <fmt>] -# -# Options: -# --output <path> Output file (default: docs/agents/agent-team-matrix.md) -# --matrix <n> Specific matrix: 1-8, supplementary, all (default: all) -# --format <fmt> Output format: markdown, json (default: markdown) - -set -euo pipefail -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -node "$PROJECT_ROOT/.agentkit/engines/node/src/cli.mjs" analyze-agents "$@" diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/check-documentation-requirement.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/check-documentation-requirement.sh deleted file mode 100644 index 944d7501..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/check-documentation-requirement.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/check-documentation-requirement.sh -# Analyzes staged or changed files to determine whether PR documentation is required. -# -# Usage (pre-commit hook): -# ./scripts/check-documentation-requirement.sh -# -# Exit codes: -# 0 — documentation not required or already present -# 1 — documentation required but not present (when --strict is passed) -# -# Environment variables: -# GITHUB_BASE_REF — set automatically in GitHub Actions PR workflows -# STRICT — set to "true" to exit 1 when documentation is required - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -HISTORY_DIR="$REPO_ROOT/docs/history" -STRICT="${STRICT:-false}" - -# --------------------------------------------------------------------------- -# Collect changed files -# --------------------------------------------------------------------------- - -if [[ -n "${GITHUB_BASE_REF:-}" ]]; then - # Running inside GitHub Actions pull_request event - CHANGED_FILES=$(git diff --name-only "origin/${GITHUB_BASE_REF}" HEAD 2>/dev/null || git diff --name-only HEAD~1 HEAD) -else - # Running locally — inspect staged files, fall back to last commit - CHANGED_FILES=$(git diff --cached --name-only 2>/dev/null) - if [[ -z "$CHANGED_FILES" ]]; then - CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || true) - fi -fi - -if [[ -z "$CHANGED_FILES" ]]; then - echo "ℹ️ No changed files detected." - exit 0 -fi - -# --------------------------------------------------------------------------- -# Impact assessment -# --------------------------------------------------------------------------- - -IMPACT_HIGH=false -IMPACT_MEDIUM=false - -while IFS= read -r file; do - # High impact: project files, CI, security configs, infrastructure - if [[ "$file" == *.csproj || "$file" == package.json || "$file" == Cargo.toml || \ - "$file" == go.mod || "$file" == pyproject.toml || "$file" == build.gradle || \ - "$file" == .github/workflows/*.yml || "$file" == .github/workflows/*.yaml || \ - "$file" == Dockerfile* || "$file" == docker-compose*.yml || \ - "$file" == **/terraform/**/*.tf || "$file" == **/infra/**/*.tf ]]; then - IMPACT_HIGH=true - # Medium impact: source code files - elif [[ "$file" == src/**/*.cs || "$file" == src/**/*.ts || "$file" == src/**/*.tsx || \ - "$file" == src/**/*.py || "$file" == src/**/*.rs || "$file" == src/**/*.go || \ - "$file" == lib/**/*.* || "$file" == packages/**/*.* ]]; then - IMPACT_MEDIUM=true - fi -done <<< "$CHANGED_FILES" - -# --------------------------------------------------------------------------- -# Count changed files -# --------------------------------------------------------------------------- - -CHANGED_COUNT=$(echo "$CHANGED_FILES" | wc -l | tr -d ' ') - -if [[ "$CHANGED_COUNT" -gt 50 ]]; then - IMPACT_HIGH=true -fi - -# --------------------------------------------------------------------------- -# Check if documentation already exists for this branch/PR -# --------------------------------------------------------------------------- - -# Count history docs that have been staged or added in this branch -HISTORY_DOCS=0 -if [[ -n "${GITHUB_BASE_REF:-}" ]]; then - HISTORY_DOCS=$(git diff --name-only "origin/${GITHUB_BASE_REF}" HEAD -- 'docs/history/**/*.md' 2>/dev/null | grep -v 'README\.md\|TEMPLATE-' | wc -l | tr -d ' ' || echo 0) -else - HISTORY_DOCS=$(git diff --cached --name-only -- 'docs/history/*.md' 'docs/history/**/*.md' 2>/dev/null | grep -v 'README\.md\|TEMPLATE-' | wc -l | tr -d ' ' || echo 0) -fi - -# --------------------------------------------------------------------------- -# Output assessment -# --------------------------------------------------------------------------- - -if [[ "$IMPACT_HIGH" == true ]]; then - echo "⚠️ HIGH IMPACT change detected — documentation required" - echo " Changed files: $CHANGED_COUNT" - if [[ "$HISTORY_DOCS" -gt 0 ]]; then - echo "✅ Documentation found ($HISTORY_DOCS new doc(s) in docs/history/)" - exit 0 - else - echo " Run: ./scripts/create-doc.sh <type> \"<title>\" <pr-number>" - echo " See: docs/engineering/06_pr_documentation.md" - if [[ "$STRICT" == "true" ]]; then - exit 1 - fi - fi -elif [[ "$IMPACT_MEDIUM" == true ]]; then - echo "ℹ️ MEDIUM IMPACT change detected — documentation recommended" - echo " Run: ./scripts/create-doc.sh <type> \"<title>\" <pr-number>" -else - echo "✅ LOW IMPACT change — documentation optional" -fi - -exit 0 diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/consolidate-branches.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/consolidate-branches.sh deleted file mode 100644 index 9aa9b746..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/consolidate-branches.sh +++ /dev/null @@ -1,289 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# ============================================================================= -# consolidate-branches.sh — Merge all unmerged feature branches into one -# ============================================================================= -# Usage: scripts/consolidate-branches.sh [base-branch] [--dry-run] [--skip=branch1,branch2] -# -# Discovers all local and remote branches not yet merged into <base-branch>, -# filters out protected branches, and merges them one by one into the current -# branch. Uses resolve-merge.sh for auto-resolution of generated files. -# -# Arguments: -# base-branch Branch to check "merged" status against (default: main) -# --dry-run List branches that would be merged without doing anything -# --skip=X,Y Comma-separated list of branch names to skip -# -# Examples: -# scripts/consolidate-branches.sh # merge all into current -# scripts/consolidate-branches.sh dev --dry-run # preview what would merge -# scripts/consolidate-branches.sh main --skip=wip/experiment -# ============================================================================= -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -# Colours (disabled when piped) -if [ -t 1 ]; then - GREEN='\033[0;32m' - YELLOW='\033[1;33m' - RED='\033[0;31m' - CYAN='\033[0;36m' - BOLD='\033[1m' - NC='\033[0m' -else - GREEN='' YELLOW='' RED='' CYAN='' BOLD='' NC='' -fi - -info() { echo -e "${CYAN}[info]${NC} $*"; } -ok() { echo -e "${GREEN}[ok]${NC} $*"; } -warn() { echo -e "${YELLOW}[warn]${NC} $*"; } -err() { echo -e "${RED}[error]${NC} $*"; } - -# --------------------------------------------------------------------------- -# Parse arguments -# --------------------------------------------------------------------------- -BASE_BRANCH="main" -DRY_RUN=false -SKIP_BRANCHES="" - -for arg in "$@"; do - case "$arg" in - --dry-run) DRY_RUN=true ;; - --skip=*) SKIP_BRANCHES="${arg#--skip=}" ;; - -*) err "Unknown flag: $arg"; exit 1 ;; - *) BASE_BRANCH="$arg" ;; - esac -done - -cd "$REPO_ROOT" - -CURRENT_BRANCH="$(git branch --show-current)" -if [ -z "$CURRENT_BRANCH" ]; then - err "Not on a branch (detached HEAD). Checkout a branch first." - exit 1 -fi - -# --------------------------------------------------------------------------- -# Protected branches — never auto-merge these -# --------------------------------------------------------------------------- -PROTECTED_BRANCHES="main master develop release" - -is_protected() { - local branch="$1" - for p in $PROTECTED_BRANCHES; do - [ "$branch" = "$p" ] && return 0 - done - return 1 -} - -is_skipped() { - local branch="$1" - if [ -n "$SKIP_BRANCHES" ]; then - IFS=',' read -ra SKIPS <<< "$SKIP_BRANCHES" - for s in "${SKIPS[@]}"; do - [ "$branch" = "$s" ] && return 0 - done - fi - return 1 -} - -# --------------------------------------------------------------------------- -# 1. Fetch all remotes -# --------------------------------------------------------------------------- -info "Fetching all remotes..." -git fetch --all --prune 2>/dev/null || warn "Fetch failed — continuing with local state" - -# --------------------------------------------------------------------------- -# 2. Discover unmerged branches -# --------------------------------------------------------------------------- -info "Finding branches not merged into ${BASE_BRANCH}..." - -# Get all remote branches not merged into base -UNMERGED=() -while IFS= read -r ref; do - [ -z "$ref" ] && continue - # Strip 'origin/' prefix for display - branch="${ref#origin/}" - - # Skip current branch, base branch, HEAD pointer - [ "$branch" = "$CURRENT_BRANCH" ] && continue - [ "$branch" = "$BASE_BRANCH" ] && continue - [ "$branch" = "HEAD" ] && continue - - # Skip protected branches - is_protected "$branch" && continue - - # Skip user-specified branches - is_skipped "$branch" && continue - - UNMERGED+=("$branch") -done < <(git branch -r --no-merged "origin/${BASE_BRANCH}" 2>/dev/null | sed 's/^[* ]*//' | sort) - -# Also check local-only branches (not on remote) -while IFS= read -r branch; do - [ -z "$branch" ] && continue - [ "$branch" = "$CURRENT_BRANCH" ] && continue - [ "$branch" = "$BASE_BRANCH" ] && continue - is_protected "$branch" && continue - is_skipped "$branch" && continue - - # Check if already in UNMERGED list - already=false - for u in "${UNMERGED[@]+"${UNMERGED[@]}"}"; do - [ "$u" = "$branch" ] && already=true && break - done - $already && continue - - UNMERGED+=("$branch") -done < <(git branch --no-merged "$BASE_BRANCH" 2>/dev/null | sed 's/^[* ]*//' | sort) - -if [ ${#UNMERGED[@]} -eq 0 ]; then - ok "No unmerged branches found. Everything is up to date with ${BASE_BRANCH}." - exit 0 -fi - -# --------------------------------------------------------------------------- -# 3. Display plan -# --------------------------------------------------------------------------- -echo "" -echo -e "${BOLD}Branch Consolidation Plan${NC}" -echo -e "${BOLD}========================${NC}" -echo "" -echo -e " Current branch: ${GREEN}${CURRENT_BRANCH}${NC}" -echo -e " Base branch: ${CYAN}${BASE_BRANCH}${NC}" -echo -e " Branches to merge: ${#UNMERGED[@]}" -echo "" - -for i in "${!UNMERGED[@]}"; do - branch="${UNMERGED[$i]}" - # Get commit count ahead of base - ahead=$(git rev-list --count "origin/${BASE_BRANCH}..origin/${branch}" 2>/dev/null || echo "?") - echo -e " $((i + 1)). ${YELLOW}${branch}${NC} (${ahead} commits ahead)" -done - -echo "" - -if $DRY_RUN; then - info "Dry run — no changes made." - exit 0 -fi - -# --------------------------------------------------------------------------- -# 4. Merge each branch -# --------------------------------------------------------------------------- -MERGED=() -FAILED=() -SKIPPED_DIRTY=() - -for branch in "${UNMERGED[@]}"; do - echo "" - echo -e "${BOLD}─────────────────────────────────────────${NC}" - info "Merging ${branch} ($(( ${#MERGED[@]} + ${#FAILED[@]} + 1 ))/${#UNMERGED[@]})..." - - # Check for uncommitted changes before each merge - if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then - warn "Uncommitted changes detected. Stashing before merge..." - git stash push -m "consolidate-branches: before merging ${branch}" 2>/dev/null - fi - - # Try merging from remote first, fall back to local - merge_ref="origin/${branch}" - if ! git rev-parse --verify "$merge_ref" &>/dev/null; then - merge_ref="$branch" - fi - - merge_output=$(git merge "$merge_ref" --no-edit 2>&1) && { - ok "Merged ${branch} cleanly." - MERGED+=("$branch") - continue - } - - # Check if it's a conflict or other error - if echo "$merge_output" | grep -qF "CONFLICT"; then - warn "Conflicts merging ${branch}. Attempting auto-resolution..." - - # Use resolve-merge logic inline (auto-resolve generated files) - auto_resolved=0 - while IFS= read -r file; do - [ -z "$file" ] && continue - case "$file" in - .claude/*|.cursor/*|.windsurf/*|.roo/*|.clinerules/*|.github/instructions/*|\ - .github/copilot-instructions.md|.github/PULL_REQUEST_TEMPLATE.md|\ - .github/agents/*|.github/chatmodes/*|.github/prompts/*|\ - .agents/*|.gemini/*|docs/*/README.md|scripts/*.sh|scripts/*.ps1|\ - AGENTS.md|UNIFIED_AGENT_TEAMS.md|COMMAND_GUIDE.md|QUALITY_GATES.md|\ - RUNBOOK_AI.md|CONTRIBUTING.md) - git checkout --theirs -- "$file" 2>/dev/null && git add "$file" 2>/dev/null - ok " Auto-resolved: $file" - auto_resolved=$((auto_resolved + 1)) - ;; - pnpm-lock.yaml|.agentkit/pnpm-lock.yaml|package-lock.json|yarn.lock|.agentkit/yarn.lock) - git checkout --theirs -- "$file" 2>/dev/null && git add "$file" 2>/dev/null - ok " Auto-resolved (lockfile): $file" - auto_resolved=$((auto_resolved + 1)) - ;; - esac - done < <(git diff --name-only --diff-filter=U 2>/dev/null) - - # Check if any conflicts remain - remaining=$(git diff --name-only --diff-filter=U 2>/dev/null || true) - if [ -z "$remaining" ]; then - git commit --no-edit 2>/dev/null - ok "Merged ${branch} (${auto_resolved} auto-resolved)." - MERGED+=("$branch") - else - err "Unresolved conflicts merging ${branch}:" - echo "$remaining" | while IFS= read -r f; do - echo -e " ${RED}✗${NC} $f" - done - warn "Aborting merge of ${branch}. Resolve manually or re-run with --skip=${branch}" - git merge --abort 2>/dev/null || true - FAILED+=("$branch") - fi - else - err "Merge of ${branch} failed (not a conflict):" - echo " $merge_output" - git merge --abort 2>/dev/null || true - FAILED+=("$branch") - fi -done - -# --------------------------------------------------------------------------- -# 5. Summary -# --------------------------------------------------------------------------- -echo "" -echo -e "${BOLD}═══════════════════════════════════════════${NC}" -echo -e "${BOLD}Consolidation Summary${NC}" -echo -e "${BOLD}═══════════════════════════════════════════${NC}" -echo "" -echo -e " ${GREEN}Merged:${NC} ${#MERGED[@]}/${#UNMERGED[@]}" - -if [ ${#MERGED[@]} -gt 0 ]; then - for b in "${MERGED[@]}"; do - echo -e " ${GREEN}✓${NC} $b" - done -fi - -if [ ${#FAILED[@]} -gt 0 ]; then - echo "" - echo -e " ${RED}Failed:${NC} ${#FAILED[@]}/${#UNMERGED[@]}" - for b in "${FAILED[@]}"; do - echo -e " ${RED}✗${NC} $b" - done - echo "" - warn "Re-run with: scripts/consolidate-branches.sh ${BASE_BRANCH} --skip=$(IFS=,; echo "${MERGED[*]}")" -fi - -echo "" -if [ ${#MERGED[@]} -gt 0 ]; then - info "Next steps:" - echo " 1. Run: pnpm -C .agentkit agentkit:sync" - echo " 2. Run: pnpm test" - echo " 3. Review with: git log --oneline -20" -fi - -exit ${#FAILED[@]} diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/create-doc.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/create-doc.sh deleted file mode 100644 index 318e7fe7..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/create-doc.sh +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/create-doc.sh -# Creates a new history document from the appropriate template. -# -# Usage: -# ./scripts/create-doc.sh <type> "<title>" [pr-number] -# -# Arguments: -# type Document type: implementation | bugfix | feature | migration -# title Human-readable title for the document -# pr-number Optional PR number to include in the document -# -# Examples: -# ./scripts/create-doc.sh implementation "TreatWarningsAsErrors" 42 -# ./scripts/create-doc.sh bugfix "Null Reference in Auth" 43 -# ./scripts/create-doc.sh feature "User Authentication" 44 -# ./scripts/create-doc.sh migration "Upgrade to Node 22" 45 - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -HISTORY_DIR="$REPO_ROOT/docs/history" -INDEX_FILE="$HISTORY_DIR/.index.json" - -# --------------------------------------------------------------------------- -# Argument validation -# --------------------------------------------------------------------------- - -usage() { - echo "Usage: $0 <type> \"<title>\" [pr-number]" - echo " type: implementation | bugfix | feature | migration | issue | lesson" - exit 1 -} - -if [[ $# -lt 2 ]]; then - usage -fi - -TYPE="$1" -TITLE="$2" -PR_NUMBER="${3:-}" - -case "$TYPE" in - implementation|bugfix|feature|migration|issue|lesson) ;; - *) echo "Error: unknown type '$TYPE'. Must be one of: implementation, bugfix, feature, migration, issue, lesson"; exit 1 ;; -esac - -# --------------------------------------------------------------------------- -# Determine subdirectory from type -# --------------------------------------------------------------------------- - -case "$TYPE" in - implementation) SUBDIR="implementations" ;; - bugfix) SUBDIR="bug-fixes" ;; - feature) SUBDIR="features" ;; - migration) SUBDIR="migrations" ;; - issue) SUBDIR="issues" ;; - lesson) SUBDIR="lessons-learned" ;; -esac - -# --------------------------------------------------------------------------- -# Read and update the sequential index -# --------------------------------------------------------------------------- - -if [[ ! -f "$INDEX_FILE" ]]; then - echo '{"sequences":{"implementation":1,"bugfix":1,"feature":1,"migration":1,"issue":1,"lesson":1},"entries":[]}' > "$INDEX_FILE" -fi - -# Use node to read the current sequence number safely (no user input interpolated) -SEQ_NUM=$(node - "$INDEX_FILE" "$TYPE" << 'NODEEOF' - const [,, indexFile, type] = process.argv; - const fs = require('fs'); - const idx = JSON.parse(fs.readFileSync(indexFile, 'utf8')); - process.stdout.write(String(idx.sequences[type] || 1)); -NODEEOF -) - -PADDED=$(printf "%04d" "$SEQ_NUM") -DATE=$(date +%Y-%m-%d) - -# Sanitize title: lowercase, spaces to hyphens, remove non-alphanumeric except hyphens -SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-\|-$//g') - -FILENAME="${PADDED}-${DATE}-${SLUG}-${TYPE}.md" -DEST_DIR="$HISTORY_DIR/$SUBDIR" -DEST_FILE="$DEST_DIR/$FILENAME" - -mkdir -p "$DEST_DIR" - -# --------------------------------------------------------------------------- -# Copy template and substitute placeholders -# --------------------------------------------------------------------------- - -TEMPLATE_SRC="$REPO_ROOT/.agentkit/templates/docs/history/$SUBDIR/TEMPLATE-${TYPE}.md" - -if [[ ! -f "$TEMPLATE_SRC" ]]; then - echo "Error: template not found at $TEMPLATE_SRC" - exit 1 -fi - -PR_REF="${PR_NUMBER:+#${PR_NUMBER}}" - -# Perform literal replacements using Node.js to avoid sed injection -TITLE_VAL="$TITLE" DATE_VAL="$DATE" PR_REF_VAL="${PR_REF:-[#PR-Number]}" \ -node - "$TEMPLATE_SRC" "$DEST_FILE" << 'NODEEOF' - const fs = require('fs'); - const [,, src, dest] = process.argv; - let content = fs.readFileSync(src, 'utf8'); - - const replacements = { - '[Feature/Change Name]': process.env.TITLE_VAL, - '[Bug Description]': process.env.TITLE_VAL, - '[Feature Name]': process.env.TITLE_VAL, - '[Migration Name]': process.env.TITLE_VAL, - '[Issue Title]': process.env.TITLE_VAL, - '[Lesson Title]': process.env.TITLE_VAL, - '[YYYY-MM-DD]': process.env.DATE_VAL, - '[#PR-Number]': process.env.PR_REF_VAL - }; - - for (const [placeholder, value] of Object.entries(replacements)) { - content = content.split(placeholder).join(value); - } - - fs.writeFileSync(dest, content, 'utf8'); -NODEEOF - -# --------------------------------------------------------------------------- -# Update index -# --------------------------------------------------------------------------- - -node - "$INDEX_FILE" "$TYPE" "$SEQ_NUM" "$TITLE" "$DATE" "${PR_NUMBER:-}" "$SUBDIR/$FILENAME" << 'NODEEOF' - const [,, indexFile, type, seqNum, title, date, pr, file] = process.argv; - const fs = require('fs'); - const idx = JSON.parse(fs.readFileSync(indexFile, 'utf8')); - idx.sequences[type] = (idx.sequences[type] || 1) + 1; - idx.entries = idx.entries || []; - idx.entries.push({ number: Number(seqNum), type, title, date, pr, file }); - fs.writeFileSync(indexFile, JSON.stringify(idx, null, 2) + '\n'); -NODEEOF - -echo "Created: $DEST_FILE" - -# --------------------------------------------------------------------------- -# Update CHANGELOG.md -# --------------------------------------------------------------------------- - -# Map history doc type to changelog section -case "$TYPE" in - feature) CHANGELOG_SECTION="Added" ;; - implementation) CHANGELOG_SECTION="Added" ;; - bugfix) CHANGELOG_SECTION="Fixed" ;; - migration) CHANGELOG_SECTION="Changed" ;; - issue) CHANGELOG_SECTION="" ;; # Issues don't go in changelog - lesson) CHANGELOG_SECTION="" ;; # Lessons don't go in changelog -esac - -UPDATE_CHANGELOG="$SCRIPT_DIR/update-changelog.sh" -if [[ -z "$CHANGELOG_SECTION" ]]; then - echo "ℹ️ ${TYPE} records are not added to CHANGELOG.md — skipping changelog update." -elif [[ -f "$UPDATE_CHANGELOG" ]]; then - bash "$UPDATE_CHANGELOG" "$CHANGELOG_SECTION" "$TITLE" "${PR_NUMBER:-}" "$SUBDIR/$FILENAME" || \ - echo "⚠️ Could not update CHANGELOG.md — please add the entry manually." -else - echo "ℹ️ update-changelog.sh not found — skipping changelog update." -fi diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/resolve-merge.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/resolve-merge.sh deleted file mode 100644 index a3daecff..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/resolve-merge.sh +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# ============================================================================= -# resolve-merge.sh — Apply standard merge conflict resolutions -# ============================================================================= -# Usage: scripts/resolve-merge.sh [target-branch] -# -# Merges origin/<target-branch> into the current branch and auto-resolves -# generated/framework-managed files per the AgentKit merge resolution matrix. -# Remaining conflicts (engine source, spec files) are listed for manual review. -# ============================================================================= -set -euo pipefail - -TARGET="${1:-main}" -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -# Colours (disabled when piped) -if [ -t 1 ]; then - GREEN='\033[0;32m' - YELLOW='\033[1;33m' - RED='\033[0;31m' - CYAN='\033[0;36m' - NC='\033[0m' -else - GREEN='' YELLOW='' RED='' CYAN='' NC='' -fi - -info() { echo -e "${CYAN}[info]${NC} $*"; } -ok() { echo -e "${GREEN}[ok]${NC} $*"; } -warn() { echo -e "${YELLOW}[warn]${NC} $*"; } -err() { echo -e "${RED}[error]${NC} $*"; } - -cd "$REPO_ROOT" - -# --------------------------------------------------------------------------- -# 1. Fetch and attempt merge -# --------------------------------------------------------------------------- -info "Fetching origin/${TARGET}..." -git fetch origin "$TARGET" 2>/dev/null || { - err "Failed to fetch origin/${TARGET}. Check your remote." - exit 1 -} - -CURRENT_BRANCH="$(git branch --show-current)" -info "Merging origin/${TARGET} into ${CURRENT_BRANCH}..." - -merge_output=$(git merge "origin/${TARGET}" --no-edit 2>&1) && { - ok "Merge completed cleanly — no conflicts." - exit 0 -} - -# Distinguish real merge conflicts from other failures -if ! echo "$merge_output" | grep -qF "CONFLICT"; then - err "Merge failed for a reason other than conflicts:" - echo "$merge_output" - exit 1 -fi - -info "Merge conflicts detected. Applying resolution matrix..." - -# --------------------------------------------------------------------------- -# 2. Auto-resolve generated files (KEEP_THEIRS — accept upstream) -# --------------------------------------------------------------------------- -GENERATED_PATTERNS=( - '.agents/skills/*/SKILL.md' - '.github/agents/*.agent.md' - '.github/chatmodes/*.chatmode.md' - '.github/prompts/*.prompt.md' - 'docs/*/README.md' - '.github/copilot-instructions.md' - '.github/PULL_REQUEST_TEMPLATE.md' -) - -auto_resolved=0 -for pattern in "${GENERATED_PATTERNS[@]}"; do - # Find conflicted files matching this pattern - while IFS= read -r file; do - [ -z "$file" ] && continue - if git checkout --theirs -- "$file" 2>/dev/null; then - git add "$file" 2>/dev/null - ok "Auto-resolved (accept upstream): $file" - auto_resolved=$((auto_resolved + 1)) - fi - done < <(git diff --name-only --diff-filter=U | grep -E "$pattern" 2>/dev/null || true) -done - -# --------------------------------------------------------------------------- -# 3. Auto-resolve lockfiles (KEEP_THEIRS — accept upstream, regenerate later) -# --------------------------------------------------------------------------- -LOCKFILE_PATTERNS=( - 'pnpm-lock.yaml' - '.agentkit/pnpm-lock.yaml' - 'package-lock.json' - '.agentkit/package-lock.json' -) - -for lockfile in "${LOCKFILE_PATTERNS[@]}"; do - if git diff --name-only --diff-filter=U | grep -qx "$lockfile" 2>/dev/null; then - if git checkout --theirs -- "$lockfile" 2>/dev/null; then - git add "$lockfile" 2>/dev/null - ok "Auto-resolved (accept upstream): $lockfile" - auto_resolved=$((auto_resolved + 1)) - fi - fi -done - -# --------------------------------------------------------------------------- -# 4. Auto-resolve generated config (KEEP_THEIRS) -# --------------------------------------------------------------------------- -GENERATED_CONFIGS=( - '.gemini/config.yaml' -) - -for config in "${GENERATED_CONFIGS[@]}"; do - if git diff --name-only --diff-filter=U | grep -qx "$config" 2>/dev/null; then - if git checkout --theirs -- "$config" 2>/dev/null; then - git add "$config" 2>/dev/null - ok "Auto-resolved (accept upstream): $config" - auto_resolved=$((auto_resolved + 1)) - fi - fi -done - -# --------------------------------------------------------------------------- -# 5. Report remaining conflicts -# --------------------------------------------------------------------------- -REMAINING="$(git diff --name-only --diff-filter=U 2>/dev/null || true)" - -echo "" -info "Auto-resolved: ${auto_resolved} file(s)" - -if [ -n "$REMAINING" ]; then - echo "" - warn "Manual merge required for the following file(s):" - echo "" - while IFS= read -r file; do - [ -z "$file" ] && continue - # Categorise for the developer - case "$file" in - .agentkit/engines/*) echo -e " ${RED}[engine]${NC} $file — semantic merge required (runtime logic)" ;; - .agentkit/spec/*) echo -e " ${YELLOW}[spec]${NC} $file — preserve both intents" ;; - *) echo -e " ${CYAN}[source]${NC} $file" ;; - esac - done <<< "$REMAINING" - echo "" - info "Resolve the files above, then run: git add -A && git commit" - exit 1 -else - ok "All conflicts resolved automatically." - info "Committing merge..." - git commit --no-edit - ok "Merge committed successfully." - - # Suggest lockfile regeneration - if git diff --name-only "HEAD~1..HEAD" | grep -q "lock\.\(yaml\|json\)$" 2>/dev/null; then - echo "" - warn "Lockfiles were updated. Consider running: pnpm install" - fi -fi diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/setup-agentkit-branch-governance.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/setup-agentkit-branch-governance.sh deleted file mode 100644 index f955e11b..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/setup-agentkit-branch-governance.sh +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -set -euo pipefail - -REPO="" -DRY_RUN=false -SKIP_DEFAULT_BRANCH=false -SKIP_PROTECTION=false - -while [[ $# -gt 0 ]]; do - case "$1" in - --repo) - if [[ $# -lt 2 || -z "${2:-}" || "${2:-}" == -* ]]; then - echo "Error: --repo requires a value in the form owner/name" - exit 1 - fi - REPO="$2" - shift 2 - ;; - --dry-run) - DRY_RUN=true - shift - ;; - --skip-default-branch) - SKIP_DEFAULT_BRANCH=true - shift - ;; - --skip-protection) - SKIP_PROTECTION=true - shift - ;; - --help|-h) - echo "Usage: $(basename "$0") [--repo owner/name] [--dry-run] [--skip-default-branch] [--skip-protection]" - exit 0 - ;; - *) - echo "Unknown option: $1" - exit 1 - ;; - esac -done - -if ! command -v gh >/dev/null 2>&1; then - echo "gh CLI is not installed. Install from https://cli.github.com/" - exit 1 -fi - -if ! gh auth status >/dev/null 2>&1; then - echo "gh CLI is not authenticated. Run 'gh auth login' first." - exit 1 -fi - -if [[ -z "$REPO" ]]; then - REPO=$(gh repo view --json nameWithOwner -q '.nameWithOwner' 2>/dev/null || true) -fi - -if [[ -z "$REPO" ]]; then - echo "Could not determine repository. Pass --repo <owner/name>." - exit 1 -fi - -echo "=== AgentKit Branch Governance Setup ===" -echo "Repository: $REPO" -echo "DryRun: $DRY_RUN" -echo - -if [[ "$SKIP_DEFAULT_BRANCH" == false ]]; then - if [[ "$DRY_RUN" == true ]]; then - echo "[dry-run] Would set default branch to 'main' for $REPO" - else - gh api --method PATCH "/repos/$REPO" -f default_branch='main' >/dev/null - echo "Default branch set to 'main'." - fi -fi - -PAYLOAD=$(cat <<'JSON' -{ - "required_status_checks": { - "strict": true, - "contexts": [ - "Test", - "Validate", - "Branch Protection / branch-rules" - ] - }, - "enforce_admins": false, - "required_pull_request_reviews": { - "required_approving_review_count": 1, - "dismiss_stale_reviews": true, - "require_code_owner_reviews": true, - "require_last_push_approval": false - }, - "restrictions": null, - "required_linear_history": true, - "allow_force_pushes": false, - "allow_deletions": false, - "block_creations": false, - "required_conversation_resolution": true -} -JSON -) - -if [[ "$SKIP_PROTECTION" == false ]]; then - # Deduplicate: if defaultBranch is 'main', don't apply twice - for BRANCH in $(echo "main main" | tr ' ' '\n' | awk '!seen[$0]++'); do - # Skip if the branch does not exist on the remote - if ! gh api "/repos/$REPO/branches/$BRANCH" --silent 2>/dev/null; then - echo "[skip] Branch '$BRANCH' does not exist on $REPO — skipping protection." - continue - fi - - if [[ "$DRY_RUN" == true ]]; then - echo "[dry-run] Would apply branch protection to $REPO/$BRANCH" - continue - fi - - gh api --method PUT "/repos/$REPO/branches/$BRANCH/protection" --input - <<< "$PAYLOAD" >/dev/null - echo "Branch protection applied to $BRANCH." - done -fi - -echo -echo "Done." -for BRANCH in $(echo "main main" | tr ' ' '\n' | awk '!seen[$0]++'); do - echo "Verify with: gh api /repos/$REPO/branches/$BRANCH/protection" -done diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/sync-issues.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/sync-issues.sh deleted file mode 100644 index 9ace772a..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/sync-issues.sh +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/sync-issues.sh -# Syncs local issue docs (docs/history/issues/) to GitHub Issues. -# -# Local issue markdown files that have "gh_synced: false" are candidates for -# sync. In dry-run mode (default) the script prints what would be created. -# With --apply it creates GitHub Issues via `gh` and stamps the file with the -# resulting issue number. -# -# Usage: -# ./scripts/sync-issues.sh # Dry-run — preview only -# ./scripts/sync-issues.sh --apply # Create GitHub Issues -# ./scripts/sync-issues.sh --apply --label "from-local" # Add extra label -# -# Requirements: -# - gh CLI installed and authenticated -# - Current directory inside the git repository - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -ISSUES_DIR="$REPO_ROOT/docs/history/issues" - -APPLY=false -EXTRA_LABEL="" - -while [[ $# -gt 0 ]]; do - case "$1" in - --apply) APPLY=true; shift ;; - --label) - [[ $# -ge 2 ]] || { echo "Error: --label requires a value"; exit 1; } - EXTRA_LABEL="$2"; shift 2 ;; - -h|--help) - echo "Usage: $0 [--apply] [--label <label>]" - echo " --apply Create GitHub Issues (default is dry-run)" - echo " --label Extra label to add to created issues" - exit 0 - ;; - *) echo "Unknown option: $1"; exit 1 ;; - esac -done - -# --------------------------------------------------------------------------- -# Preflight checks (only needed when actually creating issues) -# --------------------------------------------------------------------------- - -if [[ "$APPLY" == true ]]; then - if ! command -v gh &>/dev/null; then - echo "Error: gh CLI is not installed. Install it from https://cli.github.com/" - exit 1 - fi - - if ! gh auth status &>/dev/null; then - echo "Error: gh is not authenticated. Run 'gh auth login' first." - exit 1 - fi -fi - -# --------------------------------------------------------------------------- -# Discover unsynced issue files -# --------------------------------------------------------------------------- - -CANDIDATES=0 -SKIPPED=0 -FAILED=0 - -# Glob matches the enforced naming convention: XXXX-YYYY-MM-DD-slug-issue.md -# Files created outside create-doc.sh without the -issue suffix are not picked up. -for issue_file in "$ISSUES_DIR"/*-issue.md; do - [[ -f "$issue_file" ]] || continue - - basename_file="$(basename "$issue_file")" - - # Skip templates - if [[ "$basename_file" == TEMPLATE-* ]]; then - continue - fi - - # Check sync status - if ! grep -q 'gh_synced.*false' "$issue_file" 2>/dev/null; then - SKIPPED=$((SKIPPED + 1)) - continue - fi - - # Extract title from first H1 (|| true prevents set -e exit on no match) - TITLE="$(grep -m1 '^# ' "$issue_file" | sed 's/^# //' | sed 's/ - Issue Record$//')" || true - if [[ -z "$TITLE" ]]; then - TITLE="$basename_file" - fi - - # Extract severity for labeling - SEVERITY="$(grep -m1 '^\*\*Severity\*\*:' "$issue_file" | sed 's/.*: *//' | tr '[:upper:]' '[:lower:]')" || true - if [[ -z "$SEVERITY" ]]; then - echo " [warn] No severity found in $basename_file — defaulting to unlabelled" - fi - - # Extract summary section as the issue body - BODY="$(sed -n '/^## Summary$/,/^## /{/^## Summary$/d;/^## /d;p}' "$issue_file" | sed '/^$/N;/^\n$/d')" - if [[ -z "$BODY" ]]; then - echo " [warn] No ## Summary section found in $basename_file — using fallback body" - BODY="Synced from local issue doc: $basename_file" - fi - - # Append a link back to the local file - BODY="$BODY - ---- -_Synced from \`docs/history/issues/$basename_file\`_" - - # Build labels - LABELS="synced-from-local" - if [[ -n "$SEVERITY" && "$SEVERITY" != *"["* ]]; then - LABELS="$LABELS,severity:$SEVERITY" - fi - if [[ -n "$EXTRA_LABEL" ]]; then - LABELS="$LABELS,$EXTRA_LABEL" - fi - - if [[ "$APPLY" == false ]]; then - echo "[dry-run] Would create issue: \"$TITLE\"" - echo " Labels: $LABELS" - echo " Source: $basename_file" - echo "" - CANDIDATES=$((CANDIDATES + 1)) - continue - fi - - # Create the GitHub Issue — capture stderr separately so it can be surfaced - # on failure without polluting the URL on success. - echo "Creating issue: \"$TITLE\" ..." - GH_STDERR_FILE="$(mktemp)" - ISSUE_URL="$(gh issue create \ - --title "$TITLE" \ - --body "$BODY" \ - --label "$LABELS" 2>"$GH_STDERR_FILE")" || { - echo " FAILED to create issue: \"$TITLE\"" - echo " gh stderr: $(cat "$GH_STDERR_FILE")" - rm -f "$GH_STDERR_FILE" - FAILED=$((FAILED + 1)) - continue - } - rm -f "$GH_STDERR_FILE" - - # Extract issue number from URL (https://github.com/owner/repo/issues/123) - ISSUE_NUMBER="${ISSUE_URL##*/}" - if [[ ! "$ISSUE_NUMBER" =~ ^[0-9]+$ ]]; then - ISSUE_NUMBER="$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')" || true - [[ -z "$ISSUE_NUMBER" ]] && ISSUE_NUMBER="unknown" - fi - - echo " Created: $ISSUE_URL (#$ISSUE_NUMBER)" - - # Stamp the local file with sync metadata (portable: temp file instead of sed -i). - SYNC_DATE="$(date +%Y-%m-%d)" - TMPFILE="$(mktemp)" - sed \ - -e "s/^\(- \*\*gh_synced\*\*:\) .*/\1 true/" \ - -e "s/^\(- \*\*gh_issue_number\*\*:\) .*/\1 #$ISSUE_NUMBER/" \ - -e "s/^\(- \*\*gh_synced_at\*\*:\) .*/\1 $SYNC_DATE/" \ - -e "s|\(- \*\*Issue tracker\*\*:\) \[GitHub Issue.*\]|\1 $ISSUE_URL|" \ - "$issue_file" > "$TMPFILE" && mv "$TMPFILE" "$issue_file" - - CANDIDATES=$((CANDIDATES + 1)) -done - -# --------------------------------------------------------------------------- -# Summary -# --------------------------------------------------------------------------- - -echo "---" -if [[ "$APPLY" == false ]]; then - echo "Dry-run complete. $CANDIDATES issue(s) would be created, $SKIPPED already synced." - echo "Run with --apply to create GitHub Issues." -else - echo "Sync complete. $CANDIDATES created, $SKIPPED already synced, $FAILED failed." -fi diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/sync-split-pr.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/sync-split-pr.sh deleted file mode 100644 index 1bbf61ac..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/sync-split-pr.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -set -euo pipefail - -BASE_BRANCH="" -NEW_BRANCH="" -COMMIT_MESSAGE="chore(sync): regenerate generated outputs" -PR_TITLE="chore(sync): regenerate generated outputs" -DRY_RUN=0 - -while [[ $# -gt 0 ]]; do - case "$1" in - --base) - BASE_BRANCH="${2:-}" - shift 2 - ;; - --branch) - NEW_BRANCH="${2:-}" - shift 2 - ;; - --commit-message) - COMMIT_MESSAGE="${2:-}" - shift 2 - ;; - --pr-title) - PR_TITLE="${2:-}" - shift 2 - ;; - --dry-run) - DRY_RUN=1 - shift - ;; - -h|--help) - cat <<'EOF' -Usage: scripts/sync-split-pr.sh [options] - -Creates a dedicated branch + commit + PR for files produced by `agentkit:sync`. - -Options: - --base <branch> PR base branch (default: current branch) - --branch <name> Branch name for sync commit (default: chore/sync-generated-<utc>) - --commit-message <msg> Commit message - --pr-title <title> PR title - --dry-run Run sync and report changes without creating branch/commit/PR - -h, --help Show help -EOF - exit 0 - ;; - *) - echo "Unknown option: $1" >&2 - exit 1 - ;; - esac -done - -if [[ -n "$(git status --porcelain)" ]]; then - echo "Working tree is not clean. Commit/stash/discard changes before running sync split." >&2 - exit 1 -fi - -CURRENT_BRANCH="$(git branch --show-current)" -if [[ -z "$BASE_BRANCH" ]]; then - BASE_BRANCH="$CURRENT_BRANCH" -fi - -if [[ -z "$NEW_BRANCH" ]]; then - TS="$(date -u +%Y%m%d-%H%M%S)" - NEW_BRANCH="chore/sync-generated-$TS" -fi - -echo "Running sync..." -pnpm -C .agentkit agentkit:sync - -CHANGED_FILES="$(git status --porcelain)" -if [[ -z "$CHANGED_FILES" ]]; then - echo "No sync-generated changes detected." - mkdir -p .agentkit/logs - printf '{"timestamp":"%s","tool":"sync-split-pr","outcome":"no_changes","base":"%s","branch":"%s"}\n' \ - "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$BASE_BRANCH" "$CURRENT_BRANCH" >> .agentkit/logs/tool-usage.jsonl - exit 0 -fi - -FILES_COUNT="$(git status --porcelain | wc -l | tr -d ' ')" -echo "Detected $FILES_COUNT changed file(s) from sync." - -if [[ "$DRY_RUN" -eq 1 ]]; then - echo "Dry run enabled; not creating branch/commit/PR." - git status --short - mkdir -p .agentkit/logs - printf '{"timestamp":"%s","tool":"sync-split-pr","outcome":"dry_run","files":%s,"base":"%s","branch":"%s"}\n' \ - "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$FILES_COUNT" "$BASE_BRANCH" "$CURRENT_BRANCH" >> .agentkit/logs/tool-usage.jsonl - exit 0 -fi - -git checkout -b "$NEW_BRANCH" -git add -A -git commit -m "$COMMIT_MESSAGE" -git push -u origin "$NEW_BRANCH" - -PR_BODY="Automated sync-only PR. - -- Source branch: $CURRENT_BRANCH -- Sync command: pnpm -C .agentkit agentkit:sync -- Changed files: $FILES_COUNT" - -PR_URL="$(gh pr create --base "$BASE_BRANCH" --head "$NEW_BRANCH" --title "$PR_TITLE" --body "$PR_BODY")" -echo "Created PR: $PR_URL" - -mkdir -p .agentkit/logs -printf '{"timestamp":"%s","tool":"sync-split-pr","outcome":"pr_created","files":%s,"base":"%s","source":"%s","syncBranch":"%s","prUrl":"%s"}\n' \ - "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$FILES_COUNT" "$BASE_BRANCH" "$CURRENT_BRANCH" "$NEW_BRANCH" "$PR_URL" >> .agentkit/logs/tool-usage.jsonl diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/update-changelog.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/update-changelog.sh deleted file mode 100644 index e5693e00..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/update-changelog.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/update-changelog.sh -# Inserts an entry into the [Unreleased] section of CHANGELOG.md. -# -# Usage: -# ./scripts/update-changelog.sh <section> "<description>" [pr-number] [history-doc-path] -# -# Arguments: -# section Changelog section: Added | Fixed | Changed | Removed | Security | Deprecated -# description Human-readable description of the change -# pr-number Optional PR number (e.g. 42) -# history-doc-path Optional relative path to the history document -# -# Examples: -# ./scripts/update-changelog.sh Added "New user auth feature" 44 -# ./scripts/update-changelog.sh Fixed "Null reference in login flow" 43 \ -# "docs/history/bug-fixes/0001-2026-03-01-null-reference-bugfix.md" - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -CHANGELOG="$REPO_ROOT/CHANGELOG.md" - -# --------------------------------------------------------------------------- -# Argument validation -# --------------------------------------------------------------------------- - -usage() { - echo "Usage: $0 <section> \"<description>\" [pr-number] [history-doc-path]" - echo " section: Added | Fixed | Changed | Removed | Security | Deprecated" - exit 1 -} - -if [[ $# -lt 2 ]]; then - usage -fi - -SECTION="$1" -DESCRIPTION="$2" -PR_NUMBER="${3:-}" -HISTORY_DOC="${4:-}" - -case "$SECTION" in - Added|Fixed|Changed|Removed|Security|Deprecated) ;; - *) echo "Error: unknown section '$SECTION'. Must be one of: Added, Fixed, Changed, Removed, Security, Deprecated"; exit 1 ;; -esac - -if [[ ! -f "$CHANGELOG" ]]; then - echo "Error: CHANGELOG.md not found at $CHANGELOG" - exit 1 -fi - -# --------------------------------------------------------------------------- -# Build the entry line -# --------------------------------------------------------------------------- - -ENTRY="- $DESCRIPTION" - -if [[ -n "$PR_NUMBER" && -n "$HISTORY_DOC" ]]; then - ENTRY="$ENTRY ([#${PR_NUMBER}](../../pull/${PR_NUMBER}), [history](${HISTORY_DOC}))" -elif [[ -n "$PR_NUMBER" ]]; then - ENTRY="$ENTRY ([#${PR_NUMBER}](../../pull/${PR_NUMBER}))" -elif [[ -n "$HISTORY_DOC" ]]; then - ENTRY="$ENTRY ([history](${HISTORY_DOC}))" -fi - -# --------------------------------------------------------------------------- -# Insert entry into CHANGELOG.md using Node.js for reliable multiline editing -# --------------------------------------------------------------------------- - -node - "$CHANGELOG" "$SECTION" "$ENTRY" << 'NODEEOF' -const [,, changelogPath, section, entry] = process.argv; -const fs = require('fs'); -const content = fs.readFileSync(changelogPath, 'utf8'); -const lines = content.split('\n'); - -// Find the [Unreleased] section -const unreleasedIdx = lines.findIndex(l => /^## \[Unreleased\]/i.test(l)); -if (unreleasedIdx === -1) { - console.error('Error: could not find ## [Unreleased] section in CHANGELOG.md'); - process.exit(1); -} - -// Find or create the target ### section within [Unreleased] -// The [Unreleased] block ends at the next ## line -let blockEnd = lines.findIndex((l, i) => i > unreleasedIdx && /^## /.test(l)); -if (blockEnd === -1) blockEnd = lines.length; - -const sectionHeader = `### ${section}`; -let sectionIdx = lines.findIndex((l, i) => i > unreleasedIdx && i < blockEnd && l.trim() === sectionHeader); - -if (sectionIdx === -1) { - // Section doesn't exist — insert before blockEnd (or before the next ---/## delimiter) - let insertAt = blockEnd; - // Look for a trailing --- separator just before blockEnd - for (let i = blockEnd - 1; i > unreleasedIdx; i--) { - if (lines[i].trim() === '---') { insertAt = i; break; } - if (lines[i].trim() !== '') break; - } - lines.splice(insertAt, 0, '', sectionHeader, entry); -} else { - // Section exists — insert after the header line (and any existing entries) - let insertAt = sectionIdx + 1; - // Find the end of this section's entries (next ### or ## or blank+##/###) - while ( - insertAt < blockEnd && - lines[insertAt].trim() !== '' && - !lines[insertAt].startsWith('###') && - !lines[insertAt].startsWith('##') - ) { - insertAt++; - } - lines.splice(insertAt, 0, entry); -} - -fs.writeFileSync(changelogPath, lines.join('\n'), 'utf8'); -console.log(`Updated CHANGELOG.md — ${section}: ${entry}`); -NODEEOF diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/validate-documentation.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/validate-documentation.sh deleted file mode 100644 index e5a60220..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/validate-documentation.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/validate-documentation.sh -# Validates that history documents meet structural requirements. -# -# Usage: -# ./scripts/validate-documentation.sh [file...] -# -# If no files are given, validates all markdown files under docs/history/. - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -HISTORY_DIR="$REPO_ROOT/docs/history" - -ERRORS=0 - -validate_file() { - local file="$1" - local base - base="$(basename "$file")" - - # Skip template and README files - if [[ "$base" == TEMPLATE-* || "$base" == README.md ]]; then - return 0 - fi - - # Validate naming convention: XXXX-YYYY-MM-DD-*-{type}.md - if ! [[ "$base" =~ ^[0-9]{4}-[0-9]{4}-[0-9]{2}-[0-9]{2}-.+-(implementation|bugfix|feature|migration)\.md$ ]]; then - echo "❌ $file" - echo " Invalid filename format. Expected: XXXX-YYYY-MM-DD-[title]-[type].md" - ERRORS=$((ERRORS + 1)) - return 0 - fi - - # Check that required placeholder sections have been filled in - if grep -q '\[YYYY-MM-DD\]' "$file"; then - echo "❌ $file" - echo " Unfilled placeholder: [YYYY-MM-DD]" - ERRORS=$((ERRORS + 1)) - fi - - if grep -q '\[#PR-Number\]' "$file"; then - echo "⚠️ $file" - echo " Missing PR number: [#PR-Number] not replaced" - fi - - # Check that file is non-empty beyond the title line - local line_count - line_count=$(wc -l < "$file") - if [[ "$line_count" -lt 10 ]]; then - echo "❌ $file" - echo " Document too short ($line_count lines). Please fill in the template." - ERRORS=$((ERRORS + 1)) - fi -} - -# Determine files to validate -if [[ $# -gt 0 ]]; then - FILES=("$@") -else - mapfile -t FILES < <(find "$HISTORY_DIR" -name "*.md" -not -name "README.md" -not -name "TEMPLATE-*" 2>/dev/null || true) -fi - -if [[ ${#FILES[@]} -eq 0 ]]; then - echo "ℹ️ No history documents found to validate." - exit 0 -fi - -for f in "${FILES[@]}"; do - validate_file "$f" -done - -if [[ "$ERRORS" -gt 0 ]]; then - echo "" - echo "Found $ERRORS validation error(s)." - exit 1 -else - echo "✅ All history documents are valid." -fi diff --git a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/validate-numbering.sh b/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/validate-numbering.sh deleted file mode 100644 index 00c2a506..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/.scaffold-cache/scripts/validate-numbering.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge -# Regenerate: pnpm -C .agentkit agentkit:sync -# scripts/validate-numbering.sh -# Validates the sequential numbering of history documents against .index.json. -# -# Usage: -# ./scripts/validate-numbering.sh - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -HISTORY_DIR="$REPO_ROOT/docs/history" -INDEX_FILE="$HISTORY_DIR/.index.json" - -ERRORS=0 - -if [[ ! -f "$INDEX_FILE" ]]; then - echo "ℹ️ No .index.json found at $INDEX_FILE — skipping numbering validation." - exit 0 -fi - -# Check for duplicate sequence numbers per type -for subdir in implementations bug-fixes features migrations; do - case "$subdir" in - implementations) TYPE="implementation" ;; - bug-fixes) TYPE="bugfix" ;; - features) TYPE="feature" ;; - migrations) TYPE="migration" ;; - esac - - DIR="$HISTORY_DIR/$subdir" - if [[ ! -d "$DIR" ]]; then - continue - fi - - declare -A seen_numbers=() - - while IFS= read -r -d '' file; do - base="$(basename "$file")" - # Skip templates and READMEs - if [[ "$base" == TEMPLATE-* || "$base" == README.md ]]; then - continue - fi - # Extract leading 4-digit number - if [[ "$base" =~ ^([0-9]{4})- ]]; then - num="${BASH_REMATCH[1]}" - if [[ -n "${seen_numbers[$num]+x}" ]]; then - echo "❌ Duplicate number $num in $subdir/:" - echo " ${seen_numbers[$num]}" - echo " $base" - ERRORS=$((ERRORS + 1)) - else - seen_numbers[$num]="$base" - fi - fi - done < <(find "$DIR" -maxdepth 1 -name "*.md" -print0 2>/dev/null || true) - - unset seen_numbers -done - -if [[ "$ERRORS" -gt 0 ]]; then - echo "" - echo "Found $ERRORS numbering error(s)." - exit 1 -else - echo "✅ Sequential numbering is valid." -fi diff --git a/.claude/worktrees/tender-margulis/.agentkit/logs/usage-2026-03-16.jsonl b/.claude/worktrees/tender-margulis/.agentkit/logs/usage-2026-03-16.jsonl deleted file mode 100644 index ec570e61..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/logs/usage-2026-03-16.jsonl +++ /dev/null @@ -1,16 +0,0 @@ -{ - "timestamp": "2026-03-16T21:12:21.000Z", - "event": "session_start", - "sessionId": "3b5b142a-2318-46de-8e68-3b2a1156ec61", - "user": "6d0e0d6bc477", - "branch": "claude/tender-margulis", - "cwd": "C:\\Users\\smitj\\repos\\agentkit-forge\\.claude\\worktrees\\tender-margulis" -} -{ - "timestamp": "2026-03-16T23:15:13.000Z", - "event": "session_start", - "sessionId": "3b5b142a-2318-46de-8e68-3b2a1156ec61", - "user": "6d0e0d6bc477", - "branch": "claude/tender-margulis", - "cwd": "C:\\Users\\smitj\\repos\\agentkit-forge\\.claude\\worktrees\\tender-margulis" -} diff --git a/.claude/worktrees/tender-margulis/.agentkit/logs/usage-2026-03-17.jsonl b/.claude/worktrees/tender-margulis/.agentkit/logs/usage-2026-03-17.jsonl deleted file mode 100644 index b090941e..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/logs/usage-2026-03-17.jsonl +++ /dev/null @@ -1,32 +0,0 @@ -{ - "timestamp": "2026-03-17T01:36:58.000Z", - "event": "session_start", - "sessionId": "3b5b142a-2318-46de-8e68-3b2a1156ec61", - "user": "6d0e0d6bc477", - "branch": "claude/tender-margulis", - "cwd": "C:\\Users\\smitj\\repos\\agentkit-forge\\.claude\\worktrees\\tender-margulis" -} -{ - "timestamp": "2026-03-17T02:03:22.000Z", - "event": "session_start", - "sessionId": "3b5b142a-2318-46de-8e68-3b2a1156ec61", - "user": "6d0e0d6bc477", - "branch": "claude/tender-margulis", - "cwd": "C:\\Users\\smitj\\repos\\agentkit-forge\\.claude\\worktrees\\tender-margulis" -} -{ - "timestamp": "2026-03-17T05:00:11.000Z", - "event": "session_start", - "sessionId": "3b5b142a-2318-46de-8e68-3b2a1156ec61", - "user": "6d0e0d6bc477", - "branch": "claude/tender-margulis", - "cwd": "C:\\Users\\smitj\\repos\\agentkit-forge\\.claude\\worktrees\\tender-margulis" -} -{ - "timestamp": "2026-03-17T09:06:27.000Z", - "event": "session_start", - "sessionId": "3b5b142a-2318-46de-8e68-3b2a1156ec61", - "user": "6d0e0d6bc477", - "branch": "claude/tender-margulis", - "cwd": "C:\\Users\\smitj\\repos\\agentkit-forge\\.claude\\worktrees\\tender-margulis" -} diff --git a/.claude/worktrees/tender-margulis/.agentkit/package-lock.json b/.claude/worktrees/tender-margulis/.agentkit/package-lock.json deleted file mode 100644 index 0ecd531d..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/package-lock.json +++ /dev/null @@ -1,2764 +0,0 @@ -{ - "name": "agentkit-forge-runtime", - "version": "3.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "agentkit-forge-runtime", - "version": "3.1.0", - "dependencies": { - "@clack/prompts": "^1.0.1", - "js-yaml": "^4.1.0" - }, - "devDependencies": { - "markdownlint-cli2": "^0.18.1", - "prettier": "^3.5.3", - "vitest": "^4.0.18" - }, - "engines": { - "node": ">=22.0.0" - } - }, - "node_modules/@clack/core": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.0.1.tgz", - "integrity": "sha512-WKeyK3NOBwDOzagPR5H08rFk9D/WuN705yEbuZvKqlkmoLM2woKtXb10OO2k1NoSU4SFG947i2/SCYh+2u5e4g==", - "license": "MIT", - "dependencies": { - "picocolors": "^1.0.0", - "sisteransi": "^1.0.5" - } - }, - "node_modules/@clack/prompts": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.0.1.tgz", - "integrity": "sha512-/42G73JkuYdyWZ6m8d/CJtBrGl1Hegyc7Fy78m5Ob+jF85TOUmLR5XLce/U3LxYAw0kJ8CT5aI99RIvPHcGp/Q==", - "license": "MIT", - "dependencies": { - "@clack/core": "1.0.1", - "picocolors": "^1.0.0", - "sisteransi": "^1.0.5" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/chai": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/katex": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz", - "integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "4.0.18", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "4.0.18", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chai": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decode-named-character-reference": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", - "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", - "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/katex": { - "version": "0.16.33", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.33.tgz", - "integrity": "sha512-q3N5u+1sY9Bu7T4nlXoiRBXWfwSefNGoKeOwekV+gw0cAXQlz2Ww6BLcmBxVDeXBMUDQv6fK5bcNaJLxob3ZQA==", - "dev": true, - "funding": [ - "https://opencollective.com/katex", - "https://github.com/sponsors/katex" - ], - "license": "MIT", - "dependencies": { - "commander": "^8.3.0" - }, - "bin": { - "katex": "cli.js" - } - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/markdownlint": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.38.0.tgz", - "integrity": "sha512-xaSxkaU7wY/0852zGApM8LdlIfGCW8ETZ0Rr62IQtAnUMlMuifsg09vWJcNYeL4f0anvr8Vo4ZQar8jGpV0btQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark": "4.0.2", - "micromark-core-commonmark": "2.0.3", - "micromark-extension-directive": "4.0.0", - "micromark-extension-gfm-autolink-literal": "2.1.0", - "micromark-extension-gfm-footnote": "2.1.0", - "micromark-extension-gfm-table": "2.1.1", - "micromark-extension-math": "3.1.0", - "micromark-util-types": "2.0.2" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/DavidAnson" - } - }, - "node_modules/markdownlint-cli2": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.18.1.tgz", - "integrity": "sha512-/4Osri9QFGCZOCTkfA8qJF+XGjKYERSHkXzxSyS1hd3ZERJGjvsUao2h4wdnvpHp6Tu2Jh/bPHM0FE9JJza6ng==", - "dev": true, - "license": "MIT", - "dependencies": { - "globby": "14.1.0", - "js-yaml": "4.1.0", - "jsonc-parser": "3.3.1", - "markdown-it": "14.1.0", - "markdownlint": "0.38.0", - "markdownlint-cli2-formatter-default": "0.0.5", - "micromatch": "4.0.8" - }, - "bin": { - "markdownlint-cli2": "markdownlint-cli2-bin.mjs" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/DavidAnson" - } - }, - "node_modules/markdownlint-cli2-formatter-default": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.5.tgz", - "integrity": "sha512-4XKTwQ5m1+Txo2kuQ3Jgpo/KmnG+X90dWt4acufg6HVGadTUG5hzHF/wssp9b5MBYOMCnZ9RMPaU//uHsszF8Q==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/DavidAnson" - }, - "peerDependencies": { - "markdownlint-cli2": ">=0.0.4" - } - }, - "node_modules/markdownlint-cli2/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-directive": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-4.0.0.tgz", - "integrity": "sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "parse-entities": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-math": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", - "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/katex": "^0.16.0", - "devlop": "^1.0.0", - "katex": "^0.16.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/sxzz", - "https://opencollective.com/debug" - ], - "license": "MIT" - }, - "node_modules/parse-entities": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prettier": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "license": "MIT" - }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyrainbow": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", - "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", - "magic-string": "^0.30.21", - "obug": "^2.1.1", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^3.10.0", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@opentelemetry/api": "^1.9.0", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser-playwright": { - "optional": true - }, - "@vitest/browser-preview": { - "optional": true - }, - "@vitest/browser-webdriverio": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - } - } -} diff --git a/.claude/worktrees/tender-margulis/.agentkit/state/orchestrator.json.template b/.claude/worktrees/tender-margulis/.agentkit/state/orchestrator.json.template deleted file mode 100644 index 076c20ed..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/state/orchestrator.json.template +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": "1.0.0", - "repo_id": "agentkit-forge", - "branch": "main", - "session_id": "", - "current_phase": 1, - "phase_name": "Discovery", - "last_phase_completed": 0, - "next_action": "Run /orchestrate to begin project assessment", - "team_progress": { - "team-backend": { "status": "idle", "notes": "" }, - "team-frontend": { "status": "idle", "notes": "" }, - "team-data": { "status": "idle", "notes": "" }, - "team-infra": { "status": "idle", "notes": "" }, - "team-devops": { "status": "idle", "notes": "" }, - "team-testing": { "status": "idle", "notes": "" }, - "team-security": { "status": "idle", "notes": "" }, - "team-docs": { "status": "idle", "notes": "" }, - "team-product": { "status": "idle", "notes": "" }, - "team-quality": { "status": "idle", "notes": "" } - }, - "todo_items": [], - "recent_results": [], - "completed": false -} diff --git a/.claude/worktrees/tender-margulis/.agentkit/state/schema.json b/.claude/worktrees/tender-margulis/.agentkit/state/schema.json deleted file mode 100644 index 7bfdc405..00000000 --- a/.claude/worktrees/tender-margulis/.agentkit/state/schema.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "AgentKit Forge Orchestrator State", - "description": "Schema for the orchestrator state file managed by /orchestrate", - "type": "object", - "required": ["schema_version", "repo_id", "current_phase", "phase_name", "team_progress"], - "properties": { - "schema_version": { - "type": "string", - "const": "1.0.0", - "description": "Schema version for forward compatibility" - }, - "repo_id": { - "type": "string", - "description": "Repository identifier (from .agentkit-repo)" - }, - "branch": { - "type": "string", - "description": "Current git branch" - }, - "session_id": { - "type": "string", - "description": "Current session identifier" - }, - "current_phase": { - "type": "integer", - "minimum": 1, - "maximum": 5, - "description": "Current lifecycle phase (1-5)" - }, - "phase_name": { - "type": "string", - "enum": ["Discovery", "Planning", "Implementation", "Validation", "Ship"], - "description": "Human-readable phase name" - }, - "last_phase_completed": { - "type": "integer", - "minimum": 0, - "maximum": 5, - "description": "Last fully completed phase (0 = none)" - }, - "next_action": { - "type": "string", - "description": "Recommended next action" - }, - "team_progress": { - "type": "object", - "description": "Per-team status tracking", - "patternProperties": { - "^team-": { - "type": "object", - "required": ["status"], - "properties": { - "status": { - "type": "string", - "enum": ["idle", "in_progress", "blocked", "done"] - }, - "notes": { - "type": "string" - }, - "last_updated": { - "type": "string", - "format": "date-time" - }, - "assigned_to": { - "type": "string" - } - } - } - } - }, - "todo_items": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "title", "status"], - "properties": { - "id": { "type": "string" }, - "title": { "type": "string" }, - "status": { - "type": "string", - "enum": ["pending", "in_progress", "done", "blocked"] - }, - "team": { "type": "string" }, - "priority": { - "type": "string", - "enum": ["critical", "high", "medium", "low"] - } - } - } - }, - "recent_results": { - "type": "array", - "items": { - "type": "object", - "properties": { - "timestamp": { "type": "string", "format": "date-time" }, - "action": { "type": "string" }, - "result": { "type": "string" }, - "team": { "type": "string" } - } - } - }, - "completed": { - "type": "boolean", - "description": "Whether all phases are complete" - }, - "last_healthcheck": { - "type": "string", - "format": "date-time", - "description": "Timestamp of last healthcheck run" - }, - "health_status": { - "type": "string", - "enum": ["HEALTHY", "UNHEALTHY"], - "description": "Overall health status from last healthcheck" - }, - "session_metrics": { - "type": "object", - "description": "Cost tracking session metrics", - "properties": { - "current_session_id": { - "type": "string", - "description": "Active session ID for cost tracking" - }, - "total_sessions": { - "type": "integer", - "description": "Total sessions recorded" - }, - "last_session_end": { - "type": "string", - "format": "date-time", - "description": "When the last session ended" - } - } - } - } -} diff --git a/.claude/worktrees/tender-margulis/.claude/settings.local.json b/.claude/worktrees/tender-margulis/.claude/settings.local.json deleted file mode 100644 index b36185b5..00000000 --- a/.claude/worktrees/tender-margulis/.claude/settings.local.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(git ls-remote https://github.com/actions/checkout.git refs/tags/v4.2.2)", - "Bash(git ls-remote https://github.com/anthropics/claude-code-action.git refs/tags/v1)", - "Bash(git ls-remote https://github.com/actions/github-script.git refs/tags/v7)", - "Bash(pnpm -C .agentkit test)", - "Bash(pnpm -C .agentkit vitest run src/__tests__/prettier.test.mjs src/__tests__/expansion-analyzer.test.mjs src/__tests__/budget-guard.test.mjs src/__tests__/feature-manager.test.mjs src/__tests__/backlog-store.test.mjs src/__tests__/discover.test.mjs)", - "Bash(pnpm -C .agentkit agentkit:sync)", - "Bash(grep -rn 'uses:' .agentkit/templates/github/workflows/*.yml)", - "Bash(grep -rn 'uses:.*@[a-f0-9]\\\\{40\\\\}' .agentkit/templates/github/workflows/*.yml)", - "Bash(grep -rn 'uses:.*@v[0-9]' .agentkit/templates/github/workflows/*.yml)", - "Bash(git ls-remote https://github.com/pnpm/action-setup.git refs/tags/v4.2.0)", - "Bash(git ls-remote https://github.com/actions/setup-node.git refs/tags/v4.4.0)", - "Bash(git ls-remote https://github.com/actions/setup-python.git refs/tags/v5.6.0)", - "Bash(git ls-remote https://github.com/pnpm/action-setup.git refs/tags/v4)", - "Bash(git checkout -- AGENT_TEAMS.md .clinerules/git-workflow.md)", - "Bash(for branch in dev chore/merge-all-open-branches ci/enforce-sha-pinning-and-templates claude/fix-full-tier-black-elements-gkgln docs/consolidate-pending-items docs/restructure-agentkit-docs fix/review-findings-round1 fix/template-numbered-paths refactor/remove-team-prefix)", - "Bash(do echo \"=== $branch ===\")", - "Bash(git checkout -- .)", - "Bash(git pull)", - "Bash(git cherry-pick 097e0cc --no-edit)", - "Bash(git remote prune origin)", - "Bash(pnpm -C /c/Users/smitj/repos/retort/.agentkit test)", - "Bash(gh repo list JustAGhosT --limit 50)", - "Bash(gh label create \"priority:P3\" --repo phoenixvc/cognitive-mesh --color \"0E8A16\" --description \"Priority 3 - Nice to have\")", - "Bash(git add -A)", - "Bash(gh label list --repo phoenixvc/cognitive-mesh --json name,description,color --limit 100)", - "Bash(gh label list --repo JustAGhosT/retort --json name,description,color --limit 100)", - "mcp__filesystem__read_multiple_files", - "Bash(grep -E \"\\\\.\\(yml|yaml|json|ts|js\\)$\")", - "Bash(gh label:*)", - "Bash(git add:*)", - "Bash(gh api:*)" - ] - } -} diff --git a/.claude/worktrees/tender-margulis/.claude/state/events.log b/.claude/worktrees/tender-margulis/.claude/state/events.log deleted file mode 100644 index 30a818dd..00000000 --- a/.claude/worktrees/tender-margulis/.claude/state/events.log +++ /dev/null @@ -1,104 +0,0 @@ -{"timestamp":"2026-02-26T17:31:21.524Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":92388},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1253},{"step":"build","status":"FAIL","durationMs":2299}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T17:32:22.387Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":57877},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1756}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T17:40:11.462Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":300556},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":12726},{"step":"build","status":"FAIL","durationMs":4619}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T17:44:14.114Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":236951},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":2693}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T17:57:01.313Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":54449},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1488},{"step":"build","status":"FAIL","durationMs":1535}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T17:57:39.437Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":35135},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1489}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T18:00:44.882Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":18855},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":599},{"step":"build","status":"FAIL","durationMs":755}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T18:00:57.395Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":11525},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":587}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T22:50:22.150Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":43407},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1370},{"step":"build","status":"FAIL","durationMs":1982}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T22:50:57.402Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":34361},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":485}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T22:59:44.909Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":72662},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1055},{"step":"build","status":"FAIL","durationMs":1767}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T23:00:12.840Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":26869},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":598}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T23:27:21.525Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":54059},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1538},{"step":"build","status":"FAIL","durationMs":2558}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T23:27:55.191Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":31691},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1126}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-26T23:47:11.830Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":54257},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":2146},{"step":"build","status":"FAIL","durationMs":3389}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-26T23:47:43.881Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":30944},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":619}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-02-28T15:41:34.550Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":118},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":15063},{"step":"build","status":"FAIL","durationMs":4029}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-02-28T15:41:38.884Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":29},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":3080}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-01T04:51:06.914Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":43},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":9}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-01T04:51:08.526Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":19},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-01T04:54:06.715Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":53},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":28}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-01T04:54:08.867Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":75},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-01T05:10:28.549Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":106},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":22},{"step":"build","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-01T05:10:30.610Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":19},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T14:57:27.967Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":158},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":7}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T14:57:29.567Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":22},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T15:01:59.380Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":30},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T15:02:00.404Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":20},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:05:27.157Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":20},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":1913},{"step":"build","status":"FAIL","durationMs":3071}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:05:57.398Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":22},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":8}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:05:59.276Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":16},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:14:48.130Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":26},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":8},{"step":"build","status":"FAIL","durationMs":153}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:14:55.776Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":438},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":35}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:16:15.728Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":46},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":101184},{"step":"build","status":"FAIL","durationMs":9256}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:19:12.380Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":29},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":7},{"step":"build","status":"FAIL","durationMs":11}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:19:14.119Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":21},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:25:42.885Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":27},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":8},{"step":"build","status":"FAIL","durationMs":160}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:25:46.626Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":181},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":26}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:27:05.654Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":18},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"PASS","durationMs":95529},{"step":"build","status":"PASS","durationMs":7674}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:32:51.735Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":252},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":75},{"step":"build","status":"FAIL","durationMs":42}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:32:55.553Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":192},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":22}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:34:25.998Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":23},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":120925},{"step":"build","status":"PASS","durationMs":7972}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:36:16.808Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":109},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":10},{"step":"build","status":"FAIL","durationMs":9}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:36:19.087Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":51},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":8}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:39:23.323Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":269},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":37},{"step":"build","status":"FAIL","durationMs":46}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:39:26.597Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":142},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":27}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:41:21.411Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":262},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":138},{"step":"build","status":"FAIL","durationMs":74}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:41:25.946Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":179},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":68}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T17:42:47.046Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":16},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":92882},{"step":"build","status":"PASS","durationMs":10552}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:43:49.613Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":250},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":81},{"step":"build","status":"FAIL","durationMs":105}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T17:43:53.957Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":444},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":19}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T18:57:58.751Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":64},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":7},{"step":"build","status":"FAIL","durationMs":7}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T18:58:00.655Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":40},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":8}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T18:58:46.509Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":24},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":60941},{"step":"build","status":"PASS","durationMs":3076}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T19:00:40.415Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":83},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":97},{"step":"build","status":"FAIL","durationMs":171}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T19:00:50.568Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":562},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":58}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T19:15:27.769Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":48},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":7}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T19:15:29.811Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":19},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T19:18:40.784Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":56},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":8}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T19:18:42.732Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":21},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T19:36:57.250Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":25},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":9}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T19:36:58.289Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":17},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:14:44.559Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":45},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":11}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:14:46.176Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":40},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:20:45.419Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":72},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4},{"step":"build","status":"FAIL","durationMs":8}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:20:46.671Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":17},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:21:33.859Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":21},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":9}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:21:35.551Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":24},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:22:37.730Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":36},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":7}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:22:39.534Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":16},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:23:58.276Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":56},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":9}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:23:59.332Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":17},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-03T20:27:17.403Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":231},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":17},{"step":"build","status":"FAIL","durationMs":15}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-03T20:27:19.502Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":75},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":14}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-04T10:20:44.292Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":15},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":3},{"step":"build","status":"FAIL","durationMs":3}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T11:40:03.234Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":12},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":3},{"step":"build","status":"FAIL","durationMs":3}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T11:40:14.944Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":24},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6},{"step":"build","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T11:40:16.696Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":20},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":6}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-04T13:37:02.860Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":37},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5},{"step":"build","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T13:37:04.586Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":18},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":5}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-04T14:57:52.992Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"PASS","durationMs":12865},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4}]}],"flags":{"fix":false,"fast":true,"stack":null}} -{"timestamp":"2026-03-04T16:26:18.432Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"PASS","durationMs":8533},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":3},{"step":"build","status":"FAIL","durationMs":3}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T18:50:47.548Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":10054},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":4},{"step":"build","status":"FAIL","durationMs":3}]}],"flags":{"fix":false,"fast":false,"stack":null}} -{"timestamp":"2026-03-04T18:53:17.017Z","action":"check_completed","overallStatus":"FAIL","stacks":[{"stack":"node","steps":[{"step":"format","status":"FAIL","durationMs":9339},{"step":"lint","status":"SKIP","durationMs":0},{"step":"typecheck","status":"SKIP","durationMs":0},{"step":"test","status":"FAIL","durationMs":3},{"step":"build","status":"FAIL","durationMs":3}]}],"flags":{"fix":false,"fast":false,"stack":null}} -[2026-03-11T03:17:17.000Z] [HANDOFF] [ORCHESTRATOR] Session complete. Done: 6 items. Blockers: 0. Next: "Start Phase 1 cost-provider-schema on feat/cost-provider-schema branch". -[2026-03-11T17:00:03Z] [ORCHESTRATE] [W1] Phase 5 Ship. Tests: 110/110. Sync: clean. Branch: fix/ci-remediation. Commits ahead: 51. Ready for PR to main. -[2026-03-15T07:06:00Z] [ORCHESTRATE] [W1] Phase 5 Ship. Branch: feat/source-code-conventions. Build: pass. agentkit:check fails (Duplicate export auditUnresolvedPlaceholders). orchestrator.test.mjs: 22 failed. Health: at_risk. Next: fix test/check then PR. -[2026-03-15T07:13:00Z] [ORCHESTRATE] [W1] Phase 5 Ship. Branch: feat/source-code-conventions. Build: pass. No lock. Validation: build re-run PASS. Tests running in background. Health: at_risk (check CLI + orchestrator tests). Next: fix then PR to main. -[2026-03-15T07:16:00Z] [ORCHESTRATE] [W1] Fixed check.mjs duplicate export (auditUnresolvedPlaceholders). agentkit:check runs; format PASS. NB added to CLAUDE.md: this repo may modify .agentkit files. Next: orchestrator.test.mjs fixes then PR. -[2026-03-15T09:25:00Z] [ORCHESTRATE] [W1] Phase 5 Ship. Fixed orchestrator.test.mjs: unique temp dir per test (TEST_BASE/run-id), removed afterEach rmSync. 39/39 orchestrator tests pass. Health: healthy. Next: Create PR to main. -[2026-03-15T11:30:00Z] [ORCHESTRATE] [W1] Phase 2 Planning. Scope: all P0 and P1. Discovery: AGENT_TEAMS.md present; CI workflows present (ci.yml, branch-protection, etc.). Healthcheck: UNHEALTHY (typecheck/test/build fail in agentkit:check). Created 7 task files in .claude/state/tasks/ for P0 (2) and P1 (5). Next: teams implement then Phase 4 Validation. -[2026-03-15T12:05:00Z] [ORCHESTRATE] [W1] Assess-only run. Branch: fix/generated-files-and-conflict-markers. Phase 2. Tasks: 7 submitted, 0 in progress, 0 completed. Health: UNHEALTHY. Check: format PASS; typecheck/test/build FAIL. Next: run /team-infra, /team-quality, /team-backend, /team-data to implement tasks; then re-run /orchestrate for Validation. -[2026-03-15T12:15:00Z] [TEAM] [backend] Completed 2 items. Changes: 1 file (docs/api/07_framework-api-conventions.md). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T12:25:00Z] [TEAM] [infra] Rejected task-p0-ci-pipeline (out of scope; suggested team-devops). Completed 1 item (task-p1-staging-env). Changes: infra/README.md, docker-compose.yml. Tests: 0 added, 0 modified. Gate: N/A. -[2026-03-15T12:35:00Z] [TEAM] [data] Completed 2 items. Changes: db/README.md, migrations/README.md. Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T12:45:00Z] [TEAM] [product] Completed 1 item. Changes: docs/product/prd/README.md (PRD index). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T13:00:00Z] [TEAM] [product] Completed 1 item. Changes: docs/product/prd/README.md (P1 backlog section). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T13:10:00Z] [ORCHESTRATE] [W1] Assess. Branch: fix/generated-files-and-conflict-markers. Phase 2. Tasks: 5 completed, 1 rejected (P0 CI → devops), 1 submitted (P0 test-framework). Health: UNHEALTHY (format/typecheck/test/build FAIL). Next: /team-quality for task-p0-test-framework; reassign P0 CI to DevOps; then Phase 4 Validation. -[2026-03-15T13:15:00Z] [TEAM] [product] Completed 1 item. Changes: docs/product/prd/README.md (link to PLAN-gh371). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T13:20:00Z] [ORCHESTRATE] [W1] Assess-only. Branch: fix/generated-files-and-conflict-markers. Phase 2. Tasks: 5 completed, 1 rejected, 1 submitted (task-p0-test-framework). Health: UNHEALTHY. Next: /team-quality; reassign P0 CI to DevOps; Phase 4 Validation. -[2026-03-15T13:25:00Z] [TEAM] [product] Completed 1 item. Changes: docs/product/prd/README.md (GH#328 plan note, link to implementation plans). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T13:30:00Z] [TEAM] [product] Completed 1 item. Changes: docs/product/prd/README.md (next PRD number 008 in Creating a New PRD). Tests: 0 added, 0 modified. Gate: N/A (docs only). -[2026-03-15T13:35:00Z] [TEAM] [product] No delegated tasks; no additional backlog items completed (P1/P2 require plans or implementation). Scope: docs/product/**, docs/prd/**. -[2026-03-15T13:40:00Z] [TEAM] [docs] Completed 1 item. Changes: CONTRIBUTING.md (link to docs hub in Discovery phase). Tests: 0 added, 0 modified. Gate: N/A (docs only). diff --git a/.claude/worktrees/tender-margulis/.claude/state/orchestrator.json b/.claude/worktrees/tender-margulis/.claude/state/orchestrator.json deleted file mode 100644 index ad4dd611..00000000 --- a/.claude/worktrees/tender-margulis/.claude/state/orchestrator.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "schema_version": "1.0.0", - "repo_id": "JustAGhosT/retort", - "branch": "fix/generated-files-and-conflict-markers", - "session_id": "2026-03-15", - "current_phase": 2, - "phase_name": "Planning", - "last_phase_completed": 1, - "next_action": "Complete task-p0-test-framework (team-quality). Reassign P0 CI to DevOps. Then run Phase 4 Validation.", - "lastHealthcheck": "2026-03-15T13:10:00Z", - "healthStatus": "unhealthy", - "healthDetails": { - "dependencies": "pass", - "format": "FAIL", - "lint": "SKIP (eslint not found)", - "typecheck": "FAIL", - "tests": "FAIL", - "build": "FAIL", - "syncDrift": "not run" - }, - "taskSummary": { - "total": 7, - "completed": 5, - "rejected": 1, - "submitted": 1 - }, - "backlogSnapshot": [ - {"priority": "P0", "team": "T4-Infrastructure", "task": "Configure CI pipeline for main branch"}, - {"priority": "P0", "team": "T10-Quality", "task": "Set up test framework and coverage thresholds"}, - {"priority": "P1", "team": "T1-Backend", "task": "Define core API route structure"}, - {"priority": "P1", "team": "T3-Data", "task": "Design initial database schema"}, - {"priority": "P1", "team": "T1-Backend", "task": "Implement health check endpoint"}, - {"priority": "P1", "team": "T3-Data", "task": "Create migration tooling setup"}, - {"priority": "P1", "team": "T4-Infrastructure", "task": "Set up staging environment"} - ], - "team_progress": { - "backend": { "status": "idle", "notes": "Completed task-p1-api-routes, task-p1-health-check (docs/api/07_framework-api-conventions.md)." }, - "frontend": { "status": "idle", "notes": "start TUI component merged and tested" }, - "data": { "status": "idle", "notes": "Completed task-p1-db-schema, task-p1-migration-tooling (db/README.md, migrations/README.md; repo has no DB, adopters own schema and migrations)." }, - "infra": { "status": "idle", "notes": "Rejected P0 CI (DevOps scope). Completed P1 staging: infra/README.md, docker-compose.yml." }, - "devops": { "status": "idle", "notes": "Configurable package manager implemented" }, - "testing": { "status": "complete", "notes": "110 tests green, ConversationFlow flakiness fixed" }, - "security": { "status": "idle", "notes": "" }, - "docs": { "status": "idle", "notes": "CONTRIBUTING.md: link to docs hub (docs/README.md) in Discovery phase." }, - "product": { "status": "idle", "notes": "PRD index, P1 backlog, PLAN-gh371 link, docs/planning link, next PRD number (008) in Creating a New PRD." }, - "quality": { "status": "complete", "notes": "Review findings addressed, sync drift clean" } - }, - "todo_items": [], - "recent_results": [ - { - "date": "2026-03-11", - "action": "Fixed ConversationFlow test flakiness (ink-select-input event loop yields)", - "status": "done" - }, - { - "date": "2026-03-11", - "action": "Added pnpm-workspace.yaml packages field", - "status": "done" - }, - { - "date": "2026-03-11", - "action": "Regenerated lockfile after version pinning", - "status": "done" - }, - { - "date": "2026-03-11", - "action": "Verified sync drift clean (533 files, 0 changes)", - "status": "done" - } - ], - "completed": false -} diff --git a/.claude/worktrees/tender-margulis/.claude/state/orchestrator.json.template b/.claude/worktrees/tender-margulis/.claude/state/orchestrator.json.template deleted file mode 100644 index 076c20ed..00000000 --- a/.claude/worktrees/tender-margulis/.claude/state/orchestrator.json.template +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schema_version": "1.0.0", - "repo_id": "agentkit-forge", - "branch": "main", - "session_id": "", - "current_phase": 1, - "phase_name": "Discovery", - "last_phase_completed": 0, - "next_action": "Run /orchestrate to begin project assessment", - "team_progress": { - "team-backend": { "status": "idle", "notes": "" }, - "team-frontend": { "status": "idle", "notes": "" }, - "team-data": { "status": "idle", "notes": "" }, - "team-infra": { "status": "idle", "notes": "" }, - "team-devops": { "status": "idle", "notes": "" }, - "team-testing": { "status": "idle", "notes": "" }, - "team-security": { "status": "idle", "notes": "" }, - "team-docs": { "status": "idle", "notes": "" }, - "team-product": { "status": "idle", "notes": "" }, - "team-quality": { "status": "idle", "notes": "" } - }, - "todo_items": [], - "recent_results": [], - "completed": false -} diff --git a/.claude/worktrees/tender-margulis/.claude/state/schema.json b/.claude/worktrees/tender-margulis/.claude/state/schema.json deleted file mode 100644 index 5206822c..00000000 --- a/.claude/worktrees/tender-margulis/.claude/state/schema.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Retort Orchestrator State", - "description": "Schema for the orchestrator state file managed by /orchestrate", - "type": "object", - "required": ["schema_version", "repo_id", "current_phase", "phase_name", "team_progress"], - "properties": { - "schema_version": { - "type": "string", - "const": "1.0.0", - "description": "Schema version for forward compatibility" - }, - "repo_id": { - "type": "string", - "description": "Repository identifier (from .agentkit-repo)" - }, - "branch": { - "type": "string", - "description": "Current git branch" - }, - "session_id": { - "type": "string", - "description": "Current session identifier" - }, - "current_phase": { - "type": "integer", - "minimum": 1, - "maximum": 5, - "description": "Current lifecycle phase (1-5)" - }, - "phase_name": { - "type": "string", - "enum": ["Discovery", "Planning", "Implementation", "Validation", "Ship"], - "description": "Human-readable phase name" - }, - "last_phase_completed": { - "type": "integer", - "minimum": 0, - "maximum": 5, - "description": "Last fully completed phase (0 = none)" - }, - "next_action": { - "type": "string", - "description": "Recommended next action" - }, - "team_progress": { - "type": "object", - "description": "Per-team status tracking", - "patternProperties": { - "^team-": { - "type": "object", - "required": ["status"], - "properties": { - "status": { - "type": "string", - "enum": ["idle", "in_progress", "blocked", "done"] - }, - "notes": { - "type": "string" - }, - "last_updated": { - "type": "string", - "format": "date-time" - }, - "assigned_to": { - "type": "string" - } - } - } - } - }, - "todo_items": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "title", "status"], - "properties": { - "id": { "type": "string" }, - "title": { "type": "string" }, - "status": { - "type": "string", - "enum": ["pending", "in_progress", "done", "blocked"] - }, - "team": { "type": "string" }, - "priority": { - "type": "string", - "enum": ["critical", "high", "medium", "low"] - } - } - } - }, - "recent_results": { - "type": "array", - "items": { - "type": "object", - "properties": { - "timestamp": { "type": "string", "format": "date-time" }, - "action": { "type": "string" }, - "result": { "type": "string" }, - "team": { "type": "string" } - } - } - }, - "completed": { - "type": "boolean", - "description": "Whether all phases are complete" - }, - "last_healthcheck": { - "type": "string", - "format": "date-time", - "description": "Timestamp of last healthcheck run" - }, - "health_status": { - "type": "string", - "enum": ["HEALTHY", "UNHEALTHY"], - "description": "Overall health status from last healthcheck" - }, - "session_metrics": { - "type": "object", - "description": "Cost tracking session metrics", - "properties": { - "current_session_id": { - "type": "string", - "description": "Active session ID for cost tracking" - }, - "total_sessions": { - "type": "integer", - "description": "Total sessions recorded" - }, - "last_session_end": { - "type": "string", - "format": "date-time", - "description": "When the last session ended" - } - } - } - } -} diff --git a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p0-ci-pipeline.json b/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p0-ci-pipeline.json deleted file mode 100644 index e656cf8b..00000000 --- a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p0-ci-pipeline.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "id": "task-p0-ci-pipeline", - "type": "implement", - "status": "rejected", - "priority": "P0", - "delegator": "orchestrator", - "assignees": ["team-infra"], - "title": "Configure CI pipeline for main branch", - "description": "GitHub Actions workflow; scope: branch-protection, drift check, quality gates on main. Ensure required status checks align with ci.yml, branch-protection.yml, and drift/sync validation.", - "acceptanceCriteria": [ - "Workflow runs on push/PR to main (and dev per existing)", - "Drift check (sync then git diff) runs and is required for main", - "Quality gates (test, validate) are required; branch protection documented or enforced" - ], - "scope": [".github/workflows/**", "docs/operations/**"], - "backlogItemId": "P0-T4-CI-pipeline", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P0: Configure CI pipeline for main. See AGENT_BACKLOG.md Active Sprint." }, - { "role": "executor", "from": "infra", "timestamp": "2026-03-15T12:25:00Z", "content": "Rejected: task scope is .github/workflows/** and docs/operations/**, which is DevOps (CI/CD, pipelines), not Infra (IaC, terraform, bicep, pulumi). Suggested team: team-devops." } - ], - "artifacts": [] -} diff --git a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p0-test-framework.json b/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p0-test-framework.json deleted file mode 100644 index e69de29b..00000000 diff --git a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-api-routes.json b/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-api-routes.json deleted file mode 100644 index b76ef61f..00000000 --- a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-api-routes.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "task-p1-api-routes", - "type": "implement", - "status": "completed", - "priority": "P1", - "delegator": "orchestrator", - "assignees": ["team-backend"], - "title": "Define core API route structure", - "description": "REST endpoints for v1. Define route layout and conventions for the project (or document that this repo is framework-only and adopters define routes).", - "acceptanceCriteria": [ - "API route structure documented or implemented per project conventions", - "REST v1 layout clear for downstream adopters or for this repo if applicable" - ], - "scope": ["apps/api/**", "services/**", "docs/api/**"], - "backlogItemId": "P1-T1-api-routes", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P1: Define core API route structure. See AGENT_BACKLOG.md." }, - { "role": "executor", "from": "backend", "timestamp": "2026-03-15T12:15:00Z", "content": "Completed. Repo is framework-only (no apps/api or services). Added docs/api/07_framework-api-conventions.md documenting recommended route structure (base /api, url-segment versioning, envelope, cursor pagination) for adopters." } - ], - "artifacts": [ - { "type": "files-changed", "paths": ["docs/api/07_framework-api-conventions.md"] }, - { "type": "test-results", "passed": 0, "failed": 0, "testsAdded": 0, "testsModified": 0 } - ] -} diff --git a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-db-schema.json b/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-db-schema.json deleted file mode 100644 index b52354a2..00000000 --- a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-db-schema.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "id": "task-p1-db-schema", - "type": "implement", - "status": "completed", - "priority": "P1", - "delegator": "orchestrator", - "assignees": ["team-data"], - "title": "Design initial database schema", - "description": "Depends on T1 API design. Design initial schema for the project (or document that this repo has no DB and adopters own schema).", - "acceptanceCriteria": [ - "Schema design or decision documented", - "Dependencies on API design acknowledged" - ], - "scope": ["db/**", "migrations/**", "prisma/**", "docs/architecture/**"], - "dependsOn": ["task-p1-api-routes"], - "backlogItemId": "P1-T3-db-schema", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P1: Design initial database schema. Depends on T1." }, - { "role": "executor", "from": "data", "timestamp": "2026-03-15T12:35:00Z", "content": "Completed. Repo has no database (CLAUDE.md: Database none, ORM none). Added db/README.md documenting that adopters own schema and referencing API conventions; dependency on API design acknowledged." } - ], - "artifacts": [ - { "type": "files-changed", "paths": ["db/README.md"] }, - { "type": "test-results", "passed": 0, "failed": 0, "testsAdded": 0, "testsModified": 0 } - ] -} diff --git a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-health-check.json b/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-health-check.json deleted file mode 100644 index 10b652ef..00000000 --- a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-health-check.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "task-p1-health-check", - "type": "implement", - "status": "completed", - "priority": "P1", - "delegator": "orchestrator", - "assignees": ["team-backend"], - "title": "Implement health check endpoint", - "description": "Implement /api/health (or equivalent) for the application.", - "acceptanceCriteria": [ - "Health check endpoint implemented and documented", - "Returns appropriate status for load balancers or readiness probes" - ], - "scope": ["apps/api/**", "services/**", "docs/api/**"], - "backlogItemId": "P1-T1-health-check", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P1: Implement health check endpoint. See Backlog." }, - { "role": "executor", "from": "backend", "timestamp": "2026-03-15T12:15:00Z", "content": "Completed. No application server in this repo (framework-only). Documented health check convention in docs/api/07_framework-api-conventions.md: GET /api/health or GET /health, 200 + { status: ok } for adopters." } - ], - "artifacts": [ - { "type": "files-changed", "paths": ["docs/api/07_framework-api-conventions.md"] }, - { "type": "test-results", "passed": 0, "failed": 0, "testsAdded": 0, "testsModified": 0 } - ] -} diff --git a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-migration-tooling.json b/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-migration-tooling.json deleted file mode 100644 index 4e72185f..00000000 --- a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-migration-tooling.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "task-p1-migration-tooling", - "type": "implement", - "status": "completed", - "priority": "P1", - "delegator": "orchestrator", - "assignees": ["team-data"], - "title": "Create migration tooling setup", - "description": "Prisma or Drizzle (or document choice). Set up migration tooling for the project.", - "acceptanceCriteria": [ - "Migration tooling chosen and documented or implemented", - "Basic migration workflow documented" - ], - "scope": ["db/**", "migrations/**", "prisma/**", "package.json"], - "backlogItemId": "P1-T3-migration-tooling", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P1: Create migration tooling setup. See Backlog." }, - { "role": "executor", "from": "data", "timestamp": "2026-03-15T12:35:00Z", "content": "Completed. Repo has no DB. Added migrations/README.md documenting that adopters choose Prisma or Drizzle and documenting basic migration workflow (define schema, generate migration, run migrations)." } - ], - "artifacts": [ - { "type": "files-changed", "paths": ["migrations/README.md"] }, - { "type": "test-results", "passed": 0, "failed": 0, "testsAdded": 0, "testsModified": 0 } - ] -} diff --git a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-staging-env.json b/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-staging-env.json deleted file mode 100644 index 19f40686..00000000 --- a/.claude/worktrees/tender-margulis/.claude/state/tasks/task-p1-staging-env.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "task-p1-staging-env", - "type": "implement", - "status": "completed", - "priority": "P1", - "delegator": "orchestrator", - "assignees": ["team-infra"], - "title": "Set up staging environment", - "description": "Docker Compose (or equivalent) for staging. Set up staging environment for the project.", - "acceptanceCriteria": [ - "Staging environment defined (e.g. docker-compose or IaC)", - "Documented how to run and deploy to staging" - ], - "scope": ["infra/**", "docker/**", "docker-compose*.yml", "docs/operations/**"], - "backlogItemId": "P1-T4-staging", - "messages": [ - { "role": "delegator", "from": "orchestrator", "timestamp": "2026-03-15T12:00:00Z", "content": "P1: Set up staging environment. See Backlog." }, - { "role": "executor", "from": "infra", "timestamp": "2026-03-15T12:25:00Z", "content": "Completed. Added infra/README.md (staging and local validation; adopters define their own staging). Added docker-compose.yml at repo root with profile 'sync' to run pnpm install + agentkit:sync in a container for staging-like validation." } - ], - "artifacts": [ - { "type": "files-changed", "paths": ["infra/README.md", "docker-compose.yml"] }, - { "type": "test-results", "passed": 0, "failed": 0, "testsAdded": 0, "testsModified": 0 } - ] -} diff --git a/.claude/worktrees/tender-margulis/package-lock.json b/.claude/worktrees/tender-margulis/package-lock.json deleted file mode 100644 index 24372cf6..00000000 --- a/.claude/worktrees/tender-margulis/package-lock.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "retort-root", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "retort-root", - "dependencies": { - "js-yaml": "^4.1.1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - } - } -} diff --git a/.cursor/commands/cicd-optimize.md b/.cursor/commands/cicd-optimize.md new file mode 100644 index 00000000..3a607429 --- /dev/null +++ b/.cursor/commands/cicd-optimize.md @@ -0,0 +1,99 @@ +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-20 --> +<!-- Format: Plain Markdown. Cursor command template. --> +<!-- Docs: https://docs.cursor.com/context/rules --> + +# cicd-optimize + +CI/CD pipeline and local hook optimizer. Audits GitHub Actions workflows, pre-commit/stop hooks, and test configurations for speed bottlenecks. Identifies caching gaps, sequential jobs that could parallelize, missing path filters, redundant installs, and slow hook steps. Produces a prioritized list of improvements with estimated time savings per fix. + +## Role + +You are the **CI/CD Optimization Agent**. Analyse this project's CI/CD pipelines and local hooks for speed bottlenecks. Produce a prioritized report with concrete, copy-paste-ready fixes. + +## Step 1 — Inventory + +Collect all CI/CD surface area: + +- `.github/workflows/*.yml` — list each workflow, its triggers, jobs, and steps +- `.claude/hooks/` — list each hook file and its purpose +- `package.json` scripts: `lint`, `test`, `build`, `typecheck` +- Test framework config: `vitest.config.*`, `jest.config.*`, `pytest.ini`, `Cargo.toml [profile.test]` +- Lock files: `pnpm-lock.yaml`, `Cargo.lock`, `poetry.lock` + +## Step 2 — Bottleneck Detection + +For each workflow, check: + +### Caching + +- [ ] Node modules cached? (`actions/cache` with `node_modules` or `pnpm store`) +- [ ] Cargo registry cached? (`~/.cargo/registry` and `target/`) +- [ ] pip/poetry cached? (`~/.cache/pip`) +- [ ] Docker layer cache used? (`cache-from: type=gha`) + +### Parallelization + +- [ ] Jobs that depend on each other but don't need to — should they be parallel? +- [ ] Test suites that could use matrix strategy or `--pool` (vitest), `pytest-xdist`, `cargo nextest` +- [ ] Lint and typecheck run sequentially when they're independent + +### Trigger efficiency + +- [ ] Workflows triggered on `push` to all branches — should use `paths:` filters +- [ ] PR workflows trigger on `push` AND `pull_request` — often redundant +- [ ] Scheduled workflows running more frequently than needed + +### Install efficiency + +- [ ] `npm install` / `pnpm install` without `--frozen-lockfile` (slower) +- [ ] Install steps duplicated across jobs (should use artifacts or caching) +- [ ] `node_modules` copied between jobs instead of restored from cache + +### Hook efficiency + +- [ ] Stop hook runs tests or full builds (should be lint-only with file-change gating) +- [ ] Pre-commit hook runs expensive operations without caching +- [ ] Hooks run regardless of which files changed + +## Step 3 — Test Suite Speed + +Check for parallelization opportunities: + +- vitest: `--pool=threads` or `--pool=forks`, `--reporter=verbose` adding noise +- pytest: `pytest-xdist` (`-n auto`), test isolation issues +- cargo: `cargo nextest` (2-3x faster than `cargo test`) +- jest: `--maxWorkers` configuration + +## Step 4 — Report + +Produce a table sorted by estimated time savings (highest first): + +| # | Area | Issue | Fix | Est. saving | +| --- | ---- | ----- | --- | ----------- | +| 1 | ... | ... | ... | ~Xs per run | + +Then provide **Ready-to-apply fixes** — code blocks for each high-impact change, in order. For workflow changes, show the exact YAML diff. For hook changes, show the exact shell change. For config changes, show the file and the new content. + +## Rules + +1. Only suggest changes with clear, measurable benefit. Skip micro-optimisations. +2. Preserve correctness — never suggest removing a cache that would break reproducibility. +3. Flag any changes that require secrets or environment variables. +4. If a fix requires a new dependency (e.g. cargo-nextest), note the install command. + +## Project Context + +- Repository: retort +- Default branch: main + - Tech stack: javascript, yaml, markdown + +## Conventions + +- Write minimal, focused diffs — change only what is necessary +- Maintain backwards compatibility +- Every behavioral change must include tests +- Never commit secrets or credentials +- Follow the project's coding standards and quality gates diff --git a/.cursor/commands/handoff.md b/.cursor/commands/handoff.md index 2763d727..50513c7a 100644 --- a/.cursor/commands/handoff.md +++ b/.cursor/commands/handoff.md @@ -1,7 +1,7 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -<!-- generated_by: agentkit-forge | last_model: sync-engine | last_updated: 2026-03-05 --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-05 --> <!-- Format: Plain Markdown. Cursor command template. --> <!-- Docs: https://docs.cursor.com/context/rules --> @@ -20,7 +20,7 @@ Generates a structured handoff document for the current session. Captures what w ## Instructions -When invoked, follow the AgentKit Forge orchestration lifecycle: +When invoked, follow the Retort orchestration lifecycle: 1. **Understand** the request and any arguments provided 2. **Scan** relevant files to build context @@ -30,7 +30,7 @@ When invoked, follow the AgentKit Forge orchestration lifecycle: ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.cursor/commands/healthcheck.md b/.cursor/commands/healthcheck.md index 75718665..162b1a44 100644 --- a/.cursor/commands/healthcheck.md +++ b/.cursor/commands/healthcheck.md @@ -1,7 +1,7 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -<!-- generated_by: agentkit-forge | last_model: sync-engine | last_updated: 2026-03-05 --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-05 --> <!-- Format: Plain Markdown. Cursor command template. --> <!-- Docs: https://docs.cursor.com/context/rules --> @@ -20,7 +20,7 @@ Performs a comprehensive health check of the repository: validates builds, runs ## Instructions -When invoked, follow the AgentKit Forge orchestration lifecycle: +When invoked, follow the Retort orchestration lifecycle: 1. **Understand** the request and any arguments provided 2. **Scan** relevant files to build context @@ -30,7 +30,7 @@ When invoked, follow the AgentKit Forge orchestration lifecycle: ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.cursor/commands/init.md b/.cursor/commands/init.md new file mode 100644 index 00000000..38971627 --- /dev/null +++ b/.cursor/commands/init.md @@ -0,0 +1,68 @@ +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-20 --> +<!-- Format: Plain Markdown. Cursor command template. --> +<!-- Docs: https://docs.cursor.com/context/rules --> + +# init + +Initialise the current repository as a Retort project. Runs the interactive setup wizard to detect the tech stack, select language kits, choose AI tools, and generate the initial project.yaml and overlay configuration. Supports --dry-run to preview without writing. + +## Role + +You are the **Init Agent**. Guide users through initialising a new Retort project in the current repository. + +## How to Initialise + +Run the init command from the repository root: + +```bash +node .agentkit/engines/node/src/cli.mjs init +``` + +Or if pnpm is available: + +```bash +pnpm -C .agentkit agentkit:init +``` + +## Flags + +| Flag | Effect | +| ------------------- | ------------------------------------------------------ | +| `--dry-run` | Show what would be generated without writing any files | +| `--non-interactive` | Skip prompts, use auto-detected defaults | +| `--preset <name>` | Use a preset: minimal, full, team, infra | +| `--force` | Overwrite existing overlay configuration | +| `--repoName <name>` | Override the detected repository name | + +## Kit Selection + +During interactive init, Retort detects your tech stack and shows which +language kits will be activated (typescript, dotnet, rust, python, blockchain). +Universal kits (security, testing, git-workflow, documentation, ci-cd, +dependency-management, agent-conduct) are always included. + +Optional kits (iac, finops, ai-cost-ops) are presented for explicit opt-in. + +## Post-Init + +1. Review the generated `spec/project.yaml` — fill in any `null` fields +2. Run `/sync` to regenerate all AI tool configurations +3. Run `/validate` to verify generated outputs are well-formed +4. Commit both the spec and generated outputs together + +## Project Context + +- Repository: retort +- Default branch: main + - Tech stack: javascript, yaml, markdown + +## Conventions + +- Write minimal, focused diffs — change only what is necessary +- Maintain backwards compatibility +- Every behavioral change must include tests +- Never commit secrets or credentials +- Follow the project's coding standards and quality gates diff --git a/.cursor/commands/project-review.md b/.cursor/commands/project-review.md index e03a8a5e..130116da 100644 --- a/.cursor/commands/project-review.md +++ b/.cursor/commands/project-review.md @@ -1,7 +1,7 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -<!-- generated_by: agentkit-forge | last_model: sync-engine | last_updated: 2026-03-05 --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-05 --> <!-- Format: Plain Markdown. Cursor command template. --> <!-- Docs: https://docs.cursor.com/context/rules --> @@ -19,7 +19,7 @@ Comprehensive production-grade project review and assessment. Systematically ana ## Instructions -When invoked, follow the AgentKit Forge orchestration lifecycle: +When invoked, follow the Retort orchestration lifecycle: 1. **Understand** the request and any arguments provided 2. **Scan** relevant files to build context @@ -29,7 +29,7 @@ When invoked, follow the AgentKit Forge orchestration lifecycle: ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.cursor/rules/orchestrate.mdc b/.cursor/rules/orchestrate.mdc index 7c18205e..5e19cff8 100644 --- a/.cursor/rules/orchestrate.mdc +++ b/.cursor/rules/orchestrate.mdc @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Orchestration diff --git a/.cursor/rules/project-context.mdc b/.cursor/rules/project-context.mdc index 227de637..0e435d5d 100644 --- a/.cursor/rules/project-context.mdc +++ b/.cursor/rules/project-context.mdc @@ -1,9 +1,12 @@ +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Project Context This repository uses the AgentKit Forge unified agent team framework (v3.1.0). ## Language Profile Diagnostics -- Source: mixed (confidence: high) +- Source: configured (confidence: high) - Configured languages present: yes - JS-like: configured=true, inferred=true, effective=true - Python: configured=false, inferred=false, effective=false diff --git a/.cursor/rules/security.mdc b/.cursor/rules/security.mdc index 251d8935..2287c4ba 100644 --- a/.cursor/rules/security.mdc +++ b/.cursor/rules/security.mdc @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Security Rules - Never read, print, or commit secrets or tokens diff --git a/.cursor/settings.json b/.cursor/settings.json index 95cb789e..0122b43d 100644 --- a/.cursor/settings.json +++ b/.cursor/settings.json @@ -79,7 +79,7 @@ "menu.separatorBackground": "#18232A" }, "_agentkit_theme": { - "brand": "AgentKit Forge", + "brand": "Retort", "mode": "both", "scheme": "dark", "tier": "full", diff --git a/.gemini/config.yaml b/.gemini/config.yaml index 749f297b..efd7112a 100644 --- a/.gemini/config.yaml +++ b/.gemini/config.yaml @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # Gemini Code Assist configuration # Generated by AgentKit Forge — see .agentkit/ for source diff --git a/.gitattributes b/.gitattributes index b9765db7..a5e34706 100644 --- a/.gitattributes +++ b/.gitattributes @@ -21,38 +21,12 @@ *.ttf binary *.eot binary -# ============================================================================= -# Merge drivers — auto-resolve conflicts on generated / framework-managed files -# ============================================================================= -# These rules use custom merge drivers defined in .gitconfig (repo-local) or -# the user's global config. Run `git config --local include.path ../.gitattributes-drivers` -# or the setup script to activate them. -# -# Driver: agentkit-generated — always accept the incoming (upstream) version -# for files that are regenerated by `agentkit sync` and should never diverge. -# ============================================================================= - -# --- Generated agent/skill/prompt packs (always accept upstream) --- -.agents/skills/**/SKILL.md merge=agentkit-generated -.github/agents/*.agent.md merge=agentkit-generated -.github/chatmodes/*.chatmode.md merge=agentkit-generated -.github/prompts/*.prompt.md merge=agentkit-generated - -# --- Generated doc indexes (always accept upstream) --- -docs/*/README.md merge=agentkit-generated - -# --- Generated config files (always accept upstream) --- -.github/copilot-instructions.md merge=agentkit-generated -.github/PULL_REQUEST_TEMPLATE.md merge=agentkit-generated - -# --- Lock files (accept upstream, regenerate after merge) --- -pnpm-lock.yaml merge=agentkit-generated -.agentkit/pnpm-lock.yaml merge=agentkit-generated - -# >>> AgentKit Forge merge drivers — DO NOT EDIT below this line -# GENERATED by AgentKit Forge v3.1.0 — regenerated on every sync. +# >>> Retort merge drivers — DO NOT EDIT below this line +# GENERATED by Retort v3.1.0 — regenerated on every sync. # These custom merge drivers auto-resolve conflicts on framework-managed files. # Driver "agentkit-generated" accepts the incoming (upstream/theirs) version. +# Only scaffold:always files are listed — scaffold:managed files (CLAUDE.md, +# settings.json, etc.) are intentionally excluded so user edits are preserved. # # To activate locally, run: # git config merge.agentkit-generated.name "Accept upstream for generated files" @@ -60,20 +34,44 @@ pnpm-lock.yaml merge=agentkit-generated # # Or use: scripts/resolve-merge.sh <target-branch> -# --- Generated agent/skill/prompt packs (always accept upstream) --- -.agents/skills/**/SKILL.md merge=agentkit-generated +# --- Claude Code: agents, commands, rules, hooks, skills --- +.claude/agents/*.md merge=agentkit-generated +.claude/commands/*.md merge=agentkit-generated +.claude/rules/**/*.md merge=agentkit-generated +.claude/hooks/*.sh merge=agentkit-generated +.claude/hooks/*.ps1 merge=agentkit-generated +.claude/skills/**/SKILL.md merge=agentkit-generated + +# --- Cursor: commands and rules --- +.cursor/commands/*.md merge=agentkit-generated +.cursor/rules/**/*.md merge=agentkit-generated + +# --- Windsurf: commands, rules, and workflows --- +.windsurf/commands/*.md merge=agentkit-generated +.windsurf/rules/**/*.md merge=agentkit-generated +.windsurf/workflows/*.yml merge=agentkit-generated + +# --- Cline rules --- +.clinerules/**/*.md merge=agentkit-generated + +# --- Roo rules --- +.roo/rules/**/*.md merge=agentkit-generated + +# --- GitHub Copilot: instructions, agents, chatmodes, prompts --- +.github/instructions/**/*.md merge=agentkit-generated .github/agents/*.agent.md merge=agentkit-generated .github/chatmodes/*.chatmode.md merge=agentkit-generated .github/prompts/*.prompt.md merge=agentkit-generated - -# --- Generated doc indexes (always accept upstream) --- -docs/*/README.md merge=agentkit-generated - -# --- Generated config files (always accept upstream) --- .github/copilot-instructions.md merge=agentkit-generated .github/PULL_REQUEST_TEMPLATE.md merge=agentkit-generated +# --- Agent skills packs --- +.agents/skills/**/SKILL.md merge=agentkit-generated + +# --- Generated doc indexes --- +docs/*/README.md merge=agentkit-generated + # --- Lock files (accept upstream, regenerate after merge) --- pnpm-lock.yaml merge=agentkit-generated .agentkit/pnpm-lock.yaml merge=agentkit-generated -# <<< AgentKit Forge merge drivers — DO NOT EDIT above this line +# <<< Retort merge drivers — DO NOT EDIT above this line diff --git a/.github/ISSUES/002-maintenance-coordinator-agent.md b/.github/ISSUES/002-maintenance-coordinator-agent.md index 98f1ce3a..1f84002c 100644 --- a/.github/ISSUES/002-maintenance-coordinator-agent.md +++ b/.github/ISSUES/002-maintenance-coordinator-agent.md @@ -33,7 +33,7 @@ Append to the operations category in `.agentkit/spec/agents.yaml`: role: > System maintenance specialist responsible for framework health, rule governance, technical debt tracking, script ownership, and coordination - of maintenance-phase operations. Stewards AgentKit Forge internals and + of maintenance-phase operations. Stewards Retort internals and ensures CLI, hooks, CI, and generated outputs remain consistent with specifications. accepts: diff --git a/.github/ISSUES/009-doctor-presync-healthcheck.md b/.github/ISSUES/009-doctor-presync-healthcheck.md index 3a46cf10..2c40421c 100644 --- a/.github/ISSUES/009-doctor-presync-healthcheck.md +++ b/.github/ISSUES/009-doctor-presync-healthcheck.md @@ -25,7 +25,7 @@ It's **not called from**: ### Step 1: Integrate doctor into healthcheck.mjs (~30 min) -In `healthcheck.mjs`, after the AgentKit Setup section (line 84): +In `healthcheck.mjs`, after the Retort Setup section (line 84): ```javascript // --- Step 2b: Framework Diagnostics --- diff --git a/.github/ISSUES/013-trae-mcp-alignment-umbrella.md b/.github/ISSUES/013-trae-mcp-alignment-umbrella.md index 2b0822bd..ce11571c 100644 --- a/.github/ISSUES/013-trae-mcp-alignment-umbrella.md +++ b/.github/ISSUES/013-trae-mcp-alignment-umbrella.md @@ -10,7 +10,7 @@ ## Summary -Add first-class support for high-value MCP integrations and MCP-oriented framework behavior so AgentKit Forge can better interoperate with TRAE-style MCP workflows. +Add first-class support for high-value MCP integrations and MCP-oriented framework behavior so Retort can better interoperate with TRAE-style MCP workflows. This umbrella tracks: @@ -46,7 +46,7 @@ Additional screenshot-visible MCP categories worth grouping: ## Problem -AgentKit Forge already generates MCP-related assets (for example `.mcp/a2a-config.json`) and contains early A2A/task delegation concepts, but the framework does **not yet present a coherent strategy** for: +Retort already generates MCP-related assets (for example `.mcp/a2a-config.json`) and contains early A2A/task delegation concepts, but the framework does **not yet present a coherent strategy** for: 1. Selecting and prioritizing high-value MCP servers 2. Modeling MCP server categories in spec/config @@ -57,13 +57,13 @@ AgentKit Forge already generates MCP-related assets (for example `.mcp/a2a-confi This creates a gap between: - What MCP-capable IDEs now expose in marketplace workflows -- What AgentKit Forge can scaffold, document, validate, and maintain +- What Retort can scaffold, document, validate, and maintain --- ## Goals -- Define a canonical MCP support strategy for AgentKit Forge +- Define a canonical MCP support strategy for Retort - Prioritize practical MCP servers with clear user value - Add documentation, config, and generated output support where justified - Avoid server-by-server sprawl without governance diff --git a/.github/ISSUES/014-trae-mcp-foundation.md b/.github/ISSUES/014-trae-mcp-foundation.md index fe321275..01ec97d2 100644 --- a/.github/ISSUES/014-trae-mcp-foundation.md +++ b/.github/ISSUES/014-trae-mcp-foundation.md @@ -8,7 +8,7 @@ ## Problem -MCP support currently exists as scattered capability rather than a governed framework concern. AgentKit Forge needs a clear model for deciding: +MCP support currently exists as scattered capability rather than a governed framework concern. Retort needs a clear model for deciding: - Which MCP servers are officially supported - Which MCP servers are merely documented or recommended diff --git a/.github/ISSUES/015-priority-mcp-integrations.md b/.github/ISSUES/015-priority-mcp-integrations.md index 7e4e6c3c..d4e136cc 100644 --- a/.github/ISSUES/015-priority-mcp-integrations.md +++ b/.github/ISSUES/015-priority-mcp-integrations.md @@ -34,12 +34,12 @@ For each server, document: - expected user value - credential / environment requirements - local vs hosted execution model -- overlap with existing AgentKit capabilities +- overlap with existing Retort capabilities - target support level ### Step 2: Define framework integration surface -For each server, decide whether AgentKit Forge should add: +For each server, decide whether Retort should add: - documentation only - recommended install/onboarding workflow @@ -77,7 +77,7 @@ Beyond the first four priority MCPs, keep the following adjacent follow-ups visi - Notion MCP client support details: `033-notion-mcp-client-support.md` - Documentation MCP and Pandoc workflows: `035-documentation-mcp-and-pandoc-support.md` -- Self-hosted AgentKit MCP server strategy: `036-self-hosted-mcp-server-strategy.md` +- Self-hosted Retort MCP server strategy: `036-self-hosted-mcp-server-strategy.md` - Todoist-through-MCP task integration: `037-todoist-mcp-task-integration.md` - InsForge MCP evaluation: `034-insforge-mcp-support.md` diff --git a/.github/ISSUES/016-mcp-category-browser-devtools.md b/.github/ISSUES/016-mcp-category-browser-devtools.md index 7acb3415..0cc53551 100644 --- a/.github/ISSUES/016-mcp-category-browser-devtools.md +++ b/.github/ISSUES/016-mcp-category-browser-devtools.md @@ -8,7 +8,7 @@ ## Problem -TRAE marketplace screenshots show browser-oriented MCP workflows such as Puppeteer and Chrome DevTools MCP. AgentKit Forge should decide how these fit into platform guidance, testing workflows, and security boundaries. +TRAE marketplace screenshots show browser-oriented MCP workflows such as Puppeteer and Chrome DevTools MCP. Retort should decide how these fit into platform guidance, testing workflows, and security boundaries. --- @@ -26,7 +26,7 @@ Evaluate support patterns for browser/devtools MCP servers, including: - [ ] Browser/devtools MCP category has a support recommendation - [ ] Security constraints are documented -- [ ] Testing / debugging workflows are mapped to AgentKit commands or skills +- [ ] Testing / debugging workflows are mapped to Retort commands or skills - [ ] First-class vs documented-only support is decided per candidate --- diff --git a/.github/ISSUES/017-mcp-category-repo-data-research.md b/.github/ISSUES/017-mcp-category-repo-data-research.md index abb5db9f..0e59240c 100644 --- a/.github/ISSUES/017-mcp-category-repo-data-research.md +++ b/.github/ISSUES/017-mcp-category-repo-data-research.md @@ -8,7 +8,7 @@ ## Problem -The TRAE marketplace screenshots show strong coverage across repository, database, and research-oriented MCP servers. AgentKit Forge needs a deliberate support position for these categories rather than ad hoc adoption. +The TRAE marketplace screenshots show strong coverage across repository, database, and research-oriented MCP servers. Retort needs a deliberate support position for these categories rather than ad hoc adoption. Candidate examples visible across screenshots and request context include: @@ -35,7 +35,7 @@ This issue should identify which category members deserve separate first-class f ## Acceptance Criteria - [ ] Repo/data/research MCP categories have support recommendations -- [ ] Existing AgentKit capabilities are compared against marketplace MCP overlap +- [ ] Existing Retort capabilities are compared against marketplace MCP overlap - [ ] High-value servers are identified for first-class support - [ ] Documentation-only vs generated-config support is decided where practical diff --git a/.github/ISSUES/018-mcp-category-desktop-collab-memory.md b/.github/ISSUES/018-mcp-category-desktop-collab-memory.md index f52346a5..65b141d7 100644 --- a/.github/ISSUES/018-mcp-category-desktop-collab-memory.md +++ b/.github/ISSUES/018-mcp-category-desktop-collab-memory.md @@ -8,7 +8,7 @@ ## Problem -The TRAE marketplace includes desktop/filesystem/shell, collaboration, and memory-oriented MCP servers that can materially change agent workflows. AgentKit Forge needs a clear position on which of these should be integrated, documented, or deferred. +The TRAE marketplace includes desktop/filesystem/shell, collaboration, and memory-oriented MCP servers that can materially change agent workflows. Retort needs a clear position on which of these should be integrated, documented, or deferred. Examples visible in screenshots include: diff --git a/.github/ISSUES/019-trae-memory-support-umbrella.md b/.github/ISSUES/019-trae-memory-support-umbrella.md index c0df1952..c49e1265 100644 --- a/.github/ISSUES/019-trae-memory-support-umbrella.md +++ b/.github/ISSUES/019-trae-memory-support-umbrella.md @@ -10,7 +10,7 @@ ## Summary -Add explicit memory support strategy and implementation planning to AgentKit Forge, aligned with TRAE memory workflows. +Add explicit memory support strategy and implementation planning to Retort, aligned with TRAE memory workflows. Primary reference: @@ -27,7 +27,7 @@ This umbrella covers: ## Problem -AgentKit Forge supports rich prompts, generated rules, workflows, and orchestration, but does not yet define a framework-level position on: +Retort supports rich prompts, generated rules, workflows, and orchestration, but does not yet define a framework-level position on: - what memory means in product terms - which memories are per-session vs durable @@ -41,7 +41,7 @@ Without that, memory support risks becoming inconsistent, overly implicit, or un ## Acceptance Criteria -- [ ] A memory support model exists for AgentKit Forge +- [ ] A memory support model exists for Retort - [ ] Persistence, scope, retention, and privacy boundaries are defined - [ ] Follow-on sub-issues cover architecture, UX/governance, and generated-output integration - [ ] TRAE memory documentation is referenced in the implementation notes diff --git a/.github/ISSUES/020-memory-model-and-storage.md b/.github/ISSUES/020-memory-model-and-storage.md index 27fc71ea..f53c0aa6 100644 --- a/.github/ISSUES/020-memory-model-and-storage.md +++ b/.github/ISSUES/020-memory-model-and-storage.md @@ -8,7 +8,7 @@ ## Problem -Before implementing memory-related features, AgentKit Forge needs a clear architecture for: +Before implementing memory-related features, Retort needs a clear architecture for: - session memory vs durable memory - workspace-scoped vs user-scoped memory diff --git a/.github/ISSUES/022-memory-generated-output-support.md b/.github/ISSUES/022-memory-generated-output-support.md index bf0d02e5..3b122e15 100644 --- a/.github/ISSUES/022-memory-generated-output-support.md +++ b/.github/ISSUES/022-memory-generated-output-support.md @@ -8,7 +8,7 @@ ## Problem -If AgentKit Forge adds memory support, generated outputs need to reflect that consistently across supported platforms. +If Retort adds memory support, generated outputs need to reflect that consistently across supported platforms. This includes: diff --git a/.github/ISSUES/023-trae-codebase-indexing.md b/.github/ISSUES/023-trae-codebase-indexing.md index 0182bc06..c0a40880 100644 --- a/.github/ISSUES/023-trae-codebase-indexing.md +++ b/.github/ISSUES/023-trae-codebase-indexing.md @@ -8,7 +8,7 @@ ## Problem -TRAE documents explicit codebase indexing behavior, but AgentKit Forge does not yet define a corresponding framework posture for indexing-aware workflows. +TRAE documents explicit codebase indexing behavior, but Retort does not yet define a corresponding framework posture for indexing-aware workflows. Reference: @@ -16,7 +16,7 @@ Reference: Questions to resolve: -- What should AgentKit Forge assume about indexing availability? +- What should Retort assume about indexing availability? - Which generated instructions should be indexing-aware? - How should indexing limitations or stale index behavior be handled? - What repo guidance improves indexing quality in large or multi-root workspaces? diff --git a/.github/ISSUES/024-trae-context-compaction.md b/.github/ISSUES/024-trae-context-compaction.md index 3daec45b..1533b207 100644 --- a/.github/ISSUES/024-trae-context-compaction.md +++ b/.github/ISSUES/024-trae-context-compaction.md @@ -8,7 +8,7 @@ ## Problem -TRAE documents automated context compaction, but AgentKit Forge does not yet define how its generated prompts, workflows, and orchestration model should behave when context is compacted automatically. +TRAE documents automated context compaction, but Retort does not yet define how its generated prompts, workflows, and orchestration model should behave when context is compacted automatically. Reference: diff --git a/.github/ISSUES/025-trae-rules-revisit.md b/.github/ISSUES/025-trae-rules-revisit.md index fe004e13..1fddf6b2 100644 --- a/.github/ISSUES/025-trae-rules-revisit.md +++ b/.github/ISSUES/025-trae-rules-revisit.md @@ -8,7 +8,7 @@ ## Problem -TRAE exposes explicit rules behavior, and AgentKit Forge should revisit whether its current rule generation strategy best fits that environment. +TRAE exposes explicit rules behavior, and Retort should revisit whether its current rule generation strategy best fits that environment. Reference: @@ -40,6 +40,15 @@ Areas to revisit: - [ ] Platform-specific projection strategy is reviewed - [ ] Follow-up implementation tasks are identified if needed +## Implementation Notes (2026-03-20) + +The `feat/kit-domain-selection-onboarding` branch introduces stack-based domain filtering +(`filterDomainsByStack` in `template-utils.mjs`) which directly reduces rule noise: only +domains relevant to the declared stack are generated. A TypeScript-only project now gets +typescript + universal domains — not dotnet/rust/python/blockchain. This partially addresses +the redundancy and platform noise concerns raised here. The TRAE-specific rule format audit +remains outstanding. + --- ## Resolution diff --git a/.github/ISSUES/026-trae-skills-revisit.md b/.github/ISSUES/026-trae-skills-revisit.md index 430a815a..38ad6558 100644 --- a/.github/ISSUES/026-trae-skills-revisit.md +++ b/.github/ISSUES/026-trae-skills-revisit.md @@ -8,7 +8,7 @@ ## Problem -TRAE exposes skills as a first-class concept. AgentKit Forge should revisit whether its generated skills are scoped, named, and documented optimally for TRAE-style usage. +TRAE exposes skills as a first-class concept. Retort should revisit whether its generated skills are scoped, named, and documented optimally for TRAE-style usage. Reference: @@ -31,6 +31,13 @@ Areas to revisit: - [ ] Naming/discoverability improvements are proposed - [ ] Follow-up implementation tasks are identified if needed +## Implementation Notes (2026-03-20) + +Kit-based domain filtering (`feat/kit-domain-selection-onboarding`) reduces generated skill +volume by only activating domains relevant to the project's declared stack. The same principle +could be applied to skill generation in a follow-up: generate language-specific skills only +for active language kits. Skill format audit against TRAE expectations remains outstanding. + --- ## Note diff --git a/.github/ISSUES/027-trae-agents-revisit.md b/.github/ISSUES/027-trae-agents-revisit.md index c0bab958..f1a53c3f 100644 --- a/.github/ISSUES/027-trae-agents-revisit.md +++ b/.github/ISSUES/027-trae-agents-revisit.md @@ -8,7 +8,7 @@ ## Problem -TRAE provides both agent overview guidance and custom agents ready for one-click import. AgentKit Forge should revisit whether its agent model and generated outputs map well to those capabilities. +TRAE provides both agent overview guidance and custom agents ready for one-click import. Retort should revisit whether its agent model and generated outputs map well to those capabilities. References: @@ -37,7 +37,7 @@ Identify over-specialization, duplication, and missing platform-oriented persona ### 3. Evaluate export/import affordances -Determine whether AgentKit Forge should emit TRAE-ready agent artifacts directly or via an adapter/export step. +Determine whether Retort should emit TRAE-ready agent artifacts directly or via an adapter/export step. --- @@ -48,6 +48,13 @@ Determine whether AgentKit Forge should emit TRAE-ready agent artifacts directly - [ ] Agent overlap/gaps are identified - [ ] Follow-up implementation tasks are identified if needed +## Implementation Notes (2026-03-20) + +Issue 040 (elegance-guidelines) from `feat/kit-domain-selection-onboarding` adds per-agent +design guidance that improves agent quality independent of platform. The kit-based filtering +work means agent-related generation is more stack-aware. TRAE-specific agent packaging/import +format audit remains outstanding — this should be prioritised in the next sprint. + --- ## Note diff --git a/.github/ISSUES/028-trae-figma-support.md b/.github/ISSUES/028-trae-figma-support.md index c88b6b19..dd0f2342 100644 --- a/.github/ISSUES/028-trae-figma-support.md +++ b/.github/ISSUES/028-trae-figma-support.md @@ -8,7 +8,7 @@ ## Problem -The screenshots show Figma-oriented MCP capability (`Figma AI Bridge`). AgentKit Forge does not yet define how design-tool integration should work across prompts, agents, workflows, and generated platform guidance. +The screenshots show Figma-oriented MCP capability (`Figma AI Bridge`). Retort does not yet define how design-tool integration should work across prompts, agents, workflows, and generated platform guidance. This gap affects: diff --git a/.github/ISSUES/029-platform-support-umbrella.md b/.github/ISSUES/029-platform-support-umbrella.md index f9f7d071..8fd38a03 100644 --- a/.github/ISSUES/029-platform-support-umbrella.md +++ b/.github/ISSUES/029-platform-support-umbrella.md @@ -31,13 +31,13 @@ Requested platforms: This umbrella exists to answer two questions consistently: 1. Is the platform an IDE, an agent shell, an aggregator, or another execution surface? -2. What level of AgentKit Forge support should exist for that platform? +2. What level of Retort support should exist for that platform? --- ## Problem -AgentKit Forge already targets several AI coding environments, but support expansion is currently driven by ad hoc additions. That makes it hard to reason about: +Retort already targets several AI coding environments, but support expansion is currently driven by ad hoc additions. That makes it hard to reason about: - which platforms are officially supported - how support levels differ by platform type @@ -70,7 +70,7 @@ Review each requested platform for: ### Phase 3: Support implementation strategy -Decide for each platform whether AgentKit Forge should add: +Decide for each platform whether Retort should add: - first-class generated outputs - adapter/export support diff --git a/.github/ISSUES/031-ai-aggregator-support.md b/.github/ISSUES/031-ai-aggregator-support.md index c7c09a76..d3278dd6 100644 --- a/.github/ISSUES/031-ai-aggregator-support.md +++ b/.github/ISSUES/031-ai-aggregator-support.md @@ -8,7 +8,7 @@ ## Problem -AgentKit Forge currently focuses mostly on editor and agent-runtime targets, but there is a separate class of tools that act as AI aggregators or orchestration hubs. +Retort currently focuses mostly on editor and agent-runtime targets, but there is a separate class of tools that act as AI aggregators or orchestration hubs. Example requested category: diff --git a/.github/ISSUES/032-trae-alignment-master-umbrella.md b/.github/ISSUES/032-trae-alignment-master-umbrella.md index f94d70a6..21ce4bda 100644 --- a/.github/ISSUES/032-trae-alignment-master-umbrella.md +++ b/.github/ISSUES/032-trae-alignment-master-umbrella.md @@ -48,7 +48,7 @@ Tracking these as isolated issues is useful for execution, but there also needs ## Coordination Goals -- Define what “TRAE support” means for AgentKit Forge +- Define what “TRAE support” means for Retort - Separate first-class support from documentation-only support - Ensure platform changes do not fragment the core spec/sync architecture - Reuse common abstractions across MCP, memory, rules, skills, and agents where possible diff --git a/.github/ISSUES/033-notion-mcp-client-support.md b/.github/ISSUES/033-notion-mcp-client-support.md index 105d05a8..71f055af 100644 --- a/.github/ISSUES/033-notion-mcp-client-support.md +++ b/.github/ISSUES/033-notion-mcp-client-support.md @@ -19,10 +19,10 @@ References: ## Scope -Evaluate what AgentKit Forge should support for Notion MCP integration, including: +Evaluate what Retort should support for Notion MCP integration, including: - recommended MCP client usage patterns -- workspace/page/database operations most relevant to AgentKit workflows +- workspace/page/database operations most relevant to Retort workflows - authentication and secret handling - generated docs or setup guidance - overlap with existing Notion integration expectations @@ -35,7 +35,7 @@ Evaluate what AgentKit Forge should support for Notion MCP integration, includin Document the client-side flow and required capabilities from the Notion MCP guide. -### Step 2: Map high-value AgentKit use cases +### Step 2: Map high-value Retort use cases Candidate use cases: @@ -60,7 +60,7 @@ Decide whether support should be: - [ ] Notion MCP has a dedicated support recommendation - [ ] The official Notion MCP client guide is referenced -- [ ] High-value AgentKit use cases are documented +- [ ] High-value Retort use cases are documented - [ ] Auth/security handling is documented at a planning level --- diff --git a/.github/ISSUES/034-insforge-mcp-support.md b/.github/ISSUES/034-insforge-mcp-support.md index 19d7e6a5..670e09cb 100644 --- a/.github/ISSUES/034-insforge-mcp-support.md +++ b/.github/ISSUES/034-insforge-mcp-support.md @@ -8,7 +8,7 @@ ## Problem -InsForge MCP appeared in the marketplace screenshots, but AgentKit Forge does not yet have a dedicated issue evaluating whether it should support or document this integration. +InsForge MCP appeared in the marketplace screenshots, but Retort does not yet have a dedicated issue evaluating whether it should support or document this integration. --- @@ -16,7 +16,7 @@ InsForge MCP appeared in the marketplace screenshots, but AgentKit Forge does no Assess InsForge MCP for: -- fit with AgentKit workflows +- fit with Retort workflows - backend/app-scaffolding relevance - security and credential requirements - whether it is docs-only, experimental, or a stronger candidate @@ -26,7 +26,7 @@ Assess InsForge MCP for: ## Acceptance Criteria - [ ] InsForge MCP is evaluated with a support recommendation -- [ ] Likely use cases inside AgentKit are documented +- [ ] Likely use cases inside Retort are documented - [ ] Security/prerequisite considerations are captured --- diff --git a/.github/ISSUES/035-documentation-mcp-and-pandoc-support.md b/.github/ISSUES/035-documentation-mcp-and-pandoc-support.md index 47eb9a11..e01c81b2 100644 --- a/.github/ISSUES/035-documentation-mcp-and-pandoc-support.md +++ b/.github/ISSUES/035-documentation-mcp-and-pandoc-support.md @@ -8,7 +8,7 @@ ## Problem -There is no dedicated ticket for documentation-focused MCP workflows, despite strong relevance to AgentKit Forge. +There is no dedicated ticket for documentation-focused MCP workflows, despite strong relevance to Retort. Pandoc also appeared in the marketplace screenshots, and documentation-oriented MCP support could be valuable for: @@ -50,7 +50,7 @@ Assess whether Pandoc MCP support should help with: - markdown-to-pdf-oriented workflows - frontmatter-preserving transformations -### Step 3: Identify AgentKit-specific value +### Step 3: Identify Retort-specific value Potential value areas: @@ -65,7 +65,7 @@ Potential value areas: - [ ] Documentation MCP category is described with examples - [ ] Pandoc MCP is evaluated as a concrete candidate -- [ ] Documentation-oriented use cases for AgentKit are listed +- [ ] Documentation-oriented use cases for Retort are listed - [ ] Follow-up implementation work is identified if warranted --- diff --git a/.github/ISSUES/036-self-hosted-mcp-server-strategy.md b/.github/ISSUES/036-self-hosted-mcp-server-strategy.md index 2fc89177..8bbb0814 100644 --- a/.github/ISSUES/036-self-hosted-mcp-server-strategy.md +++ b/.github/ISSUES/036-self-hosted-mcp-server-strategy.md @@ -1,4 +1,4 @@ -# feat(mcp): Evaluate hosting our own MCP server for AgentKit Forge +# feat(mcp): Evaluate hosting our own MCP server for Retort **Priority:** P1 — High **Labels:** `enhancement`, `mcp`, `architecture`, `platform` @@ -8,7 +8,7 @@ ## Problem -AgentKit Forge currently consumes or plans around third-party MCP servers, but there is no dedicated issue evaluating whether the project should host its own MCP server. +Retort currently consumes or plans around third-party MCP servers, but there is no dedicated issue evaluating whether the project should host its own MCP server. This needs a deliberate architectural decision before ad hoc implementation begins. @@ -18,12 +18,12 @@ This needs a deliberate architectural decision before ad hoc implementation begi Candidate responsibilities worth evaluating: -- expose AgentKit project/spec metadata to MCP-capable clients +- expose Retort project/spec metadata to MCP-capable clients - expose backlog/tasks/orchestrator state in a stable tool interface - expose docs/ADR/PRD retrieval with project-aware filtering - expose workflow execution surfaces safely - expose project health/status summaries -- provide a stable adapter over AgentKit-native concepts instead of leaking file layout details +- provide a stable adapter over Retort-native concepts instead of leaking file layout details Possible non-goals: @@ -41,7 +41,7 @@ Answer whether a first-party MCP server would improve: - interoperability - platform portability -- discoverability of AgentKit capabilities +- discoverability of Retort capabilities - safer integrations for external tools ### Step 2: Define candidate tool surface diff --git a/.github/ISSUES/037-todoist-mcp-task-integration.md b/.github/ISSUES/037-todoist-mcp-task-integration.md index ac66f63b..09eb9cf1 100644 --- a/.github/ISSUES/037-todoist-mcp-task-integration.md +++ b/.github/ISSUES/037-todoist-mcp-task-integration.md @@ -1,4 +1,4 @@ -# feat(mcp): Integrate AgentKit tasks with Todoist through MCP +# feat(mcp): Integrate Retort tasks with Todoist through MCP **Priority:** P2 — Medium **Labels:** `enhancement`, `mcp`, `tasks`, `todoist`, `integration` @@ -8,7 +8,7 @@ ## Problem -AgentKit Forge has task and backlog concepts, but there is no dedicated issue to evaluate syncing or integrating them with Todoist through MCP. +Retort has task and backlog concepts, but there is no dedicated issue to evaluate syncing or integrating them with Todoist through MCP. --- @@ -16,8 +16,8 @@ AgentKit Forge has task and backlog concepts, but there is no dedicated issue to Evaluate whether Todoist-through-MCP should support: -- pushing AgentKit tasks to Todoist -- importing Todoist tasks into AgentKit backlog/task views +- pushing Retort tasks to Todoist +- importing Todoist tasks into Retort backlog/task views - one-way vs two-way sync - tagging/project mapping - priority/status translation @@ -37,7 +37,7 @@ Decide whether the initial target should be: ### Step 2: Define mapping model -Map AgentKit concepts to Todoist concepts: +Map Retort concepts to Todoist concepts: - task type - priority @@ -55,7 +55,7 @@ Clarify conflict and ownership rules so Todoist does not become an unsafe parall ## Acceptance Criteria - [ ] Todoist-through-MCP integration has a support recommendation -- [ ] Mapping between AgentKit tasks and Todoist concepts is documented +- [ ] Mapping between Retort tasks and Todoist concepts is documented - [ ] Sync direction and conflict model are documented - [ ] Follow-up implementation work is identified if warranted diff --git a/.github/ISSUES/038-platform-support-zed-codex-opencode.md b/.github/ISSUES/038-platform-support-zed-codex-opencode.md index 9e9943e1..06258719 100644 --- a/.github/ISSUES/038-platform-support-zed-codex-opencode.md +++ b/.github/ISSUES/038-platform-support-zed-codex-opencode.md @@ -23,7 +23,7 @@ These are close enough to core coding-agent/editor workflows that they deserve e For each platform, evaluate: - platform type and target model -- current overlap with existing AgentKit outputs +- current overlap with existing Retort outputs - rules/skills/agent/workflow fit - adapter/export opportunities - first-class vs docs-only support recommendation diff --git a/.github/ISSUES/040-agents-should-consider-architectural-elegance.md b/.github/ISSUES/040-agents-should-consider-architectural-elegance.md index 0e278f4b..2928dcf6 100644 --- a/.github/ISSUES/040-agents-should-consider-architectural-elegance.md +++ b/.github/ISSUES/040-agents-should-consider-architectural-elegance.md @@ -31,7 +31,7 @@ elegance-guidelines: - Prefer standard library patterns unless a custom abstraction is clearly justified ``` -### Why this fits AgentKit Forge +### Why this fits Retort - It lives in the agent persona definition, where agents already look for guidance - It can be tailored per agent (backend vs frontend vs infra) @@ -40,11 +40,18 @@ elegance-guidelines: ## Acceptance criteria -- [ ] Add `elegance-guidelines` as an optional field in the agent schema -- [ ] Populate initial elegance guidelines for core engineering agents (backend, frontend, infra, devops) -- [ ] Update spec-validator to accept the new field -- [ ] Regenerate issue templates and agent files to confirm compatibility -- [ ] Document the new field in the agents.yaml header comment +- [x] Add `elegance-guidelines` as an optional field in the agent schema + - Documented in `agents.yaml` header with example + - `spec-validator` does not reject unknown fields; no change needed +- [x] Populate initial elegance guidelines for core engineering agents (backend, frontend, infra, devops) + - `backend`: single-responsibility, thin abstractions, DRY extraction, explicit contracts + - `frontend`: composition > inheritance, design tokens, small components, simple state + - `devops`: composite actions, workflow clarity, fail-fast + - `infra`: thin root modules, consistent naming locals, Terragrunt DRY, minimal parameters +- [x] Update spec-validator to accept the new field (no change needed — validator allows unknown fields) +- [x] Regenerate issue templates and agent files to confirm compatibility (run sync) + - Sync run as part of `feat/kit-domain-selection-onboarding`; no compatibility issues found +- [x] Document the new field in the agents.yaml header comment ## Alternatives considered @@ -61,7 +68,7 @@ This change is inspired by recent code review feedback where technically correct - `.agentkit/engines/node/src/spec-validator.mjs` — accept the new field - Update generated files via `pnpm -C .agentkit agentkit:sync` -**IMPORTANT**: Do not edit generated files directly. All spec changes must be made in `.agentkit/spec/agents.yaml` and regenerated via the sync command. Files marked "GENERATED by AgentKit Forge — DO NOT EDIT" must not be modified directly. Any engine/template changes should be submitted as a PR to the agentkit-forge repository. +**IMPORTANT**: Do not edit generated files directly. All spec changes must be made in `.agentkit/spec/agents.yaml` and regenerated via the sync command. Files marked "GENERATED by Retort — DO NOT EDIT" must not be modified directly. Any engine/template changes should be submitted as a PR to the retort repository. --- @@ -77,3 +84,9 @@ Implemented in `feat(init): kit-based wizard with dry-run, elegance-guidelines, - Sync run confirmed compatibility; no generated file breakage The `elegance-guidelines` field is now part of every agent's persona definition, alongside existing `conventions` and `anti-patterns` fields. + +### Acceptance Criteria + +- [x] `elegance-guidelines` field added to agents.yaml schema +- [x] At least 3 agents have initial elegance guidelines +- [x] Generated files updated and validated diff --git a/.github/ISSUES/agent-maintainer-proposal.md b/.github/ISSUES/agent-maintainer-proposal.md index f3546595..6765b907 100644 --- a/.github/ISSUES/agent-maintainer-proposal.md +++ b/.github/ISSUES/agent-maintainer-proposal.md @@ -34,7 +34,7 @@ The system has 19 agents covering engineering, design, marketing, operations, pr role: > System maintenance specialist responsible for framework health, rule governance, technical debt tracking, script ownership, and coordination - of maintenance-phase operations. Acts as the steward of AgentKit Forge + of maintenance-phase operations. Acts as the steward of Retort internals and ensures CLI, hooks, CI, and generated outputs remain consistent with specifications. accepts: diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 64720d32..a4c3b6cf 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync name: Bug Report description: Report a bug to help us improve diff --git a/.github/ISSUE_TEMPLATE/doc-audit-command.md b/.github/ISSUE_TEMPLATE/doc-audit-command.md index f6e6b7e5..db968faa 100644 --- a/.github/ISSUE_TEMPLATE/doc-audit-command.md +++ b/.github/ISSUE_TEMPLATE/doc-audit-command.md @@ -1,13 +1,13 @@ --- name: 'feat: add /doc-audit slash command' -about: 'Add a repeatable documentation audit command to agentkit-forge' +about: 'Add a repeatable documentation audit command to retort' title: 'feat: add /doc-audit slash command for repeatable documentation audits' labels: enhancement, documentation --- ## Summary -Add a dedicated `/doc-audit` command to agentkit-forge that provides repeatable, systematic documentation audits. Currently, documentation auditing is either a manual one-off exercise or a narrow subset of `/project-review --focus docs`. +Add a dedicated `/doc-audit` command to retort that provides repeatable, systematic documentation audits. Currently, documentation auditing is either a manual one-off exercise or a narrow subset of `/project-review --focus docs`. ## Context diff --git a/.github/ISSUE_TEMPLATE/doc-audit-command.yml b/.github/ISSUE_TEMPLATE/doc-audit-command.yml index 5879a0b5..48b61648 100644 --- a/.github/ISSUE_TEMPLATE/doc-audit-command.yml +++ b/.github/ISSUE_TEMPLATE/doc-audit-command.yml @@ -1,5 +1,5 @@ name: 'feat: add /doc-audit slash command' -description: Add a repeatable documentation audit command to agentkit-forge +description: Add a repeatable documentation audit command to retort title: '[FEATURE] add /doc-audit slash command for repeatable documentation audits' labels: ['enhancement', 'documentation', 'triage'] assignees: [] @@ -10,7 +10,7 @@ body: value: | ## Summary - Add a dedicated `/doc-audit` command to agentkit-forge that provides repeatable, systematic documentation audits. Currently, documentation auditing is either a manual one-off exercise or a narrow subset of `/project-review --focus docs`. + Add a dedicated `/doc-audit` command to retort that provides repeatable, systematic documentation audits. Currently, documentation auditing is either a manual one-off exercise or a narrow subset of `/project-review --focus docs`. ## Context diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 7c545c86..1556c9d5 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync name: Feature Request description: Suggest a new feature or enhancement diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5c85bcfd..1659ec44 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> ## Summary diff --git a/.github/ai-framework-ci.yml b/.github/ai-framework-ci.yml index bee50056..2dc581e7 100644 --- a/.github/ai-framework-ci.yml +++ b/.github/ai-framework-ci.yml @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync name: AI Framework Validation diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index 1ff8fe90..5bc21e5f 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -1,4 +1,4 @@ -name: 'agentkit-forge CodeQL Config' +name: 'retort CodeQL Config' paths: - .agentkit/engines/node/src diff --git a/.github/instructions/rust.md b/.github/instructions/rust.md index 4a092aba..461d9005 100644 --- a/.github/instructions/rust.md +++ b/.github/instructions/rust.md @@ -1,7 +1,7 @@ -<!-- GENERATED by AgentKit Forge v0.2.1 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v0.2.1 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -<!-- generated_by: agentkit-forge | last_model: sync-engine | last_updated: 2026-03-01 --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-01 --> <!-- Format: Plain Markdown. Copilot domain-specific instructions. --> <!-- Docs: https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot --> diff --git a/.github/prompts/cicd-optimize.prompt.md b/.github/prompts/cicd-optimize.prompt.md new file mode 100644 index 00000000..25097b45 --- /dev/null +++ b/.github/prompts/cicd-optimize.prompt.md @@ -0,0 +1,115 @@ +--- +mode: 'agent' +description: 'CI/CD pipeline and local hook optimizer. Audits GitHub Actions workflows, pre-commit/stop hooks, and test configurations for speed bottlenecks. Identifies caching gaps, sequential jobs that could parallelize, missing path filters, redundant installs, and slow hook steps. Produces a prioritized list of improvements with estimated time savings per fix.' +generated_by: 'retort' +last_model: 'sync-engine' +last_updated: '2026-03-20' +# Format: YAML frontmatter + Markdown body. Copilot reusable prompt. +# Docs: https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot +--- + +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> + +# cicd-optimize + +CI/CD pipeline and local hook optimizer. Audits GitHub Actions workflows, pre-commit/stop hooks, and test configurations for speed bottlenecks. Identifies caching gaps, sequential jobs that could parallelize, missing path filters, redundant installs, and slow hook steps. Produces a prioritized list of improvements with estimated time savings per fix. + +## Role + +You are the **CI/CD Optimization Agent**. Analyse this project's CI/CD pipelines and local hooks for speed bottlenecks. Produce a prioritized report with concrete, copy-paste-ready fixes. + +## Step 1 — Inventory + +Collect all CI/CD surface area: + +- `.github/workflows/*.yml` — list each workflow, its triggers, jobs, and steps +- `.claude/hooks/` — list each hook file and its purpose +- `package.json` scripts: `lint`, `test`, `build`, `typecheck` +- Test framework config: `vitest.config.*`, `jest.config.*`, `pytest.ini`, `Cargo.toml [profile.test]` +- Lock files: `pnpm-lock.yaml`, `Cargo.lock`, `poetry.lock` + +## Step 2 — Bottleneck Detection + +For each workflow, check: + +### Caching + +- [ ] Node modules cached? (`actions/cache` with `node_modules` or `pnpm store`) +- [ ] Cargo registry cached? (`~/.cargo/registry` and `target/`) +- [ ] pip/poetry cached? (`~/.cache/pip`) +- [ ] Docker layer cache used? (`cache-from: type=gha`) + +### Parallelization + +- [ ] Jobs that depend on each other but don't need to — should they be parallel? +- [ ] Test suites that could use matrix strategy or `--pool` (vitest), `pytest-xdist`, `cargo nextest` +- [ ] Lint and typecheck run sequentially when they're independent + +### Trigger efficiency + +- [ ] Workflows triggered on `push` to all branches — should use `paths:` filters +- [ ] PR workflows trigger on `push` AND `pull_request` — often redundant +- [ ] Scheduled workflows running more frequently than needed + +### Install efficiency + +- [ ] `npm install` / `pnpm install` without `--frozen-lockfile` (slower) +- [ ] Install steps duplicated across jobs (should use artifacts or caching) +- [ ] `node_modules` copied between jobs instead of restored from cache + +### Hook efficiency + +- [ ] Stop hook runs tests or full builds (should be lint-only with file-change gating) +- [ ] Pre-commit hook runs expensive operations without caching +- [ ] Hooks run regardless of which files changed + +## Step 3 — Test Suite Speed + +Check for parallelization opportunities: + +- vitest: `--pool=threads` or `--pool=forks`, `--reporter=verbose` adding noise +- pytest: `pytest-xdist` (`-n auto`), test isolation issues +- cargo: `cargo nextest` (2-3x faster than `cargo test`) +- jest: `--maxWorkers` configuration + +## Step 4 — Report + +Produce a table sorted by estimated time savings (highest first): + +| # | Area | Issue | Fix | Est. saving | +| --- | ---- | ----- | --- | ----------- | +| 1 | ... | ... | ... | ~Xs per run | + +Then provide **Ready-to-apply fixes** — code blocks for each high-impact change, in order. For workflow changes, show the exact YAML diff. For hook changes, show the exact shell change. For config changes, show the file and the new content. + +## Rules + +1. Only suggest changes with clear, measurable benefit. Skip micro-optimisations. +2. Preserve correctness — never suggest removing a cache that would break reproducibility. +3. Flag any changes that require secrets or environment variables. +4. If a fix requires a new dependency (e.g. cargo-nextest), note the install command. + +## Project Context + +- Repository: retort +- Default branch: main + - Tech stack: javascript, yaml, markdown + +## Conventions + +- Write minimal, focused diffs — change only what is necessary +- Maintain backwards compatibility +- Every behavioral change must include tests +- Never commit secrets or credentials +- Follow the project's coding standards and quality gates + +## References + +- See `AGENTS.md` for universal project instructions +- See `UNIFIED_AGENT_TEAMS.md` for team ownership and escalation +- See `AGENT_TEAMS.md` for repo-specific team boundaries +- See `AGENT_BACKLOG.md` for active work items +- See `CLAUDE.md` for project context and workflow +- See `docs/` for architecture, runbooks, and guides diff --git a/.github/prompts/handoff.prompt.md b/.github/prompts/handoff.prompt.md index 2f7732c8..aa12a407 100644 --- a/.github/prompts/handoff.prompt.md +++ b/.github/prompts/handoff.prompt.md @@ -1,15 +1,15 @@ --- mode: 'agent' description: 'Generates a structured handoff document for the current session. Captures what was accomplished, what remains, open questions, and context needed by the next session or developer. Writes to docs/ai_handoffs/.' -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-04' # Format: YAML frontmatter + Markdown body. Copilot reusable prompt. # Docs: https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot --- -<!-- GENERATED by AgentKit Forge v0.2.1 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v0.2.1 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # handoff @@ -18,7 +18,7 @@ Generates a structured handoff document for the current session. Captures what w ## Instructions -When invoked, follow the AgentKit Forge orchestration lifecycle: +When invoked, follow the Retort orchestration lifecycle: 1. **Understand** the request and any arguments provided 2. **Scan** relevant files to build context @@ -28,7 +28,7 @@ When invoked, follow the AgentKit Forge orchestration lifecycle: ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.github/prompts/healthcheck.prompt.md b/.github/prompts/healthcheck.prompt.md index fb26a657..92d320f7 100644 --- a/.github/prompts/healthcheck.prompt.md +++ b/.github/prompts/healthcheck.prompt.md @@ -1,15 +1,15 @@ --- mode: 'agent' description: 'Performs a comprehensive health check of the repository: validates builds, runs tests, checks linting, verifies configuration files, and reports on the overall state of the codebase across all detected tech stacks.' -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-04' # Format: YAML frontmatter + Markdown body. Copilot reusable prompt. # Docs: https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot --- -<!-- GENERATED by AgentKit Forge v0.2.1 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v0.2.1 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # healthcheck @@ -18,7 +18,7 @@ Performs a comprehensive health check of the repository: validates builds, runs ## Instructions -When invoked, follow the AgentKit Forge orchestration lifecycle: +When invoked, follow the Retort orchestration lifecycle: 1. **Understand** the request and any arguments provided 2. **Scan** relevant files to build context @@ -28,7 +28,7 @@ When invoked, follow the AgentKit Forge orchestration lifecycle: ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.github/prompts/init.prompt.md b/.github/prompts/init.prompt.md new file mode 100644 index 00000000..136610fe --- /dev/null +++ b/.github/prompts/init.prompt.md @@ -0,0 +1,84 @@ +--- +mode: 'agent' +description: 'Initialise the current repository as a Retort project. Runs the interactive setup wizard to detect the tech stack, select language kits, choose AI tools, and generate the initial project.yaml and overlay configuration. Supports --dry-run to preview without writing.' +generated_by: 'retort' +last_model: 'sync-engine' +last_updated: '2026-03-20' +# Format: YAML frontmatter + Markdown body. Copilot reusable prompt. +# Docs: https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot +--- + +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> + +# init + +Initialise the current repository as a Retort project. Runs the interactive setup wizard to detect the tech stack, select language kits, choose AI tools, and generate the initial project.yaml and overlay configuration. Supports --dry-run to preview without writing. + +## Role + +You are the **Init Agent**. Guide users through initialising a new Retort project in the current repository. + +## How to Initialise + +Run the init command from the repository root: + +```bash +node .agentkit/engines/node/src/cli.mjs init +``` + +Or if pnpm is available: + +```bash +pnpm -C .agentkit agentkit:init +``` + +## Flags + +| Flag | Effect | +| ------------------- | ------------------------------------------------------ | +| `--dry-run` | Show what would be generated without writing any files | +| `--non-interactive` | Skip prompts, use auto-detected defaults | +| `--preset <name>` | Use a preset: minimal, full, team, infra | +| `--force` | Overwrite existing overlay configuration | +| `--repoName <name>` | Override the detected repository name | + +## Kit Selection + +During interactive init, Retort detects your tech stack and shows which +language kits will be activated (typescript, dotnet, rust, python, blockchain). +Universal kits (security, testing, git-workflow, documentation, ci-cd, +dependency-management, agent-conduct) are always included. + +Optional kits (iac, finops, ai-cost-ops) are presented for explicit opt-in. + +## Post-Init + +1. Review the generated `spec/project.yaml` — fill in any `null` fields +2. Run `/sync` to regenerate all AI tool configurations +3. Run `/validate` to verify generated outputs are well-formed +4. Commit both the spec and generated outputs together + +## Project Context + +- Repository: retort +- Default branch: main + - Tech stack: javascript, yaml, markdown + +## Conventions + +- Write minimal, focused diffs — change only what is necessary +- Maintain backwards compatibility +- Every behavioral change must include tests +- Never commit secrets or credentials +- Follow the project's coding standards and quality gates + +## References + +- See `AGENTS.md` for universal project instructions +- See `UNIFIED_AGENT_TEAMS.md` for team ownership and escalation +- See `AGENT_TEAMS.md` for repo-specific team boundaries +- See `AGENT_BACKLOG.md` for active work items +- See `CLAUDE.md` for project context and workflow +- See `docs/` for architecture, runbooks, and guides diff --git a/.github/prompts/project-review.prompt.md b/.github/prompts/project-review.prompt.md index a7e2b9da..1d5779ca 100644 --- a/.github/prompts/project-review.prompt.md +++ b/.github/prompts/project-review.prompt.md @@ -1,15 +1,15 @@ --- mode: 'agent' description: 'Comprehensive production-grade project review and assessment. Systematically analyzes code quality, architecture, security, UX, performance, documentation, and feature completeness. Produces structured findings with a prioritized roadmap organized into implementation waves.' -generated_by: 'agentkit-forge' +generated_by: 'retort' last_model: 'sync-engine' last_updated: '2026-03-04' # Format: YAML frontmatter + Markdown body. Copilot reusable prompt. # Docs: https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot --- -<!-- GENERATED by AgentKit Forge v0.2.1 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v0.2.1 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # project-review @@ -18,7 +18,7 @@ Comprehensive production-grade project review and assessment. Systematically ana ## Instructions -When invoked, follow the AgentKit Forge orchestration lifecycle: +When invoked, follow the Retort orchestration lifecycle: 1. **Understand** the request and any arguments provided 2. **Scan** relevant files to build context @@ -28,7 +28,7 @@ When invoked, follow the AgentKit Forge orchestration lifecycle: ## Project Context -- Repository: agentkit-forge +- Repository: retort - Default branch: main - Tech stack: javascript, yaml, markdown diff --git a/.github/scripts/README.md b/.github/scripts/README.md index 82e3388f..18256599 100644 --- a/.github/scripts/README.md +++ b/.github/scripts/README.md @@ -1,3 +1,6 @@ +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> <!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> <!-- Source: .agentkit/templates/github/scripts/ --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> diff --git a/.github/scripts/resolve-merge.ps1 b/.github/scripts/resolve-merge.ps1 index e4d295d2..d458f8fd 100644 --- a/.github/scripts/resolve-merge.ps1 +++ b/.github/scripts/resolve-merge.ps1 @@ -1,3 +1,6 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync # ============================================================================= # resolve-merge.ps1 — Apply standard merge conflict resolutions (Windows) # GENERATED by AgentKit Forge v3.1.0 — regenerated on every sync diff --git a/.github/scripts/resolve-merge.sh b/.github/scripts/resolve-merge.sh index ad53eda5..6f400e0d 100755 --- a/.github/scripts/resolve-merge.sh +++ b/.github/scripts/resolve-merge.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync # ============================================================================= # resolve-merge.sh — Apply standard merge conflict resolutions # GENERATED by AgentKit Forge v3.1.0 — regenerated on every sync diff --git a/.github/scripts/setup-branch-protection.ps1 b/.github/scripts/setup-branch-protection.ps1 index 551b6f24..b371e340 100644 --- a/.github/scripts/setup-branch-protection.ps1 +++ b/.github/scripts/setup-branch-protection.ps1 @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # --------------------------------------------------------------------------- # setup-branch-protection.ps1 diff --git a/.github/scripts/setup-branch-protection.sh b/.github/scripts/setup-branch-protection.sh index 4f413d43..4f7ae845 100755 --- a/.github/scripts/setup-branch-protection.sh +++ b/.github/scripts/setup-branch-protection.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # --------------------------------------------------------------------------- # setup-branch-protection.sh diff --git a/.github/workflows/block-agentkit-changes.yml b/.github/workflows/block-agentkit-changes.yml index 0ab015ec..03820ce8 100644 --- a/.github/workflows/block-agentkit-changes.yml +++ b/.github/workflows/block-agentkit-changes.yml @@ -1,4 +1,4 @@ -name: Block AgentKit Changes +name: Block Retort Changes on: pull_request: @@ -20,8 +20,8 @@ jobs: - name: Detect .agentkit changes shell: bash run: | - if [[ "${{ github.repository }}" == "JustAGhosT/agentkit-forge" ]]; then - echo "Info: Skipping .agentkit/ change block for exception repository JustAGhosT/agentkit-forge." + if [[ "${{ github.repository }}" == "JustAGhosT/retort" ]]; then + echo "Info: Skipping .agentkit/ change block for exception repository JustAGhosT/retort." exit 0 fi diff --git a/.github/workflows/branch-protection.yml b/.github/workflows/branch-protection.yml index b05631fc..94cf1458 100644 --- a/.github/workflows/branch-protection.yml +++ b/.github/workflows/branch-protection.yml @@ -11,8 +11,8 @@ concurrency: # Enforce that all PRs to main pass required checks before merge. # Configure GitHub branch protection rules to require these status checks: -# - AgentKit Forge CI / Test (ubuntu-latest) -# - AgentKit Forge CI / Validate +# - Retort CI / Test (ubuntu-latest) +# - Retort CI / Validate # - Branch Protection / branch-rules jobs: @@ -101,20 +101,20 @@ jobs: const isAgentkitForgeRepo = context.repo.owner.toLowerCase() === 'justaghost' && - context.repo.repo.toLowerCase() === 'agentkit-forge'; + context.repo.repo.toLowerCase() === 'retort'; if (isAgentkitForgeRepo) { - core.info('Running in agentkit-forge source repo; upstream issue link check skipped.'); + core.info('Running in retort source repo; upstream issue link check skipped.'); return; } const body = pr.body || ''; - const hasUpstreamIssueLink = /https:\/\/github\.com\/JustAGhosT\/agentkit-forge\/issues\/\d+/i.test(body); + const hasUpstreamIssueLink = /https:\/\/github\.com\/JustAGhosT\/retort\/issues\/\d+/i.test(body); if (!hasUpstreamIssueLink) { core.setFailed( 'This PR modifies .agentkit/** and must include an upstream issue link in the PR body.\n' + - 'Required format example: https://github.com/JustAGhosT/agentkit-forge/issues/170' + 'Required format example: https://github.com/JustAGhosT/retort/issues/170' ); return; } diff --git a/.github/workflows/breaking-change-detection.yml b/.github/workflows/breaking-change-detection.yml index e14d10bc..1192b9d0 100644 --- a/.github/workflows/breaking-change-detection.yml +++ b/.github/workflows/breaking-change-detection.yml @@ -1,5 +1,8 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync # GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # # Detects potential breaking changes in PRs by analyzing version files, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df8fcdfe..23d66558 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: AgentKit Forge CI +name: Retort CI on: push: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e211b410..1c9a00bf 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,10 +1,14 @@ name: CodeQL on: + # Reduced to weekly + manual to cut GitHub Actions costs + # Was running on every push/PR including Renovate bot push: - branches: [main] + branches: + - main pull_request: - branches: [main] + branches: + - main schedule: - cron: '0 6 * * 1' workflow_dispatch: @@ -17,10 +21,10 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} cancel-in-progress: true - jobs: analyze: name: analyze-javascript + if: github.actor != 'renovate[bot]' runs-on: self-hosted strategy: fail-fast: false diff --git a/.github/workflows/coverage-report.yml b/.github/workflows/coverage-report.yml index fcef4885..77afd5ab 100644 --- a/.github/workflows/coverage-report.yml +++ b/.github/workflows/coverage-report.yml @@ -1,5 +1,8 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync # GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # # Collects code coverage from test runs and reports regressions on PRs. diff --git a/.github/workflows/dependency-audit.yml b/.github/workflows/dependency-audit.yml index 9eaa1041..89461b35 100644 --- a/.github/workflows/dependency-audit.yml +++ b/.github/workflows/dependency-audit.yml @@ -1,5 +1,8 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync # GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # # Non-blocking dependency audit. Runs when lockfiles or manifests change. diff --git a/.github/workflows/documentation-quality.yml b/.github/workflows/documentation-quality.yml index e59f5df1..722f37d4 100644 --- a/.github/workflows/documentation-quality.yml +++ b/.github/workflows/documentation-quality.yml @@ -1,5 +1,8 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync # GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # # Lints and validates documentation quality for history records. diff --git a/.github/workflows/documentation-validation.yml b/.github/workflows/documentation-validation.yml index 104fb536..9918c180 100644 --- a/.github/workflows/documentation-validation.yml +++ b/.github/workflows/documentation-validation.yml @@ -1,5 +1,8 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync # GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # # Validates documentation requirements and structure on pull requests. diff --git a/.github/workflows/issue-label-validation.yml b/.github/workflows/issue-label-validation.yml index 1ad0b984..36a34d91 100644 --- a/.github/workflows/issue-label-validation.yml +++ b/.github/workflows/issue-label-validation.yml @@ -227,7 +227,7 @@ jobs: 'Please edit this issue and select valid options from the dropdowns.', '', '---', - '*This check is automated by AgentKit Forge issue field validation.*' + '*This check is automated by Retort issue field validation.*' ].join('\n'); await github.rest.issues.createComment({ diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 178b0372..0f37bb61 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -1,5 +1,8 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync # GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # # Validates PR changes: Terraform formatting, shell script linting, and diff --git a/.github/workflows/retrospective-quality.yml b/.github/workflows/retrospective-quality.yml index 9e62afdf..3d288da4 100644 --- a/.github/workflows/retrospective-quality.yml +++ b/.github/workflows/retrospective-quality.yml @@ -1,5 +1,8 @@ +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort +# Regenerate: pnpm -C .agentkit agentkit:sync # GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # # Non-blocking CI job that validates retrospective records (issues and lessons). diff --git a/.github/workflows/template-protection.yml b/.github/workflows/template-protection.yml index 7b89d9fa..8847d862 100644 --- a/.github/workflows/template-protection.yml +++ b/.github/workflows/template-protection.yml @@ -40,9 +40,9 @@ jobs: with: script: | const body = [ - '## AgentKit Forge Source Change Detected', + '## Retort Source Change Detected', '', - 'This PR modifies files in the AgentKit Forge source directories:', + 'This PR modifies files in the Retort source directories:', '- `.agentkit/templates/` — output templates', '- `.agentkit/spec/` — YAML specifications', '- `.agentkit/engines/` — sync engine code', @@ -69,7 +69,7 @@ jobs: }); const existing = comments.data.find(c => - c.body.includes('AgentKit Forge Source Change Detected') + c.body.includes('Retort Source Change Detected') ); if (!existing) { diff --git a/.gitignore b/.gitignore index b5bdfa73..27377406 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,4 @@ temp_benchmark/ temp_discover_benchmark/ .benchmark/ bench-temp/ +.claude/worktrees/ diff --git a/.gitmessage b/.gitmessage index 6a267d2c..81ffc7af 100644 --- a/.gitmessage +++ b/.gitmessage @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # <type>(<scope>): <short description> # diff --git a/.roadmap.yaml b/.roadmap.yaml new file mode 100644 index 00000000..3ad51ec2 --- /dev/null +++ b/.roadmap.yaml @@ -0,0 +1,37 @@ +version: "1.0" +scope: roadmap +repo: phoenixvc/retort +updated_at: 2026-03-18 + +tasks: + - id: repo-rename + title: "Rename retort (avoid Google ADK / Coinbase Retort collision)" + description: "173 stars. agent-forge = independent open-source identity. phoenix-forge = Phoenix-branded. Decision must happen before 500+ stars to minimise redirect confusion." + priority: high + status: todo + quarter: "2026-Q2" + tags: [naming, brand, strategy] + + - id: agents-hub-overlay + title: "agents-hub overlay — port Mystira .agents/ pattern as syncable template" + description: "Extract session-startup skill, end-session lifecycle, users/ system, hookify guards into an overlay that agentkit:sync can deploy to any repo. Phase 5 of agent-consolidation roadmap." + priority: medium + status: todo + quarter: "2026-Q2" + tags: [agent, portability, template] + depends_on: [phoenixvc/mystira-workspace#agent-infra-enhancement] + + - id: mcp-integration + title: "Add /mcp/ endpoint (Tier 1 project MCP)" + priority: medium + status: todo + quarter: "2026-Q3" + tags: [mcp, agent] + depends_on: [phoenixvc/org-meta#mcp-ecosystem-build] + + - id: ai-gateway-connect + title: "Route retort agent calls through ai-gateway for cost tracking" + priority: low + status: todo + quarter: "2026-Q3" + tags: [ai-gateway, cost-ops] diff --git a/.todo.yaml b/.todo.yaml new file mode 100644 index 00000000..3060a36c --- /dev/null +++ b/.todo.yaml @@ -0,0 +1,19 @@ +version: "1.0" +scope: todo +repo: phoenixvc/retort +updated_at: 2026-03-18 + +tasks: + - id: rename-decision + title: "Decide rename: agent-forge vs phoenix-forge (or keep retort)" + description: "173 stars. Collides with Google ADK and Coinbase Retort. agent-forge = independent product, phoenix-forge = Phoenix-branded. Decide before 500+ stars." + priority: high + status: todo + tags: [naming, brand, strategy] + + - id: agents-hub-portability + title: "Extract Mystira .agents/ skeleton as Retort overlay template" + description: "Target: .agentkit/overlays/agents-hub/. Makes session-startup, end-session, skill-discovery portable via agentkit:sync." + priority: medium + status: todo + tags: [agent, portability, template] diff --git a/.vscode/settings.json b/.vscode/settings.json index 7c6c237d..0acb4939 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -91,7 +91,7 @@ "menu.separatorBackground": "#18232A" }, "_agentkit_theme": { - "brand": "AgentKit Forge", + "brand": "Retort", "mode": "both", "scheme": "dark", "tier": "full", diff --git a/.windsurf/commands/cicd-optimize.md b/.windsurf/commands/cicd-optimize.md new file mode 100644 index 00000000..49665f13 --- /dev/null +++ b/.windsurf/commands/cicd-optimize.md @@ -0,0 +1,99 @@ +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-20 --> +<!-- Format: Plain Markdown. Windsurf command template. --> +<!-- Docs: https://docs.windsurf.com/windsurf/cascade --> + +# /cicd-optimize — CI/CD pipeline and local hook optimizer. Audits GitHub Actions workflows, pre-commit/stop hooks, and test configurations for speed bottlenecks. Identifies caching gaps, sequential jobs that could parallelize, missing path filters, redundant installs, and slow hook steps. Produces a prioritized list of improvements with estimated time savings per fix. + +## When to Use + +Invoke this command when the user requests or implies the +`cicd-optimize` operation. + +## Purpose + +CI/CD pipeline and local hook optimizer. Audits GitHub Actions workflows, pre-commit/stop hooks, and test configurations for speed bottlenecks. Identifies caching gaps, sequential jobs that could parallelize, missing path filters, redundant installs, and slow hook steps. Produces a prioritized list of improvements with estimated time savings per fix. + +## Role + +You are the **CI/CD Optimization Agent**. Analyse this project's CI/CD pipelines and local hooks for speed bottlenecks. Produce a prioritized report with concrete, copy-paste-ready fixes. + +## Step 1 — Inventory + +Collect all CI/CD surface area: + +- `.github/workflows/*.yml` — list each workflow, its triggers, jobs, and steps +- `.claude/hooks/` — list each hook file and its purpose +- `package.json` scripts: `lint`, `test`, `build`, `typecheck` +- Test framework config: `vitest.config.*`, `jest.config.*`, `pytest.ini`, `Cargo.toml [profile.test]` +- Lock files: `pnpm-lock.yaml`, `Cargo.lock`, `poetry.lock` + +## Step 2 — Bottleneck Detection + +For each workflow, check: + +### Caching + +- [ ] Node modules cached? (`actions/cache` with `node_modules` or `pnpm store`) +- [ ] Cargo registry cached? (`~/.cargo/registry` and `target/`) +- [ ] pip/poetry cached? (`~/.cache/pip`) +- [ ] Docker layer cache used? (`cache-from: type=gha`) + +### Parallelization + +- [ ] Jobs that depend on each other but don't need to — should they be parallel? +- [ ] Test suites that could use matrix strategy or `--pool` (vitest), `pytest-xdist`, `cargo nextest` +- [ ] Lint and typecheck run sequentially when they're independent + +### Trigger efficiency + +- [ ] Workflows triggered on `push` to all branches — should use `paths:` filters +- [ ] PR workflows trigger on `push` AND `pull_request` — often redundant +- [ ] Scheduled workflows running more frequently than needed + +### Install efficiency + +- [ ] `npm install` / `pnpm install` without `--frozen-lockfile` (slower) +- [ ] Install steps duplicated across jobs (should use artifacts or caching) +- [ ] `node_modules` copied between jobs instead of restored from cache + +### Hook efficiency + +- [ ] Stop hook runs tests or full builds (should be lint-only with file-change gating) +- [ ] Pre-commit hook runs expensive operations without caching +- [ ] Hooks run regardless of which files changed + +## Step 3 — Test Suite Speed + +Check for parallelization opportunities: + +- vitest: `--pool=threads` or `--pool=forks`, `--reporter=verbose` adding noise +- pytest: `pytest-xdist` (`-n auto`), test isolation issues +- cargo: `cargo nextest` (2-3x faster than `cargo test`) +- jest: `--maxWorkers` configuration + +## Step 4 — Report + +Produce a table sorted by estimated time savings (highest first): + +| # | Area | Issue | Fix | Est. saving | +| --- | ---- | ----- | --- | ----------- | +| 1 | ... | ... | ... | ~Xs per run | + +Then provide **Ready-to-apply fixes** — code blocks for each high-impact change, in order. For workflow changes, show the exact YAML diff. For hook changes, show the exact shell change. For config changes, show the file and the new content. + +## Rules + +1. Only suggest changes with clear, measurable benefit. Skip micro-optimisations. +2. Preserve correctness — never suggest removing a cache that would break reproducibility. +3. Flag any changes that require secrets or environment variables. +4. If a fix requires a new dependency (e.g. cargo-nextest), note the install command. + +## Related Commands + +- `/orchestrate` — Full lifecycle coordination (uses this command as a phase) +- `/plan` — Structured planning before implementation +- `/project-review` — Comprehensive project audit +- See `COMMAND_GUIDE.md` for when to choose each command diff --git a/.windsurf/commands/handoff.md b/.windsurf/commands/handoff.md index 11203158..a49b2b75 100644 --- a/.windsurf/commands/handoff.md +++ b/.windsurf/commands/handoff.md @@ -1,7 +1,7 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -<!-- generated_by: agentkit-forge | last_model: sync-engine | last_updated: 2026-03-05 --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-05 --> <!-- Format: Plain Markdown. Windsurf command template. --> <!-- Docs: https://docs.windsurf.com/windsurf/cascade --> diff --git a/.windsurf/commands/healthcheck.md b/.windsurf/commands/healthcheck.md index 1de19aee..3ab1906b 100644 --- a/.windsurf/commands/healthcheck.md +++ b/.windsurf/commands/healthcheck.md @@ -1,7 +1,7 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -<!-- generated_by: agentkit-forge | last_model: sync-engine | last_updated: 2026-03-05 --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-05 --> <!-- Format: Plain Markdown. Windsurf command template. --> <!-- Docs: https://docs.windsurf.com/windsurf/cascade --> diff --git a/.windsurf/commands/init.md b/.windsurf/commands/init.md new file mode 100644 index 00000000..460ec08d --- /dev/null +++ b/.windsurf/commands/init.md @@ -0,0 +1,68 @@ +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-20 --> +<!-- Format: Plain Markdown. Windsurf command template. --> +<!-- Docs: https://docs.windsurf.com/windsurf/cascade --> + +# /init — Initialise the current repository as a Retort project. Runs the interactive setup wizard to detect the tech stack, select language kits, choose AI tools, and generate the initial project.yaml and overlay configuration. Supports --dry-run to preview without writing. + +## When to Use + +Invoke this command when the user requests or implies the +`init` operation. + +## Purpose + +Initialise the current repository as a Retort project. Runs the interactive setup wizard to detect the tech stack, select language kits, choose AI tools, and generate the initial project.yaml and overlay configuration. Supports --dry-run to preview without writing. + +## Role + +You are the **Init Agent**. Guide users through initialising a new Retort project in the current repository. + +## How to Initialise + +Run the init command from the repository root: + +```bash +node .agentkit/engines/node/src/cli.mjs init +``` + +Or if pnpm is available: + +```bash +pnpm -C .agentkit agentkit:init +``` + +## Flags + +| Flag | Effect | +| ------------------- | ------------------------------------------------------ | +| `--dry-run` | Show what would be generated without writing any files | +| `--non-interactive` | Skip prompts, use auto-detected defaults | +| `--preset <name>` | Use a preset: minimal, full, team, infra | +| `--force` | Overwrite existing overlay configuration | +| `--repoName <name>` | Override the detected repository name | + +## Kit Selection + +During interactive init, Retort detects your tech stack and shows which +language kits will be activated (typescript, dotnet, rust, python, blockchain). +Universal kits (security, testing, git-workflow, documentation, ci-cd, +dependency-management, agent-conduct) are always included. + +Optional kits (iac, finops, ai-cost-ops) are presented for explicit opt-in. + +## Post-Init + +1. Review the generated `spec/project.yaml` — fill in any `null` fields +2. Run `/sync` to regenerate all AI tool configurations +3. Run `/validate` to verify generated outputs are well-formed +4. Commit both the spec and generated outputs together + +## Related Commands + +- `/orchestrate` — Full lifecycle coordination (uses this command as a phase) +- `/plan` — Structured planning before implementation +- `/project-review` — Comprehensive project audit +- See `COMMAND_GUIDE.md` for when to choose each command diff --git a/.windsurf/commands/project-review.md b/.windsurf/commands/project-review.md index 814dad00..5357cb7e 100644 --- a/.windsurf/commands/project-review.md +++ b/.windsurf/commands/project-review.md @@ -1,7 +1,7 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -<!-- generated_by: agentkit-forge | last_model: sync-engine | last_updated: 2026-03-05 --> +<!-- generated_by: retort | last_model: sync-engine | last_updated: 2026-03-05 --> <!-- Format: Plain Markdown. Windsurf command template. --> <!-- Docs: https://docs.windsurf.com/windsurf/cascade --> diff --git a/.windsurf/settings.json b/.windsurf/settings.json index 95cb789e..0122b43d 100644 --- a/.windsurf/settings.json +++ b/.windsurf/settings.json @@ -79,7 +79,7 @@ "menu.separatorBackground": "#18232A" }, "_agentkit_theme": { - "brand": "AgentKit Forge", + "brand": "Retort", "mode": "both", "scheme": "dark", "tier": "full", diff --git a/.windsurf/workflows/full-assessment.yml b/.windsurf/workflows/full-assessment.yml index b384ac7a..1392da29 100644 --- a/.windsurf/workflows/full-assessment.yml +++ b/.windsurf/workflows/full-assessment.yml @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync name: full-assessment description: 'Run complete codebase assessment' diff --git a/.windsurf/workflows/phase-execution.yml b/.windsurf/workflows/phase-execution.yml index ceb93236..9e578027 100644 --- a/.windsurf/workflows/phase-execution.yml +++ b/.windsurf/workflows/phase-execution.yml @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync name: phase-execution description: 'Execute a specific workflow phase' diff --git a/AGENTS.md b/AGENTS.md index 2ee9e781..676d68ee 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,9 +1,9 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# agentkit-forge +# retort -AgentKit Forge framework for multi-tool AI agent team orchestration, sync generation, and quality-gated workflows. +Retort framework for multi-tool AI agent team orchestration, sync generation, and quality-gated workflows. ## Project Context diff --git a/AGENT_TEAMS.md b/AGENT_TEAMS.md index 83313985..a3af0062 100644 --- a/AGENT_TEAMS.md +++ b/AGENT_TEAMS.md @@ -1,8 +1,8 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Agent Teams — agentkit-forge +# Agent Teams — retort > Repo-local team mapping derived from `.agentkit/spec/teams.yaml`. > Customize the **Status**, **Primary Scope**, **Tech Stack**, and **Lead Agent** @@ -12,7 +12,7 @@ ## Overview -This document maps the canonical AgentKit team definitions (see +This document maps the canonical Retort team definitions (see [UNIFIED_AGENT_TEAMS.md](./UNIFIED_AGENT_TEAMS.md)) to the concrete structure of this repository. Not all teams may be active — mark inactive teams so the orchestrator skips them during dispatch. diff --git a/CHANGELOG.md b/CHANGELOG.md index 02e52678..eb9e65fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Changelog — agentkit-forge +# Changelog — retort All notable changes to this project will be documented in this file. @@ -17,8 +17,9 @@ Activate the commit template: `git config commit.template .gitmessage` ## [Unreleased] ### Added +- Kit-based domain selection and onboarding redesign ([#432](../../pull/432), [history](implementations/0001-2026-03-20-kit-based-domain-selection-and-onboarding-redesign-implementation.md)) -- Initial AgentKit Forge integration (v3.1.0) +- Initial Retort integration (v3.1.0) - Multi-agent team framework with 10 teams - 5-phase lifecycle orchestration model - Support for Claude Code, Cursor, Windsurf, Copilot, and MCP/A2A @@ -39,6 +40,6 @@ Activate the commit template: `git config commit.template .gitmessage` --- -_Maintained by AgentKit Forge. Update this file as part of the Ship phase._ +_Maintained by Retort. Update this file as part of the Ship phase._ _For significant changes, also create a history document: `./scripts/create-doc.sh <type> "<title>" <pr>`_ _See [Changelog Best Practices](docs/engineering/07_changelog.md) for tooling options._ diff --git a/COMMAND_GUIDE.md b/COMMAND_GUIDE.md index 8c2897a3..58b8f2e8 100644 --- a/COMMAND_GUIDE.md +++ b/COMMAND_GUIDE.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Command Guide — When to Use Which diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b62e6bfb..f75f12e1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributing to agentkit-forge +# Contributing to retort > Guidelines for contributing to this project, including both human and > AI-assisted development workflows. @@ -81,7 +81,7 @@ Use [Conventional Commits](https://www.conventionalcommits.org/): When using AI agents (Claude Code, Cursor, Copilot, etc.): -- Generated configuration files (marked `GENERATED by AgentKit Forge`) should +- Generated configuration files (marked `GENERATED by Retort`) should not be edited directly — modify the spec and run `agentkit sync` instead - Use `/orchestrate` for multi-team coordination tasks - Use `/check` to validate changes before committing @@ -103,4 +103,4 @@ Key conventions: --- -This guide is maintained by AgentKit Forge. Run `pnpm -C .agentkit agentkit:sync` to regenerate. +This guide is maintained by Retort. Run `pnpm -C .agentkit agentkit:sync` to regenerate. diff --git a/MIGRATIONS.md b/MIGRATIONS.md index 31ca4a88..32f490f7 100644 --- a/MIGRATIONS.md +++ b/MIGRATIONS.md @@ -1,10 +1,10 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Migration Guide — agentkit-forge +# Migration Guide — retort -> How to upgrade between AgentKit Forge versions and handle breaking changes. +> How to upgrade between Retort versions and handle breaking changes. --- @@ -20,7 +20,7 @@ ### Standard Upgrade -1. Pull the latest AgentKit Forge changes +1. Pull the latest Retort changes 2. Review the changelog for breaking changes 3. Run `agentkit sync` to regenerate all configs 4. Run `agentkit validate` to verify integrity @@ -41,7 +41,7 @@ When upgrading introduces new spec fields: ### v0.1.0 (Initial) -- Initial release of AgentKit Forge +- Initial release of Retort - Spec-driven config generation for 6 AI tools - 10-team framework with 5-phase lifecycle - Hook-based security guardrails @@ -57,4 +57,4 @@ No breaking changes — this is the initial release. --- -_This guide is maintained by AgentKit Forge. Run `pnpm -C .agentkit agentkit:sync` to regenerate._ +_This guide is maintained by Retort. Run `pnpm -C .agentkit agentkit:sync` to regenerate._ diff --git a/QUALITY_GATES.md b/QUALITY_GATES.md index 92374755..6e1bc584 100644 --- a/QUALITY_GATES.md +++ b/QUALITY_GATES.md @@ -1,8 +1,11 @@ +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> <!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Quality Gates — agentkit-forge +# Quality Gates — retort > Definition of done for each lifecycle phase. No work item may advance to the > next phase until all quality gates for the current phase are satisfied. diff --git a/RUNBOOK_AI.md b/RUNBOOK_AI.md index f5e72bab..d203d4d4 100644 --- a/RUNBOOK_AI.md +++ b/RUNBOOK_AI.md @@ -1,4 +1,8 @@ -# AI Runbook — agentkit-forge +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> + +# AI Runbook — retort > Operational runbook for AI agent workflows. Covers common scenarios, > troubleshooting, and recovery procedures. diff --git a/SECURITY.md b/SECURITY.md index 1629d006..c4d5576d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,8 +1,8 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# Security Policy — agentkit-forge +# Security Policy — retort > Security policies, vulnerability reporting, and hardening guidelines > for this repository and its AI agent workflows. @@ -48,7 +48,7 @@ These conventions are enforced by the `security` rule domain ### Hook-based Protection -AgentKit Forge installs hook scripts that guard against common risks: +Retort installs hook scripts that guard against common risks: | Hook | Trigger | Protection | | ------------------------------- | --------------------- | ------------------------------------------------ | @@ -119,4 +119,4 @@ The `validate` command scans for common secret patterns: --- -_This policy is maintained by AgentKit Forge. Run `pnpm -C .agentkit agentkit:sync` to regenerate._ +_This policy is maintained by Retort. Run `pnpm -C .agentkit agentkit:sync` to regenerate._ diff --git a/UNIFIED_AGENT_TEAMS.md b/UNIFIED_AGENT_TEAMS.md index 1cb73678..7d4fb6b8 100644 --- a/UNIFIED_AGENT_TEAMS.md +++ b/UNIFIED_AGENT_TEAMS.md @@ -1,5 +1,8 @@ +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> <!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Unified Agent Teams Specification v1.0 diff --git a/agentkit_feedback.md b/agentkit_feedback.md index e9aca564..f82c348f 100644 --- a/agentkit_feedback.md +++ b/agentkit_feedback.md @@ -1,6 +1,6 @@ -# AgentKit Forge Sync Feedback (pvc-costops-analytics) +# Retort Sync Feedback (pvc-costops-analytics) -This document captures practical feedback from using AgentKit Forge v3.1.0 in this repository, with a focus on sync behavior, Windows developer experience, and documentation workflows. +This document captures practical feedback from using Retort v3.1.0 in this repository, with a focus on sync behavior, Windows developer experience, and documentation workflows. ## Summary @@ -82,7 +82,7 @@ Suggestion: - Multi-editor instructions and rules are consistently generated for Claude/Cursor/Windsurf/Copilot. - Documentation structure under `docs/` is scaffolded and kept consistent across runs (when not overridden). -## Recommended next steps (AgentKit) +## Recommended next steps (Retort) - Add official support for repo-local overrides of specific generated docs (e.g., incident response). - Improve unresolved placeholder diagnostics. diff --git a/db/README.md b/db/README.md index 4aa5463f..036128f3 100644 --- a/db/README.md +++ b/db/README.md @@ -1,6 +1,12 @@ +<<<<<<< HEAD +# Database — retort + +This repository (**retort**) is the Retort framework. It has **no database** and no ORM (see root `CLAUDE.md`: Database: none, ORM: none). +======= # Database — agentkit-forge This repository (**agentkit-forge**) is the AgentKit Forge framework. It has **no database** and no ORM (see root `CLAUDE.md`: Database: none, ORM: none). +>>>>>>> origin/main ## For adopters diff --git a/docs/README.md b/docs/README.md index 2456d94e..b2be74b6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,10 +1,13 @@ +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> +<!-- Regenerate: pnpm -C .agentkit agentkit:sync --> <!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> -# agentkit-forge — Documentation +# retort — Documentation -Welcome to the agentkit-forge documentation hub. This index links to every +Welcome to the retort documentation hub. This index links to every documentation category maintained by this repository. ## Categories @@ -36,7 +39,7 @@ documentation category maintained by this repository. ## Conventions -- Placeholder tokens `agentkit-forge` and `3.1.0` are replaced at sync time. +- Placeholder tokens `retort` and `3.1.0` are replaced at sync time. - Do **not** edit generated files directly — run `pnpm -C .agentkit agentkit:sync` to regenerate them from the AgentKit Forge spec and overlays. diff --git a/docs/agents/README.md b/docs/agents/README.md index f8f7e3cb..1c37f398 100644 --- a/docs/agents/README.md +++ b/docs/agents/README.md @@ -1,6 +1,6 @@ # Agents Documentation -This category catalogs all agent personas, roles, and team mappings for AgentKit Forge. See: +This category catalogs all agent personas, roles, and team mappings for Retort. See: - [catalog.md](catalog.md) diff --git a/docs/api/01_overview.md b/docs/api/01_overview.md index 0fdb3944..f3e260ed 100644 --- a/docs/api/01_overview.md +++ b/docs/api/01_overview.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # API Overview ## Introduction -<!-- Describe the purpose and scope of the agentkit-forge API. --> +<!-- Describe the purpose and scope of the retort API. --> **Base URL:** `https://api.example.com/v1` **Current Version:** 3.1.0 diff --git a/docs/api/02_endpoints.md b/docs/api/02_endpoints.md index 04b9419c..59cc14b8 100644 --- a/docs/api/02_endpoints.md +++ b/docs/api/02_endpoints.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Endpoint Reference diff --git a/docs/api/03_authentication.md b/docs/api/03_authentication.md index 479dccad..b1dc1f0d 100644 --- a/docs/api/03_authentication.md +++ b/docs/api/03_authentication.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Authentication ## Overview -<!-- Describe the authentication strategy used by the agentkit-forge API. --> +<!-- Describe the authentication strategy used by the retort API. --> ## Authentication Methods diff --git a/docs/api/04_examples.md b/docs/api/04_examples.md index df295233..0e2728d1 100644 --- a/docs/api/04_examples.md +++ b/docs/api/04_examples.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # API Examples ## Overview -This document provides practical examples for common agentkit-forge API workflows. +This document provides practical examples for common retort API workflows. ## Prerequisites diff --git a/docs/api/05_errors.md b/docs/api/05_errors.md index 4bfee2f1..c6b07a1f 100644 --- a/docs/api/05_errors.md +++ b/docs/api/05_errors.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # API Errors diff --git a/docs/api/06_versioning.md b/docs/api/06_versioning.md index df77ebcc..b7cde98a 100644 --- a/docs/api/06_versioning.md +++ b/docs/api/06_versioning.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # API Versioning diff --git a/docs/api/07_framework-api-conventions.md b/docs/api/07_framework-api-conventions.md index 590e4ced..2bd134e6 100644 --- a/docs/api/07_framework-api-conventions.md +++ b/docs/api/07_framework-api-conventions.md @@ -1,6 +1,10 @@ # Framework API Conventions (Adopter Guide) +<<<<<<< HEAD +This repository (**retort**) is the Retort framework. It does **not** ship an application API or run an HTTP server. Adopters of the framework implement their own APIs in their repositories. +======= This repository (**agentkit-forge**) is the AgentKit Forge framework. It does **not** ship an application API or run an HTTP server. Adopters of the framework implement their own APIs in their repositories. +>>>>>>> origin/main ## Recommended API Route Structure diff --git a/docs/api/README.md b/docs/api/README.md index e91f44ae..a022da06 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # API Docs Index diff --git a/docs/architecture/01_overview.md b/docs/architecture/01_overview.md index 6901a95e..a687eabe 100644 --- a/docs/architecture/01_overview.md +++ b/docs/architecture/01_overview.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Architecture Overview ## Introduction -<!-- High-level description of the agentkit-forge architecture. --> +<!-- High-level description of the retort architecture. --> ## Principles @@ -44,7 +44,7 @@ See [diagrams/](./diagrams/) for visual representations. Architecture Decision Records (ADRs) are stored in [decisions/](./decisions/). See -[ADR-01](./decisions/01-adopt-agentkit-forge.md) for the foundational decision. +[ADR-01](./decisions/01-adopt-retort.md) for the foundational decision. ## References diff --git a/docs/architecture/README.md b/docs/architecture/README.md index de2050fe..a2b4a5ed 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Architecture Docs Index diff --git a/docs/architecture/Retort System Connections.png b/docs/architecture/Retort System Connections.png new file mode 100644 index 0000000000000000000000000000000000000000..b0cd72406746427911efbc6afacb21b80dcf6b02 GIT binary patch literal 356693 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%0DdARCcrb-R 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 v?zzeRY7X<O!F5A6iS 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 literal 0 HcmV?d00001 diff --git a/docs/architecture/decisions/02-fallback-policy-tokens-problem.md b/docs/architecture/decisions/02-fallback-policy-tokens-problem.md index 689b4fbc..fadcdbab 100644 --- a/docs/architecture/decisions/02-fallback-policy-tokens-problem.md +++ b/docs/architecture/decisions/02-fallback-policy-tokens-problem.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # ADR-02: Fallback Policy for Missing Evidence Metric @@ -14,9 +14,9 @@ Proposed ## Context -The `agentkit-forge` project uses one or more evidence-driven scoring or gating metrics (for example: cost evidence, telemetry confidence, quality signal confidence). In some workflows, required evidence can be missing at decision time. +The `retort` project uses one or more evidence-driven scoring or gating metrics (for example: cost evidence, telemetry confidence, quality signal confidence). In some workflows, required evidence can be missing at decision time. -Baseline source for this template: the current fallback ADR from `agentkit-forge`. +Baseline source for this template: the current fallback ADR from `retort`. ## Decision @@ -36,4 +36,4 @@ This fallback policy is approved by repository maintainers. ## Scope -Applies to `/infra-eval` scoring dimensions, `/review` quality gates, and related evaluation workflows in `agentkit-forge`. +Applies to `/infra-eval` scoring dimensions, `/review` quality gates, and related evaluation workflows in `retort`. diff --git a/docs/architecture/decisions/03-tooling-strategy.md b/docs/architecture/decisions/03-tooling-strategy.md index b17585b3..ac024b96 100644 --- a/docs/architecture/decisions/03-tooling-strategy.md +++ b/docs/architecture/decisions/03-tooling-strategy.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # ADR-03: Tooling Strategy — Tool Selection @@ -14,9 +14,9 @@ Proposed ## Context -This ADR defines the repository-specific tooling strategy for `agentkit-forge`, balancing delivery speed, quality, security, and dependency governance. +This ADR defines the repository-specific tooling strategy for `retort`, balancing delivery speed, quality, security, and dependency governance. -Baseline source for this template: the current ADR bundle from `agentkit-forge`. +Baseline source for this template: the current ADR bundle from `retort`. Evaluate needs across facets: @@ -77,5 +77,5 @@ Use the current ADR version as a baseline and fill in a repository-specific weig ## References -- [ADR-01: Adopt AgentKit Forge](01-adopt-agentkit-forge.md) +- [ADR-01: Adopt Retort](01-adopt-retort.md) - [Architecture Overview](../01_overview.md) diff --git a/docs/architecture/decisions/04-static-security-analysis-depth-tooling.md b/docs/architecture/decisions/04-static-security-analysis-depth-tooling.md index 38194f2b..47c0f787 100644 --- a/docs/architecture/decisions/04-static-security-analysis-depth-tooling.md +++ b/docs/architecture/decisions/04-static-security-analysis-depth-tooling.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # ADR-04: Static Security Analysis Depth — Tool Selection @@ -14,9 +14,9 @@ Proposed ## Context -This ADR evaluates alternatives for static security analysis depth in `agentkit-forge`. +This ADR evaluates alternatives for static security analysis depth in `retort`. -Baseline source for this template: the current `agentkit-forge` security-depth ADR. +Baseline source for this template: the current `retort` security-depth ADR. Decision scope: diff --git a/docs/architecture/decisions/05-dependency-supply-chain-detection-tooling.md b/docs/architecture/decisions/05-dependency-supply-chain-detection-tooling.md index 10720604..b4daffd3 100644 --- a/docs/architecture/decisions/05-dependency-supply-chain-detection-tooling.md +++ b/docs/architecture/decisions/05-dependency-supply-chain-detection-tooling.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # ADR-05: Dependency and Supply-Chain Detection — Tool Selection @@ -14,9 +14,9 @@ Proposed ## Context -This ADR evaluates dependency and supply-chain detection for package update workflows in `agentkit-forge`. +This ADR evaluates dependency and supply-chain detection for package update workflows in `retort`. -Baseline source for this template: the current `agentkit-forge` dependency ADR. +Baseline source for this template: the current `retort` dependency ADR. Decision scope: diff --git a/docs/architecture/decisions/06-code-quality-maintainability-signal-tooling.md b/docs/architecture/decisions/06-code-quality-maintainability-signal-tooling.md index a1a8416d..fb7fe613 100644 --- a/docs/architecture/decisions/06-code-quality-maintainability-signal-tooling.md +++ b/docs/architecture/decisions/06-code-quality-maintainability-signal-tooling.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # ADR-06: Code Quality and Maintainability Signal — Tool Selection @@ -14,9 +14,9 @@ Proposed ## Context -This ADR evaluates tooling for maintainability signal and code quality feedback in `agentkit-forge`. +This ADR evaluates tooling for maintainability signal and code quality feedback in `retort`. -Baseline source for this template: the current `agentkit-forge` quality ADR. +Baseline source for this template: the current `retort` quality ADR. Decision scope: diff --git a/docs/architecture/decisions/07-delivery-strategy.md b/docs/architecture/decisions/07-delivery-strategy.md index 39e9225b..fbabdc16 100644 --- a/docs/architecture/decisions/07-delivery-strategy.md +++ b/docs/architecture/decisions/07-delivery-strategy.md @@ -1,4 +1,4 @@ -# ADR-07: Delivery Strategy (Refined) — AgentKit Forge Distribution +# ADR-07: Delivery Strategy (Refined) — Retort Distribution ## Status @@ -10,7 +10,7 @@ ## Context -AgentKit Forge, a core platform for deploying mesh-native agents at scale, faces rising friction in delivering updates, onboarding new customers, and supporting diverse consumption models. Historically, Forge delivery methods lagged industry and developer best practices, relying on manual binary distribution and ad hoc integrations. This produced pain for both CLI-first engineers and UI-oriented operators, delayed onboarding, and created avoidable support overhead amid growing cloud-native adoption. +Retort, a core platform for deploying mesh-native agents at scale, faces rising friction in delivering updates, onboarding new customers, and supporting diverse consumption models. Historically, Forge delivery methods lagged industry and developer best practices, relying on manual binary distribution and ad hoc integrations. This produced pain for both CLI-first engineers and UI-oriented operators, delayed onboarding, and created avoidable support overhead amid growing cloud-native adoption. **Executive Summary:** Market analysis, customer interviews, and operational metrics all highlight these delivery inefficiencies as blockers for broader adoption and hamper ecosystem integration efforts. To support customer GTM targets for Q3–Q4 2024—especially for mid-market and enterprise cohorts—Forge must move to a modern, multi-modal distribution model. This ADR formalizes the shift to three distribution mechanisms: npm (modern package distribution), GitHub Actions (automation-centric CI/CD), and PWA (progressive web onboarding), providing consistency, reliability, and seamless migration for varied user segments. @@ -22,7 +22,7 @@ The forge repository is added as a git submodule at `.agentkit/`. All specs, tem **How it works today:** ```bash -git submodule add https://github.com/org/agentkit-forge.git .agentkit +git submodule add https://github.com/org/retort.git .agentkit pnpm -C .agentkit install node .agentkit/engines/node/src/cli.mjs init --repoName my-project node .agentkit/engines/node/src/cli.mjs sync @@ -30,14 +30,14 @@ node .agentkit/engines/node/src/cli.mjs sync ### Option B: npm Package with CLI -Publish agentkit-forge as an npm package (`agentkit-forge`). The consumer installs it as a devDependency. The CLI is exposed via `npx agentkit-forge <command>`. Specs and templates ship inside the package. Overlays remain in the consumer repo. +Publish retort as an npm package (`retort`). The consumer installs it as a devDependency. The CLI is exposed via `npx retort <command>`. Specs and templates ship inside the package. Overlays remain in the consumer repo. **Consumer workflow:** ```bash -npm install -D agentkit-forge -npx agentkit-forge init --repoName my-project -npx agentkit-forge sync +npm install -D retort +npx retort init --repoName my-project +npx retort sync ``` **Overlay location:** `.agentkit/overlays/<repoName>/` (same as today, but the engine and templates come from `node_modules/`). @@ -49,8 +49,8 @@ Publish a lightweight CLI tool that fetches templates and specs on demand from a **Consumer workflow:** ```bash -npx agentkit-forge@latest init --repoName my-project -npx agentkit-forge@latest sync +npx retort@latest init --repoName my-project +npx retort@latest sync ``` **Key difference from Option B:** no `devDependency` entry, no `node_modules/` footprint. The tool is ephemeral — invoked when needed, not installed permanently. @@ -63,7 +63,7 @@ Deliver the forge as a GitHub Action. Sync runs in CI on push/PR, and generated ```yaml # .github/workflows/agentkit-sync.yml -- uses: org/agentkit-forge-action@v3 +- uses: org/retort-action@v3 with: overlay: my-project version: '3.4.0' @@ -71,23 +71,23 @@ Deliver the forge as a GitHub Action. Sync runs in CI on push/PR, and generated ### Option E: Template Repository + Upstream Sync -Publish agentkit-forge as a GitHub template repository. Consumers create repos from the template. Updates are pulled via `git merge` from the upstream template remote. +Publish retort as a GitHub template repository. Consumers create repos from the template. Updates are pulled via `git merge` from the upstream template remote. **Consumer workflow:** ```bash # Initial -gh repo create my-project --template org/agentkit-forge-template +gh repo create my-project --template org/retort-template # Update -git remote add forge-upstream https://github.com/org/agentkit-forge-template.git +git remote add forge-upstream https://github.com/org/retort-template.git git fetch forge-upstream git merge forge-upstream/main --allow-unrelated-histories ``` ### Option F: Hybrid — npm Package + GitHub Action -Combine Options B and D. The npm package handles local development (`npx agentkit-forge sync`). The GitHub Action handles CI enforcement (drift detection, auto-sync on version bumps). Both share the same engine and templates from the npm package. +Combine Options B and D. The npm package handles local development (`npx retort sync`). The GitHub Action handles CI enforcement (drift detection, auto-sync on version bumps). Both share the same engine and templates from the npm package. ### Option G: PWA / Lightweight Desktop UI @@ -107,7 +107,7 @@ Wrap the forge engine in a small UI shell — either a Progressive Web App (serv │ │ Manager │ │ (add/remove) │ │ │ └───────────┘ └────────────────┘ │ ├─────────────────────────────────────┤ -│ agentkit-forge engine (npm pkg) │ +│ retort engine (npm pkg) │ │ specs ─► templates ─► outputs │ └─────────────────────────────────────┘ ``` @@ -115,7 +115,7 @@ Wrap the forge engine in a small UI shell — either a Progressive Web App (serv **Consumer workflow (PWA):** ```bash -npx agentkit-forge ui # launches localhost:4827 +npx retort ui # launches localhost:4827 # Browser opens → visual wizard for init, overlay editing, sync ``` @@ -123,8 +123,8 @@ npx agentkit-forge ui # launches localhost:4827 ```bash # Download from releases page or: -brew install agentkit-forge # macOS -winget install agentkit-forge # Windows +brew install retort # macOS +winget install retort # Windows # Open app → point at repo → visual init + sync ``` @@ -241,7 +241,7 @@ All legacy/manual mechanisms to be deprecated by end of Q3 2024. ### CLI-First Personas -**Install AgentKit Forge via npm:** +**Install Retort via npm:** | Layer | Audience | Problem it solves | | -------------------- | ---------- | ------------------------------------------------------ | | **npm package** | Developers | Local sync, version pinning, offline support | @@ -256,10 +256,10 @@ All legacy/manual mechanisms to be deprecated by end of Q3 2024. - `src/` — CLI entry point and engine (currently `engines/node/src/`) - `templates/` — all Mustache templates - `spec/` — canonical YAML specs - - `bin/agentkit-forge` — CLI binary entry point + - `bin/retort` — CLI binary entry point 2. **Add `package.json`** with: - - `"name": "agentkit-forge"` - - `"bin": { "agentkit-forge": "./bin/agentkit-forge" }` + - `"name": "retort"` + - `"bin": { "retort": "./bin/retort" }` - `"files": ["src/", "templates/", "spec/", "bin/"]` 3. **Update the sync engine** to resolve templates/specs from the package installation path (`import.meta.resolve` or `require.resolve`) instead of relative `../../` paths. 4. **Preserve overlay location** at `.agentkit/overlays/<repoName>/` in the consumer repo — this directory is the only forge artifact that lives in the consumer repo. @@ -269,7 +269,7 @@ All legacy/manual mechanisms to be deprecated by end of Q3 2024. 1. **Create `action.yml`** that: - Installs the npm package at the specified version. - - Runs `agentkit-forge sync` with the consumer's overlay. + - Runs `retort sync` with the consumer's overlay. - Compares generated outputs against committed files (drift detection). - Fails the check if drift is detected (with a diff summary). 2. **Add an optional auto-commit mode** for repos that want CI to keep outputs in sync automatically. @@ -277,7 +277,7 @@ All legacy/manual mechanisms to be deprecated by end of Q3 2024. #### Phase 3 — Migration (weeks 5–7) -1. **Write a migration script** (`agentkit-forge migrate-from-submodule`) that: +1. **Write a migration script** (`retort migrate-from-submodule`) that: - Reads the current overlay from `.agentkit/overlays/`. - Removes the git submodule. - Installs the npm package. @@ -288,7 +288,7 @@ All legacy/manual mechanisms to be deprecated by end of Q3 2024. #### Phase 4 — PWA / Desktop UI (weeks 7–12) 1. **Choose the shell framework:** - - **PWA (recommended first)** — lower build/distribution overhead. Ship as `npx agentkit-forge ui` which starts a local server on `localhost:4827`. Uses a lightweight framework (Preact, Svelte, or plain web components). Runs in any browser. No app store, no code signing, no platform-specific builds. + - **PWA (recommended first)** — lower build/distribution overhead. Ship as `npx retort ui` which starts a local server on `localhost:4827`. Uses a lightweight framework (Preact, Svelte, or plain web components). Runs in any browser. No app store, no code signing, no platform-specific builds. - **Tauri (follow-up)** — for teams that want a native app experience. Wraps the same web UI. Smaller binary than Electron (~5 MB vs ~150 MB). Auto-updater built in. Distribute via GitHub Releases, Homebrew, or winget. 2. **Core UI screens:** - **Init wizard** — repo name, tech stack detection (from `discover`), render target selection via checkboxes, overlay creation. @@ -298,8 +298,8 @@ All legacy/manual mechanisms to be deprecated by end of Q3 2024. - **Health report** — visual rendering of `doctor` and `healthcheck` output. Red/amber/green status per check. 3. **API boundary** — the UI communicates with the forge engine via a thin JSON-RPC or REST layer over the local server. No direct file system access from the browser. The same API can be consumed by IDE extensions later. 4. **Distribution:** - - PWA: `npx agentkit-forge ui` (zero install, opens browser). - - Tauri: GitHub Releases with `brew install agentkit-forge` / `winget install agentkit-forge`. + - PWA: `npx retort ui` (zero install, opens browser). + - Tauri: GitHub Releases with `brew install retort` / `winget install retort`. - Both auto-update when the underlying npm package updates. ### Consumer Experience After Migration @@ -307,7 +307,7 @@ All legacy/manual mechanisms to be deprecated by end of Q3 2024. **Developer (CLI-first):** ```bash -npm install -g agentkit-forge +npm install -g retort ``` - Immediate CLI and SDK access with autoupdate support @@ -329,14 +329,14 @@ Day-zero onboarding: minimal manual steps, rapid path to first agent deployed or **Non-developer / visual preference (UI):** ```bash -npx agentkit-forge ui +npx retort ui # Browser opens → visual wizard → click through init → toggle tools → sync ``` **Or with the desktop app:** ``` -1. Open AgentKit Forge app +1. Open Retort app 2. Click "Open Repo" → select project folder 3. Visual wizard detects stack, suggests render targets 4. Click "Sync" → see diff of generated files @@ -384,7 +384,7 @@ Adopting the Hybrid model unlocks growth and developer satisfaction, at the cost ## References -- AgentKit Forge Architectural Overview (Doc A1-Overview.pdf) +- Retort Architectural Overview (Doc A1-Overview.pdf) - CI/CD Integration Guide - Ecosystem Compatibility Matrix - Internal Security and Audit Policy @@ -393,7 +393,7 @@ Adopting the Hybrid model unlocks growth and developer satisfaction, at the cost - [PRD-007: Adopter Autoupdate](../../product/PRD-007-adopter-autoupdate.md) — follow-up capability building on the npm CLI distribution channel defined in this ADR; specifically the "Immediate CLI and SDK access with autoupdate support" requirement from the Consumer Experience section. -- [#196: adoption/startup-hooks: enforce required CLI toolchain availability](https://github.com/phoenixvc/agentkit-forge/issues/196) +- [#196: adoption/startup-hooks: enforce required CLI toolchain availability](https://github.com/phoenixvc/retort/issues/196) — prerequisite for the autoupdate preflight checks. -- [#194: governance: enforce agentkit sync pre-PR for adopters](https://github.com/phoenixvc/agentkit-forge/issues/194) +- [#194: governance: enforce agentkit sync pre-PR for adopters](https://github.com/phoenixvc/retort/issues/194) — sync enforcement gate that autoupdate must satisfy. diff --git a/docs/architecture/decisions/08-directive-classification-type-and-phase.md b/docs/architecture/decisions/08-directive-classification-type-and-phase.md index f0e9e706..a476303e 100644 --- a/docs/architecture/decisions/08-directive-classification-type-and-phase.md +++ b/docs/architecture/decisions/08-directive-classification-type-and-phase.md @@ -10,7 +10,7 @@ ## Context -AgentKit Forge's `rules.yaml` defines ~90 conventions across 14 domains. All +Retort's `rules.yaml` defines ~90 conventions across 14 domains. All conventions carry a `severity` field (critical / error / warning / info), but severity alone conflates two concerns: @@ -154,4 +154,4 @@ conventions: - [rules.yaml](../../../.agentkit/spec/rules.yaml) — canonical rule definitions - [spec-validator.mjs](../../../.agentkit/engines/node/src/spec-validator.mjs) — schema validation - [synchronize.mjs](../../../.agentkit/engines/node/src/synchronize.mjs) — template rendering -- [ADR-01: Adopt AgentKit Forge](./01-adopt-agentkit-forge.md) +- [ADR-01: Adopt Retort](./01-adopt-retort.md) diff --git a/docs/architecture/decisions/08-expansion-analyst-agent.md b/docs/architecture/decisions/08-expansion-analyst-agent.md index 6c3e166c..4b183de5 100644 --- a/docs/architecture/decisions/08-expansion-analyst-agent.md +++ b/docs/architecture/decisions/08-expansion-analyst-agent.md @@ -10,7 +10,7 @@ ## Context -AgentKit Forge has excellent execution infrastructure — orchestrator, task protocol, +Retort has excellent execution infrastructure — orchestrator, task protocol, team routing, review gates, handoff chains — but lacks a strategic analysis layer that identifies **what is missing** from a repository. The discovery engine reports what exists; nothing systematically identifies gaps in documentation, testing, diff --git a/docs/architecture/decisions/08-issue-sync-strategy.md b/docs/architecture/decisions/08-issue-sync-strategy.md index 34fdaeda..14f8c849 100644 --- a/docs/architecture/decisions/08-issue-sync-strategy.md +++ b/docs/architecture/decisions/08-issue-sync-strategy.md @@ -127,4 +127,4 @@ can pass `--label` for additional labels. - [docs/history/issues/README.md](../../history/issues/README.md) - [docs/history/README.md](../../history/README.md) - [scripts/sync-issues.sh](../../../scripts/sync-issues.sh) -- [ADR-01: Adopt AgentKit Forge](./01-adopt-agentkit-forge.md) +- [ADR-01: Adopt Retort](./01-adopt-retort.md) diff --git a/docs/architecture/decisions/10-tool-neutral-agent-hub.md b/docs/architecture/decisions/10-tool-neutral-agent-hub.md new file mode 100644 index 00000000..0e682fd0 --- /dev/null +++ b/docs/architecture/decisions/10-tool-neutral-agent-hub.md @@ -0,0 +1,69 @@ +# ADR-10: Adopt Tool-Neutral `.agents/` Hub Pattern + +**Status:** Proposed +**Date:** 2026-03-17 +**Deciders:** JustAGhosT +**Related:** [Findings Report](../specs/tool-neutral-agent-hub-findings.md), [Multi-IDE Plugin Plan](../../../.claude/projects/C--Users-smitj-repos-agentkit-forge/memory/project_multi_ide_plugin_plan.md) + +## Context + +AgentKit Forge currently generates tool-specific configuration into isolated directories (`.claude/`, `.cursor/`, `.github/instructions/`, `.gemini/`, etc.). Each tool gets its own copy of agents, rules, commands, and skills. This creates two problems: + +1. **No shared discovery layer.** An agent running in Cursor cannot read Claude's agent personas. An agent in Gemini cannot consume Claude's skills. Cross-tool collaboration requires reading another tool's proprietary directory format. + +2. **Governance is platform-coupled.** Enforcement hooks (`.claude/hooks/`) are shell scripts that only work for tools executing through a shell. Browser agents, API agents, and sandboxed environments bypass all governance. + +The Mystira.workspace project independently developed a `.agents/` directory pattern that addresses both problems through a tool-neutral hub with reflective guards. + +## Decision + +Adopt the `.agents/` directory as a **first-class sync output target** in AgentKit Forge, alongside existing tool-specific directories. + +### Directory Structure + +``` +.agents/ # Tool-neutral hub (NEW) + guards/ # Governance rules (portable) + skills/ # Shared skills (tool-agnostic) + traces/ # Cross-session reasoning context + roadmaps/ # Strategic multi-session goals + .readme.yaml # Directory metadata + +.claude/ # Claude-specific (existing, slimmed) + hooks/ # Platform hooks (generated from guards) + settings.json # Claude permissions + state/ # Runtime state (unchanged) + +.cursor/, .gemini/, etc. # Other tools (existing, slimmed) + rules/ # Platform-specific rule format only +``` + +### Principles + +1. **`.agents/` is the canonical shared layer.** Any content readable by multiple agent tools lives here. +2. **Tool-specific dirs become thin wrappers.** They contain only platform hooks, permissions, and format-specific adaptations. +3. **Guards are the canonical governance source.** Shell hooks are generated from guard definitions for tools that support automated enforcement. +4. **The sync engine owns `.agents/`.** It is generated from `.agentkit/spec/` — not hand-authored — preserving the spec-driven architecture. + +## Consequences + +### Positive + +- Any agent from any tool can discover shared agents, skills, guards, and roadmaps by reading `.agents/` +- Governance becomes portable — guards work for shell-based, browser-based, and API-based agents +- Cross-session continuity improves via traces and roadmaps +- Token cost decreases — agents read one shared location instead of parsing tool-specific dirs +- Path toward an industry convention for multi-agent repository configuration + +### Negative + +- Sync engine must generate an additional output target (development effort) +- Existing tool-specific content must be migrated or deduplicated (one-time cost) +- Projects already using `.agents/` for other purposes (rare) would conflict +- Guard "reflective enforcement" is weaker than hook-based enforcement — trust gap for non-cooperative agents + +### Neutral + +- `.agentkit/spec/` remains the single source of truth — no change to the authoring workflow +- Existing CI drift checks extend naturally to `.agents/` output +- Hook generation from guards is an optimisation, not a requirement — can ship incrementally diff --git a/docs/architecture/decisions/ADR-08-split-brain-analysis.md b/docs/architecture/decisions/ADR-08-split-brain-analysis.md index 06964b4d..581fe60f 100644 --- a/docs/architecture/decisions/ADR-08-split-brain-analysis.md +++ b/docs/architecture/decisions/ADR-08-split-brain-analysis.md @@ -8,7 +8,7 @@ ## 1. Context -AgentKit Forge governs agent behaviour through **three enforcement layers**: +Retort governs agent behaviour through **three enforcement layers**: | Layer | Mechanism | Binding? | Audience | | ------------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------------- | @@ -96,7 +96,7 @@ A "split-brain" occurs when two layers encode the **same rule with different sem | Source | Says | | ---------------------------------- | -------------------------------------------------------------------------------------- | -| **CLAUDE.md** safety rule #5 | "Never directly edit files marked `GENERATED by AgentKit Forge`" | +| **CLAUDE.md** safety rule #5 | "Never directly edit files marked `GENERATED by Retort`" | | **CLAUDE.md** safety rule #4 | "Never modify files in `.agentkit/spec/`" | | **CLAUDE.md** sync section | "Edit spec files in `.agentkit/spec/`" then run sync | | **rules.yaml** `tp-no-direct-edit` | "`.agentkit/spec/` is the intended edit point — users (not AI agents) may modify spec" | @@ -132,7 +132,7 @@ A "split-brain" occurs when two layers encode the **same rule with different sem | Source | Says | | ---------------------------------- | -------------------------------------------------------------------------------- | | **.gitignore** line 42 | Commented out: `# /.github/copilot-instructions.md` — scaffold-once, edit freely | -| **copilot-instructions.md** header | `<!-- GENERATED by AgentKit Forge v0.2.1 — DO NOT EDIT -->` | +| **copilot-instructions.md** header | `<!-- GENERATED by Retort v0.2.1 — DO NOT EDIT -->` | | **Sync engine** | Regenerates it every sync | **Split-brain**: The .gitignore explicitly **does not** ignore `copilot-instructions.md` (it's commented out as "scaffold-once — commit after first sync, edit freely"). But the file itself has a `GENERATED — DO NOT EDIT` header, and the sync engine overwrites it on every run. If a user edits it manually (as the gitignore pattern suggests), the next sync will silently overwrite their changes. The file is simultaneously "scaffold-once, owned by project" and "always-regenerated, don't edit." @@ -143,9 +143,9 @@ A "split-brain" occurs when two layers encode the **same rule with different sem | Source | Version | | ---------------------------------- | ----------------------- | -| **AGENTS.md** header | `AgentKit Forge v3.1.0` | -| **copilot-instructions.md** header | `AgentKit Forge v0.2.1` | -| **COMMAND_GUIDE.md** header | `AgentKit Forge v3.1.0` | +| **AGENTS.md** header | `Retort v3.1.0` | +| **copilot-instructions.md** header | `Retort v0.2.1` | +| **COMMAND_GUIDE.md** header | `Retort v3.1.0` | **Split-brain**: Different generated files claim different framework versions. This suggests the sync engine uses a per-template version or the files were generated at different times. Agents reading these files get inconsistent version signals. diff --git a/docs/architecture/decisions/README.md b/docs/architecture/decisions/README.md index e488986f..22a13552 100644 --- a/docs/architecture/decisions/README.md +++ b/docs/architecture/decisions/README.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # ADR Index ## Decision Records -- [01-adopt-agentkit-forge.md](./01-adopt-agentkit-forge.md) +- [01-adopt-retort.md](./01-adopt-retort.md) - [02-fallback-policy-tokens-problem.md](./02-fallback-policy-tokens-problem.md) - [03-tooling-strategy.md](./03-tooling-strategy.md) - [04-static-security-analysis-depth-tooling.md](./04-static-security-analysis-depth-tooling.md) diff --git a/docs/architecture/diagrams/README.md b/docs/architecture/diagrams/README.md index f93d1b98..11868964 100644 --- a/docs/architecture/diagrams/README.md +++ b/docs/architecture/diagrams/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Architecture Diagrams Index diff --git a/docs/architecture/expansion-agent-analysis.md b/docs/architecture/expansion-agent-analysis.md index 4e9e3dd8..746003ba 100644 --- a/docs/architecture/expansion-agent-analysis.md +++ b/docs/architecture/expansion-agent-analysis.md @@ -8,7 +8,7 @@ ## 1. Executive Summary -This document analyzes the feasibility, design considerations, and integration strategy for adding a **Feature Expansion/Addition Agent** to agentkit-forge. The agent would analyze a repository's current state and suggest new features, missing capabilities, documentation gaps, and architectural improvements — then optionally generate specification artifacts (ADR, PRD, functional specs, technical specs) for approved suggestions. +This document analyzes the feasibility, design considerations, and integration strategy for adding a **Feature Expansion/Addition Agent** to retort. The agent would analyze a repository's current state and suggest new features, missing capabilities, documentation gaps, and architectural improvements — then optionally generate specification artifacts (ADR, PRD, functional specs, technical specs) for approved suggestions. **Verdict**: The idea is **sound but must be carefully scoped**. The repository already has strong primitives that support this (team routing, task protocol, review gates, documentation structure, discovery engine). However, the agent carries unique risks around scope creep, hallucinated requirements, and autonomy overreach that demand explicit human-in-the-loop controls beyond what existing agents require. diff --git a/docs/architecture/specs/01_functional_spec.md b/docs/architecture/specs/01_functional_spec.md index e80d24c6..f0ade7a2 100644 --- a/docs/architecture/specs/01_functional_spec.md +++ b/docs/architecture/specs/01_functional_spec.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Functional Specification @@ -8,7 +8,7 @@ <!-- Describe what the system does from the user's perspective. --> -**Project:** agentkit-forge +**Project:** retort **Version:** 3.1.0 ## Feature Inventory diff --git a/docs/architecture/specs/02_technical_spec.md b/docs/architecture/specs/02_technical_spec.md index 1b87394b..f76e0778 100644 --- a/docs/architecture/specs/02_technical_spec.md +++ b/docs/architecture/specs/02_technical_spec.md @@ -1,14 +1,14 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Technical Specification ## Overview -<!-- High-level technical approach for agentkit-forge. --> +<!-- High-level technical approach for retort. --> -**Project:** agentkit-forge +**Project:** retort **Version:** 3.1.0 ## System Context diff --git a/docs/architecture/specs/03_api_spec.md b/docs/architecture/specs/03_api_spec.md index b965ceee..ae92aac1 100644 --- a/docs/architecture/specs/03_api_spec.md +++ b/docs/architecture/specs/03_api_spec.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # API Specification ## Overview -<!-- Describe the API surface for agentkit-forge. --> +<!-- Describe the API surface for retort. --> **Base URL:** `https://api.example.com/v1` **Version:** 3.1.0 diff --git a/docs/architecture/specs/04_data_models.md b/docs/architecture/specs/04_data_models.md index 1393f68c..adf9145c 100644 --- a/docs/architecture/specs/04_data_models.md +++ b/docs/architecture/specs/04_data_models.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Data Models ## Overview -<!-- Describe the data model layer for agentkit-forge. --> +<!-- Describe the data model layer for retort. --> ## Entity Relationship Summary diff --git a/docs/architecture/specs/PLAN-template-variable-audit.md b/docs/architecture/specs/PLAN-template-variable-audit.md index 69d8e256..f296772d 100644 --- a/docs/architecture/specs/PLAN-template-variable-audit.md +++ b/docs/architecture/specs/PLAN-template-variable-audit.md @@ -57,7 +57,7 @@ These variables are used **directly** (no conditional guard) and will render as | `version` | 88 | ✅ from package.json | Low | | `syncDate` | 74 | ✅ `new Date().toISOString()` | Low | | `lastModel` | 74 | ✅ env var or `'sync-engine'` | Low | -| `lastAgent` | 74 | ✅ env var or `'agentkit-forge'` | Low | +| `lastAgent` | 74 | ✅ env var or `'retort'` | Low | | `defaultBranch` | 26 | ✅ `'main'` | Low | | `testingCoverage` | 19 | ❌ No default, used bare | **Medium** — will render `{{testingCoverage}}` | | `commitConvention` | 7 | ❌ comes from project.yaml only | **Medium** | diff --git a/docs/architecture/specs/README.md b/docs/architecture/specs/README.md index abdab96a..2ea560d0 100644 --- a/docs/architecture/specs/README.md +++ b/docs/architecture/specs/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Specs Docs Index diff --git a/docs/architecture/specs/competitive-landscape-report.md b/docs/architecture/specs/competitive-landscape-report.md new file mode 100644 index 00000000..3e606412 --- /dev/null +++ b/docs/architecture/specs/competitive-landscape-report.md @@ -0,0 +1,396 @@ +# Strategic Research Report: AI Agent Configuration & Orchestration Landscape + +**Date:** 2026-03-17 +**Author:** Claude Opus 4.6 (strategic analysis) +**Scope:** Multi-tool AI agent configuration, orchestration frameworks, and developer tooling +**Status:** Complete + +--- + +## Executive Summary + +AgentKit Forge operates at the intersection of two converging markets: **multi-tool agent configuration sync** (getting rules/agents/skills into 15+ AI coding tools) and **multi-agent orchestration** (coordinating teams of agents to complete complex work). These markets are evolving rapidly: + +**Key findings:** + +1. **The "rules sync" category is commoditising.** Six open-source tools (Ruler, ai-rules-sync, agent-rules, ai-rules, rulesync, SyncAI) now offer basic rules-to-multiple-tools sync. None yet offer agent personas, team orchestration, or quality gates — this is AgentKit Forge's moat. + +2. **AGENTS.md is becoming the de facto instruction standard.** Backed by OpenAI and adopted by 10+ tools, AGENTS.md provides a universal instruction file. However, recent research (ETH Zurich, March 2026) questions its effectiveness — LLM-generated context files may hinder agents. + +3. **Agent orchestration frameworks (CrewAI, LangGraph, AG2) solve a different problem.** They orchestrate runtime agent execution (API calls, tool use, conversation flow). AgentKit Forge orchestrates **development-time agent configuration** (what agents know, what rules they follow, what they can do). These are complementary, not competing. + +4. **The market is missing a portable governance layer.** No competitor offers reflective guards — governance rules that agents self-check regardless of platform. This is the innovation from Mystira.workspace that AgentKit Forge should adopt. + +5. **Market size:** The AI coding assistant market is ~$8.5B in 2026 (24% CAGR to $47.3B by 2034). 62% of professional developers use AI coding tools. The configuration/orchestration tooling layer is pre-revenue but growing fast in OSS adoption. + +**Strategic recommendation:** Double down on the three capabilities no competitor has: (1) spec-driven multi-tool sync with CI validation, (2) team orchestration with task delegation, and (3) portable governance via reflective guards. Resist the urge to compete on simple rules sync — that's a race to the bottom. + +--- + +## 1. Industry Trends & Direction + +### 1.1 The Multi-Tool Reality (2025–2026) + +Developers now routinely use 2–4 AI coding tools simultaneously. A typical stack: Cursor for editing, Claude Code for CLI tasks, Copilot for inline completions, Gemini for research. This creates a configuration fragmentation problem — each tool has its own rules format, directory structure, and instruction mechanism. + +**Trajectory:** Tool proliferation will continue. JetBrains ACP (Agent Client Protocol), co-developed with Zed Industries, aims to standardise agent-to-IDE communication. Anthropic's MCP standardises tool discovery. But **no protocol standardises agent configuration** — this is the gap AgentKit Forge fills. + +### 1.2 The AGENTS.md Convergence + +OpenAI pushed AGENTS.md as an open standard in late 2025. It provides a single markdown file with instructions for AI coding agents — build commands, architecture overview, conventions, security rules. Key adoption: + +- Supported natively by: Codex, Kilo Code, Cursor, Windsurf, Builder.io +- Hierarchical: `AGENTS.md` at root, subdirectory `AGENTS.md` overrides +- Complementary to `CLAUDE.md`, `.cursorrules`, etc. + +**Critical caveat:** A March 2026 ETH Zurich paper found that LLM-generated AGENTS.md files often **hinder** agent performance. The recommendation: omit auto-generated context files; limit human-written instructions to genuinely non-inferable details. This validates AgentKit Forge's approach of generating tool-specific output from validated specs rather than dumping everything into one file. + +### 1.3 Protocol Standardisation Wave + +| Protocol | Owner | Scope | Status | +|----------|-------|-------|--------| +| MCP (Model Context Protocol) | Anthropic | Tool discovery & execution | Widely adopted | +| ACP (Agent Client Protocol) | JetBrains + Zed | Agent-to-IDE communication | Early adoption | +| Agent Protocol | LangChain | Agent runtime API | Moderate adoption | +| AGENTS.md | OpenAI / AAIF | Agent instruction files | Rapid adoption | +| W3C Agent Protocol | W3C CG | Web-standard agent comms | Spec drafting (2026–27) | + +**Missing from all protocols:** Agent configuration management, governance rules, cross-session continuity, team orchestration. This is AgentKit Forge's category. + +### 1.4 Inflection Points (Next 12–24 Months) + +1. **Rules sync becomes table stakes.** Every major IDE will support native agent configuration; basic sync tools will lose relevance. +2. **Governance becomes critical.** As agents gain more autonomy (Claude Code, Codex), preventing destructive actions becomes a production concern, not a nice-to-have. +3. **Multi-agent teams go mainstream.** Claude's sub-agent system, Codex's parallel tasks, and Cursor's background agents all point to multi-agent being the default. +4. **Cross-session memory matures.** Agents will need structured handoff, traces, and strategic context — not just chat history. + +--- + +## 2. Best Practices & Standards + +### 2.1 Configuration Management + +| Practice | Leaders | Adoption | +|----------|---------|----------| +| Single source of truth (YAML/MD → tool-specific output) | AgentKit Forge, Agent OS, Ruler | Growing | +| Hierarchical instructions (root + subdirectory overrides) | AGENTS.md, CLAUDE.md | Standard | +| CI drift validation (spec vs generated output) | AgentKit Forge | Unique | +| Reflective guards (portable governance) | Mystira.workspace | Novel | +| `.readme.yaml` (machine-readable metadata) | Mystira.workspace | Novel | + +### 2.2 What Industry Leaders Are Implementing + +**Block (formerly Square):** +- Open-sourced `ai-rules` for managing rules, commands, and skills across agents +- Built Goose, an open-source autonomous agent with extensible plugin architecture +- Uses AGENTS.md + repeatable "agent skills" as packaged workflows + +**Anthropic:** +- Claude Code hooks system for automated enforcement +- Sub-agent architecture for parallel task execution +- MCP for tool discovery standardisation + +**GitHub/Microsoft:** +- Copilot agents with `.github/agents/` directory +- Copilot chatmodes for team-based interaction patterns +- CODEOWNERS integration for agent access control + +**JetBrains:** +- ACP protocol for agent-IDE interop +- Moving toward agent-neutral IDE support + +### 2.3 Emerging Practices Gaining Traction + +1. **Spec-driven development** — Define what you want (spec), let agents implement. Agent OS calls this "enhanced specification shaping." +2. **Guard rails as code** — Governance rules checked into the repo alongside the code they protect. +3. **Cross-session traces** — Preserving agent reasoning context across sessions (pioneered by Mystira.workspace). +4. **Token budget awareness** — Monitoring and optimising agent token consumption per operation. +5. **Conventional commit enforcement** — CI-level validation that agents follow commit message conventions. + +--- + +## 3. Competitive Landscape + +### 3.1 Competitor Profiles + +#### Primary Competitors (Direct) + +**1. Ruler** (intellectronica/ruler) +- **What:** CLI tool that syncs a single rules file to 11+ AI coding tool directories +- **Stars:** ~2,500 GitHub stars +- **Mechanism:** Reads `ruler.md` (or config), writes to `.cursor/rules/`, `.claude/CLAUDE.md`, `.github/copilot-instructions.md`, etc. +- **Strengths:** Simple, focused, good tool coverage (11 targets), auto-manages `.gitignore` +- **Weaknesses:** Rules only (no agents, skills, commands, teams), no CI validation, no governance, no orchestration +- **Pricing:** Free, open source (MIT) + +**2. Agent OS** (buildermethods/agent-os) +- **What:** System for injecting coding standards into AI-powered development +- **Stars:** Moderate +- **Mechanism:** Discover patterns → document standards → inject into context → shape specifications +- **Strengths:** Standards discovery from existing codebases, spec-driven philosophy, Claude Code integration +- **Weaknesses:** Primarily Claude Code focused, no multi-tool sync engine, no team orchestration, no CI validation +- **Pricing:** Free and open source; paid training via Builder Methods Pro + +**3. ai-rules-sync** (lbb00/ai-rules-sync) +- **What:** Sync rules, skills, commands, and subagents across 8+ tools via symlinks +- **Stars:** Growing +- **Mechanism:** Git-based rule storage, symlink sync, web dashboard UI +- **Strengths:** Supports skills and commands (not just rules), multi-repo support, team sharing, web UI +- **Weaknesses:** Symlink-based (fragile on Windows), no spec validation, no governance, no orchestration +- **Pricing:** Free, open source + +**4. agent-rules** (jeejeeguan/agent-rules) +- **What:** Centralise rules in `AGENT_RULES.md`, auto-sync to each agent's directory via CI +- **Stars:** Small +- **Mechanism:** CI pipeline copies single file to `.claude/CLAUDE.md`, `.codex/AGENTS.md`, `.gemini/GEMINI.md`, etc. +- **Strengths:** CI-first approach (sync on push), backup before overwrite +- **Weaknesses:** One-file-fits-all (no per-tool customisation), no spec YAML, no agents/skills/commands, no orchestration +- **Pricing:** Free, open source + +**5. Block ai-rules** (block/ai-rules) +- **What:** Manage AI rules, commands, and skills across multiple agents from one place +- **Stars:** Notable (Block/Square backing) +- **Mechanism:** Centralised configuration with distribution +- **Strengths:** Enterprise backing (Block/Square), supports commands and skills +- **Weaknesses:** Less mature than Ruler, limited orchestration +- **Pricing:** Free, open source + +#### Secondary Competitors (Adjacent) + +**6. AGENTS.md (standard)** +- Not a tool but a standard. Competes by making per-tool configuration seem unnecessary — "just write one AGENTS.md." In practice, tools interpret it differently, and it doesn't cover governance, orchestration, or cross-session continuity. + +**7. LIDR-academy/ai-specs** +- Comprehensive development rules and AI agent configurations designed to work with multiple copilots. Portable, importable into any project. More of a "rules library" than a sync tool. + +**8. snowdreamtech/template** +- Enterprise-grade template claiming 50+ AI IDE support. Single source of truth for rules, workflows, and configurations. Template-based (copy/fork) rather than sync-engine-based. + +#### Runtime Orchestration (Different Category) + +**CrewAI, LangGraph, AG2 (AutoGen), Semantic Kernel** — These orchestrate agent *execution* at runtime (API calls, conversations, tool use). They don't manage agent *configuration* in repositories. Complementary to AgentKit Forge, not competing. + +### 3.2 Competitive Evaluation Matrix + +| Dimension | AgentKit Forge | Ruler | Agent OS | ai-rules-sync | agent-rules | Block ai-rules | AGENTS.md | +|-----------|---------------|-------|----------|---------------|-------------|----------------|-----------| +| **Multi-tool output** | 15+ targets | 11 targets | 1 (Claude) | 8+ targets | 5 targets | Multi | 1 file | +| **Spec-driven (YAML → output)** | Yes | No (MD only) | Partial | No | No | Partial | N/A | +| **Agent personas** | 39 agents | None | None | None | None | None | None | +| **Team orchestration** | 13 teams + task protocol | None | None | None | None | None | None | +| **Skills/commands** | 30+ skills, 42 commands | None | Standards | Skills, commands | None | Commands, skills | None | +| **CI drift validation** | Yes | None | None | None | CI copy | None | None | +| **Governance (hooks)** | 14 shell hooks | None | None | None | None | None | None | +| **Governance (guards)** | Roadmap (Phase 2) | None | None | None | None | None | None | +| **Quality gates** | 5-phase lifecycle | None | None | None | None | None | None | +| **Cross-session traces** | Roadmap (Phase 4) | None | None | None | None | None | None | +| **`.readme.yaml`** | Roadmap (Phase 3) | None | None | None | None | None | None | +| **Maturity** | Production | Stable | Active | Active | Early | Active | Standard | +| **Effort to adopt** | Medium | Low | Low | Low | Low | Low | Trivial | +| **Lock-in risk** | Medium (Node.js engine) | Low | Low | Low | Low | Low | None | + +### 3.3 Competitive Positioning Map + +``` + Complex (orchestration, teams, governance) + │ + │ ★ AgentKit Forge + │ + │ + ──────────────┼────────────── + Few tools │ Many tools + │ + Agent OS ● │ ● Ruler + │ ● ai-rules-sync + │ ● Block ai-rules + │ + │ ○ agent-rules + │ ○ AGENTS.md + │ + Simple (rules sync only) +``` + +AgentKit Forge occupies the **upper-right quadrant** — many tools + complex capabilities. No competitor is close. The risk is that the lower-right quadrant (many tools + simple) commoditises and "good enough" wins for most teams. + +--- + +## 4. SWOT Analysis + +### Strengths + +| Strength | Evidence | Strategic Value | +|----------|----------|-----------------| +| **Only spec-driven multi-tool engine with CI validation** | 15+ output targets, drift check in CI | Hard to replicate — requires deep knowledge of each tool's format | +| **Team orchestration is unique** | 13 teams, task delegation protocol, fan-out/chain handoff | No competitor offers development-time team coordination | +| **39 agent personas** | Categorised agents with defined roles, responsibilities, context | Competitors offer rules; Forge offers full agent definitions | +| **Quality gate framework** | 5-phase lifecycle with enforcement at each transition | Connects agent config to delivery discipline | +| **Proven at scale** | Deployed across 6+ repos (chaufher, PuffWise, etc.) in production | Not theoretical — validated in real projects | +| **Deep tool format knowledge** | Supports `.mdc` (Cursor), `.chatmode.md` (Copilot), `.agent.md` (GitHub), skill YAML, etc. | Barrier to entry — each format has undocumented quirks | + +### Weaknesses + +| Weakness | Impact | Mitigation Path | +|----------|--------|-----------------| +| **High adoption effort** | New users face `.agentkit/` directory, spec YAML, sync engine, hooks — steep learning curve vs "just add a `ruler.md`" | Guided `/start` command, progressive disclosure, "lite mode" | +| **Node.js dependency** | Sync engine requires Node.js/pnpm — excludes Python-only or Rust-only teams | Consider standalone binary (Go/Rust) or WASM-based engine | +| **No portable governance** | Shell hooks only work for Claude Code; other tools bypass governance | Reflective guards (Phase 2 roadmap) | +| **Generated file noise** | 300+ generated files across tool targets; PRs are overwhelming (see: PR #428 with 444 files) | Smarter sync (hash-based skip), `.gitattributes` to collapse diffs | +| **No schema versioning** | Format changes would break existing consumers with no migration path | Add `version` field to all generated frontmatter | +| **Timestamp churn** | Every sync bumps `last_updated` on all files even when content unchanged | Content-hash-based timestamps (only update if content actually changed) | + +### Opportunities + +| Opportunity | Market Signal | Action | +|-------------|--------------|--------| +| **Portable governance (guards)** | No competitor offers this; Mystira.workspace validated the pattern | ADR-10 Phase 2 — adopt reflective guards | +| **`.readme.yaml` standard** | Token cost is a growing concern (62% of devs use AI tools daily) | ADR-10 Phase 3 — generate machine-readable metadata | +| **ETH Zurich finding re: AGENTS.md** | Auto-generated context files may hinder agents | Position Forge's spec-validated, tool-specific output as superior to "dump everything in AGENTS.md" | +| **Enterprise demand for governance** | 90% of Fortune 100 use AI coding tools; compliance is lagging | Governance-as-code offering for enterprise teams | +| **Cross-session memory** | No tool solves agent continuity well; `/handoff` is a start | ADR-10 Phase 4 — traces + roadmaps | +| **Plugin marketplace** | Claude Code plugins, Cursor extensions, Copilot agents are all growing | Package team definitions as distributable plugins | +| **Standard body participation** | W3C Agent Protocol CG, AAIF — no configuration standard exists yet | Propose `.agents/` convention to AAIF or W3C | + +### Threats + +| Threat | Likelihood | Impact | Mitigation | +|--------|-----------|--------|------------| +| **IDE-native configuration** | High | Medium | IDEs add built-in agent config → sync tools become less needed. Counter: Forge syncs *across* IDEs, which IDE-native can't do | +| **AGENTS.md becomes sufficient** | Medium | High | If tools converge on one format, multi-tool sync loses value. Counter: Forge offers orchestration, governance, and team coordination beyond rules sync | +| **Ruler reaches feature parity** | Low | Medium | Ruler adds agents, skills, CI validation. Counter: Deep format knowledge and spec-driven architecture are hard to replicate | +| **Enterprise vendor enters** | Medium | High | GitHub/JetBrains build native multi-tool config. Counter: Move fast on governance and orchestration — features enterprises want but vendors are slow to ship | +| **Adoption friction kills growth** | Medium | High | Teams choose "good enough" simple tools over Forge's power. Counter: Lite mode, progressive adoption, one-command onboarding | + +--- + +## 5. KPI Framework & Metrics Dashboard + +### 5.1 Key Performance Indicators + +| # | KPI | Current Baseline | Target (6mo) | Measurement Method | +|---|-----|-----------------|--------------|-------------------| +| 1 | **Onboarded repos** | 6 | 15 | Count of repos with `.agentkit/` and passing CI drift check | +| 2 | **Tool targets supported** | 15 | 18 | Count of render targets in sync engine | +| 3 | **Agent persona count** | 39 | 45 | Count of agent definitions in spec | +| 4 | **Team count** | 13 | 13 | Stable — quality over quantity | +| 5 | **CI drift check pass rate** | ~90% (manual observation) | 99% | Ratio of drift-check-passing PRs to total PRs | +| 6 | **Governance coverage** | Hooks only (1 platform) | Guards + hooks (all platforms) | Count of platforms with automated or reflective governance | +| 7 | **Adoption effort (time to first sync)** | ~30 min | <10 min | Time from `git clone` to first successful `agentkit:sync` | +| 8 | **Generated file churn ratio** | High (all files bump on sync) | <10% (content-changed only) | Ratio of content-changed files to timestamp-only-changed files per sync | +| 9 | **Cross-session trace coverage** | 0% | 50% | Percentage of sessions that produce a structured trace | +| 10 | **PR review noise ratio** | 444 files for 3 docs (PR #428) | <50 files for docs-only changes | Count of files in PR vs count of meaningful changes | +| 11 | **External contributor onboarding** | 0 external contributors | 3 | Count of non-org contributors with merged PRs | +| 12 | **Competitive feature gap** | 6+ unique features | 8+ unique features | Count of features in evaluation matrix where Forge = "Yes" and all competitors = "None" | + +### 5.2 Benchmarks Against Competitors + +| KPI | AgentKit Forge | Ruler | Agent OS | ai-rules-sync | +|-----|---------------|-------|----------|---------------| +| Tool targets | **15** | 11 | 1 | 8 | +| Adoption effort | 30 min | **2 min** | 5 min | 5 min | +| Governance platforms | 1 | 0 | 0 | 0 | +| CI validation | **Yes** | No | No | No | +| Agent definitions | **39** | 0 | 0 | 0 | +| Team orchestration | **13 teams** | 0 | 0 | 0 | +| GitHub stars | ~50 | ~2,500 | ~200 | ~300 | +| Generated file noise | High | **None** | None | None | + +### 5.3 Scoring Methodology + +Each KPI maps to a SWOT quadrant: + +| SWOT Category | KPIs | Weight | +|---------------|------|--------| +| **Strengths (protect)** | #2, #3, #4, #5, #12 | 30% | +| **Weaknesses (fix)** | #7, #8, #10 | 30% | +| **Opportunities (pursue)** | #6, #9, #11 | 25% | +| **Threats (monitor)** | #1, #12 | 15% | + +**Scoring per KPI:** 0 = below baseline, 1 = at baseline, 2 = at target, 3 = exceeds target. + +**Composite score** = weighted average × 33.3 (normalised to 100). + +**Current estimated score:** ~55/100 (strong on strengths, weak on adoption friction and file churn). + +### 5.4 Tracking Dashboard Template + +``` +┌─────────────────────────────────────────────────────────┐ +│ AgentKit Forge — Strategic Health Dashboard │ +│ Last updated: YYYY-MM-DD │ +├──────────────────┬──────────┬──────────┬────────────────┤ +│ Metric │ Current │ Target │ Status │ +├──────────────────┼──────────┼──────────┼────────────────┤ +│ Onboarded repos │ 6 │ 15 │ 🟡 40% │ +│ Tool targets │ 15 │ 18 │ 🟢 83% │ +│ Agent personas │ 39 │ 45 │ 🟢 87% │ +│ CI pass rate │ ~90% │ 99% │ 🟡 91% │ +│ Governance plat. │ 1 │ all │ 🔴 17% │ +│ Time to 1st sync │ 30 min │ 10 min │ 🔴 33% │ +│ File churn ratio │ high │ <10% │ 🔴 5% │ +│ Trace coverage │ 0% │ 50% │ 🔴 0% │ +│ PR noise ratio │ 444:3 │ 50:3 │ 🔴 1% │ +│ Ext contributors │ 0 │ 3 │ 🔴 0% │ +│ Feature gap │ 6+ │ 8+ │ 🟢 75% │ +├──────────────────┴──────────┴──────────┴────────────────┤ +│ Composite Score: 55/100 │ +│ Priority: Fix file churn → Reduce adoption friction │ +│ → Add portable governance → Attract externals │ +└─────────────────────────────────────────────────────────┘ +``` + +### 5.5 Priority Matrix (What to Fix First) + +Based on the metrics, the prioritised action list for product/strategy teams: + +| Priority | Action | KPIs Improved | Effort | Impact | +|----------|--------|---------------|--------|--------| +| **P0** | Content-hash-based sync (skip unchanged files) | #8, #10 | Medium | High — eliminates the #1 user complaint (noisy PRs) | +| **P0** | One-command onboarding (`npx agentkit-forge init`) | #7, #11 | Medium | High — reduces adoption barrier from 30min to <5min | +| **P1** | Reflective guards (ADR-10 Phase 2) | #6, #12 | Medium | High — unique feature, governance for all platforms | +| **P1** | `.readme.yaml` generation (ADR-10 Phase 3) | #12 | Low | Medium — token cost reduction, machine-readable metadata | +| **P2** | Cross-session traces (ADR-10 Phase 4) | #9 | Low-Med | Medium — agent continuity improvement | +| **P2** | Publish as distributable package (npm/brew) | #7, #11 | Medium | High — prerequisite for external adoption | +| **P3** | Schema formalisation (ADR-10 Phase 5) | #11, #12 | Medium | Medium — enables ecosystem adoption | + +--- + +## 6. Actionable Recommendations + +### For Executive Leadership + +1. **Position AgentKit Forge as the "Terraform for AI agents"** — infrastructure-as-code for agent configuration. This resonates with enterprises who already think in IaC terms. +2. **The competitive moat is orchestration + governance, not rules sync.** Rules sync is commoditising. Invest in the features competitors can't easily replicate: team orchestration, quality gates, and portable governance. +3. **The ETH Zurich finding is an opportunity.** Auto-generated AGENTS.md files hurt agent performance. Position Forge's spec-validated, tool-specific output as the evidence-based alternative. + +### For Product/Strategy + +1. **Fix the noise problem first.** PR #428 had 444 files for 3 meaningful docs. Content-hash-based sync that skips unchanged files would dramatically improve the developer experience. +2. **Ship a "lite mode."** Not every team needs 13 teams and 39 agents. Offer a minimal config that generates basic rules for 3–5 tools from a single YAML file. Progressive disclosure to full power. +3. **Adopt the `.agents/` hub pattern.** Per ADR-10, this gives every AI tool a shared discovery point. Ship Phase 1 to validate before investing in Phases 2–5. + +### For R&D/Technical + +1. **Implement content-hash-based timestamps.** Only bump `last_updated` when file content actually changes. This is the single highest-impact technical change. +2. **Build guard-to-hook generation.** Reflective guards (markdown) as the canonical source; shell hooks generated from guards for tools that support automation. +3. **Publish JSON Schemas.** For guards, traces, `.readme.yaml`, and agent persona definitions. Enables IDE validation, external tool integration, and ecosystem adoption. +4. **Consider a standalone binary.** The Node.js/pnpm dependency limits adoption. A Go or Rust binary (or WASM) would make `agentkit-forge` installable via `brew`, `cargo`, or `go install` with zero runtime dependencies. + +--- + +## Sources + +- [AGENTS.md specification](https://agents.md/) +- [AGENTS.md GitHub repository](https://github.com/agentsmd/agents.md) +- [ETH Zurich — Reassessing AGENTS.md value (InfoQ)](https://www.infoq.com/news/2026/03/agents-context-file-value-review/) +- [Ruler — apply rules to all coding agents](https://github.com/intellectronica/ruler) +- [Agent OS — coding standards for AI development](https://buildermethods.com/agent-os) +- [ai-rules-sync](https://github.com/lbb00/ai-rules-sync) +- [agent-rules (AGENT_RULES.md sync)](https://github.com/jeejeeguan/agent-rules) +- [Block ai-rules](https://github.com/block/ai-rules) +- [JetBrains ACP](https://www.adwaitx.com/jetbrains-acp-ai-agent-ide-integration/) +- [AI coding market statistics 2026](https://www.getpanto.ai/blog/ai-coding-assistant-statistics) +- [Agentic coding 2026 guide](https://halallens.no/en/blog/agentic-coding-in-2026-the-complete-guide-to-plugins-multi-model-orchestration-and-ai-agent-teams) +- [AI agent protocols guide](https://www.ruh.ai/blogs/ai-agent-protocols-2026-complete-guide) +- [OpenAI Codex AGENTS.md guide](https://developers.openai.com/codex/guides/agents-md/) +- [Best multi-agent frameworks 2026](https://gurusup.com/blog/best-multi-agent-frameworks-2026) +- [Anthropic 2026 Agentic Coding Trends Report](https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf) diff --git a/docs/architecture/specs/tool-neutral-agent-hub-findings.md b/docs/architecture/specs/tool-neutral-agent-hub-findings.md new file mode 100644 index 00000000..8d9f779d --- /dev/null +++ b/docs/architecture/specs/tool-neutral-agent-hub-findings.md @@ -0,0 +1,262 @@ +# Architectural Findings: Tool-Neutral Agent Hub Pattern + +**Date:** 2026-03-17 +**Status:** Analysis complete — pending adoption decision +**Repositories analysed:** `agentkit-forge` (main), `Mystira.workspace` (dev) + +--- + +## Executive Summary + +AgentKit Forge and Mystira.workspace have independently evolved two complementary approaches to multi-agent configuration. AgentKit Forge uses a **spec-driven sync engine** that generates tool-specific output from YAML specs. Mystira.workspace uses a **hand-authored tool-neutral hub** (`.agents/`) shared across all agent tools. Neither approach alone is sufficient — but combining them creates a significantly stronger architecture. + +This document captures findings from a structural comparison and recommends a convergence path. + +--- + +## 1. Current Architecture: AgentKit Forge + +### Directory Map + +``` +.agentkit/ + spec/ ← YAML source of truth (project, teams, commands, rules) + templates/ ← Output templates for 15+ tools + engines/ ← Node.js sync engine + overlays/ ← Per-repo customisations + bin/ ← Cross-platform CLI scripts + +.claude/ + agents/ ← 39 agent persona definitions (generated) + commands/ ← 42 slash commands (generated) + rules/ ← Domain rules + languages/ subdirectory (generated) + skills/ ← 30+ skill definitions (generated) + hooks/ ← 14 lifecycle hooks (shell scripts) + state/ ← Orchestrator state, events log, task files + plans/ ← Implementation plans (runtime) +``` + +### Strengths + +| Capability | Detail | +|---|---| +| **Multi-tool sync** | One YAML change propagates to Claude, Cursor, Copilot, Gemini, Cline, Windsurf, Roo (15+ targets) | +| **Automated enforcement** | Shell hooks block destructive commands, protect templates, validate pre-push | +| **Spec-driven architecture** | CI drift check ensures generated output matches spec — no silent divergence | +| **Team orchestration** | 13 teams with task delegation protocol, fan-out, and chained handoff | +| **Quality gates** | 5-phase lifecycle with enforcement at each transition | + +### Weaknesses + +| Issue | Impact | +|---|---| +| **Tool-specific output dirs** | Every tool gets its own copy of agents, rules, commands — no shared layer agents can read across tools | +| **No cross-session traces** | `/handoff` captures session state but doesn't preserve reasoning context or mental models | +| **No directory-boundary metadata** | Agents must read full `README.md` or spec YAML to understand project structure | +| **Flat agent listing** | 39 agents in one directory with no categorisation (empty category dirs exist but unused) | +| **No reflective guards** | Enforcement is hook-based only — agents without shell access bypass all governance | +| **No strategic roadmaps** | Backlog tracks tasks; nothing tracks multi-session strategic goals | +| **State accumulation** | `events.log` grows unbounded; no rotation, archival, or freshness signals | + +--- + +## 2. Current Architecture: Mystira.workspace + +### Directory Map + +``` +.agents/ ← Tool-neutral hub (shared across ALL agents) + guards/ ← Constraint-based governance rules + memory-governance.md + respect-shared-docs.md + skill-autonomy-guard.md + skills/ ← Shared domain knowledge + end-session/SKILL.md + mystira-css-tokens/SKILL.md + obsidian-styling/SKILL.md + traces/ ← Cross-session investigative findings + 2026-03-16-handover-ui-infra-aesthetics.md + 2026-03-16-obsidian-washing-trace.md + history/ ← Per-conversation artifacts + {uuid}/ + task.md, walkthrough.md, implementation_plan.md + agent_trace_n7.md, media__*.png, *.resolved + roadmaps/ ← Strategic planning + agent-handover.md + guard-enforcement.md + multi-agent-collaboration.md + ui-finalization.md + +.claude/settings.json ← Claude-specific hooks/permissions only +.gemini/skills/ ← Gemini-specific skills (e.g. antigravity-trace-standard) +.serena/memories/ ← Serena MCP server memories (another tool-specific store) +.cursor/rules/ ← Empty placeholder +.windsurf/rules/ ← Empty placeholder + +.readme.yaml ← Machine-readable project metadata (root) +apps/.readme.yaml ← Per-directory metadata +packages/.readme.yaml ← Per-directory metadata +``` + +### Strengths + +| Capability | Detail | +|---|---| +| **Tool-neutral hub** | `.agents/` is readable by any agent regardless of platform — no tool-specific parsing required | +| **Reflective guards** | YAML frontmatter + regex patterns — agents self-check during planning; no shell dependency | +| **Cross-session traces** | Captures outgoing agent's mental model, blocked work, and first-3-tool-calls for incoming agent | +| **`.readme.yaml`** | Structured, parseable project metadata at directory boundaries — cheaper than parsing markdown | +| **Full audit trail** | Per-conversation-ID history with task lists, walkthroughs, plans, screenshots, `.resolved` copies | +| **Strategic roadmaps** | Multi-session goals that bridge individual task backlogs (4 active roadmaps) | +| **Investigation traces** | Dated traces capture root-cause analysis with architectural guards derived from debugging | + +### Weaknesses + +| Issue | Impact | +|---|---| +| **No automation** | Hand-authored files with no sync engine — changes don't propagate across tools | +| **Trust-based enforcement** | Reflective guards have zero automated consequences if an agent ignores them | +| **No spec validation** | No CI check that guard patterns are valid regex or that skills follow a schema | +| **Accumulation without lifecycle** | `traces/` and `history/` grow unbounded — no freshness signal or retention policy | +| **Dual maintenance** | `.readme.yaml` + `README.md` will drift without validation | +| **No team orchestration** | No task delegation protocol, no fan-out, no dependency chains | + +--- + +## 3. Pattern Comparison Matrix + +| Concern | AgentKit Forge | Mystira | Winner | Notes | +|---|---|---|---|---| +| Multi-tool output generation | Sync engine (15+ targets) | Manual per-tool | **Forge** | Automation beats manual every time | +| Agent discoverability across tools | Tool-specific dirs only | `.agents/` neutral hub | **Mystira** | Agents from any tool can read `.agents/` | +| Governance enforcement | Shell hooks (automated) | Guards (reflective) | **Draw** | Both needed — automated for capable tools, reflective for others | +| Cross-session continuity | `/handoff` (task state only) | Traces + history + roadmaps | **Mystira** | Mental model capture is qualitatively superior to task lists | +| Project structure discovery | `.agentkit/spec/project.yaml` | `.readme.yaml` at boundaries | **Mystira** | Boundary-level metadata is more granular and cheaper to read | +| Quality gate enforcement | CI drift check + hooks | None | **Forge** | Mystira has no automated validation | +| Team coordination | 13 teams + task protocol | None | **Forge** | Mystira is single-agent focused | +| Strategic planning | Backlog only | Roadmaps as first-class | **Mystira** | Roadmaps bridge session-level and project-level goals | +| Schema versioning | None | None | **Neither** | Both lack format evolution strategy | +| Cost attribution | Rules exist, no tracking | None | **Neither** | Both describe cost awareness but don't measure it | + +--- + +## 4. Key Innovations Worth Adopting + +### 4.1 `.agents/` as Tool-Neutral Hub + +**What it is:** A top-level directory (not nested under any tool-specific dir) containing shared agent infrastructure: guards, skills, traces, history, roadmaps. + +**Why it matters:** Currently, an agent running in Cursor cannot discover Claude's agent personas. An agent in Gemini cannot read Claude's skills. The sync engine generates parallel copies, but there's no shared canonical location. `.agents/` solves this by providing one directory that all tools can read natively. + +**Adoption implication:** The sync engine should generate `.agents/` content as a first-class output target alongside `.claude/`, `.cursor/`, etc. Tool-specific dirs become thin wrappers containing only platform hooks and permissions. + +### 4.2 Reflective Guards + +**What it is:** Markdown files with YAML frontmatter (name, enabled, regex pattern) and natural-language instructions that agents self-check during planning. + +**Why it matters:** Shell hooks only work for tools that execute commands through a shell. Browser-based agents, API-only agents, and agents in sandboxed environments bypass hook enforcement entirely. Guards provide a portable fallback. + +**Verified guard format (from Mystira):** + +```yaml +--- +name: memory-governance +enabled: true +description: Requires user consent before any memory write operation +--- +# Memory Governance Guard +**Pattern**: `\.claude/.*memory|\.serena/.*memories|\.gemini/.*brain` +**Instruction**: +1. Before writing to any memory path matching the pattern, pause +2. Inform the user what you intend to write and why +3. Proceed only with explicit consent +``` + +Three guards exist: `memory-governance` (protects cross-tool memory stores), `respect-shared-docs` (protects `CLAUDE.md`, `README.md`, shared docs from unasked modification), `skill-autonomy-guard` (prevents skills/subagents from writing to memory indices without human command). + +**Adoption implication:** Guards should complement (not replace) hooks. The sync engine can generate hooks from guard definitions for tools that support them, while the guard files themselves remain readable by any agent. + +### 4.3 `.readme.yaml` at Directory Boundaries + +**What it is:** Structured YAML files at directory boundaries containing machine-readable metadata: tech stack, workspace structure, build targets, local services. + +**Why it matters:** Agents currently parse human-written README.md files to understand project structure — expensive on tokens and error-prone. `.readme.yaml` provides the same information in a format that requires zero interpretation. + +**Verified `.readme.yaml` schema (from Mystira root):** + +```yaml +purpose: "Mystira — AI-powered interactive storytelling..." +version: "0.5.2-alpha" +tech_stack: + dotnet: "9.0" + node: "22.x" + react: "19.x" +workspace_type: "dotnet-sln + pnpm monorepo" +workspace_managers: ["dotnet sln", "pnpm workspaces"] +local_services: + api: { port: 5001, path: "apps/api" } + web: { port: 3000, path: "apps/web" } +agent_tooling: + guards: ".agents/guards/" + skills: ".agents/skills/" +last_synced: "2026-03-16" +``` + +Sub-directory variants (`apps/.readme.yaml`, `packages/.readme.yaml`) list contained projects with `name`, `path`, `stack`, `description`, and `sub_solutions` fields. + +**Adoption implication:** `.agentkit/spec/project.yaml` already contains most of this data. The sync engine should emit `.readme.yaml` files at relevant directory boundaries, derived from the spec. + +### 4.4 Cross-Session Traces + +**What it is:** Dated markdown files capturing the outgoing agent's mental model, design intuition, blocked/pending work, and concrete next steps for the incoming agent. + +**Why it matters:** Git commits and `/handoff` documents capture *what* happened. Traces capture *why* and *what the agent was thinking*. This reasoning context is exactly what's lost between sessions and what forces incoming agents to re-derive conclusions. + +**Adoption implication:** Extend the `/handoff` command to write structured traces. Add a freshness field (`valid_until` or `relevance_decay`) and implement cleanup in session-start hooks. + +### 4.5 Strategic Roadmaps + +**What it is:** Markdown files in `.agents/roadmaps/` that describe multi-session goals, phased delivery plans, and coordination protocols. + +**Why it matters:** Backlogs track individual tasks. Roadmaps provide the strategic frame that tells agents *why* tasks exist and how they fit together. An agent asked to "improve auth" can check the roadmap to know whether that means "patch the JWT bug" or "migrate to OAuth2 as part of the compliance initiative." + +**Adoption implication:** Add `.agents/roadmaps/` as a managed directory. Roadmaps should have lifecycle metadata (created, updated, status: active/completed/abandoned) and be referenced from the orchestrator state. + +--- + +## 5. Cross-Agent Ecosystem Implications + +### 5.1 Standardisation Opportunity + +The `.agents/` pattern is simple enough to become a cross-project convention. If formalised with a JSON Schema for guards and a directory layout spec, it could be adopted by any AI agent system — not just AgentKit Forge consumers. + +### 5.2 Lock-In Assessment + +| Component | Lock-in risk | Mitigation | +|---|---|---| +| `.agentkit/` sync engine | Medium — Node.js/pnpm dependency | Document the output format; allow alternative generators | +| `.agents/` hub | Low — plain markdown, no tooling dependency | Formalise the schema so other tools can generate/consume | +| `.claude/hooks/` | High — shell-specific, platform-specific | Generate from `.agents/guards/` so the canonical source is portable | +| `.readme.yaml` | Low — standard YAML | Publish a schema; align with existing conventions (`.devcontainer/`, `.editorconfig`) | + +### 5.3 Missing Capabilities (Neither Repo Addresses) + +1. **Agent capability declaration** — No mechanism for an agent to declare its tools, context window, or model capabilities for task routing +2. **Per-session cost attribution** — Cost rules exist but no measurement infrastructure +3. **Concurrent edit conflict resolution** — No protocol for when two agents modify the same file simultaneously +4. **Schema versioning** — No migration strategy when file formats evolve + +--- + +## 6. Recommendations + +| Priority | Action | Effort | Impact | +|---|---|---|---| +| **P0** | Adopt `.agents/` as sync output target | Medium | Enables tool-neutral agent discovery | +| **P0** | Resolve empty `.claude/agents/` category dirs | Low | Unblocks agent reorganisation | +| **P1** | Implement `.readme.yaml` generation | Low | Reduces token cost for project discovery | +| **P1** | Add guards to `.agents/guards/` with hook generation | Medium | Portable governance + automated enforcement | +| **P2** | Extend `/handoff` to write traces | Low | Preserves reasoning context across sessions | +| **P2** | Add roadmaps directory to state model | Low | Strategic context for multi-session work | +| **P3** | Formalise schemas (guards, traces, `.readme.yaml`) | Medium | Enables cross-project adoption | +| **P3** | Add retention policy for traces/history | Low | Prevents unbounded accumulation | diff --git a/docs/engineering/01_setup.md b/docs/engineering/01_setup.md index 11a28105..706a27d2 100644 --- a/docs/engineering/01_setup.md +++ b/docs/engineering/01_setup.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Development Setup ## Overview -Instructions for setting up a local development environment for agentkit-forge. +Instructions for setting up a local development environment for retort. ## Prerequisites @@ -22,7 +22,7 @@ Instructions for setting up a local development environment for agentkit-forge. ```bash # Clone the repository git clone <!-- REPO_URL --> -cd agentkit-forge +cd retort # Install dependencies pnpm install --frozen-lockfile diff --git a/docs/engineering/02_coding_standards.md b/docs/engineering/02_coding_standards.md index db652051..4aef4eb9 100644 --- a/docs/engineering/02_coding_standards.md +++ b/docs/engineering/02_coding_standards.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Coding Standards ## Overview -This document defines the coding standards and conventions for agentkit-forge. +This document defines the coding standards and conventions for retort. ## Language & Style diff --git a/docs/engineering/03_testing.md b/docs/engineering/03_testing.md index 0c7d706c..df586160 100644 --- a/docs/engineering/03_testing.md +++ b/docs/engineering/03_testing.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Testing Guide ## Overview -Testing strategy and conventions for agentkit-forge. +Testing strategy and conventions for retort. ## Test Pyramid diff --git a/docs/engineering/04_git_workflow.md b/docs/engineering/04_git_workflow.md index 6d8e40fa..3ab363de 100644 --- a/docs/engineering/04_git_workflow.md +++ b/docs/engineering/04_git_workflow.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Git Workflow ## Overview -Git branching strategy and contribution workflow for agentkit-forge. +Git branching strategy and contribution workflow for retort. ## Branch Strategy diff --git a/docs/engineering/05_security.md b/docs/engineering/05_security.md index 46b4ee19..bb69df4b 100644 --- a/docs/engineering/05_security.md +++ b/docs/engineering/05_security.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Security Practices ## Overview -Security guidelines and practices for agentkit-forge. +Security guidelines and practices for retort. ## Principles diff --git a/docs/engineering/06_pr_documentation.md b/docs/engineering/06_pr_documentation.md index 5e549210..16a365dc 100644 --- a/docs/engineering/06_pr_documentation.md +++ b/docs/engineering/06_pr_documentation.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # PR Documentation Strategy ## Overview -Standardized process for documenting completed PRs and implementations in agentkit-forge. +Standardized process for documenting completed PRs and implementations in retort. This ensures comprehensive historical context and effective knowledge transfer. ## When to Create Documentation diff --git a/docs/engineering/07_changelog.md b/docs/engineering/07_changelog.md index 1ace8889..bd2f675c 100644 --- a/docs/engineering/07_changelog.md +++ b/docs/engineering/07_changelog.md @@ -1,19 +1,19 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Changelog Best Practices & Tooling Guide ## Overview -This document covers changelog best practices adopted by agentkit-forge and +This document covers changelog best practices adopted by retort and the tooling options available for automating changelog maintenance. ## Principles ### Keep a Changelog Format -agentkit-forge follows [Keep a Changelog v1.1.0](https://keepachangelog.com/en/1.1.0/): +retort follows [Keep a Changelog v1.1.0](https://keepachangelog.com/en/1.1.0/): - All notable changes are documented in `CHANGELOG.md`. - Changes are grouped under: `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, `Security`. diff --git a/docs/engineering/08_code_quality_assessment.md b/docs/engineering/08_code_quality_assessment.md index 05c0c787..119e780a 100644 --- a/docs/engineering/08_code_quality_assessment.md +++ b/docs/engineering/08_code_quality_assessment.md @@ -1,6 +1,6 @@ # Code Quality Assessment: Refactoring, SOLID, DRY, Complexity & Class Size -> Comprehensive analysis of code quality practices in the agentkit-forge repository, +> Comprehensive analysis of code quality practices in the retort repository, > with language-specific baselines and actionable integration recommendations. --- @@ -18,7 +18,7 @@ ## 1. Executive Summary -AgentKit Forge is a Node.js (ESM) build-time framework that generates AI-tool +Retort is a Node.js (ESM) build-time framework that generates AI-tool configurations from YAML specs. The codebase is **well-structured** with strong foundations: comprehensive test coverage (23 test files for 24 source modules), CI/CD with drift checks, conventional commits, and an established rules system. @@ -160,11 +160,11 @@ The 30-second test timeout is a symptom of this coupling. ## 3. Language & Stack-Specific Baselines -AgentKit Forge's `teams.yaml` defines four tech stacks: **Node.js (JavaScript/TypeScript)**, **.NET (C#)**, **Rust**, and **Python**. The engine itself is pure JavaScript (ESM). Below are research-backed baselines for each. +Retort's `teams.yaml` defines four tech stacks: **Node.js (JavaScript/TypeScript)**, **.NET (C#)**, **Rust**, and **Python**. The engine itself is pure JavaScript (ESM). Below are research-backed baselines for each. ### 3.1 JavaScript / TypeScript (Node.js) -This is the **primary language** of the agentkit-forge engine. +This is the **primary language** of the retort engine. #### File & Class Size Targets @@ -662,7 +662,7 @@ provides unified dashboards with: Configuration via `sonar-project.properties`: ```properties -sonar.projectKey=agentkit-forge +sonar.projectKey=retort sonar.sources=.agentkit/engines/node/src sonar.tests=.agentkit/engines/node/src/__tests__ sonar.javascript.lcov.reportPaths=.agentkit/coverage/lcov.info diff --git a/docs/engineering/08_scaffold_management.md b/docs/engineering/08_scaffold_management.md index c600d448..baf2a20b 100644 --- a/docs/engineering/08_scaffold_management.md +++ b/docs/engineering/08_scaffold_management.md @@ -1,6 +1,6 @@ # Scaffold Management Guide -This guide explains how AgentKit Forge manages generated files, how drift detection +This guide explains how Retort manages generated files, how drift detection works, and how to control scaffold behavior for your project. ## What Are Scaffold Modes? @@ -23,7 +23,7 @@ Templates use YAML frontmatter to declare their mode: agentkit: scaffold: always --- -<!-- GENERATED by AgentKit Forge ... --> +<!-- GENERATED by Retort ... --> # My Template Content ``` @@ -155,7 +155,7 @@ If you've made improvements to a generated file that would benefit the template: 1. Modify the template in `.agentkit/templates/` 2. Run `pnpm -C .agentkit agentkit:sync` -3. Submit a PR to the agentkit-forge repository +3. Submit a PR to the retort repository ## Scaffold Cache diff --git a/docs/engineering/09_quality_framework_expansion_plan.md b/docs/engineering/09_quality_framework_expansion_plan.md index aa313b6e..0cb0d85f 100644 --- a/docs/engineering/09_quality_framework_expansion_plan.md +++ b/docs/engineering/09_quality_framework_expansion_plan.md @@ -1,6 +1,6 @@ # Strategic Plan: Code Quality Framework Expansion -> Expanding the agentkit-forge code quality assessment to cover TypeScript, HTML, +> Expanding the retort code quality assessment to cover TypeScript, HTML, > CSS, Bash, PowerShell, and their associated linting/testing ecosystems alongside > the already-documented JavaScript, Python, Rust, and C# stacks. @@ -162,7 +162,7 @@ type-aware analysis. | Framework | Role | Recommendation | | -------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Vitest** | Primary unit/integration | **Recommended primary.** Native ESM, TypeScript support via esbuild, API-compatible with Jest, fastest option for Vite-based projects. Already used by agentkit-forge itself. | +| **Vitest** | Primary unit/integration | **Recommended primary.** Native ESM, TypeScript support via esbuild, API-compatible with Jest, fastest option for Vite-based projects. Already used by retort itself. | | **Jest** | Legacy primary | **Secondary.** Still the most widely used; recommend for brownfield projects already using Jest. CJS-focused; ESM support requires configuration. | | **Playwright** | E2E testing | **Recommended for E2E.** Cross-browser, auto-wait, TypeScript-first. Already detected by discover.mjs. | | **Cypress** | Alternative E2E | **Secondary.** Excellent developer experience but limited to Chromium-based browsers for component testing. Already detected by discover.mjs. | @@ -310,7 +310,7 @@ variables, missing error handling) that cause the most shell script failures. Bash/shell scripts - **teams.yaml consideration:** Shell scripts are owned by the `devops` team. Not a separate techStack, but quality rules should apply to `.sh` files in scope. -- **CI integration:** Add ShellCheck to the CI pipeline for the agentkit-forge +- **CI integration:** Add ShellCheck to the CI pipeline for the retort repository itself (26 scripts currently unchecked). #### Recommended rules.yaml Conventions @@ -691,7 +691,7 @@ when the upstream specs and templates change: ### Phase 1: High-Impact, Low-Effort (Week 1-2) -These changes address real quality gaps in the agentkit-forge repository itself. +These changes address real quality gaps in the retort repository itself. | # | Action | Impact | Effort | Dependencies | | --- | -------------------------------------------------------------------------- | ---------- | ------ | -------------------------------------- | diff --git a/docs/engineering/12_package_management.md b/docs/engineering/12_package_management.md index a44ac448..4cbd9ff1 100644 --- a/docs/engineering/12_package_management.md +++ b/docs/engineering/12_package_management.md @@ -1,11 +1,11 @@ # Package Management Architecture -This guide explains how AgentKit Forge manages package dependencies, scripts, and +This guide explains how Retort manages package dependencies, scripts, and package managers across its two-layer architecture. ## Two-Layer Design -AgentKit Forge uses a two-layer package architecture: +Retort uses a two-layer package architecture: ``` ┌─────────────────────────────────────────────────────────┐ diff --git a/docs/engineering/13_template_system.md b/docs/engineering/13_template_system.md index b6613939..df0b3575 100644 --- a/docs/engineering/13_template_system.md +++ b/docs/engineering/13_template_system.md @@ -1,6 +1,6 @@ # Template System Guide -This guide explains how AgentKit Forge's template engine works, including scaffold +This guide explains how Retort's template engine works, including scaffold modes, frontmatter, three-way merge, and the rendering pipeline. ## Template Rendering Pipeline diff --git a/docs/engineering/14_brand_theming.md b/docs/engineering/14_brand_theming.md index 8fcccd28..75796cc7 100644 --- a/docs/engineering/14_brand_theming.md +++ b/docs/engineering/14_brand_theming.md @@ -1,6 +1,6 @@ # Brand & Theming Guide -This guide explains how AgentKit Forge generates editor themes and design tokens +This guide explains how Retort generates editor themes and design tokens from the brand specification. ## Brand Spec Structure diff --git a/docs/engineering/README.md b/docs/engineering/README.md index 9deaffc9..2fb206da 100644 --- a/docs/engineering/README.md +++ b/docs/engineering/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Engineering Docs Index diff --git a/docs/engineering/doc-audit-command-proposal.md b/docs/engineering/doc-audit-command-proposal.md index 972eb04f..18b0d527 100644 --- a/docs/engineering/doc-audit-command-proposal.md +++ b/docs/engineering/doc-audit-command-proposal.md @@ -2,7 +2,7 @@ > **Status**: Proposed > **Date**: 2026-03-04 -> **Purpose**: Add a repeatable documentation audit command to agentkit-forge +> **Purpose**: Add a repeatable documentation audit command to retort --- @@ -73,7 +73,7 @@ You are a documentation specialist performing a **systematic audit** of this pro 1. **Read before judging.** Always read the actual file content — never assume from filenames. 2. **Cross-reference the specs.** The source of truth for commands, agents, and teams lives in `.agentkit/spec/`. Compare published docs against spec YAML. -3. **Respect generated files.** Files marked `GENERATED by AgentKit Forge — DO NOT EDIT` should only be flagged if they are out of sync with their spec — never edit them directly. +3. **Respect generated files.** Files marked `GENERATED by Retort — DO NOT EDIT` should only be flagged if they are out of sync with their spec — never edit them directly. 4. **Prioritize impact.** A missing API doc is higher priority than a typo in a deep reference page. 5. **Use finding IDs.** Prefix findings with `DOC-GAP-*` (missing), `DOC-STALE-*` (outdated), `DOC-LINK-*` (broken link), `DOC-DRIFT-*` (spec/doc mismatch), `DOC-DUP-*` (duplicate/conflicting). diff --git a/docs/engineering/reviews/cicd-implementation-plan.md b/docs/engineering/reviews/cicd-implementation-plan.md index 4e62d1ad..bfcd5a32 100644 --- a/docs/engineering/reviews/cicd-implementation-plan.md +++ b/docs/engineering/reviews/cicd-implementation-plan.md @@ -29,7 +29,7 @@ Adopt the `[Category] Description` pattern for all workflow `name:` fields. This | -------------------------------- | -------------------------- | ------------------------------------- | ---------- | | `ci.yml` | `CI` | `[CI] Test & Validate` | CI | | `branch-protection.yml` | `Branch Protection` | `[Governance] Branch Rules` | Governance | -| `block-agentkit-changes.yml` | `block-agentkit-changes` | `[Governance] Block AgentKit Changes` | Governance | +| `block-agentkit-changes.yml` | `block-agentkit-changes` | `[Governance] Block Retort Changes` | Governance | | `template-protection.yml` | `Template Protection` | `[Framework] Template Protection` | Framework | | `codeql.yml` | `CodeQL` | `[Security] CodeQL Analysis` | Security | | `semgrep.yml` | `Semgrep (Advisory)` | `[Security] Semgrep Scan` | Security | @@ -45,7 +45,7 @@ Renaming workflows changes the status check names used by branch protection. All - `"CI / test (ubuntu-latest, 24)"` → `"[CI] Test & Validate / test (ubuntu-latest, 24)"` - `"CI / validate"` → `"[CI] Test & Validate / validate"` - `"Branch Protection / branch-rules"` → `"[Governance] Branch Rules / branch-rules"` - - `"block-agentkit-changes / check_agentkit_changes"` → `"[Governance] Block AgentKit Changes / check-agentkit-changes"` + - `"block-agentkit-changes / check_agentkit_changes"` → `"[Governance] Block Retort Changes / check-agentkit-changes"` 2. **`.agentkit/templates/github/scripts/setup-branch-protection.sh`** — update the generated template's `contexts` array similarly @@ -175,7 +175,7 @@ Update the sync engine to generate `a2a-config.json` agent capabilities from `te Extract the repeated pnpm + Node + install pattern into a reusable composite action: ```yaml -name: Setup AgentKit +name: Setup Retort description: Install pnpm, Node.js, and agentkit dependencies inputs: node-version: diff --git a/docs/engineering/reviews/cicd-infrastructure-review-2026-03-04.md b/docs/engineering/reviews/cicd-infrastructure-review-2026-03-04.md index 163d10db..ebb8bb74 100644 --- a/docs/engineering/reviews/cicd-infrastructure-review-2026-03-04.md +++ b/docs/engineering/reviews/cicd-infrastructure-review-2026-03-04.md @@ -7,7 +7,7 @@ ## Executive Summary -AgentKit Forge has a well-structured CI/CD foundation with 8 GitHub Actions workflows, comprehensive branch governance, and a powerful spec-driven generation pipeline. However, there are **meaningful gaps between the CI/CD infrastructure and the agentic workforce it supports**. The workflows validate the _forge itself_ but don't yet generate CI/CD that exercises the full agent team model, and several hardening opportunities exist in the existing pipelines. +Retort has a well-structured CI/CD foundation with 8 GitHub Actions workflows, comprehensive branch governance, and a powerful spec-driven generation pipeline. However, there are **meaningful gaps between the CI/CD infrastructure and the agentic workforce it supports**. The workflows validate the _forge itself_ but don't yet generate CI/CD that exercises the full agent team model, and several hardening opportunities exist in the existing pipelines. This review identifies **28 findings** organized into 4 categories: diff --git a/docs/history/README.md b/docs/history/README.md index ecab947d..0cce2880 100644 --- a/docs/history/README.md +++ b/docs/history/README.md @@ -1,10 +1,10 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # History -Historical documentation for significant PRs and implementations in agentkit-forge. +Historical documentation for significant PRs and implementations in retort. ## Directory Structure diff --git a/docs/history/bug-fixes/0001-2026-03-04-infra-eval-review-fixes-bugfix.md b/docs/history/bug-fixes/0001-2026-03-04-infra-eval-review-fixes-bugfix.md index cc344d2a..e839f662 100644 --- a/docs/history/bug-fixes/0001-2026-03-04-infra-eval-review-fixes-bugfix.md +++ b/docs/history/bug-fixes/0001-2026-03-04-infra-eval-review-fixes-bugfix.md @@ -67,7 +67,7 @@ These were review-stage findings caught before merge. No user impact. The drift ## Lessons Learned 1. **Sync-then-verify discipline**: Spec changes and sync output must be committed together. A CI drift check exists but wasn't catching this because it ran on the generated output dir, not the agent files. -2. **Template protection hook awareness**: The `protect-templates.sh` PreToolUse hook blocks Edit/Write tools on `.agentkit/` paths. When working in the agentkit-forge repo itself (not an adopting repo), Bash `sed` is the workaround, but this is fragile and should be documented. +2. **Template protection hook awareness**: The `protect-templates.sh` PreToolUse hook blocks Edit/Write tools on `.agentkit/` paths. When working in the retort repo itself (not an adopting repo), Bash `sed` is the workaround, but this is fragile and should be documented. 3. **Step numbering cascades**: Handlebars conditional numbering creates a maintenance burden — every step after a conditional insert must also be conditional. Consider using ordered lists (`1.` repeated) in Markdown instead, which auto-number. --- diff --git a/docs/history/bug-fixes/README.md b/docs/history/bug-fixes/README.md index 21146d8f..366e8d49 100644 --- a/docs/history/bug-fixes/README.md +++ b/docs/history/bug-fixes/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Bug Fixes diff --git a/docs/history/bug-fixes/TEMPLATE-bugfix.md b/docs/history/bug-fixes/TEMPLATE-bugfix.md index dc63ca8f..07938299 100644 --- a/docs/history/bug-fixes/TEMPLATE-bugfix.md +++ b/docs/history/bug-fixes/TEMPLATE-bugfix.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # [Bug Description] Resolution - Historical Summary diff --git a/docs/history/features/README.md b/docs/history/features/README.md index 9a4c6080..3d63abeb 100644 --- a/docs/history/features/README.md +++ b/docs/history/features/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Features diff --git a/docs/history/features/TEMPLATE-feature.md b/docs/history/features/TEMPLATE-feature.md index cb3075b7..caaaa905 100644 --- a/docs/history/features/TEMPLATE-feature.md +++ b/docs/history/features/TEMPLATE-feature.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # [Feature Name] Launch - Historical Summary diff --git a/docs/history/implementations/0001-2026-03-01-origin-main-merge-reconciliation-implementation.md b/docs/history/implementations/0001-2026-03-01-origin-main-merge-reconciliation-implementation.md index 93b3b5f5..b74c715e 100644 --- a/docs/history/implementations/0001-2026-03-01-origin-main-merge-reconciliation-implementation.md +++ b/docs/history/implementations/0001-2026-03-01-origin-main-merge-reconciliation-implementation.md @@ -3,7 +3,7 @@ **Completed**: 2026-03-01 **Duration**: Multi-session merge and validation pass **Status**: ✅ **Near completion — verification pending** -**PR**: [#72](https://github.com/phoenixvc/agentkit-forge/pull/72) ⚡ optimize sync command with async I/O and concurrency +**PR**: [#72](https://github.com/phoenixvc/retort/pull/72) ⚡ optimize sync command with async I/O and concurrency ## Overview @@ -88,7 +88,7 @@ Merge was completed without unresolved conflicts, and critical paths were valida ## Related Documentation - **Merge Matrix**: `MERGE_RESOLUTION_MATRIX.md` -- **PR**: <https://github.com/phoenixvc/agentkit-forge/pull/72> +- **PR**: <https://github.com/phoenixvc/retort/pull/72> --- diff --git a/docs/history/implementations/0001-2026-03-20-kit-based-domain-selection-and-onboarding-redesign-implementation.md b/docs/history/implementations/0001-2026-03-20-kit-based-domain-selection-and-onboarding-redesign-implementation.md new file mode 100644 index 00000000..fb5c6268 --- /dev/null +++ b/docs/history/implementations/0001-2026-03-20-kit-based-domain-selection-and-onboarding-redesign-implementation.md @@ -0,0 +1,86 @@ +# Kit-Based Domain Selection and Onboarding Redesign — Implementation + +**Completed**: 2026-03-20 +**Duration**: 2 sessions +**Status**: ✅ **SUCCESSFULLY COMPLETED** +**PR**: #432 — `feat/kit-domain-selection-onboarding` + +## Overview + +Retort was generating rules, agents, and commands for all 16 domains regardless of the +adopter's tech stack. A TypeScript-only project received dotnet, rust, python, and blockchain +rules it would never use. This implementation adds stack-aware domain filtering, an interactive +init wizard, a CLI-spec parity validator, and resolves the agentkit-forge → retort identity +rename. + +## Key Changes + +| Commit | Change | +|--------|--------| +| `chore(spec)` | Renamed `agentkit-forge` → `retort` across all 10 spec YAML files | +| `feat(engine)` | `filterDomainsByStack()` + `filterTechStacks()` in `template-utils.mjs` + `synchronize.mjs` | +| `feat(engine)` | 16 fixture-based generation tests in `__tests__/generation.test.mjs` | +| `feat(init)` | Interactive kit wizard with dry-run mode, stack detection, optional kit selection | +| `fix(hooks)` | Truncate `run_check()` output to prevent `jq: Argument list too long` (ARG_MAX crash) | +| `perf(hooks)` | Stop hook: removed full sync + full test suite; lint-only per stack | +| `perf(hooks)` | Changed-files gating — hook costs <0.1s when nothing relevant changed | +| `feat(validate)` | Phase 10 CLI-spec parity check in `validate.mjs` | +| `chore(spec)` | `skills.yaml` spec for skill distribution model | +| `docs` | TRAE compatibility audit stub — `docs/integrations/trae-compatibility.md` | + +## Implementation Approach + +### Phase 1 — Identity rename +Replaced all 16 `agentkit-forge` references in `.agentkit/spec/` with `retort`. + +### Phase 2+3 — Domain filtering +Added `filterDomainsByStack(rules, vars, project)` and `filterTechStacks(stacks, vars)` to +`template-utils.mjs`. Applied at all domain generation call sites in `synchronize.mjs`. +`languageProfile.mode: heuristic` preserves backward-compatible all-domains behaviour. + +### Phase 4 — Init wizard +`init.mjs` now runs an interactive flow: detect stack → show active kits → prompt for +opt-in extras → write `project.yaml` → run sync → validate. `--dry-run` shows the plan +without writing. + +### Phase 6 — Generation tests +4 fixture scenarios (`js-only`, `fullstack`, `explicit-domains`, `heuristic`) assert the +correct domains appear/are absent after a sync run. + +### Stop hook fixes (cross-cutting) +- ARG_MAX fix: `run_check()` truncates output to 3000 chars before passing to `jq --arg` +- Performance: replaced 30s+ drift sync + full test suite with lightweight `git diff` warn + and lint-only checks; changed-files gating skips all checks when nothing relevant changed + +### Phase 5 — Issue tracking +- Issue 006: `validate.mjs` Phase 10 CLI-spec parity; all checkboxes closed +- Issue 040: elegance-guidelines sync compatibility; final checkbox closed +- `/cicd-optimize` command added to `commands.yaml` +- `init` added as `type: framework`; `FRAMEWORK_COMMANDS` documented + +## Results + +- **Stop hook**: worst-case 277s → <5s; unchanged-code path <0.1s +- **Domain noise**: JS-only projects now receive 9 domains instead of 16 +- **Test suite**: 1243 tests, all passing (1 skipped Prettier formatting check) +- **Issues closed**: 006 (fully), 040 (fully) +- **Identity**: zero `agentkit-forge` references remain in `.agentkit/spec/` + +## Deferred + +- **TRAE format audit** (Issues 025/026/027): requires WebFetch — blocked this session. + Tracking doc at `docs/integrations/trae-compatibility.md` with 4 URLs and audit questions. + +## Lessons Learned + +- `jq --arg` silently fails on ARG_MAX-sized strings — truncate before passing +- Stop hooks must be <5s to avoid blocking interactive sessions; test suites are never appropriate +- Changed-files gating is the right pattern for all language checks in stop hooks +- `languageProfile.mode` as a three-way switch (heuristic / hybrid / configured) gives + clean backward-compat story for domain filtering + +--- + +**Implementation Team**: Claude Sonnet 4.6 + JustAGhosT +**Review Status**: PR #432 open, pending merge +**Next Steps**: Merge PR #432; TRAE audit in next session with web access diff --git a/docs/history/implementations/0002-2026-03-01-sync-test-performance-stabilization-implementation.md b/docs/history/implementations/0002-2026-03-01-sync-test-performance-stabilization-implementation.md index 34938d76..f70ddade 100644 --- a/docs/history/implementations/0002-2026-03-01-sync-test-performance-stabilization-implementation.md +++ b/docs/history/implementations/0002-2026-03-01-sync-test-performance-stabilization-implementation.md @@ -89,7 +89,7 @@ Sync integration suite became stable and significantly faster in hotspot cases w ## Related Documentation -- **PR**: <https://github.com/phoenixvc/agentkit-forge/pull/72> +- **PR**: <https://github.com/phoenixvc/retort/pull/72> - **Engine Source**: `.agentkit/engines/node/src/synchronize.mjs` - **Tests**: `.agentkit/engines/node/src/__tests__/sync-integration.test.mjs` diff --git a/docs/history/implementations/0003-2026-03-01-post-history-ci-and-config-stabilization-implementation.md b/docs/history/implementations/0003-2026-03-01-post-history-ci-and-config-stabilization-implementation.md index aca1de06..67dfe0df 100644 --- a/docs/history/implementations/0003-2026-03-01-post-history-ci-and-config-stabilization-implementation.md +++ b/docs/history/implementations/0003-2026-03-01-post-history-ci-and-config-stabilization-implementation.md @@ -3,7 +3,7 @@ **Completed**: 2026-03-01 **Duration**: Multi-pass validation and corrective updates **Status**: ✅ **SUCCESSFULLY COMPLETED** -**PR**: [#72](https://github.com/phoenixvc/agentkit-forge/pull/72) ⚡ optimize sync command with async I/O and concurrency +**PR**: [#72](https://github.com/phoenixvc/retort/pull/72) ⚡ optimize sync command with async I/O and concurrency ## Overview @@ -70,7 +70,7 @@ This phase restored CI alignment and reduced recurrence risk for test and genera - **Previous baseline**: `docs/history/implementations/0001-2026-03-01-origin-main-merge-reconciliation-implementation.md` - **Previous baseline**: `docs/history/implementations/0002-2026-03-01-sync-test-performance-stabilization-implementation.md` -- **PR**: <https://github.com/phoenixvc/agentkit-forge/pull/72> +- **PR**: <https://github.com/phoenixvc/retort/pull/72> --- diff --git a/docs/history/implementations/0004-2026-03-04-infra-eval-template-integration-implementation.md b/docs/history/implementations/0004-2026-03-04-infra-eval-template-integration-implementation.md index bd66d645..ab600188 100644 --- a/docs/history/implementations/0004-2026-03-04-infra-eval-template-integration-implementation.md +++ b/docs/history/implementations/0004-2026-03-04-infra-eval-template-integration-implementation.md @@ -67,7 +67,7 @@ The `/infra-eval` command is now available to any project that sets `evaluation. 1. **Handlebars conditional numbering is brittle**: When inserting a conditionally-numbered step in a Markdown ordered list, every subsequent step must also be conditionalized. This creates a maintenance cascade. A better pattern would be to use Markdown auto-numbering (all steps as `1.`) or to restructure the template to isolate conditional sections. -2. **Template protection hook blocks the forge repo too**: The `protect-templates.sh` hook doesn't distinguish between "adopting repo" and "the agentkit-forge repo itself." When developing templates in the forge repo, the hook blocks Edit/Write tools, forcing the use of Bash `sed` as a workaround. This is by design (protects against accidental edits) but should be documented in the contributing guide. +2. **Template protection hook blocks the forge repo too**: The `protect-templates.sh` hook doesn't distinguish between "adopting repo" and "the retort repo itself." When developing templates in the forge repo, the hook blocks Edit/Write tools, forcing the use of Bash `sed` as a workaround. This is by design (protects against accidental edits) but should be documented in the contributing guide. 3. **Event schema must be centrally registered**: Defining a new event type in a command template without adding it to the orchestrator's enum creates a silent inconsistency. The orchestrator won't recognize the event. Consider adding a spec-level validation that cross-references event types across command templates. diff --git a/docs/history/implementations/0005-2026-03-06-cost-management-plan-implementation.md b/docs/history/implementations/0005-2026-03-06-cost-management-plan-implementation.md index 99bd4d5f..3792ca2a 100644 --- a/docs/history/implementations/0005-2026-03-06-cost-management-plan-implementation.md +++ b/docs/history/implementations/0005-2026-03-06-cost-management-plan-implementation.md @@ -1,7 +1,7 @@ # Cost Management Infrastructure — Comprehensive Plan > **Context**: Recent incident where agent usage spiraled out of control. -> **Scope**: Three repos — `agentkit-forge` (spec/templates), `ai-gateway` (runtime), `pvc-costops-analytics` (FinOps analytics). +> **Scope**: Three repos — `retort` (spec/templates), `ai-gateway` (runtime), `pvc-costops-analytics` (FinOps analytics). > **Goal**: Unified cost governance spanning AI agent usage, Azure infrastructure, and resource group budgeting. --- @@ -12,16 +12,16 @@ | Capability | Repo | Status | Gap | | -------------------------------------------------------- | --------------------- | ---------------------------- | ----------------------------------------------------------- | -| Session cost tracking (duration, commands, files) | agentkit-forge | Implemented | Observation-only — no enforcement | -| Budget-guard module (circuit breaker) | agentkit-forge | **Just added** (this branch) | Not wired to hooks, no tests, no CLI integration | -| `/cost` CLI command | agentkit-forge | Implemented | Reports only — no limits | -| `/infra-eval` with cost dimension (16% weight) | agentkit-forge | Implemented | Evaluation-only — no remediation | -| `infra` agent with cost-optimization responsibility | agentkit-forge | Defined | Generic — not specialized for cost governance | -| FinOps integration spec (FINOPS_AGENTKIT_INTEGRATION.md) | agentkit-forge | Documented | Phase 1 spec exists but not implemented in templates | +| Session cost tracking (duration, commands, files) | retort | Implemented | Observation-only — no enforcement | +| Budget-guard module (circuit breaker) | retort | **Just added** (this branch) | Not wired to hooks, no tests, no CLI integration | +| `/cost` CLI command | retort | Implemented | Reports only — no limits | +| `/infra-eval` with cost dimension (16% weight) | retort | Implemented | Evaluation-only — no remediation | +| `infra` agent with cost-optimization responsibility | retort | Defined | Generic — not specialized for cost governance | +| FinOps integration spec (FINOPS_AGENTKIT_INTEGRATION.md) | retort | Documented | Phase 1 spec exists but not implemented in templates | | AI Gateway with rate limiting | ai-gateway | Deployed | No budget caps, no usage telemetry export, no chargeback | | Azure Container Apps (scale-to-zero) | ai-gateway | Deployed | No Azure Budget resources in Terraform | | ADX cost analytics (KQL, Grafana) | pvc-costops-analytics | Partial | Private repo; Phase 1 spec defined but checklist incomplete | -| pvc-costops-analytics overlay | agentkit-forge | Scaffolded | Empty — no rules, commands, or cost config | +| pvc-costops-analytics overlay | retort | Scaffolded | Empty — no rules, commands, or cost config | ### 1.2 What Caused the Spiral @@ -39,9 +39,9 @@ Building on the existing model from `FINOPS_AGENTKIT_INTEGRATION.md`: | Concern | Primary Repo | What It Owns | | ---------------------------------------------- | ----------------------- | ----------------------------------------------------------------- | -| **Budget policy schema & enforcement engine** | `agentkit-forge` | `budget-guard.mjs`, policy config in `settings.yaml`, hook wiring | -| **Agent session cost tracking** | `agentkit-forge` | `cost-tracker.mjs`, `/cost` command, session JSONL logs | -| **FinOps methodology & templates** | `agentkit-forge` | Rules, Phase 1 spec template, overlay config for FinOps repos | +| **Budget policy schema & enforcement engine** | `retort` | `budget-guard.mjs`, policy config in `settings.yaml`, hook wiring | +| **Agent session cost tracking** | `retort` | `cost-tracker.mjs`, `/cost` command, session JSONL logs | +| **FinOps methodology & templates** | `retort` | Rules, Phase 1 spec template, overlay config for FinOps repos | | **Cost centre / resource group management UX** | `pvc-costops-analytics` | ADX tables, KQL functions, Grafana dashboards, cost centre CRUD | | **Azure Budget resources (IaC)** | `ai-gateway` | Terraform `azurerm_consumption_budget_*` in infra/modules | | **Gateway usage metering & telemetry** | `ai-gateway` | Request logging, token counting, usage export to ADX | @@ -105,7 +105,7 @@ This is handled by the existing template rendering pipeline — no new agent nee --- -## Part 4: Implementation Plan — agentkit-forge +## Part 4: Implementation Plan — retort ### 4.1 Complete Budget-Guard Module (budget-guard.mjs) @@ -445,7 +445,7 @@ unbudgeted_resources(_since) — Resources not in any cost centre ## Part 7: Template & Integration Changes Summary -### 7.1 agentkit-forge Changes (This PR) +### 7.1 retort Changes (This PR) | File | Change | Priority | | ------------------------------------------------------------ | --------------------------------------------- | -------- | diff --git a/docs/history/implementations/0007-2026-03-06-standardize-github-issues-implementation.md b/docs/history/implementations/0007-2026-03-06-standardize-github-issues-implementation.md index eaf01567..6e2496ba 100644 --- a/docs/history/implementations/0007-2026-03-06-standardize-github-issues-implementation.md +++ b/docs/history/implementations/0007-2026-03-06-standardize-github-issues-implementation.md @@ -8,7 +8,7 @@ ## Problem Statement -When adopting AgentKit Forge into an existing repository, GitHub issues (and +When adopting Retort into an existing repository, GitHub issues (and potentially Linear issues) already exist in various formats, labels, and states. There is no automated mechanism to: diff --git a/docs/history/implementations/0008-2026-03-17-linear-workspace-setup-implementation.md b/docs/history/implementations/0008-2026-03-17-linear-workspace-setup-implementation.md new file mode 100644 index 00000000..06fa26c0 --- /dev/null +++ b/docs/history/implementations/0008-2026-03-17-linear-workspace-setup-implementation.md @@ -0,0 +1,126 @@ +# Linear PhoenixVC Workspace Setup - Historical Summary + +**Completed**: 2026-03-17 +**Duration**: Single session (~2 hours) +**Status**: ✅ **SUCCESSFULLY COMPLETED** (with pending manual items) +**PR**: N/A — Configuration-only, no code changes + +## Overview + +Set up the Linear PhoenixVC workspace with 7 sub-teams, label-based routing, issue templates, workflow automations, auto-triage via Tembo, and a Notion intake agent. This creates a structured workflow where new issues are automatically enriched with context (codebase, Notion, Sentry), labeled, prioritized, and routed to the appropriate team for action. + +## Implementation Summary + +### Projects/Components Affected + +- ✅ **Linear PhoenixVC Workspace** — 7 sub-teams created with distinct purposes +- ✅ **Label System** — 2 label groups (Routing + Type) with 13 labels total +- ✅ **Issue Templates** — 8 templates at workspace level with default properties +- ✅ **Workflow Automations** — PR-to-status mapping, auto-close stale issues +- ✅ **Tembo Auto-Triage** — "Enrich Linear Issue" automation with routing logic +- ✅ **Notion Intake Agent** — Automated Notion → Linear filing with research, dedup, and routing +- ✅ **Issue Statuses** — 6 custom statuses added (Investigating, Findings Ready, Testing, Waiting, Passed, Failed) + +### Key Changes Made + +1. **Team Structure** — Created Coding (COD), Research (RES), QA (QA), Ops (OPS), Design (DES), Docs (DOC), Support (SUP) as sub-teams under PhoenixVC (PHO) +2. **Label-Based Routing** — Each ticket gets 1 Routing label (determines team) + 1 Type label (Bug/Feature/Improvement/chore) +3. **Auto-Triage via Tembo** — Claude Code Opus 4.6 agent enriches every new issue and applies routing labels + moves to correct team +4. **Templates with Defaults** — Each template auto-sets Team and Labels via default properties +5. **Triage Enabled** — All teams have triage enabled, assigned to Jurie Smit +6. **Workspace Agent Guidance** — Drafted instructions for Linear's AI agents section + +### Issues Resolved + +- **No routing system**: Previously, all issues landed in one bucket with no clear assignment → Now label-based routing auto-assigns to teams +- **No agent differentiation**: Unclear which AI agent to use for what → Now Codex/Cursor/Copilot for coding, Tembo/ChatGPT/Solo for research, Stilla for design +- **No enrichment**: Issues created with minimal context → Tembo now enriches with codebase/Notion/Sentry context + +## Implementation Approach + +### Phase 1: Team & Label Design + +Analyzed available Linear integrations (8 agents, 30+ available). Designed 5 teams based on work type, not tool type. Created label groups for routing and classification. + +### Phase 2: Configuration + +Created teams, labels (via GraphQL API — some worked, some required manual creation), statuses (added to parent team for inheritance), and templates (workspace level with default properties). + +### Phase 3: Automation + +Extended existing Tembo "Enrich Linear Issue" automation to also apply routing labels, type labels, priority, and move issues to the correct team. + +## Results + +### Configuration + +- **Teams**: 7 sub-teams + 1 parent = 8 total +- **Labels**: 13 workspace-level labels in 2 groups +- **Templates**: 8 issue templates with default properties +- **Statuses**: 14 total (8 default + 6 custom) +- **Automations**: PR→status mapping, auto-close stale, Tembo enrichment + routing + +### Agent Assignment + +| Team | Primary Agents | +|------|---------------| +| Coding | Codex (autonomous), Cursor (interactive), GitHub Copilot (PR gen) | +| Research | Tembo (orchestrator), ChatGPT (deep research), Solo (codebase Q&A) | +| QA | Ranger (recommended), Tusk (recommended) — not yet enabled | +| Ops | GitHub integration (broken auth) | +| Design | Stilla (meeting context + drafts) | +| Docs | Claude Code, Notion AI | +| Support | Intercom (MCP), ChatGPT | + +## Lessons Learned + +### Technical Insights + +- Linear sub-teams cannot have their own workflow states — they inherit from the parent team +- Linear's MCP OAuth connects to whichever workspace you select during auth flow — re-auth needed to switch workspaces +- Label groups should be created at workspace level, not team level, for cross-team visibility +- Tembo's "Auto" repo setting can cause wrong-repo context — use explicit repo selection + +### Process Improvements + +- Templates with default properties (Team + Labels) reduce manual routing to zero +- Every ticket needs exactly 2 labels (1 routing + 1 type) for the system to work +- Cost awareness: Opus 4.6 for every new issue is expensive — Sonnet is sufficient for enrichment + +### Best Practices Established + +- Create labels at workspace level with descriptive group names +- Use templates' default properties to auto-route, not workflow automations +- Keep team count small (7) — more teams = more routing complexity +- Single triage owner (human) as safety net until automation is proven + +## Future Considerations + +- Enable Ranger and Tusk agents for QA team when budget allows +- Fix GitHub integration auth in Tembo for Auto Fix CI, Enrich GitHub Issue, PR Review automations +- Switch Tembo agent from Opus to Sonnet for cost reduction +- Re-authorize Linear MCP plugin to PhoenixVC workspace +- Evaluate whether to add CodeRabbit for automated PR reviews +- Consider adding priority-based assignment within teams (e.g., Urgent bugs → Codex for speed) + +## Pending Manual Items + +- [ ] Revoke "Claude MCP key" Linear API key (shared in chat) +- [ ] Fix GitHub auth in Tembo +- [ ] Change Tembo repo from "Auto" to explicit +- [ ] Paste workspace agent guidance into Linear Settings → Agents +- [ ] Change stale close from 6 months to 3 months +- [ ] Enable auto-close parent issues +- [ ] Re-authorize Linear MCP to PhoenixVC workspace + +## Related Documentation + +- **Session Memory**: `~/.claude/projects/.../memory/MEMORY.md` — Linear section added +- **MCP Knowledge Graph**: 12 entities + 11 relations saved covering full workspace config +- **Notion Intake Agent**: `docs/integrations/04_notion-linear-intake-agent.md` — Full agent instructions + +--- + +**Implementation Team**: Claude Code + Jurie Smit (manual UI config) +**Review Status**: Operational — Tembo enrichment running, routing labels created +**Next Steps**: Fix GitHub auth in Tembo, revoke exposed API key, switch to Sonnet model diff --git a/docs/history/implementations/README.md b/docs/history/implementations/README.md index 7ebdcca2..c4e567cb 100644 --- a/docs/history/implementations/README.md +++ b/docs/history/implementations/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Implementations diff --git a/docs/history/implementations/TEMPLATE-implementation.md b/docs/history/implementations/TEMPLATE-implementation.md index 43a64634..8f1dcb74 100644 --- a/docs/history/implementations/TEMPLATE-implementation.md +++ b/docs/history/implementations/TEMPLATE-implementation.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # [Feature/Change Name] Implementation - Historical Summary diff --git a/docs/history/issues/README.md b/docs/history/issues/README.md index a969007d..b7cd22f2 100644 --- a/docs/history/issues/README.md +++ b/docs/history/issues/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Issues diff --git a/docs/history/issues/TEMPLATE-issue.md b/docs/history/issues/TEMPLATE-issue.md index 58f7b75b..818b5cd3 100644 --- a/docs/history/issues/TEMPLATE-issue.md +++ b/docs/history/issues/TEMPLATE-issue.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # [Issue Title] - Issue Record diff --git a/docs/history/lessons-learned/README.md b/docs/history/lessons-learned/README.md index 2eaf3812..d6714a1c 100644 --- a/docs/history/lessons-learned/README.md +++ b/docs/history/lessons-learned/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Lessons Learned diff --git a/docs/history/lessons-learned/TEMPLATE-lesson.md b/docs/history/lessons-learned/TEMPLATE-lesson.md index 2a7eb9f6..54771cf8 100644 --- a/docs/history/lessons-learned/TEMPLATE-lesson.md +++ b/docs/history/lessons-learned/TEMPLATE-lesson.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # [Lesson Title] - Lesson Learned diff --git a/docs/history/migrations/README.md b/docs/history/migrations/README.md index a2f107b5..23c2d78c 100644 --- a/docs/history/migrations/README.md +++ b/docs/history/migrations/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Migrations diff --git a/docs/history/migrations/TEMPLATE-migration.md b/docs/history/migrations/TEMPLATE-migration.md index 6cbcb6dc..0025fbc9 100644 --- a/docs/history/migrations/TEMPLATE-migration.md +++ b/docs/history/migrations/TEMPLATE-migration.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # [Migration Name] - Historical Summary diff --git a/docs/integrations/01_external_apis.md b/docs/integrations/01_external_apis.md index 66f81771..4ceccf79 100644 --- a/docs/integrations/01_external_apis.md +++ b/docs/integrations/01_external_apis.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # External APIs ## Overview -This document catalogues the external APIs that agentkit-forge integrates with. +This document catalogues the external APIs that retort integrates with. ## Integration Inventory diff --git a/docs/integrations/02_webhooks.md b/docs/integrations/02_webhooks.md index f489153d..69d77092 100644 --- a/docs/integrations/02_webhooks.md +++ b/docs/integrations/02_webhooks.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Webhooks ## Overview -<!-- Describe the webhook system for agentkit-forge — both inbound and outbound. --> +<!-- Describe the webhook system for retort — both inbound and outbound. --> ## Outbound Webhooks diff --git a/docs/integrations/03_sdk.md b/docs/integrations/03_sdk.md index 578259bb..aa7c0ee1 100644 --- a/docs/integrations/03_sdk.md +++ b/docs/integrations/03_sdk.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # SDK Guide ## Overview -<!-- Describe available SDKs and client libraries for the agentkit-forge API. --> +<!-- Describe available SDKs and client libraries for the retort API. --> ## Available SDKs diff --git a/docs/integrations/04_notion-linear-intake-agent.md b/docs/integrations/04_notion-linear-intake-agent.md new file mode 100644 index 00000000..f5450196 --- /dev/null +++ b/docs/integrations/04_notion-linear-intake-agent.md @@ -0,0 +1,168 @@ +# Notion → Linear Intake Agent Instructions + +**Last updated**: 2026-03-17 +**Platform**: Notion Automation (AI agent) +**Trigger**: New item added to Linear Intake database +**Workspace**: PhoenixVC (Linear) ↔ PhoenixVC (Notion) + +--- + +## 📖 Overview + +When a new item is added to **Linear Intake**, you must ensure it ends up in exactly one place: + +- A **Linear issue** in the correct sub-team (then mark the intake item as **Filed**), or +- **Backlog** (if it should be tracked but not filed to Linear yet), or +- **Rejections** (if it should not be tracked). + +**Rule:** Nothing may remain in Intake after you process it. + +--- + +## ✅ What to do when triggered + +### Step 1 — Read the intake item + +Read the new page's properties and content: + +- Issue Title +- Type (Bug, Feature, Improvement, chore) +- Priority +- Area, Components, Environment +- Project (which repo/product this relates to) +- Linked PR +- Any text in the page body +- Any Attachments + +### Step 2 — Gather context + +- If **Linked PR** exists, open it and extract relevant details (error messages, stack traces, affected area). +- If **Attachments** exist, open them when possible and extract relevant details. +- Search within **Linear Intake** and **Backlog** for similar items (same or very similar title). +- In Linear, search for likely duplicates by title and key terms. + +### Step 3 — Ask if unclear + +If key information is missing or the filing decision is ambiguous, **ask clarifying questions instead of guessing**. + +Examples of when to ask: + +- Unclear expected vs actual behavior +- Missing repro steps +- Missing environment +- Unclear impact or severity +- Unclear whether it is a bug vs feature +- Cannot determine which project/repo it belongs to + +### Step 4 — Create the Linear issue + +Use the best available mapping from the intake item: + +**Title:** Use Issue Title as-is. + +**Project:** Match to the relevant Linear project based on the intake item's Project property, Area, or repo references. If no matching project exists, file under the parent team (PhoenixVC). + +**Team assignment:** Assign to the correct sub-team based on the routing label you apply (see labels below): + +| Routing label | Sub-team | +|---|---| +| `ready-to-code` | Coding (COD) | +| `needs-investigation` | Research (RES) | +| `needs-tests` | QA (QA) | +| `ci-cd` or `find-similar` | Ops (OPS) | +| `needs-visual-check` | Design (DES) | +| `needs-docs` | Docs (DOC) | +| `customer-issue` | Support (SUP) | + +**Assignees:** Leave unassigned by default — the team's triage process will handle assignment. Only assign `@Tembo` if your research was inconclusive and deeper investigation is needed before the issue is actionable. + +**Priority (Linear):** + +| Notion Priority | Linear Priority | +|---|---| +| Critical | P0 (Urgent) | +| High | P1 (High) | +| Medium | P2 (Medium) | +| Low | P3 (Low) | + +**Labels (required — exactly 2):** + +1. **ONE routing label** (determines which team receives the issue): + - `ready-to-code`, `needs-investigation`, `needs-tests`, `ci-cd`, `find-similar`, `needs-visual-check`, `needs-docs`, `customer-issue` +2. **ONE type label** (classifies the work): + - `Bug`, `Feature`, `Improvement`, or `chore` + - Map from the Notion Type property when available. If Type is missing, infer from the content. + +You may also add additional surface-area labels that help based on Area, Components, Environment, and the page body (e.g. `frontend`, `api`, `database`, `redis`, `auth`, `ui/ux`, `devops`). These are optional and supplementary — the two required labels above are mandatory. + +**Description:** Summarize the context you found and include a link back to the Notion page. When you performed research, include: + +- **Suggested approach** — what you found and a hypothesis (not a certainty) +- **Related incidents** — links to prior Linear issues or internal postmortems +- **Likely code location** — repo paths with candidate class/function names + +**Confidence flag:** If you are less than 80% confident in your routing label, type label, or priority assignment, add a comment on the issue: `⚠️ Low confidence on [label/priority] — please verify during triage`. + +### Step 5 — File the intake item + +Every intake item must end up somewhere — **never leave it in Intake**. + +| Outcome | Action | +|---|---| +| **Filed to Linear** | Set Status to `Filed`. Move page out of Intake. | +| **Duplicate** | Set Status to `Duplicate`. Move page to **Rejections**. Link the existing Linear issue in the page body or comments. | +| **Track but don't file** | Move page to **Backlog**. Set Status to `Backlog` or `To Do`. | +| **Not tracking** | Move page to **Rejections**. Set Status to `Rejected`. | + +--- + +## 🔁 Duplicate handling + +- Check for duplicates in **Linear** using a reasonable title and keyword search. +- Also search within **Linear Intake** and **Backlog** to avoid double-filing the same item. +- If a likely match exists, prefer marking as **Duplicate** instead of creating a new Linear issue. +- Include the existing Linear issue link in the Notion page body or comments when marking duplicate. + +--- + +## 🔎 Research (when it helps) + +Perform research when the issue seems non-trivial, unclear, or risky. Skip research for straightforward items where the routing and context are obvious. + +**Web search:** + +- Search for known causes, fixes, and best-practice remediation steps for the symptoms and stack involved. +- If relevant, search Notion helpdocs for product-behavior details. +- Prefer actionable, credible sources (official docs, vendor docs, well-known maintainers). + +**Historic incidents:** + +- Search Linear for prior incidents or issues with similar symptoms, affected area, or error messages. +- Search within Notion for earlier related intake items. +- If there are relevant incident reports or postmortems in Notion, link them. + +**Code search** (when it would materially improve the ticket — non-trivial issues, stack traces, specific endpoints, repeat incidents): + +- Identify the most likely surface area: app (frontend), backend service, API, database, cache/redis. +- Search the relevant repo (e.g. `https://github.com/phoenixvc/Mystira.workspace` for Mystira, or the repo matching the project) for relevant files and symbols. +- If you can identify the most likely function or code path, add permalinks to the relevant files/lines. + +**Add to the Linear description:** + +- **Suggested approach** — summarize what you found. Frame as a hypothesis, not certainty. +- **Related incidents** — links to prior Linear issues and internal incident/postmortem pages. +- **Likely code location** — repo paths plus any candidate class/function names with permalinks. + +--- + +## 📊 Team routing reference + +| # | Team | Key | Routing Label | Primary Agents | +|---|------|-----|---------------|----------------| +| 1 | Coding | COD | `ready-to-code` | Codex, Cursor, Copilot | +| 2 | Research | RES | `needs-investigation` | Tembo, ChatGPT, Solo | +| 3 | QA | QA | `needs-tests` | Ranger, Tusk | +| 4 | Ops | OPS | `ci-cd` / `find-similar` | GitHub integration | +| 5 | Design | DES | `needs-visual-check` | Stilla | +| 6 | Docs | DOC | `needs-docs` | Claude Code, Notion AI | +| 7 | Support | SUP | `customer-issue` | Intercom (MCP), ChatGPT | diff --git a/docs/integrations/README.md b/docs/integrations/README.md index 48aa94c7..9ec06fca 100644 --- a/docs/integrations/README.md +++ b/docs/integrations/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Integrations Docs Index diff --git a/docs/integrations/cognitive-mesh-skill.md b/docs/integrations/cognitive-mesh-skill.md new file mode 100644 index 00000000..8522a0de --- /dev/null +++ b/docs/integrations/cognitive-mesh-skill.md @@ -0,0 +1,76 @@ +# Cognitive Mesh Integration Skill + +> **Status:** Planned — blocked on cognitive-mesh Phase 5 (HTTP API not yet live) +> **API URL:** https://cognitive-mesh-api.blackmoss-00f95c9e.southafricanorth.azurecontainerapps.io +> **Tracked in:** org-meta/.roadmap.yaml → cognitive-mesh-http-api + +## Overview + +Integrate cognitive-mesh as a reasoning backend for retort quality gates and agent routing. Instead of static rule-based gates, retort agents can invoke cognitive-mesh to reason about output quality using chain-of-thought, debate, or strategic reasoning modes. + +## Endpoints to Integrate + +### 1. Health Check (implement first) +``` +GET /api/v1/cognitive/health +``` +No auth. Retort should check this before invoking any cognitive-mesh skill — fail gracefully if down. + +### 2. Core Reasoning (primary integration) +``` +POST /api/v1/cognitive/reason +``` +Used by quality gates to reason about agent output. Replace static pass/fail rules with dynamic reasoning. + +**Proposed request shape:** +```json +{ + "mode": "chain-of-thought" | "debate" | "strategic", + "context": "string", + "input": "string", + "criteria": ["string"] +} +``` + +**Proposed response shape:** +```json +{ + "conclusion": "string", + "confidence": 0.0-1.0, + "reasoning": ["string"], + "pass": true | false +} +``` + +### 3. Agency Routing (future — after reason is stable) +``` +POST /api/v1/cognitive/agency/route +``` +Replace retort's static team assignment with cognitive-mesh routing. Pass task description, get back recommended agent team. + +## Retort Integration Points + +### Quality Gate Skill +Create `skills/cognitive-mesh-gate.ts`: +- Invoke `/health` on init +- Call `/reason` with gate criteria + agent output +- Map `pass: false` + `confidence < threshold` to gate failure +- Surface `reasoning[]` in gate failure message (actionable feedback) + +### Orchestrator Hook +In `AGENT_TEAMS.md` or orchestrator config: +- Before dispatching to a team, optionally call `/agency/route` +- Use as a hint, not hard override (cognitive-mesh down = fall back to static routing) + +## Auth +TBD — cognitive-mesh API auth not yet designed. Likely Azure Managed Identity or API key via Key Vault (`cog-shared-kv-san`). + +## Dependencies +- cognitive-mesh Phase 5 complete (CognitiveMeshController.cs implemented) +- cognitive-mesh Phase 6 complete (deployed to CAE) +- retort skill scaffolding in place + +## Notes +- cognitive-mesh ACR: `myssharedacr.azurecr.io` (shared org registry) +- cognitive-mesh dev RG: `cog-dev-rg-san` (SAF North) +- Do not add cognitive-mesh as a hard dependency — degrade gracefully when unavailable diff --git a/docs/integrations/ide-settings-sync.md b/docs/integrations/ide-settings-sync.md new file mode 100644 index 00000000..b9f93768 --- /dev/null +++ b/docs/integrations/ide-settings-sync.md @@ -0,0 +1,104 @@ +# IDE Settings Sync Reference + +> Last updated: 2026-03-19 | Status: documentation + +## Overview + +Cross-IDE settings sync strategy for the phoenixvc workspace. Baseline editor: **Zed**. + +## Supported Editors + +| Editor | Config Location | Status | Notes | +|--------|----------------|--------|-------| +| Zed | `%APPDATA%/Zed/settings.json` | **baseline** | Most refined settings | +| VS Code | `%APPDATA%/Code/User/settings.json` | parity needed | | +| Cursor | `%APPDATA%/Cursor/User/settings.json` | parity needed | Fork of VS Code | +| Windsurf | `%APPDATA%/Windsurf/User/settings.json` | parity needed | Fork of VS Code | +| Antigravity | — | pending setup | | +| Trae | — | pending setup | | +| Qoder | — | pending setup | | +| Nimbalyst | — | pending setup | | +| Rider | — | pending setup | JetBrains .NET IDE | +| PyCharm | — | pending setup | Partner's IDE (Python) | + +## Zed Baseline Settings + +Located: `C:\Users\smitj\AppData\Roaming\Zed\settings.json` + +### Key Conventions + +| Setting | Zed Value | Target Parity | +|---------|-----------|---------------| +| Terminal shell | Git bash | All editors | +| Whitespace rendering | `"boundary"` | All editors | +| Tab size (C#) | 4 | All editors | +| Tab size (Python) | 4 | All editors | +| Tab size (Rust) | 4 | All editors | +| Tab size (TS/JSON/YAML) | 2 | All editors | +| Theme | Ayu Light/Dark | Align others | +| Format on save | `on` | All editors | +| Auto save | `on_focus_change` | Align | + +### Language-Specific Overrides + +```json +{ + "languages": { + "CSharp": { "tab_size": 4, "hard_tabs": false }, + "Python": { "tab_size": 4, "format_on_save": "on" }, + "Rust": { "tab_size": 4, "hard_tabs": false }, + "TypeScript": { "tab_size": 2 }, + "TSX": { "tab_size": 2 }, + "JSON": { "tab_size": 2 }, + "YAML": { "tab_size": 2 } + } +} +``` + +## Current Gaps + +### VS Code +- Terminal defaults to PowerShell (not Git bash) +- Whitespace rendering: `"none"` (vs `"boundary"`) +- No language-specific tab size overrides + +### Cursor +- Similar gaps to VS Code +- Has unique: `cursor.windowSwitcher.sidebarHoverCollapsed` + +### Windsurf +- Similar gaps to VS Code +- Has unique: `editor.tabCompletion: "on"` + +## Task + +Mark org-meta roadmap item `org-meta-foundation` > `Cross-IDE settings sync` as done when: +- [x] Document baseline (Zed) +- [x] Align VS Code settings +- [x] Align Cursor settings +- [x] Align Windsurf settings +- [ ] Document Antigravity, Trae, Qoder, Nimbalyst configs (once installed) +- [ ] Document Rider, PyCharm configs (once partner sets up) + +## Changes Applied (2026-03-19) + +### VS Code +- `files.autoSave`: `afterDelay` → `onFocusChange` +- `editor.renderWhitespace`: `none` → `boundary` +- `terminal.integrated.defaultProfile.windows`: `PowerShell` → `Git Bash` +- Added language overrides: C# (4), Python (4), Rust (4), TS/JSON/YAML (2) + +### Cursor +- `files.autoSave`: `afterDelay` → `onFocusChange` +- `editor.renderWhitespace`: `none` → `boundary` +- Added language overrides: C# (4), Python (4), Rust (4), TS/JSON/YAML (2) + +### Windsurf +- `files.autoSave`: `afterDelay` → `onFocusChange` +- `editor.renderWhitespace`: `none` → `boundary` +- Added language overrides: C# (4), Python (4), Rust (4), TS/JSON/YAML (2) + +## Related + +- User profile: `mystira-workspace/.agents/users/smitj.yaml` +- Original task: org-meta `.roadmap.yaml` > `org-meta-foundation` diff --git a/docs/integrations/trae-compatibility.md b/docs/integrations/trae-compatibility.md new file mode 100644 index 00000000..6c65323f --- /dev/null +++ b/docs/integrations/trae-compatibility.md @@ -0,0 +1,140 @@ +# TRAE Compatibility Audit + +**Status:** Research in progress — web fetch required to complete +**Issues:** [#025](../../.github/ISSUES/025-trae-rules-revisit.md) · [#026](../../.github/ISSUES/026-trae-skills-revisit.md) · [#027](../../.github/ISSUES/027-trae-agents-revisit.md) +**Priority:** P1 (agents), P2 (rules, skills) + +--- + +## URLs to fetch + +| Topic | URL | +|-------|-----| +| Rules format | `https://docs.trae.ai/ide/rules?_lang=en` | +| Skills format | `https://docs.trae.ai/ide/skills?_lang=en` | +| Agents / one-click import | `https://docs.trae.ai/ide/custom-agents-ready-for-one-click-import` | +| Agent overview | `https://docs.trae.ai/ide/agent-overview?_lang=en` | + +Fetch all four, then compare against Retort's current output (documented below). + +--- + +## Current Retort TRAE output + +Retort generates a `.ai/` directory via `.agentkit/templates/ai/`. As of 2026-03-20: + +### Files generated + +| File | Size | Content | +|------|------|---------| +| `.ai/cursorrules` | ~950 bytes | 12-line generic conventions pointer | +| `.ai/windsurfrules` | ~950 bytes | 12-line generic conventions pointer | +| `.ai/continuerules` | ~950 bytes | 12-line generic conventions pointer | +| `.ai/README.md` | ~1.7 KB | Explains purpose of `.ai/` directory | + +### What is NOT generated + +- `.ai/rules/` subdirectory (TRAE structured rules) +- `.ai/skills/` subdirectory (TRAE skills surface) +- `.ai/agents/` subdirectory (TRAE custom agents / one-click import) + +### Template source + +``` +.agentkit/templates/ai/ +├── README.md +├── continuerules +├── cursorrules +└── windsurfrules +``` + +No skill or agent templates exist for the `ai` platform. + +### Sample generated content (windsurfrules) + +``` +Follow UNIFIED_AGENT_TEAMS.md and CLAUDE.md. +Use /discover → /healthcheck → /plan → implement → /check → /review. +Never modify .env, secrets, or credential files. +Never modify files in .agentkit/templates/, .agentkit/spec/, .agentkit/engines/, + or .agentkit/overlays/, or .agentkit/bin/ — propose changes via PR instead. +Never edit files marked "GENERATED by AgentKit Forge — DO NOT EDIT" — + modify the spec and run agentkit sync. +Prefer small, reversible changes with tests. +All commits AND PR titles MUST use Conventional Commits: type(scope): description. + Types: feat|fix|docs|style|refactor|test|chore|ci|perf|build|revert. +After editing .agentkit/spec/, ALWAYS run: pnpm -C .agentkit agentkit:sync — + then commit the regenerated output. +``` + +--- + +## Audit questions (to answer from docs) + +### Rules (Issue 025) + +1. What file path does TRAE read rules from — `.ai/windsurfrules`, `.ai/rules/*.md`, or something else? +2. Does TRAE have a concept of rule scope (global vs project vs workspace)? +3. Are rules Markdown or plain text? Is there a frontmatter schema? +4. What is the size/token limit TRAE applies to rule files? +5. Does TRAE support multiple rule files or a single file? +6. How does TRAE handle rule precedence (user vs project vs team)? +7. Does the current 12-line format match what TRAE expects, or is richer structure needed? + +### Skills (Issue 026) + +1. What directory does TRAE read skills from? (`.ai/skills/`? `.trae/skills/`?) +2. What is the skill file format — Markdown with frontmatter? JSON? YAML? +3. Required metadata fields per skill (name, description, trigger, prompt)? +4. Is there a skill size/complexity limit? +5. How do TRAE skills relate to Retort's slash commands — 1:1 mapping, or different granularity? +6. Which of Retort's ~25 commands should become TRAE skills vs remain Claude-only? + +### Agents (Issue 027) + +1. What format does TRAE use for custom agents — JSON, Markdown, YAML? +2. Required fields for one-click import (name, description, model, system prompt, tools, avatar)? +3. What is the import URL/mechanism — a `.trae/agents/*.json` file? A hosted URL? +4. Does TRAE support agent tool access configuration (file read, web search, shell)? +5. Which of Retort's 13 teams map to TRAE agents? All 13, or a curated subset? +6. Does TRAE support agent teams / multi-agent coordination, or only single agents? + +--- + +## Expected deliverables from audit + +After fetching the docs, produce: + +1. **Gap table** — for each surface (rules/skills/agents), what Retort currently emits vs what TRAE expects +2. **New templates needed** — list files to create under `.agentkit/templates/ai/` +3. **spec.yaml changes** — any new settings needed in `settings.yaml` or `agents.yaml` to support TRAE metadata +4. **Sync engine changes** — does `synchronize.mjs` need a new rendering path for `.ai/skills/` and `.ai/agents/`? +5. **Implementation issues** — create follow-up issues in `.github/ISSUES/` for each gap that requires implementation work + +--- + +## Context from `feat/kit-domain-selection-onboarding` + +The kit-based domain filtering work (Phase 2+3) partially addresses Issue 025: +- Only stack-relevant domains are now generated, reducing rule noise for consumers +- A TypeScript-only project no longer gets dotnet/rust/python/blockchain rules +- This applies to all platforms including TRAE's `.ai/` output + +The per-agent `elegance-guidelines` field (Issue 040) improves agent quality independent +of platform, which feeds into Issue 027. + +--- + +## How to continue this audit + +In a session with WebFetch access: + +``` +Fetch https://docs.trae.ai/ide/rules?_lang=en +Fetch https://docs.trae.ai/ide/skills?_lang=en +Fetch https://docs.trae.ai/ide/custom-agents-ready-for-one-click-import +Fetch https://docs.trae.ai/ide/agent-overview?_lang=en + +Then read docs/integrations/trae-compatibility.md and complete the audit +using the questions and current-state documentation in that file. +``` diff --git a/docs/operations/01_deployment.md b/docs/operations/01_deployment.md index 2dc23d9f..c1003de9 100644 --- a/docs/operations/01_deployment.md +++ b/docs/operations/01_deployment.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Deployment Guide ## Overview -<!-- Describe the deployment strategy for agentkit-forge. --> +<!-- Describe the deployment strategy for retort. --> ## Environments diff --git a/docs/operations/02_monitoring.md b/docs/operations/02_monitoring.md index 73b224c7..84a91d88 100644 --- a/docs/operations/02_monitoring.md +++ b/docs/operations/02_monitoring.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Monitoring ## Overview -<!-- Describe the monitoring strategy for agentkit-forge. --> +<!-- Describe the monitoring strategy for retort. --> ## Health Checks diff --git a/docs/operations/03_incident_response.md b/docs/operations/03_incident_response.md index 32c0294f..cd15b497 100644 --- a/docs/operations/03_incident_response.md +++ b/docs/operations/03_incident_response.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Incident Response ## Overview -<!-- Describe the incident response process for agentkit-forge. --> +<!-- Describe the incident response process for retort. --> ## Severity Levels diff --git a/docs/operations/04_troubleshooting.md b/docs/operations/04_troubleshooting.md index 61fffc27..f3b6900f 100644 --- a/docs/operations/04_troubleshooting.md +++ b/docs/operations/04_troubleshooting.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Troubleshooting ## Overview -Common issues and their resolutions for agentkit-forge. +Common issues and their resolutions for retort. ## Quick Diagnostics @@ -15,10 +15,10 @@ Common issues and their resolutions for agentkit-forge. curl -s http://localhost:3000/health | jq . # Check logs for errors -<!-- e.g. kubectl logs -l app=agentkit-forge --tail=100 --> +<!-- e.g. kubectl logs -l app=retort --tail=100 --> # Check resource utilisation -<!-- e.g. kubectl top pods -l app=agentkit-forge --> +<!-- e.g. kubectl top pods -l app=retort --> ``` ## Common Issues diff --git a/docs/operations/05_slos_slis.md b/docs/operations/05_slos_slis.md index d89a1c69..f6a9d32a 100644 --- a/docs/operations/05_slos_slis.md +++ b/docs/operations/05_slos_slis.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # SLOs and SLIs diff --git a/docs/operations/README.md b/docs/operations/README.md index 5918083e..f1dab951 100644 --- a/docs/operations/README.md +++ b/docs/operations/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Operations Docs Index diff --git a/docs/orchestration/README.md b/docs/orchestration/README.md index 4e9cd0ce..d2bb6554 100644 --- a/docs/orchestration/README.md +++ b/docs/orchestration/README.md @@ -1,6 +1,6 @@ # Orchestration Documentation -This category covers orchestration guides, PM protocols, and concurrency patterns for AgentKit Forge. See: +This category covers orchestration guides, PM protocols, and concurrency patterns for Retort. See: - [concurrency-protocol.md](concurrency-protocol.md) - [overview.md](overview.md) diff --git a/docs/orchestration/concurrency-protocol.md b/docs/orchestration/concurrency-protocol.md index e32b34a4..ac8b0ebb 100644 --- a/docs/orchestration/concurrency-protocol.md +++ b/docs/orchestration/concurrency-protocol.md @@ -1,7 +1,7 @@ # Concurrency Protocol Reference This document describes the full file-locking and concurrency protocol used by -AgentKit Forge agents when accessing shared state files. Agents receive a brief +Retort agents when accessing shared state files. Agents receive a brief summary in their persona files; this is the complete reference. ## Overview diff --git a/docs/orchestration/overview.md b/docs/orchestration/overview.md index 488f94e0..5f7b7684 100644 --- a/docs/orchestration/overview.md +++ b/docs/orchestration/overview.md @@ -1,6 +1,6 @@ # How Orchestration Works -This guide explains the AgentKit Forge orchestration pipeline — how work flows from +This guide explains the Retort orchestration pipeline — how work flows from a user request through phases, team delegation, agent personas, and quality gates. ## The Pipeline diff --git a/docs/orchestration/pm-guide.md b/docs/orchestration/pm-guide.md index d6957c4b..a02dc183 100644 --- a/docs/orchestration/pm-guide.md +++ b/docs/orchestration/pm-guide.md @@ -1,6 +1,6 @@ -# Product Manager Guide to AgentKit Forge +# Product Manager Guide to Retort -A practical guide for using AgentKit Forge's orchestration system to manage +A practical guide for using Retort's orchestration system to manage features from idea through to shipped code. ## Quick Start @@ -27,7 +27,7 @@ features from idea through to shipped code. ## The Three PM Agents -AgentKit Forge includes three PM-oriented agent personas that are loaded into +Retort includes three PM-oriented agent personas that are loaded into relevant team commands: ### Product Manager diff --git a/docs/planning/PLAN-gh371-state-cleanup-validation-session-start.md b/docs/planning/PLAN-gh371-state-cleanup-validation-session-start.md index 8e666567..2d7d01ed 100644 --- a/docs/planning/PLAN-gh371-state-cleanup-validation-session-start.md +++ b/docs/planning/PLAN-gh371-state-cleanup-validation-session-start.md @@ -2,7 +2,11 @@ **Goal:** Agent state is reliable: required state directories exist before any command runs, orchestrator state is validated on load, and stale task files can be cleaned so agents never fail or misbehave due to missing or corrupt state. +<<<<<<< HEAD +**Scope:** P1 product backlog item [GH#371](https://github.com/JustAGhosT/retort/issues/371). +======= **Scope:** P1 product backlog item [GH#371](https://github.com/JustAGhosT/agentkit-forge/issues/371). +>>>>>>> origin/main --- diff --git a/docs/planning/README.md b/docs/planning/README.md index 55c0886c..bf88702f 100644 --- a/docs/planning/README.md +++ b/docs/planning/README.md @@ -1,6 +1,6 @@ # Planning Index -Central planning registry for agentkit-forge. Each entry tracks a discrete work item with status, priority, remaining actions, and dependencies. Organized by domain. +Central planning registry for retort. Each entry tracks a discrete work item with status, priority, remaining actions, and dependencies. Organized by domain. > **Last updated**: 2026-03-10 > **Source**: Consolidated from `plan.md`, `docs/reference/issues/`, `.agentkit/docs/`, and GitHub Issues @@ -105,7 +105,7 @@ Phase 3 (after P2): CM-006 (RepoGuardian P3) + CM-003 (CommsCrew) ## FinOps & Cost Management -Multi-repo cost governance spanning agentkit-forge, ai-gateway, and pvc-costops-analytics. +Multi-repo cost governance spanning retort, ai-gateway, and pvc-costops-analytics. | ID | Title | Priority | Status | Plan File | Blockers | GH Issue | | ------ | ------------------------------------------ | -------- | ----------- | ------------------------------------------------------------------------------ | ------------------------------------ | -------- | @@ -116,7 +116,7 @@ Multi-repo cost governance spanning agentkit-forge, ai-gateway, and pvc-costops- ## Cost Governance (Local) -Items scoped to agentkit-forge cost tooling. +Items scoped to retort cost tooling. | ID | Title | Priority | Status | Plan File | Blockers | GH Issue | | ------ | ---------------------------------------------- | -------- | ----------- | ------------------------------------------------------------------------------------------ | ------------------------------------------- | -------- | @@ -126,7 +126,7 @@ Items scoped to agentkit-forge cost tooling. ## Framework & Templates -Items related to AgentKit Forge framework structure, template organization, and tooling. +Items related to Retort framework structure, template organization, and tooling. | ID | Title | Priority | Status | Plan File | Blockers | GH Issue | | ------ | ------------------------------------------------------------ | -------- | ----------- | ------------------------------------------------------------------------------------------ | ------------------------------------ | -------- | diff --git a/docs/planning/TEMPLATE-plan.md b/docs/planning/TEMPLATE-plan.md index f41c482b..16a6d0f8 100644 --- a/docs/planning/TEMPLATE-plan.md +++ b/docs/planning/TEMPLATE-plan.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # [Plan-ID]: [Plan Title] diff --git a/docs/planning/agents-teams/finops-specialist.md b/docs/planning/agents-teams/finops-specialist.md index 2d8f3316..d6e190e4 100644 --- a/docs/planning/agents-teams/finops-specialist.md +++ b/docs/planning/agents-teams/finops-specialist.md @@ -1,6 +1,6 @@ # feat(agents): Consider splitting a FinOps Specialist agent from Data Engineer -> **Target repo**: `agentkit-forge` +> **Target repo**: `retort` > **Labels**: `enhancement`, `finops`, `agents`, `cost-management` > **Priority**: P3 (future consideration) diff --git a/docs/planning/agents-teams/forge-team.md b/docs/planning/agents-teams/forge-team.md index 4a416207..08eab901 100644 --- a/docs/planning/agents-teams/forge-team.md +++ b/docs/planning/agents-teams/forge-team.md @@ -9,7 +9,7 @@ It is the "team that builds teams." ## Origin - **Source**: `phoenixvc/cognitive-mesh` issue #130 — TeamForge pipeline architecture -- **Adapted for**: agentkit-forge spec-driven architecture (YAML specs → sync → generated configs) +- **Adapted for**: retort spec-driven architecture (YAML specs → sync → generated configs) ## Pipeline Architecture diff --git a/docs/planning/agents-teams/restructuring-gaps.md b/docs/planning/agents-teams/restructuring-gaps.md index c3dee407..fed3c3af 100644 --- a/docs/planning/agents-teams/restructuring-gaps.md +++ b/docs/planning/agents-teams/restructuring-gaps.md @@ -1,6 +1,6 @@ # refactor(agents): Address team/agent mapping gaps and missing dedicated agents -> **Target repo**: `agentkit-forge` +> **Target repo**: `retort` > **Labels**: `enhancement`, `agents`, `teams`, `tech-debt` > **Priority**: P3 diff --git a/docs/planning/agents-teams/strategic-ops-team.md b/docs/planning/agents-teams/strategic-ops-team.md index a19acae8..de142107 100644 --- a/docs/planning/agents-teams/strategic-ops-team.md +++ b/docs/planning/agents-teams/strategic-ops-team.md @@ -4,11 +4,11 @@ Strategic Ops is the cross-project coordination team responsible for framework governance, portfolio-level planning, adoption strategy, impact assessment, and -release coordination across all repos using AgentKit Forge. +release coordination across all repos using Retort. ## Motivation -As AgentKit Forge scales to manage multiple downstream repos, the need for +As Retort scales to manage multiple downstream repos, the need for portfolio-level visibility and governance becomes critical. Individual teams (backend, frontend, etc.) operate within a single repo — Strategic Ops operates _across_ repos, ensuring consistency, managing breaking changes, and coordinating diff --git a/docs/planning/archive/cost-budget-flag-duplicate.md b/docs/planning/archive/cost-budget-flag-duplicate.md index 7867cde3..27611003 100644 --- a/docs/planning/archive/cost-budget-flag-duplicate.md +++ b/docs/planning/archive/cost-budget-flag-duplicate.md @@ -1,6 +1,6 @@ # chore(cost): Add `--budget` flag documentation to `/cost` command template -> **Target repo**: `agentkit-forge` +> **Target repo**: `retort` > **Labels**: `chore`, `finops`, `cost-management` > **Priority**: P2 diff --git a/docs/planning/finops/wave5-integration.md b/docs/planning/finops/wave5-integration.md index 31971956..d00b2458 100644 --- a/docs/planning/finops/wave5-integration.md +++ b/docs/planning/finops/wave5-integration.md @@ -1,6 +1,6 @@ # Wave 5: End-to-End Integration & Hardening -> **Target repos**: `agentkit-forge` (orchestration), `phoenixvc/ai-gateway` (runtime), `phoenixvc/pvc-costops-analytics` (analytics) +> **Target repos**: `retort` (orchestration), `phoenixvc/ai-gateway` (runtime), `phoenixvc/pvc-costops-analytics` (analytics) > **Labels**: `finops`, `integration`, `cost-management` > **Priority**: P2 @@ -21,7 +21,7 @@ Wire together the three enforcement layers (session budget guard → gateway spe **Data flow**: ``` -Agent session (agentkit-forge) +Agent session (retort) → cost-tracker.mjs logs to JSONL → session metrics: duration, commands, files @@ -67,7 +67,7 @@ GitHub Actions cron job (monthly, 1st of month): ### 5.4 Budget Approval Workflow (GitHub Issues) -**Repo**: `pvc-costops-analytics` (or `agentkit-forge` for template) +**Repo**: `pvc-costops-analytics` (or `retort` for template) Flesh out the budget approval process: diff --git a/docs/planning/framework/docs-wiki-generation.md b/docs/planning/framework/docs-wiki-generation.md index e2800bda..6658339a 100644 --- a/docs/planning/framework/docs-wiki-generation.md +++ b/docs/planning/framework/docs-wiki-generation.md @@ -45,7 +45,7 @@ Template-generated documentation files use numbered prefixes (`01_prd.md`, `02_e | **Cursor + MkDocs** | Use AI to auto-generate/maintain docs, serve via MkDocs | DIY approach; flexible | | **GitHub Copilot Docs** | Generate docs from code context | In-editor; no standalone site | -### 4. Considerations for AgentKit Forge +### 4. Considerations for Retort - **Numbered files**: Current `01_`, `02_` prefixes provide ordering. Most static site generators support sidebar ordering via frontmatter (`sidebar_position`) or config files, making numeric prefixes unnecessary. - **Generated files**: Docs are regenerated by `agentkit sync`. The chosen tool must work with generated markdown (not require custom frontmatter that sync doesn't produce). diff --git a/docs/planning/framework/tool-neutral-hub-adoption-roadmap.md b/docs/planning/framework/tool-neutral-hub-adoption-roadmap.md new file mode 100644 index 00000000..f13ddbcd --- /dev/null +++ b/docs/planning/framework/tool-neutral-hub-adoption-roadmap.md @@ -0,0 +1,309 @@ +# Adoption Roadmap: Tool-Neutral Agent Hub + +**Date:** 2026-03-17 +**ADR:** [ADR-10](../../architecture/decisions/10-tool-neutral-agent-hub.md) +**Findings:** [Full analysis](../../architecture/specs/tool-neutral-agent-hub-findings.md) +**Status:** Proposed + +--- + +## Overview + +This roadmap converges the AgentKit Forge sync engine with the `.agents/` hub pattern pioneered in Mystira.workspace. The goal: every AI agent tool can discover shared agents, skills, guards, traces, and roadmaps from one canonical location, while the sync engine continues to generate tool-specific output where platform differences require it. + +**5 phases, each independently shippable.** No phase depends on a later phase, but each builds on the previous. + +--- + +## Phase 1: `.agents/` Directory as Sync Target + +**Goal:** The sync engine generates `.agents/` alongside `.claude/`, `.cursor/`, etc. +**Effort:** Medium (2–3 sessions) +**Depends on:** Nothing + +### Deliverables + +| # | Task | Detail | +|---|------|--------| +| 1.1 | Define `.agents/` directory schema | Document the 5-folder structure (`guards/`, `skills/`, `traces/`, `history/`, `roadmaps/`) with file naming conventions and frontmatter schemas | +| 1.2 | Add `.agents/` output target to sync engine | New template directory `.agentkit/templates/agents/` renders shared content from spec YAML | +| 1.3 | Generate shared skills to `.agents/skills/` | Skills currently land in `.claude/skills/`, `.agents/skills/` (Claude), and `.cursor/commands/` (Cursor) separately — generate a canonical copy to `.agents/skills/` | +| 1.4 | Generate shared agents to `.agents/agents/` | Agent personas currently in `.claude/agents/` and `.github/agents/` — generate canonical versions to `.agents/agents/` with category subdirectories | +| 1.5 | CI drift check covers `.agents/` | Extend the existing drift check workflow to validate `.agents/` output against spec | +| 1.6 | Update CLAUDE.md references | Add `.agents/` to the architecture section and safety rules | + +### Success Criteria + +- `pnpm -C .agentkit agentkit:sync` generates `.agents/` directory +- CI drift check validates `.agents/` content +- Any agent tool can `ls .agents/skills/` to discover available skills without knowing tool-specific paths + +### Architecture Decision + +`.agents/` content is **generated** by the sync engine (not hand-authored). This preserves the spec-driven architecture. The `.agentkit/spec/` YAML remains the single source of truth. + +Exception: `traces/`, `history/`, and `roadmaps/` are **runtime directories** — written by agents during sessions, not generated by sync. The sync engine creates the directory structure and any seed files; agents populate content. + +--- + +## Phase 2: Reflective Guards + +**Goal:** Portable governance rules that work for any agent, regardless of shell access. +**Effort:** Medium (2–3 sessions) +**Depends on:** Phase 1 (directory structure exists) + +### Deliverables + +| # | Task | Detail | +|---|------|--------| +| 2.1 | Define guard schema | YAML frontmatter (`name`, `enabled`, `description`, `severity: warn|block`, `applies_to: glob[]`) + markdown body with `**Pattern**` regex and `**Instruction**` steps | +| 2.2 | Add `guards` section to `rules.yaml` | Each guard defined in spec YAML, rendered to `.agents/guards/` | +| 2.3 | Migrate existing hook logic to guards | Extract the governance intent from shell hooks (`protect-templates`, `guard-destructive-commands`, `protect-sensitive-files`) into guard definitions | +| 2.4 | Generate shell hooks from guards | For tools that support hooks (Claude Code), auto-generate shell hook scripts from guard definitions — the guard is the source, the hook is the platform-specific enforcement | +| 2.5 | Add guard validation to CI | Validate that guard patterns are valid regex, frontmatter follows schema, and all guards have both `Pattern` and `Instruction` sections | +| 2.6 | Seed default guards | Ship with baseline guards: `no-secrets-in-code`, `protect-generated-files`, `no-destructive-commands`, `protect-shared-docs`, `memory-governance` | + +### Guard Format (Canonical) + +```yaml +--- +name: no-secrets-in-code +enabled: true +severity: block +description: Prevents hardcoded credentials in source files +applies_to: + - "**/*.ts" + - "**/*.py" + - "**/*.cs" +--- +# No Secrets in Code + +**Pattern**: `(ConnectionString|ApiKey|Secret|Password|Bearer)\s*[=:]\s*["'][^"']{8,}` + +**Instruction**: +1. Before writing any file matching the applies_to globs, check your output against the pattern +2. If the pattern matches, do NOT write the file +3. Instead, use an environment variable reference or secret manager lookup +4. Inform the user that you detected a potential hardcoded secret +``` + +### Relationship: Guards vs Hooks vs Hookify + +| Layer | Scope | Enforcement | Portable? | +|-------|-------|-------------|-----------| +| `.agents/guards/` | All agents, all tools | Reflective (self-check) | Yes — any agent can read markdown | +| `.claude/hooks/` | Claude Code only | Automated (shell intercept) | No — requires shell execution | +| Hookify rules | Claude Code only | Automated (hook system) | No — Claude Code plugin | + +Guards are the **canonical governance source**. Hooks and hookify rules are **platform-specific enforcement** generated from or inspired by guards. An agent that can only read files (no shell) still gets governance via guards. + +--- + +## Phase 3: `.readme.yaml` Generation + +**Goal:** Machine-readable project metadata at directory boundaries, generated from spec. +**Effort:** Low (1 session) +**Depends on:** Phase 1 (sync engine changes) + +### Deliverables + +| # | Task | Detail | +|---|------|--------| +| 3.1 | Define `.readme.yaml` schema | JSON Schema for the file format: `purpose`, `version`, `tech_stack`, `workspace_type`, `local_services`, `agent_tooling`, `last_synced` | +| 3.2 | Generate root `.readme.yaml` | Derived from `.agentkit/spec/project.yaml` — purpose, version, stack languages, infrastructure config | +| 3.3 | Generate sub-directory `.readme.yaml` | For monorepo-style projects: `apps/.readme.yaml`, `packages/.readme.yaml` listing contained projects | +| 3.4 | Add `agent_tooling` section | Points agents to `.agents/guards/`, `.agents/skills/`, etc. — acts as a directory map | +| 3.5 | CI validation | Ensure `.readme.yaml` content matches spec — same drift check pattern as other generated files | + +### Schema (v1) + +```yaml +# .readme.yaml — Machine-readable project metadata for AI agents +# GENERATED by AgentKit Forge — DO NOT EDIT +purpose: "AgentKit Forge framework for multi-tool AI agent orchestration" +version: "3.1.0" +default_branch: "main" +tech_stack: + languages: [javascript, yaml, markdown] + backend: node.js + test_runner: vitest + package_manager: pnpm +infrastructure: + org_prefix: akf + default_region: global + iac_tools: [terraform, terragrunt] +agent_tooling: + guards: ".agents/guards/" + skills: ".agents/skills/" + roadmaps: ".agents/roadmaps/" + traces: ".agents/traces/" + spec: ".agentkit/spec/" +last_synced: "2026-03-17T12:00:00Z" +``` + +### Token Cost Impact + +An agent entering a new directory currently reads `README.md` (typically 200–500 lines) + `CLAUDE.md` (300+ lines) to orient. `.readme.yaml` provides the same structural data in ~30 lines of parseable YAML. For a 13-team orchestration with per-team discovery, this saves ~6,000–10,000 tokens per orchestration cycle. + +--- + +## Phase 4: Cross-Session Traces & Roadmaps + +**Goal:** Preserve reasoning context across sessions and provide strategic framing for multi-session work. +**Effort:** Low–Medium (1–2 sessions) +**Depends on:** Phase 1 (directory structure) + +### Deliverables + +| # | Task | Detail | +|---|------|--------| +| 4.1 | Define trace format | Frontmatter: `date`, `agent`, `branch`, `valid_until`, `tags[]`. Body sections: Current State, Mental Model, Blocked/Pending, Next Steps | +| 4.2 | Extend `/handoff` command | Write structured trace to `.agents/traces/YYYY-MM-DD-<topic>.md` in addition to existing `docs/handoffs/` output | +| 4.3 | Add `end-session` skill | Skill that agents invoke at session end: writes trace, updates roadmap status, flags stale traces | +| 4.4 | Define roadmap format | Frontmatter: `title`, `status` (active/completed/abandoned), `created`, `updated`, `phases[]`. Body: phased delivery plan with acceptance criteria | +| 4.5 | Seed `.agents/roadmaps/` in sync | Sync engine creates the directory and a `README.md` explaining the convention. Roadmap content is user/agent-authored (not generated) | +| 4.6 | Session-start hook reads traces | On session start, check `.agents/traces/` for recent traces (< 7 days). Surface the most recent relevant trace to the incoming agent | +| 4.7 | Retention policy | Traces older than 30 days move to `.agents/traces/archive/`. History dirs older than 90 days are candidates for deletion (warn, don't auto-delete) | + +### Trace Format + +```markdown +--- +date: 2026-03-17 +agent: claude-opus-4 +branch: feat/tool-neutral-hub +valid_until: 2026-03-24 +tags: [architecture, sync-engine, .agents] +--- +# Handover: Tool-Neutral Hub Implementation + +## Current State +- Phase 1 complete: `.agents/` directory generates via sync +- Phase 2 in progress: guard schema defined, 3/6 guards migrated + +## Mental Model +The key insight is that guards are the *canonical* governance layer and hooks +are platform-specific *enforcement*. Don't try to make guards do what hooks do +(automated blocking) — they serve different populations of agents. + +## Blocked / Pending +- [ ] Guard-to-hook generation needs a template for each hook type (PreToolUse, PostToolUse, Stop) +- [ ] Unclear whether `.agents/guards/` should be flat or categorised by domain + +## Next Steps (for incoming agent) +1. Read `.agentkit/templates/claude/hooks/` to understand current hook structure +2. Prototype guard → hook rendering in the sync engine +3. Test with `protect-templates` guard as the first migration candidate +``` + +### Roadmap Format + +```markdown +--- +title: Tool-Neutral Agent Hub Adoption +status: active +created: 2026-03-17 +updated: 2026-03-17 +phases: + - name: ".agents/ sync target" + status: in-progress + - name: "Reflective guards" + status: planned + - name: ".readme.yaml generation" + status: planned + - name: "Traces & roadmaps" + status: planned + - name: "Schema formalisation" + status: planned +--- +# Tool-Neutral Agent Hub Adoption + +## Phase 1: .agents/ Sync Target +... +``` + +--- + +## Phase 5: Schema Formalisation & Cross-Project Adoption + +**Goal:** Publish schemas so other projects (and other agent frameworks) can adopt the `.agents/` convention. +**Effort:** Medium (2 sessions) +**Depends on:** Phases 1–4 (patterns validated in practice) + +### Deliverables + +| # | Task | Detail | +|---|------|--------| +| 5.1 | JSON Schema for guards | Formal schema for guard frontmatter + body structure. Published in `.agents/schemas/` | +| 5.2 | JSON Schema for traces | Formal schema for trace frontmatter + required sections | +| 5.3 | JSON Schema for `.readme.yaml` | Formal schema for project metadata | +| 5.4 | JSON Schema for roadmaps | Formal schema for roadmap frontmatter + phase structure | +| 5.5 | `.agents/` convention spec | Single markdown document describing the full convention: directory layout, file formats, lifecycle rules, retention policy | +| 5.6 | Onboard Mystira.workspace | Migrate Mystira's hand-authored `.agents/` to use the sync engine while preserving its existing content | +| 5.7 | Onboard 2 additional repos | Validate the pattern works for different project types (e.g., `chaufher` as .NET + Next.js, `PhoenixRooivalk` as Rust + Next.js) | +| 5.8 | Publish as standalone spec | Extract `.agents/` convention into its own repository or document for adoption outside the phoenixvc org | + +### Cross-Project Compatibility + +The `.agents/` convention should work for projects that: + +- Use AgentKit Forge (sync-generated) +- Don't use AgentKit Forge (hand-authored, like Mystira today) +- Use a different agent framework entirely + +This means the convention must be **framework-independent**. The sync engine is one way to populate `.agents/` — not the only way. The schemas and convention spec must stand alone. + +--- + +## Timeline Summary + +``` +Phase 1 ─── .agents/ sync target ──────────── [2-3 sessions] +Phase 2 ─── Reflective guards ─────────────── [2-3 sessions] +Phase 3 ─── .readme.yaml generation ────────── [1 session] +Phase 4 ─── Traces & roadmaps ─────────────── [1-2 sessions] +Phase 5 ─── Schema formalisation & adoption ── [2 sessions] + Total: 8-11 sessions +``` + +Phases 1–3 can overlap (different parts of the sync engine). Phases 4–5 are sequential. + +--- + +## Risk Register + +| Risk | Likelihood | Impact | Mitigation | +|------|-----------|--------|------------| +| `.agents/` conflicts with existing directory in consumer repos | Low | Medium | Document in onboarding; provide migration guide | +| Guard reflective enforcement is ignored by non-cooperative agents | Medium | Medium | Guards complement hooks, not replace; hooks remain for tools that support them | +| `.readme.yaml` drifts from README.md | Medium | Low | Generate both from spec; add CI check for consistency | +| Trace accumulation fills repos | Medium | Low | Retention policy (30d archive, 90d deletion candidates); `.gitignore` history/ for large projects | +| Schema evolution breaks existing consumers | Low | High | Semver the schemas; use `version` field in frontmatter; maintain backwards compatibility | +| Onboarded repos resist generated `.agents/` | Low | Medium | Offer opt-in per subdirectory; support `agents.enabled: false` in spec | + +--- + +## Decision Points + +Before proceeding to each phase, confirm: + +1. **Phase 1 → 2:** Does the sync engine reliably generate `.agents/`? Has CI drift check been extended? +2. **Phase 2 → 3:** Are guards working in at least one tool (Claude Code)? Have 3+ guards been migrated from hooks? +3. **Phase 3 → 4:** Does `.readme.yaml` generate correctly for at least 2 project types? +4. **Phase 4 → 5:** Have traces been written and consumed across at least 3 sessions? Is the retention policy working? +5. **Phase 5:** Are schemas stable enough that changing them would be a breaking change? + +--- + +## Appendix: Mystira → Forge Migration Path + +Mystira.workspace currently uses hand-authored `.agents/`. When onboarding to AgentKit Forge: + +1. **Guards** → Extract guard frontmatter into `.agentkit/spec/guards.yaml` (new spec file). Sync engine renders `.agents/guards/` from this spec. +2. **Skills** → Move skill content to `.agentkit/spec/skills.yaml` or keep as `once`-mode scaffolded files that sync doesn't overwrite. +3. **Traces** → No migration needed. Traces are runtime content, not generated. +4. **History** → No migration needed. History is runtime content. +5. **Roadmaps** → No migration needed. Roadmaps are user-authored. +6. **`.readme.yaml`** → Generated from new `.agentkit/spec/project.yaml` for Mystira. +7. **`.claude/settings.json`** → Preserved as-is (Claude-specific hooks/permissions). +8. **`.serena/memories/`** → Remains tool-specific. Consider migrating governance-relevant memories to `.agents/guards/`. diff --git a/docs/product/01_prd.md b/docs/product/01_prd.md index 7f162bc7..1cdde67e 100644 --- a/docs/product/01_prd.md +++ b/docs/product/01_prd.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Product Requirements Document @@ -8,7 +8,7 @@ <!-- Provide a high-level summary of the product and its purpose. --> -**Product Name:** agentkit-forge +**Product Name:** retort **Version:** 3.1.0 **Last Updated:** <!-- DATE --> diff --git a/docs/product/02_user_stories.md b/docs/product/02_user_stories.md index bbf6844e..a93a80c0 100644 --- a/docs/product/02_user_stories.md +++ b/docs/product/02_user_stories.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # User Stories diff --git a/docs/product/03_roadmap.md b/docs/product/03_roadmap.md index 4c26cc54..0eaaaebe 100644 --- a/docs/product/03_roadmap.md +++ b/docs/product/03_roadmap.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Roadmap ## Overview -This document outlines the planned timeline and milestones for `agentkit-forge`. +This document outlines the planned timeline and milestones for `retort`. ## Timeline diff --git a/docs/product/04_personas.md b/docs/product/04_personas.md index d41fbece..2b38cac4 100644 --- a/docs/product/04_personas.md +++ b/docs/product/04_personas.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # User Personas ## Overview -Personas represent the primary user archetypes for agentkit-forge. Use these +Personas represent the primary user archetypes for retort. Use these profiles to guide feature prioritisation and UX decisions. --- diff --git a/docs/product/PRD-001-llm-decision-engine.md b/docs/product/PRD-001-llm-decision-engine.md index b5c7481d..d79f9b4d 100644 --- a/docs/product/PRD-001-llm-decision-engine.md +++ b/docs/product/PRD-001-llm-decision-engine.md @@ -1,4 +1,4 @@ -# PRD-001: AgentKit Forge LLM Decision Engine +# PRD-001: Retort LLM Decision Engine ## Status @@ -6,11 +6,11 @@ Draft ## Module / Feature Name -Multi-LLM Agent Model Optimization and Routing in AgentKit Forge +Multi-LLM Agent Model Optimization and Routing in Retort ## Marketing Name -AgentKit Forge LLM Decision Engine +Retort LLM Decision Engine ## Platform / Mesh Layers @@ -95,7 +95,7 @@ competitive advantage for team productivity, governance, and cost control. ### Business Goals - Streamline model routing and mapping for teams. -- Increase AgentKit Forge adoption. +- Increase Retort adoption. - Improve output quality and delivery speed. - Establish Forge as a mesh-native source of truth for model selection. @@ -410,7 +410,7 @@ Project start date: **2026-03-03** | Product | Centralized Mapping | Coding Scorecards | Drift Detection | Gotcha Docs | | ------------------------ | ------------------- | ----------------- | --------------- | ----------- | -| AgentKit Forge | Yes | Yes | Planned | Yes | +| Retort | Yes | Yes | Planned | Yes | | LangChain | No | Partial | No | No | | OSS Agent Bundles | No | No | No | No | | Enterprise RAG Platforms | Yes | Partial | Yes | Partial | diff --git a/docs/product/PRD-002-llm-selection-scorecard-guide.md b/docs/product/PRD-002-llm-selection-scorecard-guide.md index 8b2e842a..5d126e9b 100644 --- a/docs/product/PRD-002-llm-selection-scorecard-guide.md +++ b/docs/product/PRD-002-llm-selection-scorecard-guide.md @@ -1,4 +1,4 @@ -# PRD-002: AgentKit Forge LLM Selection and Scorecard Guide +# PRD-002: Retort LLM Selection and Scorecard Guide ## Status @@ -8,15 +8,15 @@ This document is a living draft. The appendix contains TBD markers and data that ## Module / Feature Name -AgentKit Forge LLM Model Selection and Scorecard System +Retort LLM Model Selection and Scorecard System ## Marketing Name -AgentKit Forge Model Scorecard and Recommender +Retort Model Scorecard and Recommender ## Platform / Mesh Layers -- AgentKit Forge orchestration layer +- Retort orchestration layer - Agent execution layer - Model selection engine - Reporting and telemetry layer @@ -51,7 +51,7 @@ Pro and Enterprise ## Integration Points -- AgentKit Forge model mapping config (YAML and JSON) +- Retort model mapping config (YAML and JSON) - Agent execution APIs - Reporting and analytics dashboards - Third-party LLM endpoints diff --git a/docs/product/PRD-003-agent-to-llm-weighted-matrix-config-guide.md b/docs/product/PRD-003-agent-to-llm-weighted-matrix-config-guide.md index bd176c4a..1cd8500f 100644 --- a/docs/product/PRD-003-agent-to-llm-weighted-matrix-config-guide.md +++ b/docs/product/PRD-003-agent-to-llm-weighted-matrix-config-guide.md @@ -10,11 +10,11 @@ In Review ## Module / Feature Name -AgentKit Forge: Agent-to-LLM Weighted Selection and Configuration Layer +Retort: Agent-to-LLM Weighted Selection and Configuration Layer ## Marketing Name -AgentKit Forge - Polyglot LLM Decision Matrix Configurator +Retort - Polyglot LLM Decision Matrix Configurator ## Platform / Mesh Layers @@ -62,7 +62,7 @@ Enterprise ## Integration Points -- AgentKit orchestration layer +- Retort orchestration layer - Team and agent assignment modules - Model APIs (OpenAI, Anthropic, Google, Kimi, etc.) - Audit and logging services @@ -70,7 +70,7 @@ Enterprise ## TL;DR -AgentKit Forge enables declarative, team-aware agent-to-LLM mapping through +Retort enables declarative, team-aware agent-to-LLM mapping through YAML and JSON overlays so organizations can optimize quality and spend as model capabilities, pricing, and constraints evolve. diff --git a/docs/product/PRD-005-mesh-native-distribution.md b/docs/product/PRD-005-mesh-native-distribution.md index 8bd694e9..83a203f8 100644 --- a/docs/product/PRD-005-mesh-native-distribution.md +++ b/docs/product/PRD-005-mesh-native-distribution.md @@ -1,4 +1,4 @@ -# PRD-005: AgentKit Forge Mesh-Native Distribution +# PRD-005: Retort Mesh-Native Distribution ## Status @@ -6,11 +6,11 @@ Draft ## Module / Feature Name -AgentKit Forge Distribution & Orchestration Layer +Retort Distribution & Orchestration Layer ## Marketing Name -AgentKit Forge (Unified Delivery) +Retort (Unified Delivery) ## Platform / Mesh Layers @@ -49,7 +49,7 @@ timeline below. ## TL;DR -Unified, frictionless delivery of AgentKit Forge via npm, GitHub Action, and a +Unified, frictionless delivery of Retort via npm, GitHub Action, and a GA PWA UI — accelerating onboarding and enabling configuration by any team member with minimal operational burden. This PRD codifies the delivery strategy approved in [ADR-07](../architecture/decisions/07-delivery-strategy.md). @@ -100,7 +100,7 @@ forge's core differentiator. ### Business Goals -- Maximize AgentKit Forge adoption across all user segments. +- Maximize Retort adoption across all user segments. - Eliminate configuration drift in all enabled project repositories. - Minimize operational support needs (L2/L3 ticket reduction). - Establish veritasvault.ai as the standard for mesh-native AI configuration. @@ -157,14 +157,14 @@ environment parity. **Pain:** Submodules, multiple manual steps, repo drift. -As a developer, I can install and sync AgentKit Forge in one minute using +As a developer, I can install and sync Retort in one minute using npm/CLI. Acceptance criteria: -- Clean install with a single command (`npm install -D agentkit-forge`). +- Clean install with a single command (`npm install -D retort`). - Overlays auto-pulled from package; no submodule checkout required. -- `npx agentkit-forge sync` produces identical outputs to the submodule flow. +- `npx retort sync` produces identical outputs to the submodule flow. ### DevOps / Platform Owner @@ -229,9 +229,9 @@ Acceptance criteria: #### Flow 1: CLI Onboarding (Developer) ``` -npm install -D agentkit-forge - → npx agentkit-forge init --repoName my-project - → npx agentkit-forge sync +npm install -D retort + → npx retort init --repoName my-project + → npx retort sync → git add . && git commit ``` @@ -239,7 +239,7 @@ npm install -D agentkit-forge ```yaml # .github/workflows/agentkit-sync.yml -- uses: org/agentkit-forge-action@v3 +- uses: org/retort-action@v3 with: overlay: my-project version: '3.4.0' @@ -249,7 +249,7 @@ npm install -D agentkit-forge #### Flow 3: UI Onboarding (Non-CLI User) ``` -npx agentkit-forge ui +npx retort ui → Browser opens PWA at localhost:4827 → Visual wizard: detect stack → select render targets → create overlay → Click "Sync" → review diff → apply @@ -259,8 +259,8 @@ npx agentkit-forge ui | Step | CLI / Automation | UI Path | Outcome | | ------------ | ------------------------- | ---------------------- | ---------------------- | -| Install | `npm i -D agentkit-forge` | PWA onboarding wizard | AgentKit Forge ready | -| Sync / init | `npx agentkit-forge sync` | "Sync Now" in UI | Overlays in place | +| Install | `npm i -D retort` | PWA onboarding wizard | Retort ready | +| Sync / init | `npx retort sync` | "Sync Now" in UI | Overlays in place | | Overlay mgmt | CLI commands | Dashboard editor | Changes committed | | Drift check | GitHub Action step | CI status in UI | Drift flagged/cleared | | Update | `npm update` + sync | "Apply/Rollback" in UI | State current/restored | @@ -276,19 +276,19 @@ npx agentkit-forge ui - **Failed sync in CI:** CI job fails with actionable error message and diff summary; rollback queued if auto-commit mode is enabled. - **Partial update rollbacks:** Allow restoring last known good state via - `npm install agentkit-forge@previous-version` + sync, or one-click rollback in + `npm install retort@previous-version` + sync, or one-click rollback in UI with version history. ## Functional Requirements ### Distribution Channels -- **npm package** — CLI and SDK bundled as `agentkit-forge`. Published to npm +- **npm package** — CLI and SDK bundled as `retort`. Published to npm (and optionally private registries). Supports `--registry` flag for GitHub Packages / Artifactory. -- **GitHub Action** — `org/agentkit-forge-action@v3`. Drift detection, overlay +- **GitHub Action** — `org/retort-action@v3`. Drift detection, overlay validation, and optional auto-commit. Published to GitHub Actions marketplace. -- **PWA UI** — launched via `npx agentkit-forge ui` on `localhost:4827`. +- **PWA UI** — launched via `npx retort ui` on `localhost:4827`. Schema-driven overlay editor, sync dashboard, version manager, health report. ### Core Capabilities @@ -306,11 +306,11 @@ npx agentkit-forge ui | Command | Description | | ----------------------------- | -------------------------------------------------- | -| `agentkit-forge init` | Initialize overlays for a new consumer repo | -| `agentkit-forge sync` | Regenerate outputs from current overlays and specs | -| `agentkit-forge ui` | Launch PWA UI on localhost:4827 | -| `agentkit-forge doctor` | Health check — validate environment and config | -| `agentkit-forge overlay edit` | Open overlay in editor with schema validation | +| `retort init` | Initialize overlays for a new consumer repo | +| `retort sync` | Regenerate outputs from current overlays and specs | +| `retort ui` | Launch PWA UI on localhost:4827 | +| `retort doctor` | Health check — validate environment and config | +| `retort overlay edit` | Open overlay in editor with schema validation | ### UI Screens @@ -353,7 +353,7 @@ npx agentkit-forge ui ### Required APIs -- **CLI commands** — `agentkit-forge init`, `sync`, `ui`, `doctor`, +- **CLI commands** — `retort init`, `sync`, `ui`, `doctor`, `overlay edit`. - **UI ↔ Engine API** — JSON-RPC bridge over local HTTP. The UI is a presentation layer only; all logic lives in the engine. Same API can be @@ -385,22 +385,22 @@ npx agentkit-forge ui **CLI path:** ```bash -npm install -D agentkit-forge # or npm install -g agentkit-forge -npx agentkit-forge init --repoName my-project -npx agentkit-forge sync +npm install -D retort # or npm install -g retort +npx retort init --repoName my-project +npx retort sync ``` **UI path:** ```bash -npx agentkit-forge ui +npx retort ui # Browser opens → visual wizard → detect stack → select tools → create overlay → sync ``` **CI path:** ```yaml -- uses: org/agentkit-forge-action@v3 +- uses: org/retort-action@v3 with: overlay: my-project version: '3.4.0' @@ -564,7 +564,7 @@ Minimal manual steps, rapid path to first agent deployed or registered: ### Competitive Analysis -| Capability | GitHub Copilot | Claude | Cursor | AgentKit Forge | +| Capability | GitHub Copilot | Claude | Cursor | Retort | | ------------------------- | -------------- | ------ | ------ | --------------------- | | Multi-tool overlay system | No | No | No | **Yes** | | PWA / UI-based editing | No | No | No | **Yes** | @@ -577,12 +577,12 @@ drift detection across AI tooling. This is a first-mover opportunity. ### Related Documents - [ADR-07: Delivery Strategy (Refined)](../architecture/decisions/07-delivery-strategy.md) -- [ADR-01: Adopt AgentKit Forge](../architecture/decisions/01-adopt-agentkit-forge.md) +- [ADR-01: Adopt Retort](../architecture/decisions/01-adopt-retort.md) - [ADR-03: Tooling Strategy](../architecture/decisions/03-tooling-strategy.md) - [Architecture Overview](../architecture/01_overview.md) - [PRD-001: LLM Decision Engine](PRD-001-llm-decision-engine.md) - [PRD-007: Adopter Autoupdate](PRD-007-adopter-autoupdate.md) — follow-on CLI capability for keeping adopter repositories current with the latest forge version; builds on the npm/CLI delivery channel established by this PRD. - See also: [#196](https://github.com/phoenixvc/agentkit-forge/issues/196), - [#194](https://github.com/phoenixvc/agentkit-forge/issues/194). + See also: [#196](https://github.com/phoenixvc/retort/issues/196), + [#194](https://github.com/phoenixvc/retort/issues/194). diff --git a/docs/product/PRD-006-pwa-desktop-visual-configuration.md b/docs/product/PRD-006-pwa-desktop-visual-configuration.md index c2bc326f..a536784b 100644 --- a/docs/product/PRD-006-pwa-desktop-visual-configuration.md +++ b/docs/product/PRD-006-pwa-desktop-visual-configuration.md @@ -1,4 +1,4 @@ -# PRD-006: AgentKit Forge PWA/Desktop Visual Configuration +# PRD-006: Retort PWA/Desktop Visual Configuration ## Status @@ -6,11 +6,11 @@ Draft ## Module / Feature Name -AgentKit Forge Visual Configuration PWA/Desktop Module +Retort Visual Configuration PWA/Desktop Module ## Marketing Name -AgentKit Forge Visual Editor (PWA/Desktop) +Retort Visual Editor (PWA/Desktop) ## Platform / Mesh Layers @@ -55,7 +55,7 @@ CLI/GitHub Action strategy per A schema-driven visual overlay/config editor and sync dashboard, deployable as a PWA or desktop app, that democratizes orchestration and delivers CLI parity and safety for the whole team. The UI is a presentation layer only — all logic lives -in the agentkit-forge engine, communicated via a JSON-RPC bridge. +in the retort engine, communicated via a JSON-RPC bridge. ## Problem Statement @@ -111,7 +111,7 @@ can update or validate configuration. ### Business Goals -- Expand agentkit-forge adoption in large organizations beyond the engineering +- Expand retort adoption in large organizations beyond the engineering team. - Drive engagement from PMs, designers, and team leads (not just developers). - Reduce dev team support and onboarding burden by at least 70%. @@ -219,7 +219,7 @@ identical sync outputs to CLI-created overlays. Acceptance criteria: -- UI sync output is byte-identical to `npx agentkit-forge sync` output. +- UI sync output is byte-identical to `npx retort sync` output. - "Show YAML" view displays the exact YAML that will be written. - All CLI capabilities for overlay management are accessible in the UI. @@ -240,7 +240,7 @@ Acceptance criteria: ``` 1. Launch PWA/Desktop App - └─ PWA: `npx agentkit-forge ui` → browser opens localhost:4827 + └─ PWA: `npx retort ui` → browser opens localhost:4827 └─ Desktop: open Tauri app → select repo folder 2. Select or connect to a repository @@ -266,7 +266,7 @@ Acceptance criteria: | Step | PWA Path | Desktop Path | Outcome | | -------------- | ----------------------- | ----------------------- | --------------- | -| Launch | `npx agentkit-forge ui` | Open app | UI ready | +| Launch | `npx retort ui` | Open app | UI ready | | Connect repo | Auto-detect from CWD | "Open Repo" file picker | Repo linked | | Create overlay | Wizard form | Wizard form | Overlay created | | Edit overlay | Schema-driven editor | Schema-driven editor | Changes staged | @@ -294,12 +294,12 @@ Acceptance criteria: ### Application Shell - **PWA (primary):** Single-page application served by - `npx agentkit-forge ui` on `localhost:4827`. Lightweight framework (Preact, + `npx retort ui` on `localhost:4827`. Lightweight framework (Preact, Svelte, or plain web components). Service worker for offline caching. Runs in any modern browser. - **Tauri desktop (follow-up):** Wraps the same web UI. ~5 MB binary (vs. ~150 MB for Electron). Built-in auto-updater. Distributed via GitHub Releases, - Homebrew (`brew install agentkit-forge`), or winget. + Homebrew (`brew install retort`), or winget. ### Overlay CRUD @@ -324,7 +324,7 @@ Acceptance criteria: ### Engine Communication -- JSON-RPC bridge over local HTTP to the agentkit-forge engine. +- JSON-RPC bridge over local HTTP to the retort engine. - No direct file system access from the browser — all mutations go through the engine API. - Same API contract consumed by CLI internally, ensuring parity. @@ -383,10 +383,10 @@ Acceptance criteria: | --------------------- | --------------------------------------------------------- | | Presentation / UI | Orchestration interface for `.agentkit/spec` overlays | | JSON-RPC bridge | Communication layer between UI and engine | -| agentkit-forge engine | All sync, validation, and output logic (shared with CLI) | +| retort engine | All sync, validation, and output logic (shared with CLI) | | Overlay directory | `.agentkit/overlays/` — source of truth persisted in repo | -State manipulations are routed through the agentkit-forge sync engine. The UI +State manipulations are routed through the retort sync engine. The UI never bypasses the engine to write files directly — no runtime-layer or team bypass is possible. @@ -421,7 +421,7 @@ bypass is possible. **PWA:** ```bash -npx agentkit-forge ui +npx retort ui # Browser opens → guided repo selection → scan overlays → wizard ``` @@ -530,7 +530,7 @@ npx agentkit-forge ui ### Technical Constraints -- Node.js / agentkit-forge CLI required for validation and sync (engine is not +- Node.js / retort CLI required for validation and sync (engine is not duplicated in the UI). - Tauri desktop app has full file system access; browser PWA is limited by browser security model (all FS operations via engine API). @@ -549,7 +549,7 @@ npx agentkit-forge ui | Dependency | Owner | Risk Level | | ---------------------------------------- | ---------------- | -------------- | -| agentkit-forge CLI/engine (JSON-RPC API) | Engineering Lead | Low (in-house) | +| retort CLI/engine (JSON-RPC API) | Engineering Lead | Low (in-house) | | UX/design collaboration | UX/UI Designer | Medium | | QA test coverage (GUI flows, parity) | QA Lead | Medium | | Pilot users for early feedback | Product Owner | Medium | @@ -610,7 +610,7 @@ npx agentkit-forge ui ### Competitive Analysis -| Capability | GitHub Copilot | Claude | Cursor | AgentKit Forge | +| Capability | GitHub Copilot | Claude | Cursor | Retort | | ------------------------------ | -------------- | ------ | ------ | -------------- | | Multi-tool overlay system | No | No | No | **Yes** | | Visual GUI overlay editing | No | No | No | **Yes** | @@ -628,5 +628,5 @@ first-mover opportunity for non-developer personas. parent PRD covering the full hybrid delivery strategy - [ADR-07: Delivery Strategy (Refined)](../architecture/decisions/07-delivery-strategy.md) — architectural decision record -- [ADR-01: Adopt AgentKit Forge](../architecture/decisions/01-adopt-agentkit-forge.md) +- [ADR-01: Adopt Retort](../architecture/decisions/01-adopt-retort.md) - [PRD-001: LLM Decision Engine](PRD-001-llm-decision-engine.md) diff --git a/docs/product/PRD-007-adopter-autoupdate.md b/docs/product/PRD-007-adopter-autoupdate.md index 55cedc56..bcf79e2c 100644 --- a/docs/product/PRD-007-adopter-autoupdate.md +++ b/docs/product/PRD-007-adopter-autoupdate.md @@ -1,4 +1,4 @@ -# PRD-007: AgentKit Forge Adopter Autoupdate +# PRD-007: Retort Adopter Autoupdate ## Status @@ -6,15 +6,15 @@ Draft ## Module / Feature Name -AgentKit Forge Autoupdate for Adopter Repositories +Retort Autoupdate for Adopter Repositories ## Marketing Name -AgentKit Forge Autoupdate +Retort Autoupdate ## Platform / Mesh Layers -- CLI toolchain (npm/npx-delivered `agentkit-forge` binary) +- CLI toolchain (npm/npx-delivered `retort` binary) - GitHub Actions CI/CD automation layer - Adopter repository bootstrap and governance pipeline @@ -22,14 +22,14 @@ AgentKit Forge Autoupdate - Developers (CLI-first) who manage adopter repositories - DevOps / Platform Engineers automating config drift detection and remediation -- Repository maintainers responsible for keeping AgentKit Forge versions current +- Repository maintainers responsible for keeping Retort versions current ## Core Value Proposition Eliminates manual version tracking in adopter repositories by providing a first-class autoupdate mechanism — delivered via CLI command, scheduled GitHub Action, and/or Renovate/Dependabot integration — so adopting teams always run -on a supported AgentKit Forge version without manual intervention. +on a supported Retort version without manual intervention. ## Priority @@ -50,13 +50,13 @@ Planned — design phase pending delivery channel GA (see PRD-005 Phase 1–3). ## TL;DR Provide a safe, opt-in autoupdate capability so that repositories adopting -AgentKit Forge can receive new forge versions without error-prone multi-step +Retort can receive new forge versions without error-prone multi-step manual upgrade ceremonies. Delivers update notifications, one-command upgrades, and CI-enforced version freshness. ## Problem Statement -Repositories that adopt AgentKit Forge via git submodule or npm devDependency +Repositories that adopt Retort via git submodule or npm devDependency today face a painful multi-step upgrade process: 1. Enter the submodule directory (or check npm for new versions manually) @@ -82,10 +82,10 @@ Specific pain points in the current state: forge version is more than N versions behind the current release. - **CLI toolchain dependency gap** — related issue: adopter repos may not have the required CLI tools installed to even perform an upgrade - (see issue [#196](https://github.com/phoenixvc/agentkit-forge/issues/196)). + (see issue [#196](https://github.com/phoenixvc/retort/issues/196)). - **Sync enforcement gap** — autoupdate is tightly coupled with the enforced sync contract described in issue - [#194](https://github.com/phoenixvc/agentkit-forge/issues/194); upgrading + [#194](https://github.com/phoenixvc/retort/issues/194); upgrading the forge version must trigger a re-sync before the PR passes validation. ## Core Challenge @@ -99,7 +99,7 @@ governance already planned for adopter repos. - PRD-005 (Mesh-Native Distribution) targets GA for the npm package delivery channel; autoupdate is a natural complement once the package is published. - ADR-07 explicitly calls out "autoupdate support" as part of the `npm install --g agentkit-forge` CLI consumer experience. +-g retort` CLI consumer experience. - Governance enforcement (#194) and CLI toolchain requirements (#196) create the prerequisite infrastructure for autoupdate to function safely. - Growing adopter base amplifies the support cost of manual upgrades. @@ -159,9 +159,9 @@ check for and apply a forge update, with a dry-run preview of what changes. Acceptance criteria: -- `agentkit-forge update` checks for new versions and prints a changelog summary. -- `agentkit-forge update --apply` upgrades and re-runs sync in one step. -- `agentkit-forge update --rollback` restores the previous version and outputs. +- `retort update` checks for new versions and prints a changelog summary. +- `retort update --apply` upgrades and re-runs sync in one step. +- `retort update --rollback` restores the previous version and outputs. - The command fails fast with clear guidance if prerequisite CLI tools are missing (see issue #196). @@ -198,13 +198,13 @@ Acceptance criteria: ### Primary Use Cases -- **CLI upgrade:** Developer runs `agentkit-forge update --apply` → version +- **CLI upgrade:** Developer runs `retort update --apply` → version bumped, sync re-run, outputs validated, PR opened. - **Automated PR:** Scheduled GitHub Action opens a forge-version bump PR automatically when a new release is available. -- **Version check only:** `agentkit-forge update --check` prints current vs +- **Version check only:** `retort update --check` prints current vs latest version without modifying anything. -- **Rollback:** `agentkit-forge update --rollback` restores the previous version +- **Rollback:** `retort update --rollback` restores the previous version if the new one broke overlay outputs. ### Core Flows @@ -212,12 +212,12 @@ Acceptance criteria: #### Flow 1: CLI One-Step Upgrade (Developer) ```text -agentkit-forge update --apply +retort update --apply → checks latest published version → compares with pinned version in adopter repo → prints changelog summary → bumps version (npm or submodule) - → re-runs agentkit-forge sync + → re-runs retort sync → validates generated output parity → opens draft PR on dev branch with diff ``` @@ -231,7 +231,7 @@ on: - cron: '0 9 * * 1' # weekly Monday 9am jobs: autoupdate: - uses: org/agentkit-forge-action@v3 + uses: org/retort-action@v3 with: mode: update overlay: my-project @@ -241,10 +241,10 @@ jobs: #### Flow 3: Version Check Only ```text -agentkit-forge update --check +retort update --check → Current: 3.2.1 (pinned in package.json) → Latest: 3.4.0 - → 2 minor versions behind. Run `agentkit-forge update --apply` to upgrade. + → 2 minor versions behind. Run `retort update --apply` to upgrade. → Changelog: [link to release notes] ``` @@ -252,11 +252,11 @@ agentkit-forge update --check | Step | CLI Path | Automated CI Path | Outcome | | ----------------- | ---------------------------------- | ------------------------------ | -------------------------------- | -| Detect update | `agentkit-forge update --check` | Scheduled Action detects delta | New version identified | +| Detect update | `retort update --check` | Scheduled Action detects delta | New version identified | | Preview changelog | Printed in CLI output | PR body contains changelog | Team informed of changes | -| Apply update | `agentkit-forge update --apply` | Action bumps version, re-syncs | Overlay outputs regenerated | +| Apply update | `retort update --apply` | Action bumps version, re-syncs | Overlay outputs regenerated | | Validate | Sync output diff printed; CI check | PR checks validate drift | Regression surfaced before merge | -| Rollback | `agentkit-forge update --rollback` | Close PR / revert commit | Previous state restored | +| Rollback | `retort update --rollback` | Close PR / revert commit | Previous state restored | ## Functional Requirements @@ -264,11 +264,11 @@ agentkit-forge update --check | Command | Description | | ----------------------------------- | ------------------------------------------------------ | -| `agentkit-forge update` | Check for updates and print summary (no-op, dry-run) | -| `agentkit-forge update --apply` | Upgrade to latest version and re-run sync | -| `agentkit-forge update --check` | Alias for default: check-only, machine-readable output | -| `agentkit-forge update --version X` | Upgrade to a specific version X (pinned upgrade) | -| `agentkit-forge update --rollback` | Restore previously pinned version and sync outputs | +| `retort update` | Check for updates and print summary (no-op, dry-run) | +| `retort update --apply` | Upgrade to latest version and re-run sync | +| `retort update --check` | Alias for default: check-only, machine-readable output | +| `retort update --version X` | Upgrade to a specific version X (pinned upgrade) | +| `retort update --rollback` | Restore previously pinned version and sync outputs | ### GitHub Action @@ -290,7 +290,7 @@ agentkit-forge update --check ### Prerequisite Checks -- `update --apply` runs a preflight check equivalent to `agentkit-forge doctor` +- `update --apply` runs a preflight check equivalent to `retort doctor` to validate CLI toolchain availability (addresses #196 requirements). - If required tools are missing, upgrade is blocked with an actionable error message including installation instructions. @@ -313,11 +313,11 @@ agentkit-forge update --check | Issue | Title | Relationship | | -------------------------------------------------------------- | ------------------------------------------------------ | --------------------------------------------------------------------- | -| [#196](https://github.com/phoenixvc/agentkit-forge/issues/196) | adoption/startup-hooks: enforce required CLI toolchain | Prerequisite: autoupdate preflight reuses CLI toolchain validation | -| [#194](https://github.com/phoenixvc/agentkit-forge/issues/194) | governance: enforce agentkit sync pre-PR for adopters | Prerequisite: `update --apply` must trigger sync to satisfy this gate | +| [#196](https://github.com/phoenixvc/retort/issues/196) | adoption/startup-hooks: enforce required CLI toolchain | Prerequisite: autoupdate preflight reuses CLI toolchain validation | +| [#194](https://github.com/phoenixvc/retort/issues/194) | governance: enforce agentkit sync pre-PR for adopters | Prerequisite: `update --apply` must trigger sync to satisfy this gate | | [PRD-005](./PRD-005-mesh-native-distribution.md) | Mesh-Native Distribution | Parent delivery strategy; autoupdate is a Phase 4+ CLI capability | | [ADR-07](../architecture/decisions/07-delivery-strategy.md) | Delivery Strategy | Architectural decisions that autoupdate must respect (npm, GH Action) | -| [#241](https://github.com/phoenixvc/agentkit-forge/issues/241) | feat(analytics): cross-repo usage telemetry | Future: telemetry can track autoupdate adoption and version currency | +| [#241](https://github.com/phoenixvc/retort/issues/241) | feat(analytics): cross-repo usage telemetry | Future: telemetry can track autoupdate adoption and version currency | ## Milestone @@ -326,14 +326,14 @@ which groups delivery-method improvements for adopter repositories. Related issues to include in this milestone: - This autoupdate feature issue -- [#196](https://github.com/phoenixvc/agentkit-forge/issues/196) — CLI toolchain enforcement -- [#194](https://github.com/phoenixvc/agentkit-forge/issues/194) — agentkit sync enforcement +- [#196](https://github.com/phoenixvc/retort/issues/196) — CLI toolchain enforcement +- [#194](https://github.com/phoenixvc/retort/issues/194) — agentkit sync enforcement ## Acceptance Criteria -- [ ] `agentkit-forge update` (check-only) prints current vs. latest version with changelog link. -- [ ] `agentkit-forge update --apply` upgrades, re-syncs, and validates output parity in one command. -- [ ] `agentkit-forge update --rollback` restores previous version and outputs. +- [ ] `retort update` (check-only) prints current vs. latest version with changelog link. +- [ ] `retort update --apply` upgrades, re-syncs, and validates output parity in one command. +- [ ] `retort update --rollback` restores previous version and outputs. - [ ] GitHub Action template generated by agentkit:sync supports weekly auto-update PRs. - [ ] Preflight check validates CLI toolchain availability before attempting upgrade (covers #196). - [ ] Upgrade flow always triggers sync, satisfying the pre-PR sync contract (covers #194). @@ -347,5 +347,5 @@ issues to include in this milestone: - [ADR-07: Delivery Strategy](../architecture/decisions/07-delivery-strategy.md) - [PRD-005: Mesh-Native Distribution](./PRD-005-mesh-native-distribution.md) - [PRD-006: PWA/Desktop Visual Configuration](./PRD-006-pwa-desktop-visual-configuration.md) -- [Issue #196: CLI Toolchain Enforcement](https://github.com/phoenixvc/agentkit-forge/issues/196) -- [Issue #194: agentkit sync Enforcement for Adopters](https://github.com/phoenixvc/agentkit-forge/issues/194) +- [Issue #196: CLI Toolchain Enforcement](https://github.com/phoenixvc/retort/issues/196) +- [Issue #194: agentkit sync Enforcement for Adopters](https://github.com/phoenixvc/retort/issues/194) diff --git a/docs/product/README.md b/docs/product/README.md index ce11aaf5..2054f1b9 100644 --- a/docs/product/README.md +++ b/docs/product/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Product Docs Index diff --git a/docs/reference/01_glossary.md b/docs/reference/01_glossary.md index 17b0ee9d..41e7e5b0 100644 --- a/docs/reference/01_glossary.md +++ b/docs/reference/01_glossary.md @@ -1,14 +1,14 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Glossary -## AgentKit Forge Terms +## Retort Terms | Term | Definition | | -------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| **AgentKit Forge** | An opinionated project scaffolding and documentation generation tool. | +| **Retort** | An opinionated project scaffolding and documentation generation tool. | | **Spec** | The source-of-truth configuration that defines project structure and templates. | | **Overlay** | A per-project customisation layer applied on top of the base spec. | | **Sync** | The process of regenerating files from the spec and overlays (`agentkit:sync`). | diff --git a/docs/reference/02_faq.md b/docs/reference/02_faq.md index a2e2d460..e7f82905 100644 --- a/docs/reference/02_faq.md +++ b/docs/reference/02_faq.md @@ -1,12 +1,12 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Frequently Asked Questions ## General -### What is agentkit-forge? +### What is retort? <!-- Provide a brief description of the project. --> @@ -14,13 +14,13 @@ See the [Development Setup](../engineering/01_setup.md) guide. -## AgentKit Forge +## Retort ### What are the generated files? -Files with the `GENERATED by AgentKit Forge` header are produced by the sync +Files with the `GENERATED by Retort` header are produced by the sync process and should not be edited directly. Customise them via overlays at -`.agentkit/overlays/agentkit-forge`. +`.agentkit/overlays/retort`. ### How do I regenerate the documentation? diff --git a/docs/reference/03_changelog.md b/docs/reference/03_changelog.md index 3b95b019..ed02bfb1 100644 --- a/docs/reference/03_changelog.md +++ b/docs/reference/03_changelog.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Changelog diff --git a/docs/reference/04_contributing.md b/docs/reference/04_contributing.md index fc81dae2..0a12bdc7 100644 --- a/docs/reference/04_contributing.md +++ b/docs/reference/04_contributing.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Contributing diff --git a/docs/reference/05_project_yaml_reference.md b/docs/reference/05_project_yaml_reference.md index ded3b7eb..6420c00e 100644 --- a/docs/reference/05_project_yaml_reference.md +++ b/docs/reference/05_project_yaml_reference.md @@ -1,7 +1,7 @@ # project.yaml Reference > Canonical configuration for project-level metadata consumed by -> AgentKit Forge's sync engine. All fields are **optional** — if +> Retort's sync engine. All fields are **optional** — if > missing, sync produces generic output. ## Sections diff --git a/docs/reference/README.md b/docs/reference/README.md index 3921959d..45620ea4 100644 --- a/docs/reference/README.md +++ b/docs/reference/README.md @@ -1,5 +1,5 @@ -<!-- GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT --> -<!-- Source: .agentkit/spec + .agentkit/overlays/agentkit-forge --> +<!-- GENERATED by Retort v3.1.0 — DO NOT EDIT --> +<!-- Source: .agentkit/spec + .agentkit/overlays/retort --> <!-- Regenerate: pnpm -C .agentkit agentkit:sync --> # Reference Docs Index diff --git a/docs/reference/agent-prompt-comparative-analysis.md b/docs/reference/agent-prompt-comparative-analysis.md index 3312f29a..cf2c308e 100644 --- a/docs/reference/agent-prompt-comparative-analysis.md +++ b/docs/reference/agent-prompt-comparative-analysis.md @@ -8,7 +8,7 @@ | **Prompt 2** | Structured markdown with meta-instructions | CLAUDE.md-style developer persona | ~2,200 | | **Prompt 3** | YAML frontmatter + concise markdown | `.github/agents/backend.agent.md` (Copilot agent) | ~750 | -All three prompts define the same "Senior Backend Engineer" role within the AgentKit Forge multi-agent system. They share identical focus areas, responsibilities, domain rules, and tooling. The differences lie in structure, depth, and operational guidance. +All three prompts define the same "Senior Backend Engineer" role within the Retort multi-agent system. They share identical focus areas, responsibilities, domain rules, and tooling. The differences lie in structure, depth, and operational guidance. --- @@ -140,7 +140,7 @@ All three prompts define the same "Senior Backend Engineer" role within the Agen ### 3rd Place: Prompt 3 (Copilot Agent YAML + Markdown) -**Why it's third:** Extremely token-efficient and well-structured for a configuration-driven system. However, it critically lacks concurrency controls, error handling guidance, and an autonomous decision framework. In a single-agent or human-supervised context, this prompt would be adequate. In a multi-agent autonomous environment like AgentKit Forge, the missing operational guidance makes it insufficient without heavy reliance on external documentation. +**Why it's third:** Extremely token-efficient and well-structured for a configuration-driven system. However, it critically lacks concurrency controls, error handling guidance, and an autonomous decision framework. In a single-agent or human-supervised context, this prompt would be adequate. In a multi-agent autonomous environment like Retort, the missing operational guidance makes it insufficient without heavy reliance on external documentation. --- diff --git a/docs/reference/agentkit_adopter_branch_governance_checklist.md b/docs/reference/agentkit_adopter_branch_governance_checklist.md index 42e1d54c..455ad0b8 100644 --- a/docs/reference/agentkit_adopter_branch_governance_checklist.md +++ b/docs/reference/agentkit_adopter_branch_governance_checklist.md @@ -1,23 +1,23 @@ -# AgentKit Adopter Branch Governance Checklist +# Retort Adopter Branch Governance Checklist ## Purpose -Apply the branch-governance profile to repositories that implement AgentKit Forge until template/spec automation is merged. +Apply the branch-governance profile to repositories that implement Retort until template/spec automation is merged. ## Governance source -- Rollout tracker: [Issue #167](https://github.com/phoenixvc/agentkit-forge/issues/167) -- Policy issue: [Issue #168](https://github.com/phoenixvc/agentkit-forge/issues/168) -- Infrastructure issue: [Issue #169](https://github.com/phoenixvc/agentkit-forge/issues/169) +- Rollout tracker: [Issue #167](https://github.com/phoenixvc/retort/issues/167) +- Policy issue: [Issue #168](https://github.com/phoenixvc/retort/issues/168) +- Infrastructure issue: [Issue #169](https://github.com/phoenixvc/retort/issues/169) ## Implementation checklist (per adopting repo) -- [ ] Confirm repository is enrolled in AgentKit implementer policy profile. +- [ ] Confirm repository is enrolled in Retort implementer policy profile. - [ ] Set default branch to `dev` (with owner approval and migration notice). - [ ] Enable branch protection for `dev` with required status checks and reviews. - [ ] Enable branch protection for `main` with required status checks and reviews. - [ ] Add/enable a required check that blocks direct changes to `.agentkit/**` in PRs targeting `dev` or `main`. -- [ ] Require upstream issue linkage for `.agentkit/**` change requests (must reference `phoenixvc/agentkit-forge` issue URL). +- [ ] Require upstream issue linkage for `.agentkit/**` change requests (must reference `phoenixvc/retort` issue URL). - [ ] Document exception path for maintainers (emergency only, audited): [Maintainer Exception Policy](maintainer_exception_policy.md). - [ ] Update contributor docs in the adopting repo to reflect `dev` default and upstream-first `.agentkit` policy. @@ -32,7 +32,7 @@ Apply the branch-governance profile to repositories that implement AgentKit Forg If a PR targets `dev` or `main` and includes `.agentkit/**` changes: -1. It must link a tracking issue in `phoenixvc/agentkit-forge`. +1. It must link a tracking issue in `phoenixvc/retort`. 2. If no upstream issue exists, PR must fail with actionable guidance to open one. 3. Local/direct template-source edits are rejected unless explicitly approved under [Maintainer Exception Policy](maintainer_exception_policy.md). diff --git a/docs/reference/agentkit_sync_integration_patch_plan.md b/docs/reference/agentkit_sync_integration_patch_plan.md index fd524ede..56d0de6d 100644 --- a/docs/reference/agentkit_sync_integration_patch_plan.md +++ b/docs/reference/agentkit_sync_integration_patch_plan.md @@ -1,8 +1,8 @@ -# AgentKit Sync Integration Patch Plan +# Retort Sync Integration Patch Plan ## Why this exists -This plan provides a maintainer-ready implementation blueprint to move branch-governance guardrails from runtime repo files into AgentKit sync source-of-truth. +This plan provides a maintainer-ready implementation blueprint to move branch-governance guardrails from runtime repo files into Retort sync source-of-truth. ## Target outcome @@ -41,7 +41,7 @@ In generated branch-protection workflow: - Trigger applies to PRs targeting `dev` and `main`. - If PR touches `.agentkit/**`, PR body must contain upstream issue URL pattern: - - [https://github.com/phoenixvc/agentkit-forge/issues/<number>](https://github.com/phoenixvc/agentkit-forge/issues/<number>) + - [https://github.com/phoenixvc/retort/issues/<number>](https://github.com/phoenixvc/retort/issues/<number>) - On missing link, required check fails with clear remediation message. ### 2) Branch protection script behavior diff --git a/docs/reference/analysis/README.md b/docs/reference/analysis/README.md index 37eccfc7..458e36e9 100644 --- a/docs/reference/analysis/README.md +++ b/docs/reference/analysis/README.md @@ -15,4 +15,4 @@ defined in [PRD-001](../../product/PRD-001-llm-decision-engine.md). - [PRD-001: LLM Decision Engine](../../product/PRD-001-llm-decision-engine.md) - [PRD-004: Technical API Contracts](../../architecture/specs/PRD-004-technical-api-contracts.md) -- Phase tracking issues: [#220](https://github.com/phoenixvc/agentkit-forge/issues/220), [#221](https://github.com/phoenixvc/agentkit-forge/issues/221), [#222](https://github.com/phoenixvc/agentkit-forge/issues/222), [#223](https://github.com/phoenixvc/agentkit-forge/issues/223), [#224](https://github.com/phoenixvc/agentkit-forge/issues/224), [#225](https://github.com/phoenixvc/agentkit-forge/issues/225) +- Phase tracking issues: [#220](https://github.com/phoenixvc/retort/issues/220), [#221](https://github.com/phoenixvc/retort/issues/221), [#222](https://github.com/phoenixvc/retort/issues/222), [#223](https://github.com/phoenixvc/retort/issues/223), [#224](https://github.com/phoenixvc/retort/issues/224), [#225](https://github.com/phoenixvc/retort/issues/225) diff --git a/docs/reference/analysis/language-aware-hooks-phase-plan.md b/docs/reference/analysis/language-aware-hooks-phase-plan.md index 8ae842ac..b233e83b 100644 --- a/docs/reference/analysis/language-aware-hooks-phase-plan.md +++ b/docs/reference/analysis/language-aware-hooks-phase-plan.md @@ -157,15 +157,15 @@ This sequence preserves current correctness while adding bootstrap resilience wi ### Phase 2 issues (Templates) -- #220 — https://github.com/phoenixvc/agentkit-forge/issues/220 — `OPEN` -- #221 — https://github.com/phoenixvc/agentkit-forge/issues/221 — `OPEN` -- #222 — https://github.com/phoenixvc/agentkit-forge/issues/222 — `OPEN` +- #220 — https://github.com/phoenixvc/retort/issues/220 — `OPEN` +- #221 — https://github.com/phoenixvc/retort/issues/221 — `OPEN` +- #222 — https://github.com/phoenixvc/retort/issues/222 — `OPEN` ### Phase 3 issues (CSS & HTML) -- #223 — https://github.com/phoenixvc/agentkit-forge/issues/223 — `OPEN` -- #224 — https://github.com/phoenixvc/agentkit-forge/issues/224 — `OPEN` -- #225 — https://github.com/phoenixvc/agentkit-forge/issues/225 — `OPEN` +- #223 — https://github.com/phoenixvc/retort/issues/223 — `OPEN` +- #224 — https://github.com/phoenixvc/retort/issues/224 — `OPEN` +- #225 — https://github.com/phoenixvc/retort/issues/225 — `OPEN` ### Current implementation alignment diff --git a/docs/reference/analysis/model-quirks-analysis.md b/docs/reference/analysis/model-quirks-analysis.md index 2fe565a7..9460cfc9 100644 --- a/docs/reference/analysis/model-quirks-analysis.md +++ b/docs/reference/analysis/model-quirks-analysis.md @@ -1,7 +1,7 @@ # Model Quirks Analysis **Last Updated:** 2026-02-26 -**Scope:** Systematic exploration of model-specific quirks for the AgentKit decision engine +**Scope:** Systematic exploration of model-specific quirks for the Retort decision engine **Purpose:** Enhance the "quirks" scoring dimension with specific, actionable model behaviors ## Overview diff --git a/docs/reference/analysis/quirks-scoring-implementation.md b/docs/reference/analysis/quirks-scoring-implementation.md index 2c8c971d..9f2f20be 100644 --- a/docs/reference/analysis/quirks-scoring-implementation.md +++ b/docs/reference/analysis/quirks-scoring-implementation.md @@ -1,7 +1,7 @@ # Quirks Scoring Implementation Guide **Last Updated:** 2026-02-26 -**Purpose:** Implement numerical scoring for model quirks in the AgentKit decision engine +**Purpose:** Implement numerical scoring for model quirks in the Retort decision engine **Scope:** Integration with PRD-001 weighted decision matrix ## Overview diff --git a/docs/reference/cli_delivery_improvements_milestone.md b/docs/reference/cli_delivery_improvements_milestone.md index a83442cc..73ec8c62 100644 --- a/docs/reference/cli_delivery_improvements_milestone.md +++ b/docs/reference/cli_delivery_improvements_milestone.md @@ -5,11 +5,11 @@ Delivery-method improvements for adopter repositories: CLI toolchain enforcement, agentkit sync governance, and first-class autoupdate capability. This milestone groups the issues that collectively complete the "adoption lifecycle loop" for -repositories that have integrated AgentKit Forge. +repositories that have integrated Retort. ## Milestone -- Repository: `phoenixvc/agentkit-forge` +- Repository: `phoenixvc/retort` - Milestone: `CLI Distribution & Delivery Improvements` - Milestone number: `#2` (created) @@ -17,16 +17,16 @@ repositories that have integrated AgentKit Forge. | # | Title | Status | PRD / Spec | | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------ | --------------------------------------------------- | -| [#196](https://github.com/phoenixvc/agentkit-forge/issues/196) | adoption/startup-hooks: enforce required CLI toolchain availability (gh, az, etc.) | Open | N/A | -| [#194](https://github.com/phoenixvc/agentkit-forge/issues/194) | governance: enforce agentkit sync pre-PR (blocking) and post-commit (non-blocking) for adopters | Open | N/A | -| [#258](https://github.com/phoenixvc/agentkit-forge/issues/258) | feat(cli): implement autoupdate functionality for repositories adopting AgentKit Forge | Open | [PRD-007](../product/PRD-007-adopter-autoupdate.md) | +| [#196](https://github.com/phoenixvc/retort/issues/196) | adoption/startup-hooks: enforce required CLI toolchain availability (gh, az, etc.) | Open | N/A | +| [#194](https://github.com/phoenixvc/retort/issues/194) | governance: enforce agentkit sync pre-PR (blocking) and post-commit (non-blocking) for adopters | Open | N/A | +| [#258](https://github.com/phoenixvc/retort/issues/258) | feat(cli): implement autoupdate functionality for repositories adopting Retort | Open | [PRD-007](../product/PRD-007-adopter-autoupdate.md) | > **Status update:** Milestone and autoupdate issue have been created. > -> - Milestone: [#2](https://github.com/phoenixvc/agentkit-forge/milestone/2) -> - Autoupdate issue: [#258](https://github.com/phoenixvc/agentkit-forge/issues/258) -> - Cross-reference comments added on [#196](https://github.com/phoenixvc/agentkit-forge/issues/196) -> and [#194](https://github.com/phoenixvc/agentkit-forge/issues/194) +> - Milestone: [#2](https://github.com/phoenixvc/retort/milestone/2) +> - Autoupdate issue: [#258](https://github.com/phoenixvc/retort/issues/258) +> - Cross-reference comments added on [#196](https://github.com/phoenixvc/retort/issues/196) +> and [#194](https://github.com/phoenixvc/retort/issues/194) ## Cross-References (Issue Updates Applied) @@ -40,7 +40,7 @@ Template that was added to the issue body/comment: ```markdown ## Related -- See also: [feat(cli): implement autoupdate for adopter repositories](https://github.com/phoenixvc/agentkit-forge/issues/258) +- See also: [feat(cli): implement autoupdate for adopter repositories](https://github.com/phoenixvc/retort/issues/258) — autoupdate preflight checks reuse the CLI toolchain validation requirements defined here. - Milestone: CLI Distribution & Delivery Improvements ``` @@ -52,7 +52,7 @@ Template that was added to the issue body/comment: ```markdown ## Related -- See also: [feat(cli): implement autoupdate for adopter repositories](https://github.com/phoenixvc/agentkit-forge/issues/258) +- See also: [feat(cli): implement autoupdate for adopter repositories](https://github.com/phoenixvc/retort/issues/258) — `update --apply` must trigger sync as part of its upgrade flow, satisfying the pre-PR sync enforcement contract defined here. - Milestone: CLI Distribution & Delivery Improvements @@ -64,7 +64,7 @@ Copy the following as the body for the new GitHub issue: --- -**Title:** `feat(cli): implement autoupdate functionality for repositories adopting AgentKit Forge` +**Title:** `feat(cli): implement autoupdate functionality for repositories adopting Retort` **Labels:** `enhancement` @@ -76,7 +76,7 @@ Copy the following as the body for the new GitHub issue: ## Summary Implement a first-class autoupdate mechanism so that repositories adopting -AgentKit Forge can receive and apply new forge versions without manual, +Retort can receive and apply new forge versions without manual, multi-step upgrade ceremonies. ## Context @@ -87,17 +87,17 @@ adopter repos accumulate version drift, triggering avoidable CI failures when new forge versions introduce breaking template changes. This issue tracks delivery of the autoupdate capability as described in -[PRD-007](https://github.com/phoenixvc/agentkit-forge/blob/dev/docs/product/PRD-007-adopter-autoupdate.md), building on the +[PRD-007](https://github.com/phoenixvc/retort/blob/dev/docs/product/PRD-007-adopter-autoupdate.md), building on the delivery channel established in -[ADR-07](https://github.com/phoenixvc/agentkit-forge/blob/dev/docs/architecture/decisions/07-delivery-strategy.md) and -[PRD-005](https://github.com/phoenixvc/agentkit-forge/blob/dev/docs/product/PRD-005-mesh-native-distribution.md). +[ADR-07](https://github.com/phoenixvc/retort/blob/dev/docs/architecture/decisions/07-delivery-strategy.md) and +[PRD-005](https://github.com/phoenixvc/retort/blob/dev/docs/product/PRD-005-mesh-native-distribution.md). ## Scope -- [ ] Add `agentkit-forge update` CLI command (check-only, dry-run by default). -- [ ] Add `agentkit-forge update --apply` — upgrades version, re-runs sync, validates outputs. -- [ ] Add `agentkit-forge update --rollback` — restores previous version and sync outputs. -- [ ] Add `agentkit-forge update --version X` — pin-upgrade to a specific version. +- [ ] Add `retort update` CLI command (check-only, dry-run by default). +- [ ] Add `retort update --apply` — upgrades version, re-runs sync, validates outputs. +- [ ] Add `retort update --rollback` — restores previous version and sync outputs. +- [ ] Add `retort update --version X` — pin-upgrade to a specific version. - [ ] GitHub Action template: scheduled workflow that opens an auto-update PR when the pinned forge version is behind the latest stable release. - [ ] Preflight checks validate CLI toolchain availability before attempting upgrade @@ -108,9 +108,9 @@ delivery channel established in ## Acceptance Criteria -- [ ] `agentkit-forge update` (check-only) prints current vs. latest version with changelog link. -- [ ] `agentkit-forge update --apply` upgrades, re-syncs, and validates output parity in one command. -- [ ] `agentkit-forge update --rollback` restores previous version and outputs. +- [ ] `retort update` (check-only) prints current vs. latest version with changelog link. +- [ ] `retort update --apply` upgrades, re-syncs, and validates output parity in one command. +- [ ] `retort update --rollback` restores previous version and outputs. - [ ] GitHub Action template supports weekly auto-update PRs. - [ ] Preflight check validates CLI toolchain (covers #196). - [ ] Upgrade triggers sync, satisfying pre-PR sync contract (covers #194). @@ -121,8 +121,8 @@ delivery channel established in - Prereq: #196 — CLI toolchain enforcement (preflight check dependency) - Prereq: #194 — agentkit sync pre-PR enforcement (sync gate dependency) -- Parent PRD: [PRD-007: Adopter Autoupdate](https://github.com/phoenixvc/agentkit-forge/blob/dev/docs/product/PRD-007-adopter-autoupdate.md) -- Delivery strategy: [ADR-07](https://github.com/phoenixvc/agentkit-forge/blob/dev/docs/architecture/decisions/07-delivery-strategy.md) +- Parent PRD: [PRD-007: Adopter Autoupdate](https://github.com/phoenixvc/retort/blob/dev/docs/product/PRD-007-adopter-autoupdate.md) +- Delivery strategy: [ADR-07](https://github.com/phoenixvc/retort/blob/dev/docs/architecture/decisions/07-delivery-strategy.md) - Analytics: #241 (telemetry events for version tracking) ``` diff --git a/docs/reference/governance_issue_file_impact_map.md b/docs/reference/governance_issue_file_impact_map.md index d3aa8a63..7dcc5299 100644 --- a/docs/reference/governance_issue_file_impact_map.md +++ b/docs/reference/governance_issue_file_impact_map.md @@ -35,7 +35,7 @@ Epic-level impacted files/components: Ownership: -- Primary: `phoenixvc/agentkit-forge` maintainers +- Primary: `phoenixvc/retort` maintainers - Linked downstream: `phoenixvc/ai-gateway`, `phoenixvc/pvc-costops-analytics` --- diff --git a/docs/reference/issue_170_patch_blocks.md b/docs/reference/issue_170_patch_blocks.md index e91a5012..d38bead3 100644 --- a/docs/reference/issue_170_patch_blocks.md +++ b/docs/reference/issue_170_patch_blocks.md @@ -22,7 +22,7 @@ Use the same logic as current runtime workflow in `.github/workflows/branch-prot - `pull_request` branches: `[main, dev]` - dynamic secret-scan diff base: `origin/${{ github.event.pull_request.base.ref }}...HEAD` - guardrail step: fail PR when `.agentkit/**` changed and PR body lacks upstream issue URL matching: - - `https://github.com/phoenixvc/agentkit-forge/issues/<number>` + - `https://github.com/phoenixvc/retort/issues/<number>` Recommended source for exact content: diff --git a/docs/reference/maintainer_exception_policy.md b/docs/reference/maintainer_exception_policy.md index cae9cca2..6f77790c 100644 --- a/docs/reference/maintainer_exception_policy.md +++ b/docs/reference/maintainer_exception_policy.md @@ -2,7 +2,7 @@ ## Purpose -Define the exception process for emergency changes that would otherwise be blocked by AgentKit branch-governance guardrails. +Define the exception process for emergency changes that would otherwise be blocked by Retort branch-governance guardrails. ## Allowed use @@ -12,7 +12,7 @@ Define the exception process for emergency changes that would otherwise be block ## Required controls -1. Open or reference a tracking issue in `phoenixvc/agentkit-forge`. +1. Open or reference a tracking issue in `phoenixvc/retort`. 2. Include rationale, scope, and rollback plan in the PR description. 3. Require at least one maintainer approval before merge. 4. Add post-incident follow-up task to restore normal policy path. diff --git a/docs/reference/research/aider-polyglot-leaderboard-2025.md b/docs/reference/research/aider-polyglot-leaderboard-2025.md index 45b0a772..b8e0775c 100644 --- a/docs/reference/research/aider-polyglot-leaderboard-2025.md +++ b/docs/reference/research/aider-polyglot-leaderboard-2025.md @@ -83,7 +83,7 @@ a meaningful uplift, but Claude still trails GPT-5 on this benchmark. **Agentic scaffolding inflates scores.** The Refact.ai 93.3 % result highlights that the _workflow_ (plan, code, test, iterate) is often more important than the underlying model. This is consistent with the -AgentKit Forge design principle of optimising the agent harness alongside +Retort design principle of optimising the agent harness alongside model selection. --- @@ -100,7 +100,7 @@ Key data points available in the dossiers: --- -## Implications for AgentKit Forge model guides +## Implications for Retort model guides - GPT-5.2 / 5.3 Codex High justifies its Tier 1 placement in Backend and Security guides despite a weaker long-context story — it wins on @@ -110,6 +110,6 @@ Key data points available in the dossiers: - Claude Opus 4.x should remain primary where multi-file reasoning and large context are needed, but should not be assumed best for all coding scenarios — GPT-5 family and Gemini are stronger on narrow code-edit tasks. -- The agentic scaffold (how AgentKit Forge chains tool calls) may have +- The agentic scaffold (how Retort chains tool calls) may have more impact on end-to-end results than the ±5 % differences between top-tier models. diff --git a/docs/reference/research/best-llm-for-coding-teams-2026.md b/docs/reference/research/best-llm-for-coding-teams-2026.md index 9e465a64..b964dc77 100644 --- a/docs/reference/research/best-llm-for-coding-teams-2026.md +++ b/docs/reference/research/best-llm-for-coding-teams-2026.md @@ -146,7 +146,7 @@ operational constraints on API-based models. --- -## Implications for AgentKit Forge model guides +## Implications for Retort model guides - The hybrid recommendation is already reflected in the 10 team guides: each guide has a primary and 1–2 cost-aware or context-specific diff --git a/docs/reference/research/swe-bench-leaderboard-feb-2026.md b/docs/reference/research/swe-bench-leaderboard-feb-2026.md index c9ddf459..1ddbdffa 100644 --- a/docs/reference/research/swe-bench-leaderboard-feb-2026.md +++ b/docs/reference/research/swe-bench-leaderboard-feb-2026.md @@ -77,11 +77,11 @@ more general Pro variants. **Benchmark harness matters.** Results can vary materially depending on agent scaffold (SWE-agent, Moatless, OpenHands, etc.). The leaderboard numbers above are for the published scaffold reported by each team; -internal AgentKit evaluations using a custom scaffold may differ. +internal Retort evaluations using a custom scaffold may differ. --- -## Implications for AgentKit Forge model guides +## Implications for Retort model guides - The Tier 1 choices in the team guides (Claude Opus 4.6, GPT-5.3 Codex High) are consistent with this leaderboard. diff --git a/docs/reference/router_integration_governance_rollout.md b/docs/reference/router_integration_governance_rollout.md index b9ba8785..71b085a8 100644 --- a/docs/reference/router_integration_governance_rollout.md +++ b/docs/reference/router_integration_governance_rollout.md @@ -6,26 +6,26 @@ Issue-first governance rollout for router-specialist integration with no direct ## Milestone -- Repository: `phoenixvc/agentkit-forge` +- Repository: `phoenixvc/retort` - Milestone: `Router Integration Governance Rollout` (`#1`) ## Epic and child issues -- Epic: #159 — [Issue #159](https://github.com/phoenixvc/agentkit-forge/issues/159) -- A: #160 — [Issue #160](https://github.com/phoenixvc/agentkit-forge/issues/160) -- B: #161 — [Issue #161](https://github.com/phoenixvc/agentkit-forge/issues/161) -- C: #162 — [Issue #162](https://github.com/phoenixvc/agentkit-forge/issues/162) -- D: #163 — [Issue #163](https://github.com/phoenixvc/agentkit-forge/issues/163) -- E: #164 — [Issue #164](https://github.com/phoenixvc/agentkit-forge/issues/164) -- F: #165 — [Issue #165](https://github.com/phoenixvc/agentkit-forge/issues/165) -- G: #166 — [Issue #166](https://github.com/phoenixvc/agentkit-forge/issues/166) +- Epic: #159 — [Issue #159](https://github.com/phoenixvc/retort/issues/159) +- A: #160 — [Issue #160](https://github.com/phoenixvc/retort/issues/160) +- B: #161 — [Issue #161](https://github.com/phoenixvc/retort/issues/161) +- C: #162 — [Issue #162](https://github.com/phoenixvc/retort/issues/162) +- D: #163 — [Issue #163](https://github.com/phoenixvc/retort/issues/163) +- E: #164 — [Issue #164](https://github.com/phoenixvc/retort/issues/164) +- F: #165 — [Issue #165](https://github.com/phoenixvc/retort/issues/165) +- G: #166 — [Issue #166](https://github.com/phoenixvc/retort/issues/166) ## Branch governance rollout (new) -- Tracker: #167 — [Issue #167](https://github.com/phoenixvc/agentkit-forge/issues/167) -- Policy: #168 — [Issue #168](https://github.com/phoenixvc/agentkit-forge/issues/168) -- Infrastructure: #169 — [Issue #169](https://github.com/phoenixvc/agentkit-forge/issues/169) -- Immediate guardrail: #170 — [Issue #170](https://github.com/phoenixvc/agentkit-forge/issues/170) +- Tracker: #167 — [Issue #167](https://github.com/phoenixvc/retort/issues/167) +- Policy: #168 — [Issue #168](https://github.com/phoenixvc/retort/issues/168) +- Infrastructure: #169 — [Issue #169](https://github.com/phoenixvc/retort/issues/169) +- Immediate guardrail: #170 — [Issue #170](https://github.com/phoenixvc/retort/issues/170) ## Dependency map @@ -53,7 +53,7 @@ Each child issue must include and satisfy this closure gate before status moves ## Plan decisions (locked) -- Issue-first governance only in `agentkit-forge` for this phase. +- Issue-first governance only in `retort` for this phase. - One dedicated milestone for coordinated execution. - Full render-target matrix is in scope. - FinOps scope includes rule domain + Phase 1 spec doc + skill note. diff --git a/infra/README.md b/infra/README.md index bcb82b5d..9f2b12e6 100644 --- a/infra/README.md +++ b/infra/README.md @@ -1,6 +1,12 @@ +<<<<<<< HEAD +# Infrastructure — retort + +This directory holds infrastructure and staging guidance for the Retort framework repository. +======= # Infrastructure — agentkit-forge This directory holds infrastructure and staging guidance for the AgentKit Forge framework repository. +>>>>>>> origin/main ## Staging and local validation @@ -8,7 +14,11 @@ This repo is **framework-only**: it does not deploy a runnable application. Ther - **Local:** Run `pnpm install` and `pnpm -C .agentkit agentkit:sync` (and optionally `pnpm -C .agentkit agentkit:validate`) from the repo root. - **Staging-like:** Use the root `docker-compose.yml` to run sync in a container: `docker compose --profile sync run --rm agentkit-sync`. +<<<<<<< HEAD +- **Adopters:** Projects that use Retort should define their own staging (e.g. in their `infra/`, Terraform, or Docker Compose) and deploy their application there. +======= - **Adopters:** Projects that use AgentKit Forge should define their own staging (e.g. in their `infra/`, Terraform, or Docker Compose) and deploy their application there. +>>>>>>> origin/main ## Naming and IaC diff --git a/migrations/README.md b/migrations/README.md index 2b0b3678..4a3d5868 100644 --- a/migrations/README.md +++ b/migrations/README.md @@ -1,6 +1,12 @@ +<<<<<<< HEAD +# Migrations — retort + +This repository (**retort**) is the framework and has **no database or migrations**. This directory is a placeholder for adopters. +======= # Migrations — agentkit-forge This repository (**agentkit-forge**) is the framework and has **no database or migrations**. This directory is a placeholder for adopters. +>>>>>>> origin/main ## For adopters diff --git a/package-lock.json b/package-lock.json index a38b2945..24372cf6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,10 +1,10 @@ { - "name": "agentkit-forge-root", + "name": "retort-root", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "agentkit-forge-root", + "name": "retort-root", "dependencies": { "js-yaml": "^4.1.1" } diff --git a/pnpm-setup.sh b/pnpm-setup.sh index 2c5d0130..1d30cf72 100644 --- a/pnpm-setup.sh +++ b/pnpm-setup.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -euo pipefail -# Shortcut script for AgentKit Forge setup +# Shortcut script for Retort setup # Install dependencies pnpm -C .agentkit install diff --git a/renovate.json b/renovate.json index 89757635..b7fd86d5 100644 --- a/renovate.json +++ b/renovate.json @@ -33,7 +33,7 @@ "labels": ["dependencies", "breaking-change"] }, { - "description": "AgentKit engine dependencies — require maintainer review", + "description": "Retort engine dependencies — require maintainer review", "matchFileNames": [".agentkit/package.json"], "labels": ["dependencies", "forge-source-change"], "automerge": false diff --git a/scripts/analyze-agents.ps1 b/scripts/analyze-agents.ps1 index 924a38b0..5b34fe8a 100644 --- a/scripts/analyze-agents.ps1 +++ b/scripts/analyze-agents.ps1 @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync <# agentkit: scaffold: managed #> # scripts/analyze-agents.ps1 diff --git a/scripts/analyze-agents.sh b/scripts/analyze-agents.sh index fd5324d6..6ba0e5e6 100755 --- a/scripts/analyze-agents.sh +++ b/scripts/analyze-agents.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # scripts/analyze-agents.sh # Generates agent/team relationship matrices from spec files. diff --git a/scripts/check-documentation-requirement.sh b/scripts/check-documentation-requirement.sh index 944d7501..98d752c2 100755 --- a/scripts/check-documentation-requirement.sh +++ b/scripts/check-documentation-requirement.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # scripts/check-documentation-requirement.sh # Analyzes staged or changed files to determine whether PR documentation is required. diff --git a/scripts/consolidate-branches.ps1 b/scripts/consolidate-branches.ps1 index befb78ba..3cdda437 100644 --- a/scripts/consolidate-branches.ps1 +++ b/scripts/consolidate-branches.ps1 @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync <# agentkit: scaffold: managed #> # ============================================================================= diff --git a/scripts/consolidate-branches.sh b/scripts/consolidate-branches.sh index 9aa9b746..2444a67b 100755 --- a/scripts/consolidate-branches.sh +++ b/scripts/consolidate-branches.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # ============================================================================= # consolidate-branches.sh — Merge all unmerged feature branches into one diff --git a/scripts/create-doc.ps1 b/scripts/create-doc.ps1 index 3b50b5d1..6e6c06ee 100644 --- a/scripts/create-doc.ps1 +++ b/scripts/create-doc.ps1 @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync <# agentkit: scaffold: managed #> # scripts/create-doc.ps1 diff --git a/scripts/create-doc.sh b/scripts/create-doc.sh index 318e7fe7..e3765290 100755 --- a/scripts/create-doc.sh +++ b/scripts/create-doc.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # scripts/create-doc.sh # Creates a new history document from the appropriate template. diff --git a/scripts/resolve-merge.ps1 b/scripts/resolve-merge.ps1 index 9baee2b1..2d147f32 100644 --- a/scripts/resolve-merge.ps1 +++ b/scripts/resolve-merge.ps1 @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync <# agentkit: scaffold: managed #> # ============================================================================= diff --git a/scripts/resolve-merge.sh b/scripts/resolve-merge.sh index a3daecff..0435d607 100755 --- a/scripts/resolve-merge.sh +++ b/scripts/resolve-merge.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # ============================================================================= # resolve-merge.sh — Apply standard merge conflict resolutions @@ -8,7 +8,7 @@ # Usage: scripts/resolve-merge.sh [target-branch] # # Merges origin/<target-branch> into the current branch and auto-resolves -# generated/framework-managed files per the AgentKit merge resolution matrix. +# generated/framework-managed files per the Retort merge resolution matrix. # Remaining conflicts (engine source, spec files) are listed for manual review. # ============================================================================= set -euo pipefail diff --git a/scripts/setup-agentkit-branch-governance.ps1 b/scripts/setup-agentkit-branch-governance.ps1 index 98e21a26..cd2e727b 100644 --- a/scripts/setup-agentkit-branch-governance.ps1 +++ b/scripts/setup-agentkit-branch-governance.ps1 @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync <# agentkit: scaffold: managed #> [CmdletBinding()] diff --git a/scripts/setup-agentkit-branch-governance.sh b/scripts/setup-agentkit-branch-governance.sh index f955e11b..350ef362 100755 --- a/scripts/setup-agentkit-branch-governance.sh +++ b/scripts/setup-agentkit-branch-governance.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync set -euo pipefail @@ -61,7 +61,7 @@ if [[ -z "$REPO" ]]; then exit 1 fi -echo "=== AgentKit Branch Governance Setup ===" +echo "=== Retort Branch Governance Setup ===" echo "Repository: $REPO" echo "DryRun: $DRY_RUN" echo diff --git a/scripts/sync-issues.sh b/scripts/sync-issues.sh index 9ace772a..25effcb2 100755 --- a/scripts/sync-issues.sh +++ b/scripts/sync-issues.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # scripts/sync-issues.sh # Syncs local issue docs (docs/history/issues/) to GitHub Issues. diff --git a/scripts/sync-split-pr.ps1 b/scripts/sync-split-pr.ps1 index 68a9b32b..871ca5f0 100644 --- a/scripts/sync-split-pr.ps1 +++ b/scripts/sync-split-pr.ps1 @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync <# agentkit: scaffold: managed #> [CmdletBinding()] diff --git a/scripts/sync-split-pr.sh b/scripts/sync-split-pr.sh index 1bbf61ac..69d5a06a 100755 --- a/scripts/sync-split-pr.sh +++ b/scripts/sync-split-pr.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync set -euo pipefail diff --git a/scripts/update-changelog.ps1 b/scripts/update-changelog.ps1 index 5c9c9e15..f64bdb0d 100644 --- a/scripts/update-changelog.ps1 +++ b/scripts/update-changelog.ps1 @@ -1,5 +1,5 @@ -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync <# agentkit: scaffold: managed #> # scripts/update-changelog.ps1 diff --git a/scripts/update-changelog.sh b/scripts/update-changelog.sh index e5693e00..16244613 100755 --- a/scripts/update-changelog.sh +++ b/scripts/update-changelog.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # scripts/update-changelog.sh # Inserts an entry into the [Unreleased] section of CHANGELOG.md. diff --git a/scripts/validate-documentation.sh b/scripts/validate-documentation.sh index e5a60220..0d8797ab 100755 --- a/scripts/validate-documentation.sh +++ b/scripts/validate-documentation.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # scripts/validate-documentation.sh # Validates that history documents meet structural requirements. diff --git a/scripts/validate-numbering.sh b/scripts/validate-numbering.sh index 00c2a506..7e31bf84 100755 --- a/scripts/validate-numbering.sh +++ b/scripts/validate-numbering.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# GENERATED by AgentKit Forge v3.1.0 — DO NOT EDIT -# Source: .agentkit/spec + .agentkit/overlays/agentkit-forge +# GENERATED by Retort v3.1.0 — DO NOT EDIT +# Source: .agentkit/spec + .agentkit/overlays/retort # Regenerate: pnpm -C .agentkit agentkit:sync # scripts/validate-numbering.sh # Validates the sequential numbering of history documents against .index.json. diff --git a/src/start/index.js b/src/start/index.js index 60d33785..af84d0e2 100755 --- a/src/start/index.js +++ b/src/start/index.js @@ -1,7 +1,7 @@ #!/usr/bin/env node /** - * ak-start — interactive entry point for AgentKit Forge. + * ak-start — interactive entry point for Retort. * * Replaces the static markdown output of `/start` with a terminal UI * that combines two modes: @@ -27,7 +27,7 @@ const args = process.argv.slice(2); if (args.includes('--help') || args.includes('-h')) { process.stdout.write( [ - 'ak-start — interactive entry point for AgentKit Forge', + 'ak-start — interactive entry point for Retort', '', 'Usage:', ' ak-start Interactive TUI (requires a terminal)',