Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .claude/commands/benchmark.md +61 -0
- .claude/commands/checkout-branch.md +64 -0
- .claude/commands/create-branch.md +39 -0
- .claude/commands/create-pr.md +56 -0
- .claude/commands/finalize.md +79 -0
- .claude/commands/list-branches.md +40 -0
- .claude/commands/release.md +75 -0
- .claude/commands/remove-branch.md +41 -0
- .claude/package.json +1 -0
- .claude/projects/-home-david-projects-Kayba-agentic-context-engine/memory/feedback_bedrock_only.md +11 -0
- .claude/settings.json +8 -0
- .claude/skills/kayba-pipeline/SKILL.md +145 -0
- .claude/skills/kayba-pipeline/stage-1-api-analysis/SKILL.md +84 -0
- .claude/skills/kayba-pipeline/stage-2-domain-context/SKILL.md +166 -0
- .claude/skills/kayba-pipeline/stage-3-metrics/SKILL.md +180 -0
- .claude/skills/kayba-pipeline/stage-4-rubric/SKILL.md +163 -0
- .claude/skills/kayba-pipeline/stage-5-action-plan/SKILL.md +201 -0
- .claude/skills/kayba-pipeline/stage-6-hitl/SKILL.md +258 -0
- .claude/skills/kayba-pipeline/stage-7-fixer/SKILL.md +191 -0
- .env.example +69 -0
- .gitattributes +4 -0
- .github/workflows/docs.yml +55 -0
- .github/workflows/publish.yml +290 -0
- .github/workflows/test.yml +47 -0
- .gitignore +124 -0
- .gitmodules +3 -0
- .pre-commit-config.yaml +20 -0
- .specify/memory/constitution.md +121 -0
- .specify/scripts/bash/check-prerequisites.sh +166 -0
- .specify/scripts/bash/common.sh +156 -0
- .specify/scripts/bash/create-new-feature.sh +297 -0
- .specify/scripts/bash/setup-plan.sh +61 -0
- .specify/scripts/bash/update-agent-context.sh +810 -0
- .specify/templates/agent-file-template.md +28 -0
- .specify/templates/checklist-template.md +40 -0
- .specify/templates/constitution-template.md +50 -0
- .specify/templates/plan-template.md +104 -0
- .specify/templates/spec-template.md +115 -0
- .specify/templates/tasks-template.md +251 -0
- AGENTS.md +98 -0
- CHANGELOG.md +445 -0
- CLAUDE.md +99 -0
- CONTRIBUTING.md +183 -0
- Dockerfile +11 -10
- LICENSE +201 -0
- README.md +224 -10
- ace.toml +2 -0
- ace/__init__.py +197 -0
- ace/cli/__init__.py +39 -0
- ace/cli/client.py +310 -0
.claude/commands/benchmark.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Run a TAU-bench evaluation end-to-end and present results.
|
| 2 |
+
|
| 3 |
+
**Syntax:** `/benchmark <config> [mode] [extra-args]`
|
| 4 |
+
|
| 5 |
+
**Arguments:**
|
| 6 |
+
|
| 7 |
+
- `config` (from $ARGUMENTS, first word) — profile name: `haiku`, `sonnet`, `gpt4.1-mini`, `gpt4.1`, `fast`, `default`
|
| 8 |
+
- `mode` (from $ARGUMENTS, second word, optional) — `baseline` (default), `compare`, or `ace-only`
|
| 9 |
+
- `extra-args` (from $ARGUMENTS, remaining words) — forwarded verbatim to the CLI
|
| 10 |
+
|
| 11 |
+
**Workflow:**
|
| 12 |
+
|
| 13 |
+
1. **Parse arguments** from `$ARGUMENTS`:
|
| 14 |
+
- Split into: `config` (first word), `mode` (second word if it matches baseline/compare/ace-only, else default to baseline), and `extra-args` (the rest)
|
| 15 |
+
|
| 16 |
+
2. **Build the command:**
|
| 17 |
+
```
|
| 18 |
+
uv run python scripts/run_tau_benchmark.py --config <config> --save-detailed <mode-flag> <extra-args>
|
| 19 |
+
```
|
| 20 |
+
Mode flags:
|
| 21 |
+
- `baseline` → `--skip-ace`
|
| 22 |
+
- `compare` → `--compare`
|
| 23 |
+
- `ace-only` → (no flag)
|
| 24 |
+
|
| 25 |
+
3. **Show the command** to the user before running
|
| 26 |
+
|
| 27 |
+
4. **Run the command** with a 10-minute timeout (TAU-bench runs are long)
|
| 28 |
+
|
| 29 |
+
5. **Find the latest result**: list `tau_benchmark_results/` sorted by modification time, pick the newest `*_summary.json`
|
| 30 |
+
|
| 31 |
+
6. **Read the summary JSON** and present results using this format:
|
| 32 |
+
|
| 33 |
+
For baseline runs:
|
| 34 |
+
```
|
| 35 |
+
## <Mode>: <Model Short Name> — <Domain> (test split, k=<k>)
|
| 36 |
+
|
| 37 |
+
| Setting | Value |
|
| 38 |
+
|---------|-------|
|
| 39 |
+
| Model | <exact model id> |
|
| 40 |
+
| User LLM | <user_llm> |
|
| 41 |
+
| Domain | <domain> |
|
| 42 |
+
| Split | <split> (<N> tasks) |
|
| 43 |
+
| Max steps | <max_steps> |
|
| 44 |
+
| Seed | <seed> |
|
| 45 |
+
|
| 46 |
+
| Metric | Score |
|
| 47 |
+
|--------|-------|
|
| 48 |
+
| pass^1 | XX.XX% |
|
| 49 |
+
| pass^2 | XX.XX% |
|
| 50 |
+
| ... | ... |
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
For comparison runs, add Baseline / ACE / Delta columns.
|
| 54 |
+
|
| 55 |
+
**Examples:**
|
| 56 |
+
- `/benchmark haiku` → baseline haiku run
|
| 57 |
+
- `/benchmark haiku compare` → baseline vs ACE comparison
|
| 58 |
+
- `/benchmark fast` → quick smoke test (3 tasks, k=1)
|
| 59 |
+
- `/benchmark sonnet compare --domain retail` → sonnet comparison on retail
|
| 60 |
+
|
| 61 |
+
**Key fields** to always include in the results table: exact model ID, user LLM, domain, split + task count, skillbook status, and all pass^k metrics.
|
.claude/commands/checkout-branch.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Switch to an existing branch by checking out its worktree, or creating one if needed.
|
| 2 |
+
|
| 3 |
+
**Arguments:** $ARGUMENTS should be the branch name (full or partial match)
|
| 4 |
+
|
| 5 |
+
**Examples:**
|
| 6 |
+
- `/checkout-branch feature/john/add-caching` → switch to branch (create worktree if needed)
|
| 7 |
+
- `/checkout-branch add-caching` → partial match, resolve to full branch name
|
| 8 |
+
- `/checkout-branch fix` → if multiple matches, list them and ask to be specific
|
| 9 |
+
|
| 10 |
+
**Steps:**
|
| 11 |
+
1. Parse branch name from arguments
|
| 12 |
+
2. Fetch latest from remote: `git fetch --prune`
|
| 13 |
+
3. Get all branches (local + remote): `git branch -a --format='%(refname:short)'`
|
| 14 |
+
4. Resolve branch name:
|
| 15 |
+
- Exact match: use directly
|
| 16 |
+
- Partial match: find branches containing the search term
|
| 17 |
+
- No match: show error with similar branches (if any)
|
| 18 |
+
5. Get worktree list: `git worktree list --porcelain`
|
| 19 |
+
6. Check if resolved branch has an existing worktree
|
| 20 |
+
7. If worktree exists:
|
| 21 |
+
- Show path and suggest `cd <path>`
|
| 22 |
+
8. If no worktree:
|
| 23 |
+
- Construct worktree path: `../<sanitized-branch-name>` (replace all `/` with `-`)
|
| 24 |
+
- If remote-only branch (starts with `origin/`): `git worktree add <path> -b <local-name> <remote-name>`
|
| 25 |
+
- If local branch: `git worktree add <path> <branch>`
|
| 26 |
+
- Symlink `.env`: if `<main-worktree>/.env` exists (get main worktree from `git worktree list --porcelain | head -1`), run `ln -s <main-worktree>/.env <new-worktree>/.env`
|
| 27 |
+
- Show path and suggest `cd <path>`
|
| 28 |
+
|
| 29 |
+
**On success (worktree exists), output:**
|
| 30 |
+
```
|
| 31 |
+
✓ Branch already has worktree at: <worktree-path>
|
| 32 |
+
|
| 33 |
+
To switch to the worktree:
|
| 34 |
+
cd <worktree-path>
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
**On success (worktree created from local branch), output:**
|
| 38 |
+
```
|
| 39 |
+
✓ Created worktree: <worktree-path>
|
| 40 |
+
✓ Linked .env → <main-worktree>/.env
|
| 41 |
+
|
| 42 |
+
To switch to the worktree:
|
| 43 |
+
cd <worktree-path>
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
**On success (worktree created from remote branch), output:**
|
| 47 |
+
```
|
| 48 |
+
✓ Created local branch: <branch-name> (tracking origin/<branch-name>)
|
| 49 |
+
✓ Created worktree: <worktree-path>
|
| 50 |
+
✓ Linked .env → <main-worktree>/.env
|
| 51 |
+
|
| 52 |
+
To switch to the worktree:
|
| 53 |
+
cd <worktree-path>
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
**Error handling:**
|
| 57 |
+
- Branch not found: "Branch not found: <name>. Did you mean one of these?" (list similar branches)
|
| 58 |
+
- Multiple partial matches: "Multiple branches match '<term>':" (list matches, ask to be more specific)
|
| 59 |
+
- No branches at all: "No branches found matching '<term>'"
|
| 60 |
+
|
| 61 |
+
**Branch resolution priority:**
|
| 62 |
+
1. Exact match on full branch name
|
| 63 |
+
2. Exact match on last segment (e.g., "add-caching" matches "feature/john/add-caching")
|
| 64 |
+
3. Partial substring match anywhere in branch name
|
.claude/commands/create-branch.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Create a new git branch with an associated worktree following the project naming convention.
|
| 2 |
+
|
| 3 |
+
**Format:** `<type>/<developer>/<description>`
|
| 4 |
+
**Worktree:** `../<sanitized-branch-name>` (sibling to current worktree)
|
| 5 |
+
|
| 6 |
+
**Arguments:** $ARGUMENTS should be in format: `<type> <description>`
|
| 7 |
+
|
| 8 |
+
**Examples:**
|
| 9 |
+
- `/create-branch feature add-caching` → branch: `feature/<dev>/add-caching`, worktree: `../feature-<dev>-add-caching`
|
| 10 |
+
- `/create-branch fix login-error` → branch: `fix/<dev>/login-error`, worktree: `../fix-<dev>-login-error`
|
| 11 |
+
|
| 12 |
+
**Steps:**
|
| 13 |
+
1. Parse type and description from arguments (validate type is one of: feature, fix, docs, refactor, test, chore)
|
| 14 |
+
2. Get developer name from `git config user.name` (sanitize: lowercase, replace spaces with hyphens)
|
| 15 |
+
3. Construct branch name: `<type>/<developer>/<description>`
|
| 16 |
+
4. Construct worktree path: `../<type>-<developer>-<description>` (replace all `/` with `-`)
|
| 17 |
+
5. Create branch and worktree atomically: `git worktree add -b <branch> <worktree-path>`
|
| 18 |
+
6. Symlink `.env` from the main worktree into the new worktree:
|
| 19 |
+
- Get the main worktree path: `git worktree list --porcelain | head -1` (first `worktree` line)
|
| 20 |
+
- If `<main-worktree>/.env` exists, create symlink: `ln -s <main-worktree>/.env <new-worktree>/.env`
|
| 21 |
+
- If `.env` doesn't exist in main worktree, skip silently
|
| 22 |
+
7. Report success with the created branch name and worktree path
|
| 23 |
+
|
| 24 |
+
**Valid types:** feature, fix, docs, refactor, test, chore
|
| 25 |
+
|
| 26 |
+
**On success, output:**
|
| 27 |
+
```
|
| 28 |
+
✓ Created branch: <branch-name>
|
| 29 |
+
✓ Created worktree: <worktree-path>
|
| 30 |
+
✓ Linked .env → <main-worktree>/.env
|
| 31 |
+
|
| 32 |
+
To switch to the new worktree:
|
| 33 |
+
cd <worktree-path>
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
**Error handling:**
|
| 37 |
+
- If type is invalid, show valid types and abort
|
| 38 |
+
- If branch already exists, suggest checking it out instead
|
| 39 |
+
- If worktree path exists, suggest using existing worktree
|
.claude/commands/create-pr.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Create a pull request for the current branch against main.
|
| 2 |
+
|
| 3 |
+
**Arguments:** $ARGUMENTS (optional) — base branch override (defaults to `main`)
|
| 4 |
+
|
| 5 |
+
**Steps:**
|
| 6 |
+
|
| 7 |
+
1. **Validate branch state:**
|
| 8 |
+
- Get current branch: `git branch --show-current`
|
| 9 |
+
- If on `main`, abort with error: "You're on main. Switch to a feature branch first."
|
| 10 |
+
- Determine base branch: use $ARGUMENTS if provided, otherwise `main`
|
| 11 |
+
|
| 12 |
+
2. **Check for unmerged commits:**
|
| 13 |
+
- Run `git log <base>..HEAD --oneline`
|
| 14 |
+
- If no commits, abort: "No unmerged commits against <base>. Nothing to PR."
|
| 15 |
+
|
| 16 |
+
3. **Gather context (run in parallel):**
|
| 17 |
+
- `git diff <base>...HEAD --stat` — file change summary
|
| 18 |
+
- `git log <base>..HEAD --format='%h %s'` — commit list
|
| 19 |
+
- `git diff <base>...HEAD` — full diff for understanding changes
|
| 20 |
+
|
| 21 |
+
4. **Draft PR title and body:**
|
| 22 |
+
- Analyze the commits and diff to understand the change
|
| 23 |
+
- Write a short PR title (under 70 chars, imperative mood)
|
| 24 |
+
- Write the body using this format:
|
| 25 |
+
```
|
| 26 |
+
## Summary
|
| 27 |
+
<1-3 bullet points explaining the changes>
|
| 28 |
+
|
| 29 |
+
## Changes
|
| 30 |
+
<bulleted list of key file/module changes>
|
| 31 |
+
|
| 32 |
+
## Test plan
|
| 33 |
+
<how to verify the changes work>
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
5. **Present draft to user:**
|
| 37 |
+
- Show the proposed title and body
|
| 38 |
+
- Ask: "Push and create this PR?" with options: Yes (create), Edit (let me revise), Cancel
|
| 39 |
+
|
| 40 |
+
6. **On approval:**
|
| 41 |
+
- Check if branch has upstream: `git rev-parse --abbrev-ref @{upstream}`
|
| 42 |
+
- Push branch: `git push -u origin HEAD`
|
| 43 |
+
- Create PR: `gh pr create --title "<title>" --body "<body>" --base <base>`
|
| 44 |
+
- Show the resulting PR URL
|
| 45 |
+
|
| 46 |
+
**On success, output:**
|
| 47 |
+
```
|
| 48 |
+
✓ Pushed branch: <branch-name>
|
| 49 |
+
✓ Created PR: <pr-url>
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
**Error handling:**
|
| 53 |
+
- If `gh` is not installed: "GitHub CLI (gh) is required. Install it: https://cli.github.com"
|
| 54 |
+
- If not authenticated: "Run `gh auth login` first."
|
| 55 |
+
- If PR already exists: show the existing PR URL with `gh pr view --web`
|
| 56 |
+
- If push fails: show the git error and abort
|
.claude/commands/finalize.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Finalize the current work: format, test, fix, commit, and push.
|
| 2 |
+
|
| 3 |
+
Run this command after making code changes to complete the development cycle. It handles formatting, testing (with auto-fix retries), committing, and pushing.
|
| 4 |
+
|
| 5 |
+
**Arguments:** $ARGUMENTS is an optional commit message override. If not provided, compose one automatically from the diff.
|
| 6 |
+
|
| 7 |
+
**Workflow:**
|
| 8 |
+
|
| 9 |
+
1. **Format code**
|
| 10 |
+
- Run `uv run black ace/ tests/ examples/`
|
| 11 |
+
|
| 12 |
+
2. **Update CLAUDE.md**
|
| 13 |
+
- Run `/init` to update the project's CLAUDE.md file with current codebase context
|
| 14 |
+
|
| 15 |
+
3. **Review test coverage**
|
| 16 |
+
- Check if the changes have adequate test coverage
|
| 17 |
+
- Look at which lines/branches are untested for the modified files
|
| 18 |
+
- If coverage gaps exist for the changed code, add targeted tests before proceeding
|
| 19 |
+
- Focus on: new functions, error paths, edge cases, and branches introduced by this changeset
|
| 20 |
+
|
| 21 |
+
4. **Run tests**
|
| 22 |
+
- Run `uv run pytest`
|
| 23 |
+
|
| 24 |
+
5. **Test-fix loop (max 3 retries)**
|
| 25 |
+
- If tests pass, continue to step 6
|
| 26 |
+
- If tests fail:
|
| 27 |
+
- Analyze the failure output
|
| 28 |
+
- Fix the failing code or tests
|
| 29 |
+
- Add missing tests if the failures reveal gaps
|
| 30 |
+
- Re-run formatter: `uv run black ace/ tests/ examples/`
|
| 31 |
+
- Re-run tests: `uv run pytest`
|
| 32 |
+
- If tests still fail after 3 total attempts, **stop entirely** and report the failures. Never commit broken code.
|
| 33 |
+
|
| 34 |
+
6. **Security review**
|
| 35 |
+
- Run `/security-review` to scan changed code for vulnerabilities
|
| 36 |
+
- If Critical or High severity issues are found, fix them before proceeding
|
| 37 |
+
- After fixing, re-run formatter (`uv run black ace/ tests/ examples/`) and tests (`uv run pytest`)
|
| 38 |
+
- If issues can't be auto-fixed, report them and stop
|
| 39 |
+
|
| 40 |
+
7. **Review changes**
|
| 41 |
+
- Run `git diff` to review all changes
|
| 42 |
+
- Run `git status` to see untracked/modified files
|
| 43 |
+
- Determine which files to stage
|
| 44 |
+
|
| 45 |
+
8. **Stage files selectively**
|
| 46 |
+
- Use explicit `git add <file>` for each file. **Never use `git add -A` or `git add .`**
|
| 47 |
+
- **Never stage:** `.env`, credentials, secrets, `__pycache__/`, `*.pyc`, large binaries, `.DS_Store`
|
| 48 |
+
- **Only stage `uv.lock`** if dependency changes in `pyproject.toml` were intentional
|
| 49 |
+
- If unsure about a file, ask the user
|
| 50 |
+
|
| 51 |
+
9. **Compose commit message**
|
| 52 |
+
- If $ARGUMENTS was provided, use it as the commit message
|
| 53 |
+
- Otherwise, compose a Conventional Commit message: `<type>(<scope>): <short description>`
|
| 54 |
+
- Types: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `perf`, `style`
|
| 55 |
+
- Derive scope from the primary changed file path (e.g., `ace/skillbook.py` -> `skillbook`, `ace/integrations/litellm.py` -> `integrations`, `tests/test_foo.py` -> `tests`)
|
| 56 |
+
- Keep messages short and imperative
|
| 57 |
+
|
| 58 |
+
10. **Check branch safety**
|
| 59 |
+
- Run `git branch --show-current` to get the current branch
|
| 60 |
+
- If on `main` or `master`, **warn the user** and ask for explicit confirmation before committing
|
| 61 |
+
- If denied, stop without committing
|
| 62 |
+
|
| 63 |
+
11. **Commit and push**
|
| 64 |
+
- Commit with the composed message
|
| 65 |
+
- Push to remote: `git push` (or `git push -u origin <branch>` if no upstream is set)
|
| 66 |
+
|
| 67 |
+
12. **Report summary**
|
| 68 |
+
- Commit hash (short)
|
| 69 |
+
- Branch name
|
| 70 |
+
- Files changed count
|
| 71 |
+
- Test results (pass count)
|
| 72 |
+
- Any warnings encountered
|
| 73 |
+
|
| 74 |
+
**Error handling:**
|
| 75 |
+
- If no changes exist (clean working tree), report "Nothing to finalize" and stop
|
| 76 |
+
- If tests fail after 3 retries, report failures and stop without committing
|
| 77 |
+
- If push fails, report the error but keep the local commit
|
| 78 |
+
- If formatter fails, report the error and stop
|
| 79 |
+
- If security review finds unfixable Critical/High issues, report and stop without committing
|
.claude/commands/list-branches.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
List project branches with their worktree status.
|
| 2 |
+
|
| 3 |
+
**Arguments:** $ARGUMENTS (optional filters)
|
| 4 |
+
- No args: List all branches matching naming convention `<type>/<developer>/<description>`
|
| 5 |
+
- `--all`: Include all branches (not just convention-named)
|
| 6 |
+
- `--worktrees`: Only show branches with active worktrees
|
| 7 |
+
- `<type>`: Filter by type (feature, fix, docs, refactor, test, chore)
|
| 8 |
+
|
| 9 |
+
**Examples:**
|
| 10 |
+
- `/list-branches` → all convention-named branches
|
| 11 |
+
- `/list-branches feature` → only feature branches
|
| 12 |
+
- `/list-branches --worktrees` → only branches with worktrees
|
| 13 |
+
- `/list-branches --all` → all branches including main
|
| 14 |
+
|
| 15 |
+
**Steps:**
|
| 16 |
+
1. Get all local branches: `git branch --format='%(refname:short)'`
|
| 17 |
+
2. Get worktree list: `git worktree list --porcelain`
|
| 18 |
+
3. Parse worktree output to map branches to paths
|
| 19 |
+
4. Filter branches based on arguments
|
| 20 |
+
5. Format and display results
|
| 21 |
+
|
| 22 |
+
**Output format:**
|
| 23 |
+
```
|
| 24 |
+
Branch Worktree Status
|
| 25 |
+
──────────────────────────────────────────────────────────────────────────────
|
| 26 |
+
* main . current
|
| 27 |
+
feature/john/add-caching ../feature-john-add-caching active
|
| 28 |
+
fix/jane/login-error (no worktree) -
|
| 29 |
+
|
| 30 |
+
Summary: 3 branches, 2 with worktrees
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
**Column meanings:**
|
| 34 |
+
- `*` indicates current branch
|
| 35 |
+
- Worktree shows path relative to repo root, or "(no worktree)" if none
|
| 36 |
+
- Status: "current" (HEAD), "active" (has worktree), "-" (no worktree)
|
| 37 |
+
|
| 38 |
+
**Tips shown after output:**
|
| 39 |
+
- To create a worktree for a branch: `git worktree add ../<path> <branch>`
|
| 40 |
+
- To remove a branch with worktree: use `/remove-branch <branch>`
|
.claude/commands/release.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Release a new version: bump version, update changelog, tag, push, and create a GitHub release.
|
| 2 |
+
|
| 3 |
+
**Arguments:** $ARGUMENTS — the new version number (e.g. `0.9.0`). Required.
|
| 4 |
+
|
| 5 |
+
**Steps:**
|
| 6 |
+
|
| 7 |
+
1. **Validate inputs**
|
| 8 |
+
- If $ARGUMENTS is empty, abort: "Usage: /release <version> (e.g. /release 0.9.0)"
|
| 9 |
+
- Strip leading `v` if present (e.g. `v0.9.0` → `0.9.0`)
|
| 10 |
+
- Validate format matches `X.Y.Z` (semver)
|
| 11 |
+
|
| 12 |
+
2. **Validate branch state**
|
| 13 |
+
- Must be on `main`: `git branch --show-current`
|
| 14 |
+
- If not on main, abort: "Switch to main first."
|
| 15 |
+
- Pull latest: `git pull origin main`
|
| 16 |
+
- Working tree must be clean: `git status --porcelain`
|
| 17 |
+
|
| 18 |
+
3. **Check version isn't already used**
|
| 19 |
+
- Read current version from `pyproject.toml` (line with `version = "..."`)
|
| 20 |
+
- If new version equals current version, abort: "Version <ver> is already set."
|
| 21 |
+
- Check tag doesn't exist: `git tag -l v<version>`
|
| 22 |
+
- If tag exists, abort: "Tag v<version> already exists."
|
| 23 |
+
|
| 24 |
+
4. **Build changelog entry from git history**
|
| 25 |
+
- Find the latest tag: `git describe --tags --abbrev=0`
|
| 26 |
+
- Get commits since that tag: `git log <last-tag>..HEAD --format='%s'`
|
| 27 |
+
- Get merged PRs since that tag: `gh pr list --state merged --base main --search "merged:>=$(git log -1 --format=%ci <last-tag> | cut -d' ' -f1)" --json title,number --limit 50`
|
| 28 |
+
- From the commits/PRs, compose a changelog section with **only `### Added` items** — user-facing features. Skip fixes, refactors, chores, docs-only changes, and CI changes.
|
| 29 |
+
- Format:
|
| 30 |
+
```
|
| 31 |
+
## [X.Y.Z] - YYYY-MM-DD
|
| 32 |
+
|
| 33 |
+
### Added
|
| 34 |
+
- **Feature name** — short description
|
| 35 |
+
- **Feature name** — short description
|
| 36 |
+
```
|
| 37 |
+
- Also prepare a compare link for the bottom of CHANGELOG.md:
|
| 38 |
+
`[X.Y.Z]: https://github.com/Kayba-ai/agentic-context-engine/compare/v<prev>...vX.Y.Z`
|
| 39 |
+
|
| 40 |
+
5. **Present draft to user**
|
| 41 |
+
- Show: new version, changelog entry, and the release note (same as changelog "Added" bullets)
|
| 42 |
+
- Ask: "Create this release?" with options: Yes, Edit (let me revise), Cancel
|
| 43 |
+
|
| 44 |
+
6. **On approval — apply changes**
|
| 45 |
+
- Update `pyproject.toml`: replace `version = "<old>"` with `version = "<new>"`
|
| 46 |
+
- Insert the changelog entry in `CHANGELOG.md` after line 7 (before the previous release)
|
| 47 |
+
- Add the compare link at the bottom of CHANGELOG.md
|
| 48 |
+
- Stage files: `git add pyproject.toml CHANGELOG.md`
|
| 49 |
+
- Commit: `git commit -m "chore(release): bump version to <version>"`
|
| 50 |
+
|
| 51 |
+
7. **Tag and push**
|
| 52 |
+
- `git tag v<version>`
|
| 53 |
+
- `git push origin main --tags`
|
| 54 |
+
|
| 55 |
+
8. **Create GitHub release**
|
| 56 |
+
- Title: `v<version>`
|
| 57 |
+
- Notes: **only the "Added" bullets** from the changelog entry — short and clean, no preamble
|
| 58 |
+
- Append: `**Full Changelog**: https://github.com/kayba-ai/agentic-context-engine/compare/v<prev>...v<version>`
|
| 59 |
+
- Run: `gh release create v<version> --title "v<version>" --notes "<notes>"`
|
| 60 |
+
- This triggers `.github/workflows/publish.yml` → PyPI publish
|
| 61 |
+
|
| 62 |
+
9. **Report summary**
|
| 63 |
+
```
|
| 64 |
+
Released v<version>
|
| 65 |
+
- Commit: <short-hash>
|
| 66 |
+
- Tag: v<version>
|
| 67 |
+
- Release: <github-release-url>
|
| 68 |
+
- PyPI: publishing via workflow (check Actions tab)
|
| 69 |
+
```
|
| 70 |
+
|
| 71 |
+
**Error handling:**
|
| 72 |
+
- If `gh` is not installed: "GitHub CLI (gh) is required. Install it: https://cli.github.com"
|
| 73 |
+
- If not authenticated: "Run `gh auth login` first."
|
| 74 |
+
- If push fails: report error, keep local commit (user can retry)
|
| 75 |
+
- If `gh release create` fails: show the error, suggest manual creation
|
.claude/commands/remove-branch.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Remove a branch and its associated worktree.
|
| 2 |
+
|
| 3 |
+
**Arguments:** $ARGUMENTS should be the branch name (full or partial match)
|
| 4 |
+
- `--force`: Skip confirmations and force delete unmerged branches
|
| 5 |
+
|
| 6 |
+
**Examples:**
|
| 7 |
+
- `/remove-branch feature/john/add-caching` → remove branch and worktree
|
| 8 |
+
- `/remove-branch add-caching` → partial match, will prompt to confirm
|
| 9 |
+
- `/remove-branch feature/john/add-caching --force` → skip all confirmations
|
| 10 |
+
|
| 11 |
+
**Steps:**
|
| 12 |
+
1. Parse branch name and flags from arguments
|
| 13 |
+
2. Resolve branch name (support partial matching if unique)
|
| 14 |
+
3. Safety checks:
|
| 15 |
+
- Abort if trying to remove main/master
|
| 16 |
+
- Abort if trying to remove current branch (must switch first)
|
| 17 |
+
- Warn if branch has unmerged commits (show `git log main..<branch> --oneline`)
|
| 18 |
+
4. Check if branch has an associated worktree: `git worktree list`
|
| 19 |
+
5. If worktree exists:
|
| 20 |
+
- Remove worktree first: `git worktree remove <path>` (or `--force` if needed)
|
| 21 |
+
- Prune worktree list: `git worktree prune`
|
| 22 |
+
6. Delete the branch: `git branch -d <branch>` (or `-D` with `--force`)
|
| 23 |
+
7. Confirm success
|
| 24 |
+
|
| 25 |
+
**On success, output:**
|
| 26 |
+
```
|
| 27 |
+
✓ Removed worktree: <worktree-path>
|
| 28 |
+
✓ Removed branch: <branch-name>
|
| 29 |
+
```
|
| 30 |
+
|
| 31 |
+
**Error handling:**
|
| 32 |
+
- Multiple partial matches: list matches and ask user to be more specific
|
| 33 |
+
- Unmerged commits without --force: show commits and ask for confirmation
|
| 34 |
+
- Protected branches (main/master): refuse with explanation
|
| 35 |
+
- Current branch: instruct user to switch branches first
|
| 36 |
+
|
| 37 |
+
**Protected branches:** main, master
|
| 38 |
+
|
| 39 |
+
**Confirmation prompts (unless --force):**
|
| 40 |
+
- "Branch has N unmerged commits. Remove anyway? (show commits first)"
|
| 41 |
+
- For partial match: "Did you mean <full-branch-name>?"
|
.claude/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"type":"commonjs"}
|
.claude/projects/-home-david-projects-Kayba-agentic-context-engine/memory/feedback_bedrock_only.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: Always use Bedrock
|
| 3 |
+
description: Never use direct Anthropic API key or fall back to OpenAI — always use Bedrock via AWS_BEARER_TOKEN_BEDROCK
|
| 4 |
+
type: feedback
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
Always use Bedrock for LLM calls. Never use the Anthropic API key directly, never fall back to OpenAI or any other provider.
|
| 8 |
+
|
| 9 |
+
**Why:** The user has Bedrock configured with `AWS_BEARER_TOKEN_BEDROCK` and does not want direct Anthropic API usage (burns quota/money on the wrong account). Fallback logic is unacceptable — it silently uses the wrong provider.
|
| 10 |
+
|
| 11 |
+
**How to apply:** In integration tests and any code that needs an LLM model string, use `bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0` (or similar Bedrock model). Never write fallback chains like "if ANTHROPIC_KEY else OPENAI". Just use Bedrock, period.
|
.claude/settings.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"permissions": {
|
| 3 |
+
"allow": [
|
| 4 |
+
"Bash(uv run pytest:*)",
|
| 5 |
+
"Bash(uv run black:*)"
|
| 6 |
+
]
|
| 7 |
+
}
|
| 8 |
+
}
|
.claude/skills/kayba-pipeline/SKILL.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: kayba-pipeline
|
| 3 |
+
description: End-to-end agent evaluation and improvement pipeline. Takes a traces folder and optional HITL flag, then orchestrates sub-agents through 7 stages — each stage is its own skill invoked by a dedicated sub-agent. Trigger when the user says "run the pipeline", "kayba pipeline", "evaluate and fix", "full eval", "analyze traces and fix", or provides a traces folder with intent to improve their agent.
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# kayba-pipeline
|
| 7 |
+
|
| 8 |
+
End-to-end pipeline: analyze traces → define metrics → build rubric → plan fixes → implement fixes.
|
| 9 |
+
|
| 10 |
+
Each stage is a separate skill file that can be run independently or as part of this pipeline.
|
| 11 |
+
|
| 12 |
+
## Inputs
|
| 13 |
+
|
| 14 |
+
The user provides two things:
|
| 15 |
+
|
| 16 |
+
1. **`TRACES_FOLDER`** — path to a directory containing trace JSON files
|
| 17 |
+
2. **`HITL`** — `true` or `false` — whether to pause for human review before implementing fixes
|
| 18 |
+
|
| 19 |
+
If the user doesn't specify HITL, default to `true` (safe default).
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## Pipeline overview
|
| 24 |
+
|
| 25 |
+
```
|
| 26 |
+
┌─────────────────────────────────────────────────────────────────────┐
|
| 27 |
+
│ Stage 1: Kayba API Analysis → skill: kayba-pipeline:stage-1-api-analysis │
|
| 28 |
+
│ Stage 2: Domain Context Gathering → skill: kayba-pipeline:stage-2-domain-context │
|
| 29 |
+
│ ─── stages 1 & 2 run in parallel ─── │
|
| 30 |
+
│ Stage 3: Metrics & Analysis → skill: kayba-pipeline:stage-3-metrics │
|
| 31 |
+
│ Stage 4: Rubric Definition → skill: kayba-pipeline:stage-4-rubric │
|
| 32 |
+
│ Stage 5: Action Plan → skill: kayba-pipeline:stage-5-action-plan │
|
| 33 |
+
│ Stage 6: HITL Gate → skill: kayba-pipeline:stage-6-hitl │
|
| 34 |
+
│ Stage 7: Fix Implementation → skill: kayba-pipeline:stage-7-fixer │
|
| 35 |
+
└─────────────────────────────────────────────────────────────────────┘
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
---
|
| 39 |
+
|
| 40 |
+
## Orchestration instructions
|
| 41 |
+
|
| 42 |
+
You are the orchestrator. Your job is to:
|
| 43 |
+
1. Create the `eval/` directory and `eval/pipeline_log.md`
|
| 44 |
+
2. Spawn sub-agents that invoke stage skills via the Skill tool
|
| 45 |
+
3. Coordinate stage ordering and handle the HITL gate
|
| 46 |
+
|
| 47 |
+
### Setup
|
| 48 |
+
|
| 49 |
+
Create `eval/` directory and initialize `eval/pipeline_log.md`:
|
| 50 |
+
|
| 51 |
+
```markdown
|
| 52 |
+
# Pipeline Log
|
| 53 |
+
|
| 54 |
+
| Stage | Name | Status | Started | Completed | Notes |
|
| 55 |
+
|-------|------|--------|---------|-----------|-------|
|
| 56 |
+
| 1 | Kayba API Analysis | pending | | | |
|
| 57 |
+
| 2 | Domain Context | pending | | | |
|
| 58 |
+
| 3 | Metrics & Analysis | pending | | | |
|
| 59 |
+
| 4 | Rubric Definition | pending | | | |
|
| 60 |
+
| 5 | Action Plan | pending | | | |
|
| 61 |
+
| 6 | HITL Gate | pending | | | |
|
| 62 |
+
| 7 | Fix Implementation | pending | | | |
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
### Stages 1 & 2 — run in parallel
|
| 66 |
+
|
| 67 |
+
Spawn two sub-agents in parallel using the Agent tool:
|
| 68 |
+
|
| 69 |
+
**Agent 1:**
|
| 70 |
+
- Name: `api-analyst`
|
| 71 |
+
- Type: `general-purpose`
|
| 72 |
+
- Prompt: `Invoke the skill "kayba-pipeline:stage-1-api-analysis" using the Skill tool. The traces folder is: {TRACES_FOLDER}. Follow the skill instructions completely.`
|
| 73 |
+
|
| 74 |
+
**Agent 2:**
|
| 75 |
+
- Name: `domain-scout`
|
| 76 |
+
- Type: `general-purpose`
|
| 77 |
+
- Prompt: `Invoke the skill "kayba-pipeline:stage-2-domain-context" using the Skill tool. The traces folder is: {TRACES_FOLDER}. Follow the skill instructions completely.`
|
| 78 |
+
|
| 79 |
+
Wait for both to complete before proceeding.
|
| 80 |
+
|
| 81 |
+
### Stage 3 — sequential
|
| 82 |
+
|
| 83 |
+
Spawn one sub-agent after stages 1 & 2 complete:
|
| 84 |
+
|
| 85 |
+
- Name: `metric-engineer`
|
| 86 |
+
- Type: `general-purpose`
|
| 87 |
+
- Prompt: `Invoke the skill "kayba-pipeline:stage-3-metrics" using the Skill tool. The traces folder is: {TRACES_FOLDER}. Follow the skill instructions completely — this includes iterating on the metrics until you're satisfied.`
|
| 88 |
+
|
| 89 |
+
### Stage 4 — sequential
|
| 90 |
+
|
| 91 |
+
Spawn one sub-agent after stage 3 completes:
|
| 92 |
+
|
| 93 |
+
- Name: `rubric-builder`
|
| 94 |
+
- Type: `general-purpose`
|
| 95 |
+
- Prompt: `Invoke the skill "kayba-pipeline:stage-4-rubric" using the Skill tool. Follow the skill instructions completely.`
|
| 96 |
+
|
| 97 |
+
### Stage 5 — sequential
|
| 98 |
+
|
| 99 |
+
Spawn one sub-agent after stage 4 completes:
|
| 100 |
+
|
| 101 |
+
- Name: `action-planner`
|
| 102 |
+
- Type: `general-purpose`
|
| 103 |
+
- Prompt: `Invoke the skill "kayba-pipeline:stage-5-action-plan" using the Skill tool. Follow the skill instructions completely.`
|
| 104 |
+
|
| 105 |
+
### Stage 6 — HITL Gate
|
| 106 |
+
|
| 107 |
+
**If `HITL` is `true`:**
|
| 108 |
+
|
| 109 |
+
Spawn one sub-agent after stage 5 completes:
|
| 110 |
+
|
| 111 |
+
- Name: `hitl-reviewer`
|
| 112 |
+
- Type: `general-purpose`
|
| 113 |
+
- Prompt: `Invoke the skill "kayba-pipeline:stage-6-hitl" using the Skill tool. Follow the skill instructions completely. Present the full review to the user and collect their decision before proceeding.`
|
| 114 |
+
|
| 115 |
+
Wait for the sub-agent to complete. Check `eval/stage6_decision.md` for the outcome:
|
| 116 |
+
- If decision is "Approve all" or "Approve with modifications" — proceed to Stage 7
|
| 117 |
+
- If decision is "Reject" — re-run Stage 5 with the user feedback recorded in `eval/stage6_decision.md`, then re-run Stage 6
|
| 118 |
+
- Only proceed to Stage 7 after a clear approval is recorded
|
| 119 |
+
|
| 120 |
+
**If `HITL` is `false`:**
|
| 121 |
+
- Skip to Stage 7
|
| 122 |
+
- Log "HITL skipped" in `eval/pipeline_log.md`
|
| 123 |
+
|
| 124 |
+
### Stage 7 — sequential
|
| 125 |
+
|
| 126 |
+
Spawn one sub-agent after stage 6 completes (or is skipped):
|
| 127 |
+
|
| 128 |
+
- Name: `fixer`
|
| 129 |
+
- Type: `general-purpose`
|
| 130 |
+
- Prompt: `Invoke the skill "kayba-pipeline:stage-7-fixer" using the Skill tool. Follow the skill instructions completely.`
|
| 131 |
+
|
| 132 |
+
---
|
| 133 |
+
|
| 134 |
+
## Error handling
|
| 135 |
+
|
| 136 |
+
- If any stage fails, log the failure in `eval/pipeline_log.md` with the stage number and error
|
| 137 |
+
- Do not proceed to dependent stages if a prerequisite failed
|
| 138 |
+
- If Stage 1 fails (kayba CLI issues), ask the user whether to proceed without API insights — if yes, skip Stage 1 and have Stage 3 work from domain context + raw traces only
|
| 139 |
+
|
| 140 |
+
## After completion
|
| 141 |
+
|
| 142 |
+
Update `eval/pipeline_log.md` with final status for all stages. Report to the user:
|
| 143 |
+
- How many stages completed successfully
|
| 144 |
+
- Summary of metrics (from rubric)
|
| 145 |
+
- Summary of fixes applied (from changes log)
|
.claude/skills/kayba-pipeline/stage-1-api-analysis/SKILL.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: kayba-stage-1-api-analysis
|
| 3 |
+
description: Fetch pre-computed insights from the Kayba API and build a structured summary. Does NOT upload traces or trigger generation — analysis is assumed to already exist. Trigger when the user says "run stage 1", "get insights", "fetch skills", "kayba analyze", or when invoked by the kayba-pipeline orchestrator. Requires the kayba CLI to be installed and KAYBA_API_KEY to be set.
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Stage 1: Kayba API Analysis (Fetch-Only Mode)
|
| 7 |
+
|
| 8 |
+
Fetch pre-computed insights from the Kayba API. Traces have already been uploaded and analyzed — this stage only pulls results.
|
| 9 |
+
|
| 10 |
+
## Inputs
|
| 11 |
+
|
| 12 |
+
- **`TRACES_FOLDER`** — passed by the orchestrator but **ignored** in this stage. Traces are already uploaded and analyzed on the Kayba side. Do NOT upload, validate, or read trace files.
|
| 13 |
+
|
| 14 |
+
## Process
|
| 15 |
+
|
| 16 |
+
### Step 1: Setup
|
| 17 |
+
|
| 18 |
+
Ensure `eval/` directory exists at the project root.
|
| 19 |
+
|
| 20 |
+
### Step 2: Fetch insights
|
| 21 |
+
|
| 22 |
+
```
|
| 23 |
+
kayba insights list --json > eval/insights.json
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
If `kayba` is not found in PATH, search common locations (`.venv/bin/kayba`, project virtualenvs). If found, use the full path. If not found anywhere, report the error and stop.
|
| 27 |
+
|
| 28 |
+
If `KAYBA_API_KEY` is not set, report the error and stop.
|
| 29 |
+
|
| 30 |
+
### Step 3: Insight quality gate
|
| 31 |
+
|
| 32 |
+
Read `eval/insights.json` and run quality checks before building the summary:
|
| 33 |
+
|
| 34 |
+
1. **Empty check**: if the insights array is empty (0 insights returned), report this as a warning. Write a minimal summary noting "0 insights generated" and stop — downstream stages cannot proceed without insights.
|
| 35 |
+
2. **Duplicate detection**: compare insight `content` fields pairwise. If two insights cover substantially the same behavior (same section, overlapping evidence traces, similar corrective action), flag them as potential duplicates in the summary. Do not remove them — just annotate.
|
| 36 |
+
3. **Evidence coverage**: for each insight, check if the `evidence` field references specific traces (e.g., "task_7 turn 4"). Insights with no trace-specific evidence are lower quality — flag as "low-evidence" in the summary.
|
| 37 |
+
4. **Vote signal**: insights with `status: "accepted"` and `helpful > 0` have been human-validated. Insights with `status: "new"` and `helpful: 0, harmful: 0` are unvalidated — note this distinction in the summary.
|
| 38 |
+
|
| 39 |
+
Log the quality gate result: `"Insight quality: {total} insights, {accepted} accepted, {new_unvalidated} unvalidated, {duplicates} potential duplicate pairs, {low_evidence} low-evidence"`
|
| 40 |
+
|
| 41 |
+
### Step 4: Build structured summary
|
| 42 |
+
|
| 43 |
+
Extract a structured summary of each insight:
|
| 44 |
+
- Insight ID and title/summary (use the `section` field as the title)
|
| 45 |
+
- Status
|
| 46 |
+
- Evidence citations — specific trace references, error strings, behavioral patterns the reflector identified
|
| 47 |
+
- Justification / reasoning chain — the reflector's full analysis of why this is a real pattern
|
| 48 |
+
- Confidence score if available
|
| 49 |
+
- Helpful/harmful counts if available
|
| 50 |
+
- Quality flags from Step 3 (potential duplicate, low-evidence, unvalidated)
|
| 51 |
+
|
| 52 |
+
Write the structured summary to `eval/stage1_insights_summary.md` using this format:
|
| 53 |
+
|
| 54 |
+
```markdown
|
| 55 |
+
# Kayba Insights Summary
|
| 56 |
+
|
| 57 |
+
Generated from: Kayba API (pre-computed analysis)
|
| 58 |
+
Total insights: N
|
| 59 |
+
Quality: {accepted} accepted, {unvalidated} unvalidated, {duplicate_pairs} potential duplicate pairs, {low_evidence} low-evidence
|
| 60 |
+
|
| 61 |
+
## Insight: [ID] — [section title]
|
| 62 |
+
**Status:** [status] [quality flags if any, e.g., "[potential duplicate with ID]", "[low-evidence]", "[unvalidated]"]
|
| 63 |
+
**Confidence:** [score if available]
|
| 64 |
+
**Evidence:**
|
| 65 |
+
- [citation 1 — trace reference, error string, or behavioral pattern]
|
| 66 |
+
- [citation 2]
|
| 67 |
+
**Justification:** [reflector's reasoning for why this is a real pattern]
|
| 68 |
+
**Helpful/Harmful:** [counts if available]
|
| 69 |
+
|
| 70 |
+
---
|
| 71 |
+
[repeat for each insight]
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
## Error handling
|
| 75 |
+
|
| 76 |
+
- If `kayba` is not found in PATH or common locations, report the error and stop
|
| 77 |
+
- If `KAYBA_API_KEY` is not set, report the error and stop
|
| 78 |
+
- If `kayba insights list` fails (network error, auth error), report the error and stop
|
| 79 |
+
- If 0 insights are returned, write a minimal summary and stop — downstream stages need insights
|
| 80 |
+
|
| 81 |
+
## Outputs
|
| 82 |
+
|
| 83 |
+
- `eval/insights.json` — raw API response
|
| 84 |
+
- `eval/stage1_insights_summary.md` — structured summary with quality annotations for downstream stages
|
.claude/skills/kayba-pipeline/stage-2-domain-context/SKILL.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: kayba-stage-2-domain-context
|
| 3 |
+
description: Gather domain context about the repository and agent — system prompt, tool definitions, domain docs, and behavior patterns from traces. Trigger when the user says "run stage 2", "gather context", "domain context", or when invoked by the kayba-pipeline orchestrator.
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Stage 2: Domain Context Gathering
|
| 7 |
+
|
| 8 |
+
Understand the agent's world — what it does, what tools it has, and what "success" looks like.
|
| 9 |
+
|
| 10 |
+
## Inputs
|
| 11 |
+
|
| 12 |
+
- **`TRACES_FOLDER`** — path to directory containing trace JSON files
|
| 13 |
+
|
| 14 |
+
## Process
|
| 15 |
+
|
| 16 |
+
### 0. Detect trace format
|
| 17 |
+
|
| 18 |
+
Before reading traces, identify the framework that produced them. Read 1 trace file and check:
|
| 19 |
+
|
| 20 |
+
| Signal | Framework |
|
| 21 |
+
|--------|-----------|
|
| 22 |
+
| `info.agent_info.implementation`, `info.environment_info`, `simulation.messages[]` with `role`/`tool_calls`/`turn_idx` | **tau2-bench** |
|
| 23 |
+
| `runs[].steps[]` with `type: "tool"`, `lc_kwargs` | **LangChain / LangSmith** |
|
| 24 |
+
| `events[]` with `event_type`, `span_id`, `parent_id` | **LlamaIndex** |
|
| 25 |
+
| `choices[].message.tool_calls[]` at top level | **Raw OpenAI API logs** |
|
| 26 |
+
| `trace.spans[]` with `attributes`, `trace_id` | **OpenTelemetry / Arize / Langfuse** |
|
| 27 |
+
|
| 28 |
+
Record the detected format in the output under **Trace Format**. All subsequent trace-reading steps use the field paths appropriate for that format.
|
| 29 |
+
|
| 30 |
+
If the format is unrecognized, note the top-level keys and structure, then proceed best-effort with field names found in the data.
|
| 31 |
+
|
| 32 |
+
### 1. Detect architecture
|
| 33 |
+
|
| 34 |
+
Read 2-3 traces and determine if this is a single-agent or multi-agent system:
|
| 35 |
+
|
| 36 |
+
- **Single agent**: one `agent_info` entry, one conversation thread, tool calls from one identity
|
| 37 |
+
- **Multi-agent / router**: look for multiple `agent_info` entries, routing tool calls (e.g., `transfer_to_*`, `delegate_to_*`), sub-conversation arrays, or distinct system prompts per agent identity
|
| 38 |
+
|
| 39 |
+
If multi-agent: document each agent separately (name, role, tools, handoff triggers) and note the routing logic. The remaining steps apply per-agent.
|
| 40 |
+
|
| 41 |
+
### 2. Find the system prompt
|
| 42 |
+
|
| 43 |
+
Use a fallback chain — stop at the first hit:
|
| 44 |
+
|
| 45 |
+
1. **Config files** — grep for keys: `system_prompt`, `system_message`, `instructions`, `AGENT_INSTRUCTION`, `SYSTEM_PROMPT` in YAML/JSON/TOML/Python/JS files
|
| 46 |
+
2. **Source code** — search for prompt template strings, f-strings, or `.format()` calls that build the system message (look in agent implementation files)
|
| 47 |
+
3. **Trace extraction** — read 3 trace files from `{TRACES_FOLDER}`:
|
| 48 |
+
- Check `info.environment_info.policy` (tau2-bench format)
|
| 49 |
+
- Check first message with `role: "system"` in the messages array
|
| 50 |
+
- Check `raw_data` fields for system-level content
|
| 51 |
+
4. **Not found** — if none of the above yields a system prompt, explicitly record `SYSTEM_PROMPT_STATUS: NOT_FOUND` in the output and flag this for the orchestrator. Do not fabricate or guess.
|
| 52 |
+
|
| 53 |
+
When found, record both the prompt content and its **source location** (file path + line, or trace field path).
|
| 54 |
+
|
| 55 |
+
### 3. Extract tool definitions
|
| 56 |
+
|
| 57 |
+
Two-pass approach: source code first (ground truth), then traces (usage evidence).
|
| 58 |
+
|
| 59 |
+
**Pass 1 — Source code discovery:**
|
| 60 |
+
- Search for tool/function definition patterns: `@tool`, `@is_tool`, `def tool_`, function schema arrays, OpenAPI specs, `tools=[]` arguments
|
| 61 |
+
- For each tool, extract from source:
|
| 62 |
+
- Name
|
| 63 |
+
- Input parameters with types and defaults
|
| 64 |
+
- Return type / output schema (document the structure, not just "returns a dict")
|
| 65 |
+
- Side effects: READ (no state change), WRITE (mutates state), GENERIC (neither)
|
| 66 |
+
- Validation rules the tool does NOT enforce (critical — grep for comments like "API does not check", "agent must enforce")
|
| 67 |
+
|
| 68 |
+
**Pass 2 — Trace usage evidence:**
|
| 69 |
+
- Read ALL traces (if <= 20) or a stratified sample (see step 4 for sampling)
|
| 70 |
+
- Extract every unique `tool_calls[].name` from assistant messages
|
| 71 |
+
- Extract every `role: "tool"` response to document actual output shapes
|
| 72 |
+
- For each tool, record one example input/output pair from traces
|
| 73 |
+
|
| 74 |
+
**Reconcile the two passes:**
|
| 75 |
+
- Tools in source but NOT in traces = "available but unused" — flag these; they may be relevant for edge cases the agent should handle
|
| 76 |
+
- Tools in traces but NOT in source = possible dynamic tools or external APIs — investigate
|
| 77 |
+
|
| 78 |
+
Output the full tool inventory as a table with columns: Name, Category, Input Schema, Output Schema, Observed in Traces (Y/N), Unvalidated Rules.
|
| 79 |
+
|
| 80 |
+
### 4. Find domain documentation
|
| 81 |
+
|
| 82 |
+
- READMEs, product docs, wiki links
|
| 83 |
+
- Policy files (e.g., `data/*/policy.md`, domain-specific docs)
|
| 84 |
+
- Inline code comments explaining business logic
|
| 85 |
+
- Test files that describe expected behavior
|
| 86 |
+
- Anything that explains what the agent does and what "success" means for its users
|
| 87 |
+
|
| 88 |
+
### 5. Catalogue agent behavior patterns
|
| 89 |
+
|
| 90 |
+
**Trace selection — stratified sampling** (do not just grab "5-10 random traces"):
|
| 91 |
+
|
| 92 |
+
1. Count total traces in `{TRACES_FOLDER}`. If <= 20, read ALL of them.
|
| 93 |
+
2. If > 20, select a stratified sample:
|
| 94 |
+
- Sort by `termination_reason` — include at least 2 per unique reason
|
| 95 |
+
- Sort by conversation length (message count) — include shortest, longest, and 2 median
|
| 96 |
+
- Sort by tool call count — include lowest and highest
|
| 97 |
+
- If task outcomes are available (pass/fail), include at least 3 of each
|
| 98 |
+
- Target: ~15 traces total, or 30% of the corpus, whichever is larger
|
| 99 |
+
|
| 100 |
+
For each selected trace, document:
|
| 101 |
+
- **Function call frequency** — which tools are called most, in what order
|
| 102 |
+
- **Tool call sequences** — common tool chains (e.g., get_user -> get_reservation -> cancel)
|
| 103 |
+
- **Success patterns** — what does a thread that accomplishes its goal look like?
|
| 104 |
+
- **Failure patterns** — what does a thread that fails or gets stuck look like?
|
| 105 |
+
- **Error patterns** — what error strings appear in tool outputs? Group by root cause
|
| 106 |
+
- **Policy violation patterns** — where does the agent break its own rules? (e.g., multiple tool calls per turn, acting without confirmation)
|
| 107 |
+
- **User feedback signals** — reverts, ratings, explicit corrections, escalations, stop tokens, transfer tokens
|
| 108 |
+
|
| 109 |
+
### 6. Write findings
|
| 110 |
+
|
| 111 |
+
Write all findings to `eval/stage2_domain_context.md`:
|
| 112 |
+
|
| 113 |
+
```markdown
|
| 114 |
+
# Domain Context
|
| 115 |
+
|
| 116 |
+
## Trace Format
|
| 117 |
+
- Framework: [detected framework name]
|
| 118 |
+
- Key field paths: [e.g., simulation.messages[], info.environment_info.policy]
|
| 119 |
+
|
| 120 |
+
## Architecture
|
| 121 |
+
- Type: [single-agent | multi-agent]
|
| 122 |
+
- [If multi-agent: agent roster with roles and handoff triggers]
|
| 123 |
+
|
| 124 |
+
## Agent Purpose
|
| 125 |
+
[1-2 sentence summary of what this agent does]
|
| 126 |
+
|
| 127 |
+
## System Prompt
|
| 128 |
+
- **Source**: [file path + line, or trace field path, or NOT_FOUND]
|
| 129 |
+
- **Status**: [verbatim | reconstructed | not_found]
|
| 130 |
+
|
| 131 |
+
[The system prompt content, or "NOT_FOUND — downstream stages should account for missing system prompt"]
|
| 132 |
+
|
| 133 |
+
## Tools
|
| 134 |
+
| Tool | Category | Input Schema | Output Schema | In Traces? | Unvalidated Rules |
|
| 135 |
+
|------|----------|-------------|---------------|------------|-------------------|
|
| 136 |
+
| tool_name | READ/WRITE/GENERIC | `{param: type}` | `{field: type}` | Y/N | "API does not check X" |
|
| 137 |
+
|
| 138 |
+
### Tools available but never called in traces
|
| 139 |
+
- [tool_name — why it matters]
|
| 140 |
+
|
| 141 |
+
## Domain Rules
|
| 142 |
+
[Key business rules, constraints, policies the agent must follow]
|
| 143 |
+
|
| 144 |
+
## Behavior Patterns
|
| 145 |
+
|
| 146 |
+
### Success patterns
|
| 147 |
+
- [pattern 1]
|
| 148 |
+
|
| 149 |
+
### Failure patterns
|
| 150 |
+
- [pattern 1]
|
| 151 |
+
|
| 152 |
+
### Policy violation patterns
|
| 153 |
+
- [violation with frequency: N/M turns]
|
| 154 |
+
|
| 155 |
+
### Error patterns
|
| 156 |
+
| Error | Frequency | Root cause |
|
| 157 |
+
|-------|-----------|------------|
|
| 158 |
+
| error string | N traces | cause |
|
| 159 |
+
|
| 160 |
+
### User feedback signals
|
| 161 |
+
- [signal 1]
|
| 162 |
+
```
|
| 163 |
+
|
| 164 |
+
## Outputs
|
| 165 |
+
|
| 166 |
+
- `eval/stage2_domain_context.md`
|
.claude/skills/kayba-pipeline/stage-3-metrics/SKILL.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: kayba-stage-3-metrics
|
| 3 |
+
description: Define metrics from Kayba insights, implement them as Python measurement code, run against traces, and iterate until the metrics are clean and meaningful. Trigger when the user says "run stage 3", "define metrics", "build metrics", "compute baselines", or when invoked by the kayba-pipeline orchestrator. Requires eval/stage1_insights_summary.md and eval/stage2_domain_context.md to exist.
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Stage 3: Metrics and Programmatic Analysis
|
| 7 |
+
|
| 8 |
+
Define metrics from insights, implement as code, run, review, iterate.
|
| 9 |
+
|
| 10 |
+
## Inputs
|
| 11 |
+
|
| 12 |
+
- **`TRACES_FOLDER`** — path to directory containing trace JSON files
|
| 13 |
+
- **`eval/stage1_insights_summary.md`** — output from Stage 1
|
| 14 |
+
- **`eval/stage2_domain_context.md`** — output from Stage 2
|
| 15 |
+
|
| 16 |
+
Read both input files before starting.
|
| 17 |
+
|
| 18 |
+
## Process
|
| 19 |
+
|
| 20 |
+
This stage is iterative. You cycle through define → implement → run → review, with a hard cap of **3 iterations**. A metric set is "clean" when ALL of the following hold:
|
| 21 |
+
|
| 22 |
+
1. **No small-sample metrics in the priority set** — every metric used for priority ranking has denominator >= 5. Metrics with denominator < 5 are kept but labeled `"confidence": "directional-only"` and excluded from priority sorting.
|
| 23 |
+
2. **No unexplained extremes** — no metric reads 0% or 100% unless you can write a one-sentence justification (e.g., "0% is correct because the agent never calls send_certificate anywhere in the dataset"). Record the justification in the metric's `"extreme_justification"` field.
|
| 24 |
+
3. **No redundant pairs** — no two metrics share > 70% of their denominator events. Check this: for each pair, compute `|events_A ∩ events_B| / min(|events_A|, |events_B|)`. If > 0.70, merge or drop one.
|
| 25 |
+
4. **Script runs without errors** on the full trace set.
|
| 26 |
+
|
| 27 |
+
If after 3 iterations the set is not fully clean, ship what you have and log remaining issues in `eval/baseline_metrics.json` under a top-level `"warnings"` key.
|
| 28 |
+
|
| 29 |
+
### Step 1: Define metrics
|
| 30 |
+
|
| 31 |
+
For each insight from the Kayba analysis, use the evidence fields to identify observable signals in the traces:
|
| 32 |
+
|
| 33 |
+
1. Read the insights summary — focus on evidence citations, error strings, behavioral patterns
|
| 34 |
+
2. For each valid insight, determine what trace signal would change if the agent followed the skill
|
| 35 |
+
3. Classify each metric by detector pattern type:
|
| 36 |
+
|
| 37 |
+
**Recovery detectors** — consecutive calls to the same function where first has error, next succeeds
|
| 38 |
+
```python
|
| 39 |
+
def has_recovery(calls, function_name):
|
| 40 |
+
for i in range(len(calls) - 1):
|
| 41 |
+
if calls[i]['name'] == function_name and is_error(calls[i]['output']):
|
| 42 |
+
if calls[i+1]['name'] == function_name and is_success(calls[i+1]['output']):
|
| 43 |
+
return True
|
| 44 |
+
return False
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
**Loop detectors** — N+ consecutive calls to the same function (stuck agent)
|
| 48 |
+
|
| 49 |
+
**Give-up detectors** — regex match agent output for abandonment phrases ("I'm unable to", "cannot complete", "beyond my capabilities")
|
| 50 |
+
|
| 51 |
+
**Error classifiers** — match function outputs against domain-specific error patterns. Build a pattern table:
|
| 52 |
+
```python
|
| 53 |
+
ERROR_PATTERNS = {
|
| 54 |
+
'pattern_name': r'regex matching the error',
|
| 55 |
+
# one entry per distinct error type
|
| 56 |
+
}
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
**Over-exploration detectors** — ratio of explore vs action calls. Use the tool categories from Stage 2. If explore ratio exceeds threshold AND task didn't complete → analysis paralysis
|
| 60 |
+
|
| 61 |
+
**Ground-truth comparison detectors** — agent claims a value (dollar amount, flight number, policy rule) in natural language, and the preceding tool response contains the actual value. Extract candidate values from agent text via regex, then compare against structured fields in the tool response JSON. Examples:
|
| 62 |
+
```python
|
| 63 |
+
# Extract dollar amounts from agent text
|
| 64 |
+
DOLLAR_PATTERN = r'\$\s?([\d,]+(?:\.\d{2})?)'
|
| 65 |
+
|
| 66 |
+
# Extract flight numbers (3 letters + 3 digits)
|
| 67 |
+
FLIGHT_PATTERN = r'\b([A-Z]{2,3}\d{3,4})\b'
|
| 68 |
+
|
| 69 |
+
def check_agent_claims_against_tool(agent_text, preceding_tool_response):
|
| 70 |
+
"""Compare values the agent states against the tool response ground truth."""
|
| 71 |
+
claimed_amounts = re.findall(DOLLAR_PATTERN, agent_text)
|
| 72 |
+
actual_amounts = extract_amounts_from_json(preceding_tool_response)
|
| 73 |
+
# A claim is fabricated if it doesn't match any actual value
|
| 74 |
+
fabricated = [c for c in claimed_amounts if not any(matches(c, a) for a in actual_amounts)]
|
| 75 |
+
return len(fabricated) == 0, fabricated
|
| 76 |
+
```
|
| 77 |
+
This pattern covers data accuracy (fabricated prices/flights), post-action verification (quoted vs actual cost), and policy accuracy (claimed restrictions vs policy text). These are NOT qualitative-only — regex + JSON comparison is noisy but produces a real signal. Build the detector even if it's imperfect; a noisy metric that produces a fix is better than a clean classification that produces nothing.
|
| 78 |
+
|
| 79 |
+
**Ordering/sequencing detectors** — agent performs actions in the wrong order (e.g., searches for flights before checking if the reservation is even modifiable). Check whether tool call A appears before tool call B when B should come first.
|
| 80 |
+
|
| 81 |
+
**Clean success** — threads where all tasks completed with no errors and no other tags
|
| 82 |
+
|
| 83 |
+
4. **Validate each detector before coding it at scale.** Pick 2-3 traces where you already know the ground truth from Stage 1 evidence. Run your detector logic mentally (or in a scratch script) against those traces. If it misclassifies any of them, fix the logic before writing the full implementation. This catches regex and pattern bugs early — the Stage 3 trace showed multiple iterations wasted on broken confirmation-phrase matching that a quick manual check would have caught.
|
| 84 |
+
|
| 85 |
+
### Step 2: Implement and run
|
| 86 |
+
|
| 87 |
+
1. Write `eval/compute_baselines.py` with:
|
| 88 |
+
- CLI args: `--traces-dir` (required), `--output` (default: `eval/baseline_metrics.json`)
|
| 89 |
+
- `load_traces(traces_dir)` — loads all JSON trace files
|
| 90 |
+
- Error pattern table built from reading 20-30 traces
|
| 91 |
+
- `tag_thread(thread)` — combines all detectors, returns list of tags
|
| 92 |
+
- One measurement function per metric, computing `numerator / denominator`
|
| 93 |
+
- `compute_all_baselines(traces_dir)` — runs all metrics, returns dict
|
| 94 |
+
- Main block that runs everything and prints summary
|
| 95 |
+
|
| 96 |
+
2. Run it:
|
| 97 |
+
```
|
| 98 |
+
python eval/compute_baselines.py --traces-dir {TRACES_FOLDER} --output eval/baseline_metrics.json
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
### Step 3: Review and iterate
|
| 102 |
+
|
| 103 |
+
Run these checks in order after every run. Each check either passes or produces a concrete fix action.
|
| 104 |
+
|
| 105 |
+
**Check A — Script health.** Did the script error or produce `null` values? → fix and re-run. This is iteration 0-cost; don't count it toward the 3-iteration cap.
|
| 106 |
+
|
| 107 |
+
**Check B — Small-sample guard.** For each metric, examine the denominator:
|
| 108 |
+
- denominator >= 5 → full-confidence metric, usable for priority ranking
|
| 109 |
+
- denominator 1-4 → label `"confidence": "directional-only"` in the output JSON. The metric stays in the report but is excluded from priority sorting in Stage 4. Do NOT drop it — small-sample metrics can still inform qualitative analysis.
|
| 110 |
+
- denominator 0 → the detector found no applicable events. Either the detector is broken (fix it) or the behavior genuinely doesn't occur in this trace set (log as `"confidence": "not-observed"` and move on).
|
| 111 |
+
|
| 112 |
+
**Check C — Extreme-value triage.** For any metric at exactly 0% or 100%:
|
| 113 |
+
- Ask: "Is there a plausible trace where this metric would NOT be extreme?" If yes → detector is likely broken, fix it.
|
| 114 |
+
- If no (the behavior legitimately always/never happens in this dataset) → write a one-sentence justification and add it as `"extreme_justification"` in the output. Example: M5=0% is correct because both cancellations in the dataset were on ineligible reservations.
|
| 115 |
+
- Do NOT reflexively drop 0%/100% metrics. A metric that correctly reads 0% is a strong signal for Stage 5 action planning.
|
| 116 |
+
- **Ceiling/floor flag for 100% and 0% metrics:** If a metric baseline is already at 100% (or 0% where 0% is the desired direction), add `"at_ceiling": true` (or `"at_floor": true`) to its entry in the output JSON. This signals to Stage 4 (direction setting) and Stage 5 (action planning) that the metric is already optimal and should NOT be listed as needing improvement. Stage 4 must set its direction to `"↑ maintain"` or `"— already optimal"`, never bare `"↑"`.
|
| 117 |
+
|
| 118 |
+
**Check D — Correlation / overlap audit.** For every pair of metrics, compute event overlap: `|denom_A ∩ denom_B| / min(|denom_A|, |denom_B|)`. If > 0.70:
|
| 119 |
+
- The two metrics are measuring overlapping populations. Keep the one with the sharper behavioral distinction (measures a more specific failure mode). Drop or merge the other.
|
| 120 |
+
- In the Stage 3 trace, M1 and M2 shared identical denominators (29 tool-calling turns) and were never flagged. They survived because they measure different *properties* of the same events — this is acceptable only if the numerator overlap is also checked. If both numerators move in lockstep (one is a strict subset of the other), merge them.
|
| 121 |
+
|
| 122 |
+
**Check E — Coverage (strict).** For EVERY Stage 1 insight, verify it has a corresponding metric. If an insight has no metric:
|
| 123 |
+
- First, try harder to build one. Can you extract values from agent text and compare against tool responses? Can you detect the wrong tool-call ordering? Can you pattern-match the failure mode with keywords + JSON field checks?
|
| 124 |
+
- Only after a concrete failed attempt, classify as unmeasurable with a specific reason why the approach you tried doesn't work.
|
| 125 |
+
- An insight classified as unmeasurable means Stage 5 will NOT produce a fix for it. That is a real cost. Treat every unmeasurable classification as a missed fix.
|
| 126 |
+
|
| 127 |
+
After checks, if any produced a fix action: apply fixes and re-run (counts as one iteration). If all checks pass → the metric set is clean. **Stop iterating.**
|
| 128 |
+
|
| 129 |
+
### Design principles
|
| 130 |
+
|
| 131 |
+
- **Target one metric per insight.** Every insight should have a metric unless it is genuinely unmeasurable (see above). If you end up with fewer metrics than insights, you are being too conservative. Directional-only metrics (denominator < 5) still count — they produce fixes in Stage 5. Only apply the redundancy check (Check D) to merge metrics that truly overlap; do not use the metric count as a reason to skip building detectors.
|
| 132 |
+
- **Express every metric as a ratio or percentage.** Absolute counts aren't comparable across trace sets.
|
| 133 |
+
- **Prefer per-event denominators over per-thread.** "% of EditScript calls with errors" is sharper than "% of threads with any EditScript error." Per-thread denominators compress information — a thread with 10 violations and a thread with 1 both count the same.
|
| 134 |
+
- **One metric per behavioral change.** If two would always move together, keep only the sharper one. Use Check D (overlap audit) to enforce this mechanically, not just by intuition.
|
| 135 |
+
- **Build a metric for EVERY insight. "Unmeasurable" is a last resort, not a default.** Before classifying an insight as unmeasurable, you MUST attempt to build a programmatic detector. The bar for "unmeasurable" is: you tried a concrete approach, it fundamentally cannot work (not just "it's noisy"), and you can explain why in one sentence.
|
| 136 |
+
|
| 137 |
+
Specifically:
|
| 138 |
+
- **"Agent claims X but tool response says Y"** — this is ALWAYS measurable. Use regex to extract values (dollar amounts, IDs, flight numbers) from agent text, compare against structured JSON fields in the preceding tool response. Noisy matches are fine — a metric that catches 70% of fabrications is far more useful than a qualitative note that catches 0%.
|
| 139 |
+
- **"Agent violates policy rule Z"** — if the policy rule can be stated as a condition on trace data (tool call ordering, presence/absence of a call, argument values), build a detector. Only classify as qualitative-only if the rule requires understanding the *meaning* of free-text agent output beyond keyword/pattern matching.
|
| 140 |
+
- **"Insufficient data"** — if the detector logic is clear but n < 5, build the detector anyway and label it `"confidence": "directional-only"`. Do NOT skip building the metric. A directional-only metric still produces a fix in Stage 5.
|
| 141 |
+
|
| 142 |
+
If after genuine effort an insight truly cannot be measured programmatically, classify it as:
|
| 143 |
+
- `"qualitative-only"` — requires semantic understanding that regex/JSON comparison cannot approximate. Must explain what specific semantic judgment is needed and why pattern matching fails.
|
| 144 |
+
- `"insufficient-data"` — detector exists but denominator is 0 (not just small — literally zero applicable events). Note what scenarios would need to appear in traces.
|
| 145 |
+
- `"needs-ground-truth"` — requires task-specific expected outcomes that aren't in the trace format.
|
| 146 |
+
|
| 147 |
+
Record any remaining unmeasurable insights in the output JSON under a `"unmeasurable"` key. **The goal is for this list to be as short as possible — ideally empty.**
|
| 148 |
+
|
| 149 |
+
## Outputs
|
| 150 |
+
|
| 151 |
+
- `eval/compute_baselines.py` — runnable script with `--traces-dir` and `--output` CLI args
|
| 152 |
+
- `eval/baseline_metrics.json` — computed baseline values, structured as:
|
| 153 |
+
```json
|
| 154 |
+
{
|
| 155 |
+
"M1": {
|
| 156 |
+
"name": "single_tool_call_compliance",
|
| 157 |
+
"value": 0.414,
|
| 158 |
+
"numerator": 12,
|
| 159 |
+
"denominator": 29,
|
| 160 |
+
"confidence": "full"
|
| 161 |
+
},
|
| 162 |
+
"M5": {
|
| 163 |
+
"name": "cancellation_policy_compliance",
|
| 164 |
+
"value": 0.0,
|
| 165 |
+
"numerator": 0,
|
| 166 |
+
"denominator": 2,
|
| 167 |
+
"confidence": "directional-only",
|
| 168 |
+
"extreme_justification": "0% correct: both cancellations in dataset were on ineligible reservations"
|
| 169 |
+
},
|
| 170 |
+
"warnings": ["M5 and M6 have denominator < 5; excluded from priority ranking"],
|
| 171 |
+
"unmeasurable": [
|
| 172 |
+
{
|
| 173 |
+
"insight_id": "d7494740",
|
| 174 |
+
"name": "Cabin Change Constraints",
|
| 175 |
+
"classification": "insufficient-data",
|
| 176 |
+
"reason": "Only 1 update_reservation_flights call in dataset"
|
| 177 |
+
}
|
| 178 |
+
]
|
| 179 |
+
}
|
| 180 |
+
```
|
.claude/skills/kayba-pipeline/stage-4-rubric/SKILL.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: kayba-stage-4-rubric
|
| 3 |
+
description: Organize computed metrics into a tiered evaluation rubric with leading, lagging, and quality indicators. Trigger when the user says "run stage 4", "build rubric", "tier metrics", or when invoked by the kayba-pipeline orchestrator. Requires eval/baseline_metrics.json and eval/compute_baselines.py to exist.
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Stage 4: Rubric Definition
|
| 7 |
+
|
| 8 |
+
Organize metrics into a tiered evaluation rubric. Detect and resolve redundancy quantitatively. Ensure every insight is accounted for.
|
| 9 |
+
|
| 10 |
+
## Inputs
|
| 11 |
+
|
| 12 |
+
- `eval/baseline_metrics.json` — computed baseline values from Stage 3
|
| 13 |
+
- `eval/compute_baselines.py` — to understand what each metric measures
|
| 14 |
+
- `eval/stage1_insights_summary.md` — the original insights
|
| 15 |
+
- `eval/stage2_domain_context.md` — domain context
|
| 16 |
+
|
| 17 |
+
Read all four files before starting.
|
| 18 |
+
|
| 19 |
+
## Process
|
| 20 |
+
|
| 21 |
+
### 1. Quantitative redundancy check
|
| 22 |
+
|
| 23 |
+
Before tiering, check every pair of metrics for overlap. Two metrics are redundancy candidates if ANY of the following hold:
|
| 24 |
+
|
| 25 |
+
- **Denominator overlap >70%**: compute `|denom_events(A) ∩ denom_events(B)| / min(|denom(A)|, |denom(B)|)`. If >0.70, they are candidates. To compute this, trace through the detector functions in `compute_baselines.py` and determine which trace events (turns, calls, threads) each denominator iterates over. When denominators are identical sets (same loop, same filter), overlap is 100%.
|
| 26 |
+
- **Same skill set**: the metrics map to the exact same set of insight/skill IDs from Stage 1.
|
| 27 |
+
- **Logical subsumption**: one metric's positive case is a strict subset of the other's (e.g., "turn has exactly 1 tool call" is a subset of "turn has no user-facing content alongside tool calls" only if every single-call turn also has no content — check this, don't assume it).
|
| 28 |
+
|
| 29 |
+
For each candidate pair, make an explicit decision with reasoning:
|
| 30 |
+
|
| 31 |
+
| Pair | Denom overlap | Skill overlap | Subsumption? | Decision | Reasoning |
|
| 32 |
+
|------|---------------|---------------|--------------|----------|-----------|
|
| 33 |
+
| M1/M2 | 100% (same 29 turns) | identical | No — can violate one without the other | **Keep both** | Independently actionable: batching vs. content leaking are distinct fixes |
|
| 34 |
+
|
| 35 |
+
Valid decisions: **keep both** (with reasoning why they're independently actionable), **merge** (combine into one metric, specify how), or **drop** (specify which and why). "They feel different" is not sufficient reasoning — cite the specific behavior that one catches and the other misses.
|
| 36 |
+
|
| 37 |
+
Final count target: 5-7 metrics after redundancy resolution.
|
| 38 |
+
|
| 39 |
+
### 2. Tier each metric
|
| 40 |
+
|
| 41 |
+
Use this decision flowchart for every metric:
|
| 42 |
+
|
| 43 |
+
```
|
| 44 |
+
Q1: Can a SINGLE skill/instruction change directly move this metric?
|
| 45 |
+
→ If the agent follows one new instruction and the metric improves,
|
| 46 |
+
regardless of other behaviors: LEADING.
|
| 47 |
+
|
| 48 |
+
Q2: Does moving this metric require MULTIPLE skills to be adopted together?
|
| 49 |
+
→ If improvement depends on several upstream behaviors all working
|
| 50 |
+
(e.g., proper turn structure + confirmation flow + execution):
|
| 51 |
+
LAGGING.
|
| 52 |
+
|
| 53 |
+
Q3: Does moving this metric require domain reasoning beyond following instructions?
|
| 54 |
+
→ If the agent needs to correctly interpret policy rules, evaluate
|
| 55 |
+
eligibility criteria, or make judgment calls that can't be reduced
|
| 56 |
+
to a single instruction: QUALITY.
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
Apply the flowchart to each metric and record the Q1/Q2/Q3 answer that determined the tier. If a metric could arguably be two tiers, pick the lower one (Leading < Lagging < Quality) and note the ambiguity.
|
| 60 |
+
|
| 61 |
+
Tier summary for reference:
|
| 62 |
+
|
| 63 |
+
| Tier | Purpose | Moves when... | Diagnostic signal |
|
| 64 |
+
|------|---------|---------------|-------------------|
|
| 65 |
+
| **Leading** | Behaviors a single skill directly changes | Skill is adopted | If leading moves but lagging doesn't → skill adopted but not solving the right problem |
|
| 66 |
+
| **Lagging** | Aggregate outcomes requiring multiple skills | Multiple skills coordinate | If lagging moves but leading doesn't → something else improved, not your skills |
|
| 67 |
+
| **Quality** | Requires domain understanding, not just instruction-following | Agent reasons correctly | If quality moves but lagging doesn't → agent got lucky or metric is mis-tiered |
|
| 68 |
+
|
| 69 |
+
### 3. Flag low-confidence baselines
|
| 70 |
+
|
| 71 |
+
Any metric with denominator < 5 events is a **low-confidence baseline**. These metrics:
|
| 72 |
+
- ARE included in the rubric (they measure real behaviors)
|
| 73 |
+
- Are marked with `**Confidence: low** (n=X)` in the rubric
|
| 74 |
+
- Must NOT drive priority decisions in Stage 5 — they inform direction only
|
| 75 |
+
- Should note what denominator size would make them reliable (rule of thumb: n >= 10 for a rate metric to be meaningful, n >= 30 for statistical comparisons)
|
| 76 |
+
|
| 77 |
+
### 4. Set direction
|
| 78 |
+
|
| 79 |
+
For each metric, indicate whether it should go **up higher** or **down lower**. Don't set arbitrary numerical targets — baseline + direction is enough.
|
| 80 |
+
|
| 81 |
+
**Ceiling guard:** If a metric's baseline is already 100%, its direction MUST be `"��� maintain"` or `"— already optimal"`, never `"↑"` as if it needs to go higher. A 100% metric is at ceiling — the goal is to sustain it, not improve it. Similarly, if a metric is at 0% and the desired direction is `"↓"`, mark it `"↓ maintain"` or `"— already at floor"`. Do not let any downstream stage (Stage 5 action plan, Stage 7 fixes) list a ceiling/floor metric as needing improvement.
|
| 82 |
+
|
| 83 |
+
### 5. Map insights to metrics (completeness check)
|
| 84 |
+
|
| 85 |
+
For every insight from `eval/stage1_insights_summary.md`, assign it to one of three categories:
|
| 86 |
+
|
| 87 |
+
1. **Mapped** — directly linked to one or more metrics. List which ones.
|
| 88 |
+
2. **Indirectly mapped** — supports a metric but isn't the primary driver. List the metric and explain the indirect relationship.
|
| 89 |
+
3. **Qualitative-only** — no programmatic metric captures this insight. Explicitly mark it and state why (e.g., "requires LLM-as-judge," "measures explanation quality," "efficiency pattern with no clear denominator").
|
| 90 |
+
|
| 91 |
+
Every insight MUST appear in exactly one category. If you find an insight that should have a metric but doesn't, note it as a gap for future Stage 3 iterations — but do not invent metrics at this stage.
|
| 92 |
+
|
| 93 |
+
At the end, report:
|
| 94 |
+
- `X / N insights mapped to metrics`
|
| 95 |
+
- `Y / N insights indirectly mapped`
|
| 96 |
+
- `Z / N insights qualitative-only`
|
| 97 |
+
|
| 98 |
+
### 6. Add invalidation notes
|
| 99 |
+
|
| 100 |
+
For each metric, write one sentence answering: "What would make this tier assignment wrong?"
|
| 101 |
+
|
| 102 |
+
Examples:
|
| 103 |
+
- M1 (Leading): "Wrong if fixing batching also requires the agent to change its confirmation flow — that would make it Lagging."
|
| 104 |
+
- M5 (Quality): "Wrong if cancellation compliance can be fixed by a single checklist instruction without requiring the agent to reason about policy — that would make it Leading."
|
| 105 |
+
|
| 106 |
+
These notes exist so Stage 5 can catch tier errors. If Stage 5 finds evidence that a tier is wrong (e.g., a single skill would move a "Quality" metric), it should flag the conflict rather than silently inheriting the error.
|
| 107 |
+
|
| 108 |
+
### 7. Write the rubric
|
| 109 |
+
|
| 110 |
+
Write to `eval/baseline_metrics.md`:
|
| 111 |
+
|
| 112 |
+
```markdown
|
| 113 |
+
# Eval Rubric — Baseline Metrics
|
| 114 |
+
|
| 115 |
+
## Summary
|
| 116 |
+
| # | Metric | Tier | Baseline | Direction | Confidence |
|
| 117 |
+
|---|--------|------|----------|-----------|------------|
|
| 118 |
+
| M1 | First-call success rate | Leading | 37.6% | up | ok (n=29) |
|
| 119 |
+
| M2 | ... | ... | ... | ... | ... |
|
| 120 |
+
|
| 121 |
+
## Tier Definitions
|
| 122 |
+
|
| 123 |
+
- **Leading** — Single skill directly moves this. Should change first after deployment.
|
| 124 |
+
- **Lagging** — Multiple skills must coordinate. Improves as a consequence of adoption.
|
| 125 |
+
- **Quality** — Requires domain reasoning beyond instruction-following. Hardest to move.
|
| 126 |
+
|
| 127 |
+
## Metric Details
|
| 128 |
+
|
| 129 |
+
### M1: [name]
|
| 130 |
+
**Tier:** Leading
|
| 131 |
+
**Baseline:** 37.6% (685 / 1,821)
|
| 132 |
+
**Confidence:** ok (n=1821) | low (n=X) — needs n>=Y for reliable comparison
|
| 133 |
+
**Direction:** up higher is better
|
| 134 |
+
**What it measures:** [description]
|
| 135 |
+
**How it's computed:** [reference to function in compute_baselines.py]
|
| 136 |
+
**Skills that should move this:** [list insight/skill IDs from stage 1]
|
| 137 |
+
**Tier rationale:** [which flowchart question determined the tier]
|
| 138 |
+
**Invalidation note:** [what would make this tier wrong]
|
| 139 |
+
|
| 140 |
+
### M2: [name]
|
| 141 |
+
...
|
| 142 |
+
|
| 143 |
+
## Redundancy Analysis
|
| 144 |
+
|
| 145 |
+
| Pair | Denom overlap | Skill overlap | Subsumption? | Decision | Reasoning |
|
| 146 |
+
|------|---------------|---------------|--------------|----------|-----------|
|
| 147 |
+
| ... | ... | ... | ... | ... | ... |
|
| 148 |
+
|
| 149 |
+
## Insight Coverage
|
| 150 |
+
|
| 151 |
+
### Mapped (X / N)
|
| 152 |
+
- `insight_id` — [title] → M1, M3
|
| 153 |
+
|
| 154 |
+
### Indirectly mapped (Y / N)
|
| 155 |
+
- `insight_id` — [title] → supports M5 via [explanation]
|
| 156 |
+
|
| 157 |
+
### Qualitative-only (Z / N)
|
| 158 |
+
- `insight_id` — [title] — [why no metric: e.g., "requires LLM-as-judge"]
|
| 159 |
+
```
|
| 160 |
+
|
| 161 |
+
## Outputs
|
| 162 |
+
|
| 163 |
+
- `eval/baseline_metrics.md` — human-readable tiered rubric with redundancy analysis, confidence flags, insight coverage, and invalidation notes
|
.claude/skills/kayba-pipeline/stage-5-action-plan/SKILL.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: kayba-stage-5-action-plan
|
| 3 |
+
description: Triage each insight into discard/code-fix/prompt-fix and produce a prioritized action plan with specific recommendations. Trigger when the user says "run stage 5", "make action plan", "triage skills", or when invoked by the kayba-pipeline orchestrator. Requires eval outputs from stages 1-4.
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Stage 5: Action Plan
|
| 7 |
+
|
| 8 |
+
Triage each insight and produce a concrete, prioritized action plan.
|
| 9 |
+
|
| 10 |
+
## Inputs
|
| 11 |
+
|
| 12 |
+
- `eval/stage1_insights_summary.md` — insights from Kayba
|
| 13 |
+
- `eval/stage2_domain_context.md` — domain context
|
| 14 |
+
- `eval/baseline_metrics.md` — the evaluation rubric
|
| 15 |
+
- `eval/baseline_metrics.json` — baseline values
|
| 16 |
+
- `eval/compute_baselines.py` — measurement code
|
| 17 |
+
|
| 18 |
+
Read all files before starting.
|
| 19 |
+
|
| 20 |
+
## Process
|
| 21 |
+
|
| 22 |
+
### 1. Triage each insight
|
| 23 |
+
|
| 24 |
+
For each insight/skill, answer three questions in order: Is it valid? Is it already handled? Is it a code fix or prompt fix?
|
| 25 |
+
|
| 26 |
+
#### 1a. Validity check
|
| 27 |
+
|
| 28 |
+
- Does it describe a real, recurring problem visible in traces — or noise from a one-off edge case?
|
| 29 |
+
- Is it actionable — can the agent actually change this behavior given its tools and context?
|
| 30 |
+
- If not valid → verdict: **discard** with a one-sentence reason.
|
| 31 |
+
|
| 32 |
+
#### 1b. "Already handled" verification
|
| 33 |
+
|
| 34 |
+
Do not rely on memory or assumption. Run these checks and cite what you find:
|
| 35 |
+
|
| 36 |
+
1. **Grep the codebase** for 2-3 key terms from the insight (tool names, error strings, behavioral keywords). Example: for an insight about cancellation eligibility, grep for `cancel`, `eligibility`, `criteria`.
|
| 37 |
+
2. **Read the existing system prompt text** — check `AGENT_INSTRUCTION` in the agent file and the domain policy file. Quote any existing language that addresses this behavior.
|
| 38 |
+
3. **Verdict:**
|
| 39 |
+
- If existing text partially covers it → **keep** as a strengthening fix, note what's missing.
|
| 40 |
+
- If no existing coverage → **keep**.
|
| 41 |
+
- If existing prompt text already covers the behavior thoroughly AND the baseline metric is >= 95% → **discard** (cite the existing text and metric). A high baseline alone is NOT sufficient to discard — if the metric is below 95%, there are still failures to fix. An 87% baseline means 1 in 8 attempts still fails; that is worth fixing.
|
| 42 |
+
|
| 43 |
+
#### 1c. Code-vs-prompt decision tree
|
| 44 |
+
|
| 45 |
+
Walk through this tree for every non-discarded insight:
|
| 46 |
+
|
| 47 |
+
```
|
| 48 |
+
Q1: Can the agent fix this by following different instructions?
|
| 49 |
+
(Does it have the right tools, correct data in tool responses,
|
| 50 |
+
and sufficient context to behave correctly?)
|
| 51 |
+
│
|
| 52 |
+
├─ YES → PROMPT FIX
|
| 53 |
+
│ The agent has everything it needs but acts wrong.
|
| 54 |
+
│ A system prompt addition would fix it.
|
| 55 |
+
│
|
| 56 |
+
└─ NO → Q2: What is the agent missing?
|
| 57 |
+
│
|
| 58 |
+
├─ Tool doesn't exist, schema is wrong, API returns
|
| 59 |
+
│ incomplete data, infrastructure drops information,
|
| 60 |
+
│ timeout/error not surfaced to agent
|
| 61 |
+
│ → CODE FIX
|
| 62 |
+
│ Name the file, function, and specific change.
|
| 63 |
+
│
|
| 64 |
+
└─ The agent has partial information but the prompt
|
| 65 |
+
can't fully compensate (e.g., needs a new tool
|
| 66 |
+
but a heuristic prompt workaround exists)
|
| 67 |
+
→ PROMPT FIX (primary) + CODE FIX (optional)
|
| 68 |
+
Note both. Mark the code fix as "optional" with
|
| 69 |
+
a one-sentence justification for why it's lower priority.
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
**Ambiguity default:** When genuinely uncertain, default to **prompt fix** and add a note: `"Classification uncertain — defaulting to prompt fix. Revisit if prompt change doesn't move metrics."` This is safer because prompt fixes are cheaper to test and revert, and Stage 7 handles prompt fixes and code fixes through different paths.
|
| 73 |
+
|
| 74 |
+
Use the reflector's reasoning from Stage 1 insights — it often explicitly identifies root causes that clarify the code-vs-prompt distinction.
|
| 75 |
+
|
| 76 |
+
### 2. Consolidate related insights
|
| 77 |
+
|
| 78 |
+
Before writing recommendations, merge insights that are redundant. Two insights should merge when ALL three conditions hold:
|
| 79 |
+
|
| 80 |
+
1. **Same target behavior** — they describe the agent doing (or failing to do) the same thing.
|
| 81 |
+
2. **Overlapping fix text** — the prompt instructions you'd write for each would share >50% of their content.
|
| 82 |
+
3. **Addressing one substantially addresses the other** — fixing insight A would fix >80% of the cases described by insight B.
|
| 83 |
+
|
| 84 |
+
**When NOT to merge** — two insights about the same tool or domain area but different failure modes should remain separate. Example: "agent doesn't check cancellation eligibility" and "agent doesn't execute cancellation after user confirms" both involve `cancel_reservation` but are completely different behavioral failures with different prompt fixes. Keep them separate.
|
| 85 |
+
|
| 86 |
+
For each merge, document:
|
| 87 |
+
- Which insight IDs are combined
|
| 88 |
+
- Which insight's framing is primary (use the one with stronger trace evidence)
|
| 89 |
+
- What, if anything, is lost from the secondary insight (add it as a sub-point)
|
| 90 |
+
|
| 91 |
+
### 3. Write specific recommendations
|
| 92 |
+
|
| 93 |
+
For each insight (after merging):
|
| 94 |
+
|
| 95 |
+
- **Discards:** one sentence on why it's not valid or actionable.
|
| 96 |
+
- **Code fixes:** what code/schema/infrastructure to change. Name the file, the function, the specific change. If Stage 7 needs to find the right code location, give it enough to grep for.
|
| 97 |
+
- **Prompt fixes:** the exact instruction text to add to the system prompt, where it should go (e.g., appended to `AGENT_INSTRUCTION`, added to domain policy, or as a standalone skill block), and why this wording over alternatives.
|
| 98 |
+
|
| 99 |
+
### 4. Assess risk per fix
|
| 100 |
+
|
| 101 |
+
For each non-discarded fix, assess whether the change could break currently-working behaviors:
|
| 102 |
+
|
| 103 |
+
| Risk | Definition | Example |
|
| 104 |
+
|------|-----------|---------|
|
| 105 |
+
| **None** | Change is additive; no existing behavior could be affected | Adding a new metric to compute_baselines.py |
|
| 106 |
+
| **Low** | Change targets a behavior that is currently failing; working cases are unrelated | Adding a cancellation checklist when current cancellation compliance is 0% |
|
| 107 |
+
| **Medium** | Change modifies a behavior where some cases already work correctly | Strengthening confirmation protocol when 28.6% already succeed — could the new wording break the working 28.6%? |
|
| 108 |
+
| **High** | Change rewrites or constrains a behavior that mostly works | Restricting tool-call patterns when 41.4% already comply — overly rigid wording could cause the agent to under-call tools |
|
| 109 |
+
|
| 110 |
+
For Medium and High risk fixes, add a one-sentence mitigation: what to watch for, or how to word the prompt to preserve working cases.
|
| 111 |
+
|
| 112 |
+
### 5. Handle qualitative-only insights — STILL PRODUCE FIXES
|
| 113 |
+
|
| 114 |
+
Some insights from Stage 3 may be flagged as "unmeasurable." **These still get fixes.** An insight that the agent fabricates data or violates policy is a real problem whether or not we can measure it programmatically. Treat them the same as any other insight:
|
| 115 |
+
|
| 116 |
+
- Run the same triage (validity → already-handled → code-vs-prompt) as every other insight.
|
| 117 |
+
- Include them in the **priority-ranked implementation list** alongside all other fixes. They are NOT second-class.
|
| 118 |
+
- Use the trace evidence from the insight (not the metric) to assess impact and priority. If the insight has strong trace evidence showing clear failures, rank it accordingly.
|
| 119 |
+
- For prioritization: since there is no metric denominator, use confidence = 0.5 and estimate impact from the severity described in the insight evidence.
|
| 120 |
+
- In the fix entry, note that this fix has no programmatic metric for automated before/after comparison, so improvement should be verified via manual trace review or LLM-as-judge after generating new traces.
|
| 121 |
+
|
| 122 |
+
Only relegate an insight to a non-actionable "Monitor Items" section if the triage concludes it should be **discarded** (not valid or not actionable). Being unmeasurable is NOT a reason to skip fixing it.
|
| 123 |
+
|
| 124 |
+
### 6. Link to metrics
|
| 125 |
+
|
| 126 |
+
For each non-discarded fix, identify which metric(s) from the rubric would move if this fix is implemented. Use the metric IDs from `eval/baseline_metrics.md` (e.g., M1, M2).
|
| 127 |
+
|
| 128 |
+
### 7. Prioritize
|
| 129 |
+
|
| 130 |
+
Rank non-discarded fixes using this formula:
|
| 131 |
+
|
| 132 |
+
```
|
| 133 |
+
Priority Score = Impact × Confidence × Tier Bonus ÷ Risk Factor
|
| 134 |
+
```
|
| 135 |
+
|
| 136 |
+
Where:
|
| 137 |
+
- **Impact** = estimated metric delta. Use the gap between baseline and 100% as the ceiling. A fix expected to close 50% of that gap on M1 (baseline 41.4%) has impact = 0.5 × (1.0 - 0.414) = 0.293.
|
| 138 |
+
- **Confidence** = sample size reliability. Use the denominator from `baseline_metrics.json`:
|
| 139 |
+
- denominator >= 20: confidence = 1.0
|
| 140 |
+
- denominator 10-19: confidence = 0.8
|
| 141 |
+
- denominator 5-9: confidence = 0.6
|
| 142 |
+
- denominator < 5: confidence = 0.3
|
| 143 |
+
- **Tier Bonus** = leading metrics get a 1.5x multiplier (they validate adoption), lagging and quality get 1.0x. Rationale: leading metrics move first and tell you if your fix is even being adopted — you want those signals early.
|
| 144 |
+
- **Risk Factor** = None: 1.0, Low: 1.0, Medium: 1.5, High: 2.0
|
| 145 |
+
|
| 146 |
+
You do not need to compute exact scores to three decimal places. The formula is a tiebreaker and sanity check. The point is:
|
| 147 |
+
- High-impact, high-confidence, leading-metric fixes with low risk go first.
|
| 148 |
+
- Low-confidence fixes (small denominators) get deprioritized even if the metric is at 0%.
|
| 149 |
+
- High-risk fixes get deprioritized unless impact is overwhelming.
|
| 150 |
+
|
| 151 |
+
After scoring, apply one manual adjustment pass: if a fix is a prerequisite for another fix (e.g., "confirmation protocol" must exist before "post-confirmation execution" can be measured), promote the prerequisite even if its standalone score is lower.
|
| 152 |
+
|
| 153 |
+
## Output format
|
| 154 |
+
|
| 155 |
+
Write to `eval/action_plan.md`:
|
| 156 |
+
|
| 157 |
+
```markdown
|
| 158 |
+
# Action Plan
|
| 159 |
+
|
| 160 |
+
## Summary
|
| 161 |
+
- Total insights: N
|
| 162 |
+
- Discarded: X (with reasons)
|
| 163 |
+
- Code fixes: Y
|
| 164 |
+
- Prompt fixes: Z
|
| 165 |
+
- Fixes without programmatic metric (verify manually): Q
|
| 166 |
+
|
| 167 |
+
## Implementation Priority
|
| 168 |
+
| Rank | Fix | Type | Metrics | Risk | Score rationale |
|
| 169 |
+
|------|-----|------|---------|------|-----------------|
|
| 170 |
+
| 1 | [name] | prompt | M1, M2 | Low | [one-line: why this ranks here] |
|
| 171 |
+
| 2 | ... | ... | ... | ... | ... |
|
| 172 |
+
|
| 173 |
+
---
|
| 174 |
+
|
| 175 |
+
## Skill: [insight ID(s)] — [title]
|
| 176 |
+
**Summary:** [one-line description of what the skill addresses]
|
| 177 |
+
**Verdict:** `prompt fix` | `code fix` | `discard`
|
| 178 |
+
**Classification path:** [which branch of the decision tree — e.g., "Agent has tools and data but acts wrong → prompt fix"]
|
| 179 |
+
**Rationale:** [why this verdict — reference specific trace evidence from insights]
|
| 180 |
+
**Risk:** None | Low | Medium | High — [one-sentence justification]
|
| 181 |
+
**Risk mitigation:** [for Medium/High only — what to watch for or how to preserve working cases]
|
| 182 |
+
**Recommendation:** [specific change to make]
|
| 183 |
+
**Files to modify:** [list of files, for code fixes]
|
| 184 |
+
**Metric link:** [which metrics would move, with baseline values]
|
| 185 |
+
**Already-handled check:** [what you grepped, what existing prompt text you found, verdict]
|
| 186 |
+
|
| 187 |
+
---
|
| 188 |
+
[repeat for each insight]
|
| 189 |
+
|
| 190 |
+
## Consolidated Prompt Skills
|
| 191 |
+
[After all per-insight entries, list the final merged prompt skill texts in priority order, ready for Stage 7 to implement]
|
| 192 |
+
|
| 193 |
+
## Monitor Items (Non-Actionable Only)
|
| 194 |
+
[Only insights that were triaged as genuinely non-actionable — e.g., the agent cannot change this behavior, or the insight is noise. Unmeasurable insights that are still real problems should appear in the priority list above, NOT here.]
|
| 195 |
+
```
|
| 196 |
+
|
| 197 |
+
Group related insights under cluster headings when they address the same underlying behavior. For merged insights, list all constituent insight IDs in the heading.
|
| 198 |
+
|
| 199 |
+
## Outputs
|
| 200 |
+
|
| 201 |
+
- `eval/action_plan.md`
|
.claude/skills/kayba-pipeline/stage-6-hitl/SKILL.md
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: kayba-stage-6-hitl
|
| 3 |
+
description: Human-In-The-Loop gate that presents the action plan with full context, collects an informed approval/modification/rejection decision, and records the outcome. Trigger when the user says "run stage 6", "HITL review", "approve action plan", or when invoked by the kayba-pipeline orchestrator. Requires eval/action_plan.md and eval/baseline_metrics.md to exist.
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Stage 6: Human-In-The-Loop Gate
|
| 7 |
+
|
| 8 |
+
Present the action plan with enough context for an informed decision, collect the user's approval, and record the outcome.
|
| 9 |
+
|
| 10 |
+
The goal is not rubber-stamping. The user must receive enough information to genuinely evaluate, modify, or reject the plan -- even if they have not seen Stages 1-5.
|
| 11 |
+
|
| 12 |
+
## Inputs
|
| 13 |
+
|
| 14 |
+
- `eval/action_plan.md` -- the prioritized action plan from Stage 5
|
| 15 |
+
- `eval/baseline_metrics.md` -- the evaluation rubric with baseline values
|
| 16 |
+
- `eval/baseline_metrics.json` -- raw metric data (for exact numerator/denominator counts)
|
| 17 |
+
- `eval/stage1_insights_summary.md` -- original insights (for trace evidence references)
|
| 18 |
+
|
| 19 |
+
Read all four files before starting.
|
| 20 |
+
|
| 21 |
+
## Process
|
| 22 |
+
|
| 23 |
+
### 1. Build the executive summary
|
| 24 |
+
|
| 25 |
+
Compute and present the following counts from the action plan:
|
| 26 |
+
|
| 27 |
+
- Total insights analyzed (raw count before deduplication)
|
| 28 |
+
- Distinct actionable items after deduplication
|
| 29 |
+
- Breakdown: prompt fixes, code fixes, discarded
|
| 30 |
+
- Discard rate with one-line reason per discard (e.g., "5ac7f4ce: efficiency optimization, conflicts with turn discipline constraint")
|
| 31 |
+
|
| 32 |
+
Format:
|
| 33 |
+
|
| 34 |
+
```
|
| 35 |
+
EXECUTIVE SUMMARY
|
| 36 |
+
-----------------
|
| 37 |
+
Insights analyzed: 19 (raw) -> 12 distinct after dedup
|
| 38 |
+
Actionable: 9 (8 prompt fixes, 1 code fix)
|
| 39 |
+
Discarded: 3 (reasons listed below)
|
| 40 |
+
|
| 41 |
+
Discards:
|
| 42 |
+
- 5ac7f4ce (Upfront Info Collection): conflicts with higher-priority turn discipline
|
| 43 |
+
- fe2d51cb (Proactive Reservation Lookup): already default behavior, no failure evidence
|
| 44 |
+
- 1fa1b826 (Cancellation Denial Enumeration): subsumed into cancellation checklist
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
### 2. Present the top 3 highest-impact changes
|
| 48 |
+
|
| 49 |
+
For each of the top 3 fixes by priority, present:
|
| 50 |
+
|
| 51 |
+
**Before/after behavior** -- use concrete examples from actual traces referenced in the insights. Quote the specific agent behavior that was wrong (before) and describe what the agent should do instead (after). Reference the trace task ID.
|
| 52 |
+
|
| 53 |
+
**Target metric delta** -- which metric(s) this fix targets, the current baseline value, and the expected direction. Do not fabricate precise target numbers. Use the format: "M1: 41.4% -> higher (target: 90%+)" only when the action plan provides a target; otherwise use "M1: 41.4% -> up".
|
| 54 |
+
|
| 55 |
+
**Risk rating** -- assess each fix:
|
| 56 |
+
- `Low` -- additive prompt instruction, no behavioral side effects expected
|
| 57 |
+
- `Medium` -- changes existing behavior, could affect adjacent workflows
|
| 58 |
+
- `High` -- modifies code/infrastructure, or could degrade a metric while improving another
|
| 59 |
+
|
| 60 |
+
Format each as a numbered block:
|
| 61 |
+
|
| 62 |
+
```
|
| 63 |
+
#1: Turn Discipline (covers 55c00c40, d9683144)
|
| 64 |
+
Type: prompt fix
|
| 65 |
+
Metrics: M1 (41.4% -> up), M2 (20.7% -> up)
|
| 66 |
+
Risk: Low
|
| 67 |
+
|
| 68 |
+
BEFORE (task_1, task_5, task_7, ...):
|
| 69 |
+
Agent batches 2-3 tool calls per turn (e.g., get_reservation + get_flight_status
|
| 70 |
+
in a single response). Also includes user-facing text alongside tool calls.
|
| 71 |
+
|
| 72 |
+
AFTER:
|
| 73 |
+
Exactly one tool call per response. No user-facing content in tool-call turns.
|
| 74 |
+
Agent processes each result before making the next call.
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
### 3. Present the full prioritized fix list
|
| 78 |
+
|
| 79 |
+
Display all non-discarded fixes in a table:
|
| 80 |
+
|
| 81 |
+
```
|
| 82 |
+
| Priority | Fix Name | Type | Target Metrics | Risk | Effort |
|
| 83 |
+
|----------|-----------------------------------|------------|-----------------|--------|--------|
|
| 84 |
+
| 1 | Turn Discipline | prompt fix | M1, M2 | Low | Low |
|
| 85 |
+
| 2 | Post-Confirmation Execution | prompt fix | M3 | Low | Low |
|
| 86 |
+
| 3 | Cancellation Checklist | prompt fix | M5 | Low | Low |
|
| 87 |
+
| ... | ... | ... | ... | ... | ... |
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
Effort ratings:
|
| 91 |
+
- `Low` -- single prompt addition, under 5 lines
|
| 92 |
+
- `Medium` -- multiple prompt additions or minor code change
|
| 93 |
+
- `High` -- significant code changes, new metric implementation, or architectural changes
|
| 94 |
+
|
| 95 |
+
### 4. Present "What we are NOT fixing and why"
|
| 96 |
+
|
| 97 |
+
List every discarded insight with:
|
| 98 |
+
- Insight ID and name
|
| 99 |
+
- One-line reason for discard
|
| 100 |
+
- What would change your mind (under what conditions should this be revisited)
|
| 101 |
+
|
| 102 |
+
This section exists so the user can override a discard if they disagree.
|
| 103 |
+
|
| 104 |
+
### 5. Flag small-sample and low-confidence items
|
| 105 |
+
|
| 106 |
+
Any metric with denominator < 5 must be explicitly called out:
|
| 107 |
+
|
| 108 |
+
```
|
| 109 |
+
LOW-CONFIDENCE METRICS (small sample size):
|
| 110 |
+
- M5 (Cancellation Policy Compliance): based on 2 observations -- directional only
|
| 111 |
+
- M6 (Compensation Execution Rate): based on 1 observation -- directional only
|
| 112 |
+
|
| 113 |
+
Fixes targeting these metrics (Cancellation Checklist, Compensation Rules) are
|
| 114 |
+
still recommended because the policy violations are clear from trace evidence,
|
| 115 |
+
but the measured improvement may not be statistically meaningful until the
|
| 116 |
+
trace corpus grows.
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
Also flag any fix where the action plan notes uncertainty or partial evidence.
|
| 120 |
+
|
| 121 |
+
### 6. Show the insight-to-fix traceability chain
|
| 122 |
+
|
| 123 |
+
For each fix, present the chain: insight -> metric -> fix -> expected improvement. This can be a compact list or a table. The purpose is to let the user verify that nothing was lost or invented between stages.
|
| 124 |
+
|
| 125 |
+
```
|
| 126 |
+
TRACEABILITY:
|
| 127 |
+
55c00c40 (Tool Call Discipline) -> M1, M2 -> Skill 1 (Turn Discipline) -> M1 up, M2 up
|
| 128 |
+
6ea141e1 (Execution Discipline) -> M3 -> Skill 2 (Post-Confirmation) -> M3 up
|
| 129 |
+
0f4a952b + 6ce88ebb (Cancellation) -> M5 -> Skill 3 (Cancellation Checklist) -> M5 up
|
| 130 |
+
...
|
| 131 |
+
```
|
| 132 |
+
|
| 133 |
+
### 7. Collect the decision
|
| 134 |
+
|
| 135 |
+
Present exactly three options:
|
| 136 |
+
|
| 137 |
+
```
|
| 138 |
+
OPTIONS:
|
| 139 |
+
[A] Approve all -- implement all 9 fixes as described
|
| 140 |
+
[B] Approve with modifications -- review each fix individually
|
| 141 |
+
[C] Reject -- return to Stage 5 with feedback
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
Use the appropriate mechanism to collect the user's choice (direct question or AskUserQuestion if available).
|
| 145 |
+
|
| 146 |
+
#### If the user selects [A] Approve all
|
| 147 |
+
|
| 148 |
+
Record the decision and proceed. No further interaction needed.
|
| 149 |
+
|
| 150 |
+
#### If the user selects [B] Approve with modifications
|
| 151 |
+
|
| 152 |
+
Walk through each fix individually, in priority order. For each fix, present:
|
| 153 |
+
- The fix name, type, and target metrics
|
| 154 |
+
- The recommended prompt/code change (quote the exact text from the action plan)
|
| 155 |
+
- Risk and effort ratings
|
| 156 |
+
|
| 157 |
+
Then ask: "Approve / Skip / Modify?"
|
| 158 |
+
|
| 159 |
+
- **Approve** -- keep as-is
|
| 160 |
+
- **Skip** -- remove from the plan, record reason
|
| 161 |
+
- **Modify** -- ask the user what to change, record the original and the modification
|
| 162 |
+
|
| 163 |
+
After walking through all fixes, present a summary of changes:
|
| 164 |
+
- Fixes approved as-is: N
|
| 165 |
+
- Fixes skipped: M (list with reasons)
|
| 166 |
+
- Fixes modified: K (list with what changed)
|
| 167 |
+
|
| 168 |
+
Ask for final confirmation: "Proceed with this modified plan?"
|
| 169 |
+
|
| 170 |
+
Then update `eval/action_plan.md`:
|
| 171 |
+
- Remove skipped fixes (move to a "Skipped by HITL" section at the bottom with reasons)
|
| 172 |
+
- Update modified fixes with the user's changes, preserving the original recommendation in a "Original recommendation" sub-field
|
| 173 |
+
- Add a header note: "Modified during HITL review on [date]. See eval/stage6_decision.md for details."
|
| 174 |
+
|
| 175 |
+
#### If the user selects [C] Reject
|
| 176 |
+
|
| 177 |
+
Ask the user for specific feedback:
|
| 178 |
+
- What was wrong with the plan?
|
| 179 |
+
- Which insights or metrics should be reconsidered?
|
| 180 |
+
- Any new constraints or priorities?
|
| 181 |
+
|
| 182 |
+
Record the feedback in `eval/stage6_decision.md` and signal that Stage 5 should be re-run with the user's feedback incorporated.
|
| 183 |
+
|
| 184 |
+
## Output format
|
| 185 |
+
|
| 186 |
+
### eval/stage6_decision.md
|
| 187 |
+
|
| 188 |
+
Write this file regardless of which option was selected.
|
| 189 |
+
|
| 190 |
+
```markdown
|
| 191 |
+
# Stage 6: HITL Decision Record
|
| 192 |
+
|
| 193 |
+
## Date
|
| 194 |
+
[timestamp]
|
| 195 |
+
|
| 196 |
+
## Decision
|
| 197 |
+
[Approve all | Approve with modifications | Reject]
|
| 198 |
+
|
| 199 |
+
## What was presented
|
| 200 |
+
- Total insights: N (M distinct after dedup)
|
| 201 |
+
- Actionable fixes: X (Y prompt, Z code)
|
| 202 |
+
- Discarded: W
|
| 203 |
+
- Metrics: [list metric IDs and baselines]
|
| 204 |
+
- Low-confidence flags: [list metrics with small denominators]
|
| 205 |
+
|
| 206 |
+
## Top 3 changes presented
|
| 207 |
+
1. [fix name] -- [type] -- targets [metrics] -- risk [rating]
|
| 208 |
+
2. ...
|
| 209 |
+
3. ...
|
| 210 |
+
|
| 211 |
+
## Decision details
|
| 212 |
+
|
| 213 |
+
### If Approve all:
|
| 214 |
+
User approved all N fixes without modification.
|
| 215 |
+
Reasoning: [any reasoning the user provided, or "No additional reasoning provided"]
|
| 216 |
+
|
| 217 |
+
### If Approve with modifications:
|
| 218 |
+
| Fix | Original Status | Decision | Reason |
|
| 219 |
+
|-----|----------------|----------|--------|
|
| 220 |
+
| Turn Discipline | Priority 1 | Approved | -- |
|
| 221 |
+
| Compensation Rules | Priority 5 | Modified | User changed wording to... |
|
| 222 |
+
| Cabin Change Rules | Priority 8 | Skipped | User considers low priority |
|
| 223 |
+
|
| 224 |
+
Modifications detail:
|
| 225 |
+
- [Fix name]: Original: "..." -> Modified: "..." -- User rationale: "..."
|
| 226 |
+
|
| 227 |
+
### If Reject:
|
| 228 |
+
User feedback: [verbatim feedback]
|
| 229 |
+
Specific concerns: [list]
|
| 230 |
+
Re-run instructions for Stage 5: [what to change]
|
| 231 |
+
|
| 232 |
+
## Traceability snapshot
|
| 233 |
+
[Copy of the traceability chain from step 6, so the decision record is self-contained]
|
| 234 |
+
```
|
| 235 |
+
|
| 236 |
+
### eval/action_plan.md (updated, only if modifications were made)
|
| 237 |
+
|
| 238 |
+
If the user selected [B] and made changes:
|
| 239 |
+
- Add a modification header at the top of the file
|
| 240 |
+
- Update individual fix entries with user changes
|
| 241 |
+
- Move skipped fixes to a "Skipped by HITL" section
|
| 242 |
+
- Preserve original recommendations as sub-fields for auditability
|
| 243 |
+
|
| 244 |
+
## Rules
|
| 245 |
+
|
| 246 |
+
- Do NOT auto-approve. The entire point of this stage is human judgment.
|
| 247 |
+
- Do NOT summarize so aggressively that the user cannot evaluate. When in doubt, include more context.
|
| 248 |
+
- Do NOT proceed to Stage 7 until a clear approval (full or modified) is recorded.
|
| 249 |
+
- Do NOT modify `eval/action_plan.md` unless the user explicitly requests modifications.
|
| 250 |
+
- Do NOT skip the small-sample warnings. If M5 has denominator 2 and M6 has denominator 1, the user must know this.
|
| 251 |
+
- Do NOT fabricate target metric values. Use targets from the action plan when available; otherwise state direction only.
|
| 252 |
+
- Always present the "What we are NOT fixing" section. Omitting discards hides information the user needs.
|
| 253 |
+
- If the user asks clarifying questions, answer them fully before re-presenting the decision options.
|
| 254 |
+
|
| 255 |
+
## Outputs
|
| 256 |
+
|
| 257 |
+
- `eval/stage6_decision.md` -- full record of what was presented, decided, and why
|
| 258 |
+
- `eval/action_plan.md` -- updated only if the user selected "Approve with modifications"
|
.claude/skills/kayba-pipeline/stage-7-fixer/SKILL.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: kayba-stage-7-fixer
|
| 3 |
+
description: Implement the approved fixes from the action plan and log all changes. Trigger when the user says "run stage 7", "implement fixes", "apply action plan", or when invoked by the kayba-pipeline orchestrator. Requires eval/action_plan.md to exist.
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Stage 7: Fix Implementation
|
| 7 |
+
|
| 8 |
+
Implement every non-discarded fix from the approved action plan.
|
| 9 |
+
|
| 10 |
+
## Inputs
|
| 11 |
+
|
| 12 |
+
- `eval/action_plan.md` -- the approved action plan from Stage 5 (possibly modified during HITL in Stage 6)
|
| 13 |
+
- `eval/stage6_decision.md` -- if it exists, the HITL decision record from Stage 6 (contains user modifications)
|
| 14 |
+
- `eval/baseline_metrics.json` -- the pre-fix baseline metrics from Stage 3 (for reference in changes log)
|
| 15 |
+
|
| 16 |
+
Read the action plan and stage6 decision (if present) before starting.
|
| 17 |
+
|
| 18 |
+
## Pre-flight: Git Safety Checkpoint
|
| 19 |
+
|
| 20 |
+
Before making ANY changes to source files:
|
| 21 |
+
|
| 22 |
+
1. Run `git status` to confirm the working tree state
|
| 23 |
+
2. Create a safety commit or stash:
|
| 24 |
+
```
|
| 25 |
+
git stash push -m "pre-pipeline-fixes-$(date +%Y%m%d-%H%M%S)"
|
| 26 |
+
```
|
| 27 |
+
If there are no uncommitted changes to stash, create a lightweight tag instead:
|
| 28 |
+
```
|
| 29 |
+
git tag pre-pipeline-fixes-$(date +%Y%m%d-%H%M%S)
|
| 30 |
+
```
|
| 31 |
+
3. Record the stash ref or tag name in `eval/changes_log.md` under a "Rollback" section so the user can restore if needed
|
| 32 |
+
|
| 33 |
+
This ensures every fix is reversible with a single `git stash pop` or `git checkout`.
|
| 34 |
+
|
| 35 |
+
## Pre-flight: HITL Modification Check
|
| 36 |
+
|
| 37 |
+
If `eval/stage6_decision.md` exists:
|
| 38 |
+
|
| 39 |
+
1. Read it and identify any items the user modified, added, or re-prioritized during Stage 6
|
| 40 |
+
2. Build a set of `HITL_MODIFIED_IDS` -- the insight/skill IDs that the user changed
|
| 41 |
+
3. When logging each fix later, tag modified items with `[HITL-MODIFIED]` in the changes log so reviewers know which fixes reflect user judgment vs. the original pipeline output
|
| 42 |
+
|
| 43 |
+
If the file does not exist, assume no HITL modifications were made.
|
| 44 |
+
|
| 45 |
+
## Pre-flight: Conflict Scan
|
| 46 |
+
|
| 47 |
+
Before implementing any fixes, scan the action plan for potential conflicts:
|
| 48 |
+
|
| 49 |
+
1. Build a map of `file_path -> [fix IDs that touch it]`
|
| 50 |
+
2. If two or more fixes modify the same file, flag them as **co-located**
|
| 51 |
+
3. If two or more fixes modify the same section (within ~20 lines of each other), flag them as **overlapping**
|
| 52 |
+
4. For overlapping fixes: plan to apply them sequentially in priority order, re-reading the file between each edit to ensure the second fix still makes sense on top of the first
|
| 53 |
+
5. Log any detected conflicts at the top of `eval/changes_log.md` under a "Conflict Notes" section
|
| 54 |
+
|
| 55 |
+
## Process
|
| 56 |
+
|
| 57 |
+
Work through the action plan in priority order. For each non-discarded fix:
|
| 58 |
+
|
| 59 |
+
### 1. Understand the fix
|
| 60 |
+
|
| 61 |
+
- Read the recommendation carefully
|
| 62 |
+
- Read the referenced files in the codebase
|
| 63 |
+
- Understand the surrounding code before making changes
|
| 64 |
+
- Check if this fix was flagged as co-located or overlapping in the conflict scan. If overlapping with a previously-applied fix, re-read the target file to see the current state after prior edits
|
| 65 |
+
|
| 66 |
+
### 2. Implement the change
|
| 67 |
+
|
| 68 |
+
**For code fixes:**
|
| 69 |
+
- Find the relevant files
|
| 70 |
+
- Make the minimal, targeted change described in the recommendation
|
| 71 |
+
- Do not refactor surrounding code unless the fix obviously breaks without light adjacent cleanup (e.g., an import is missing, a variable was renamed). If you make adjacent cleanup, log it explicitly as "adjacent cleanup" in the change entry
|
| 72 |
+
- Do not add features beyond what was recommended
|
| 73 |
+
|
| 74 |
+
**For prompt fixes:**
|
| 75 |
+
- Find the system prompt file (use domain context from Stage 2 if needed)
|
| 76 |
+
- Add the recommended instruction at the appropriate location
|
| 77 |
+
- Do not rewrite existing prompt text unless the recommendation explicitly says to
|
| 78 |
+
|
| 79 |
+
### 3. Log the change
|
| 80 |
+
|
| 81 |
+
Append to `eval/changes_log.md`:
|
| 82 |
+
|
| 83 |
+
```markdown
|
| 84 |
+
## Fix N: [skill/insight name] [HITL-MODIFIED if applicable]
|
| 85 |
+
**Type:** code fix | prompt fix
|
| 86 |
+
**Verdict from action plan:** [quote the recommendation]
|
| 87 |
+
**Files modified:**
|
| 88 |
+
- `path/to/file.py` -- [what changed and why]
|
| 89 |
+
**Before:**
|
| 90 |
+
\```
|
| 91 |
+
[relevant snippet before change]
|
| 92 |
+
\```
|
| 93 |
+
**After:**
|
| 94 |
+
\```
|
| 95 |
+
[relevant snippet after change]
|
| 96 |
+
\```
|
| 97 |
+
**Linked metrics:** [which metrics this should improve]
|
| 98 |
+
**Conflict notes:** [if this fix overlapped with another, note it here; otherwise "none"]
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
### 4. Handle uncertainty (NEEDS REVIEW workflow)
|
| 102 |
+
|
| 103 |
+
If a fix requires changes you are unsure about:
|
| 104 |
+
|
| 105 |
+
1. Do NOT implement it
|
| 106 |
+
2. Log it as `NEEDS REVIEW` in the changes log with:
|
| 107 |
+
- What specifically is unclear
|
| 108 |
+
- What information would resolve the ambiguity
|
| 109 |
+
- The files and lines you examined
|
| 110 |
+
3. **Continue to the next fix** -- do not block the pipeline
|
| 111 |
+
4. At the end of all fixes, collect all NEEDS REVIEW items into a dedicated section (see Output format below). The pipeline does NOT stop; these items are presented to the user after all other fixes are applied.
|
| 112 |
+
|
| 113 |
+
## Post-Fix: Next Steps (Do NOT Re-run Baselines)
|
| 114 |
+
|
| 115 |
+
Do NOT re-run `compute_baselines.py` as part of this stage. The baseline metrics were computed against the original traces, which reflect old agent behavior. Re-running against the same traces will show zero movement for prompt-only fixes and is misleading.
|
| 116 |
+
|
| 117 |
+
Instead, after all fixes are applied, include a **Next Steps** section in the changes log that tells the user:
|
| 118 |
+
|
| 119 |
+
1. Generate new traces by running the agent with the updated prompts/code
|
| 120 |
+
2. Then re-run baselines against the new traces:
|
| 121 |
+
```bash
|
| 122 |
+
python eval/compute_baselines.py --traces-dir <new_traces_folder> --output eval/post_fix_metrics.json
|
| 123 |
+
```
|
| 124 |
+
3. Compare `eval/post_fix_metrics.json` against `eval/baseline_metrics.json` to measure actual improvement
|
| 125 |
+
|
| 126 |
+
## Rules
|
| 127 |
+
|
| 128 |
+
- Do NOT modify trace files
|
| 129 |
+
- Do NOT make changes beyond what the action plan recommends (except adjacent cleanup logged explicitly)
|
| 130 |
+
- Make minimal, targeted changes -- don't clean up or refactor surrounding code
|
| 131 |
+
- If the action plan says "discard", skip that entry entirely
|
| 132 |
+
- You MAY write `eval/changes_log.md` as the primary output
|
| 133 |
+
- Do NOT run `eval/compute_baselines.py` -- baselines should only be re-computed after new traces are generated with the updated agent
|
| 134 |
+
|
| 135 |
+
## Output format
|
| 136 |
+
|
| 137 |
+
Write `eval/changes_log.md`:
|
| 138 |
+
|
| 139 |
+
```markdown
|
| 140 |
+
# Changes Log
|
| 141 |
+
|
| 142 |
+
## Rollback
|
| 143 |
+
- **Safety ref:** `git stash` ref or tag name
|
| 144 |
+
- **To undo all fixes:** `git stash pop` or `git checkout <tag>`
|
| 145 |
+
|
| 146 |
+
## Conflict Notes
|
| 147 |
+
- [any file/region conflicts detected, or "No conflicts detected"]
|
| 148 |
+
|
| 149 |
+
## Summary
|
| 150 |
+
- Code fixes applied: N
|
| 151 |
+
- Prompt fixes applied: M
|
| 152 |
+
- Skipped / needs review: K
|
| 153 |
+
- HITL-modified items: J
|
| 154 |
+
|
| 155 |
+
---
|
| 156 |
+
|
| 157 |
+
## Fix 1: [skill name]
|
| 158 |
+
...
|
| 159 |
+
|
| 160 |
+
## Fix 2: [skill name]
|
| 161 |
+
...
|
| 162 |
+
|
| 163 |
+
---
|
| 164 |
+
|
| 165 |
+
## Needs Review
|
| 166 |
+
[Collected list of all NEEDS REVIEW items with context, or "None -- all fixes applied successfully"]
|
| 167 |
+
|
| 168 |
+
For each NEEDS REVIEW item:
|
| 169 |
+
- **Fix N: [skill name]**
|
| 170 |
+
- **What is unclear:** [specific ambiguity]
|
| 171 |
+
- **What would resolve it:** [information needed]
|
| 172 |
+
- **Files examined:** [paths and lines]
|
| 173 |
+
|
| 174 |
+
---
|
| 175 |
+
|
| 176 |
+
## Next Steps
|
| 177 |
+
|
| 178 |
+
To measure actual improvement:
|
| 179 |
+
1. Generate new traces by running the agent with the updated prompts/code
|
| 180 |
+
2. Re-run baselines:
|
| 181 |
+
\```bash
|
| 182 |
+
python eval/compute_baselines.py --traces-dir <new_traces_folder> --output eval/post_fix_metrics.json
|
| 183 |
+
\```
|
| 184 |
+
3. Compare `eval/post_fix_metrics.json` against `eval/baseline_metrics.json` to measure metric deltas
|
| 185 |
+
```
|
| 186 |
+
|
| 187 |
+
## Outputs
|
| 188 |
+
|
| 189 |
+
- `eval/changes_log.md` -- full log of all changes, conflicts, NEEDS REVIEW items, and next steps
|
| 190 |
+
- The actual code/prompt changes in the repository
|
| 191 |
+
- A git stash or tag for rollback
|
.env.example
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# API Keys for LLM Providers
|
| 2 |
+
# Copy this file to .env and add your actual API keys
|
| 3 |
+
|
| 4 |
+
# OpenAI
|
| 5 |
+
OPENAI_API_KEY=your-openai-api-key-here
|
| 6 |
+
|
| 7 |
+
# Anthropic (Claude)
|
| 8 |
+
ANTHROPIC_API_KEY=your-anthropic-api-key-here
|
| 9 |
+
|
| 10 |
+
# Google (Gemini)
|
| 11 |
+
GOOGLE_API_KEY=your-google-api-key-here
|
| 12 |
+
|
| 13 |
+
# DeepSeek
|
| 14 |
+
DEEPSEEK_API_KEY=your-deepseek-api-key-here
|
| 15 |
+
|
| 16 |
+
# Ollama Cloud
|
| 17 |
+
OLLAMA_API_KEY=your_api_key
|
| 18 |
+
|
| 19 |
+
# Cohere
|
| 20 |
+
COHERE_API_KEY=your-cohere-api-key-here
|
| 21 |
+
|
| 22 |
+
# Bedrock bearer token (passed as api_key to LiteLLM, not as AWS_ACCESS_KEY_ID)
|
| 23 |
+
BEDROCK_API_KEY=your-bedrock-api-key-here
|
| 24 |
+
|
| 25 |
+
# Azure OpenAI (optional)
|
| 26 |
+
AZURE_API_KEY=your-azure-api-key-here
|
| 27 |
+
AZURE_API_BASE=https://your-resource.openai.azure.com
|
| 28 |
+
AZURE_API_VERSION=2024-02-15-preview
|
| 29 |
+
|
| 30 |
+
# AWS Bedrock (optional)
|
| 31 |
+
AWS_ACCESS_KEY_ID=your-aws-access-key
|
| 32 |
+
AWS_SECRET_ACCESS_KEY=your-aws-secret-key
|
| 33 |
+
AWS_REGION_NAME=us-east-1
|
| 34 |
+
|
| 35 |
+
# Hugging Face (optional)
|
| 36 |
+
HUGGINGFACE_API_KEY=your-huggingface-api-key-here
|
| 37 |
+
|
| 38 |
+
# Replicate (optional)
|
| 39 |
+
REPLICATE_API_KEY=your-replicate-api-key-here
|
| 40 |
+
|
| 41 |
+
# Together AI (optional)
|
| 42 |
+
TOGETHER_API_KEY=your-together-api-key-here
|
| 43 |
+
|
| 44 |
+
# Model Configuration (optional)
|
| 45 |
+
DEFAULT_MODEL=gpt-4o-mini
|
| 46 |
+
DEFAULT_TEMPERATURE=0.0
|
| 47 |
+
DEFAULT_MAX_TOKENS=512
|
| 48 |
+
|
| 49 |
+
# Cost Tracking (optional)
|
| 50 |
+
TRACK_COSTS=true
|
| 51 |
+
MAX_BUDGET=10.0
|
| 52 |
+
|
| 53 |
+
# Opik Observability (optional)
|
| 54 |
+
# Disable Opik tracing when not running a local Opik server
|
| 55 |
+
# Either variable works:
|
| 56 |
+
# OPIK_ENABLED=false
|
| 57 |
+
# OPIK_DISABLED=true
|
| 58 |
+
|
| 59 |
+
# Benchmark Configuration
|
| 60 |
+
# Cache directories for benchmark data (optional - defaults to ~/.cache/huggingface)
|
| 61 |
+
BENCHMARK_CACHE_DIR=/path/to/benchmark/cache
|
| 62 |
+
HF_DATASETS_CACHE=/path/to/huggingface/cache
|
| 63 |
+
HF_HUB_CACHE=/path/to/huggingface/hub/cache
|
| 64 |
+
|
| 65 |
+
# AppWorld configuration (required for AppWorld benchmark)
|
| 66 |
+
APPWORLD_ROOT=/path/to/appworld/data
|
| 67 |
+
|
| 68 |
+
# Results output directory (optional)
|
| 69 |
+
BENCHMARK_RESULTS_DIR=./benchmark_results
|
.gitattributes
CHANGED
|
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
assets/kayba-banner.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
benchmarks/tasks/tau_bench/Tau2Benchmark[[:space:]]Result[[:space:]]Haiku4.5.png filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
examples/seahorse-emoji-ace.gif filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
mlflow.db filter=lfs diff=lfs merge=lfs -text
|
.github/workflows/docs.yml
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Docs
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches:
|
| 6 |
+
- main
|
| 7 |
+
tags:
|
| 8 |
+
- "v*"
|
| 9 |
+
workflow_dispatch:
|
| 10 |
+
inputs:
|
| 11 |
+
version:
|
| 12 |
+
description: "Version to deploy (e.g. 0.8)"
|
| 13 |
+
required: true
|
| 14 |
+
default: "dev"
|
| 15 |
+
|
| 16 |
+
permissions:
|
| 17 |
+
contents: write
|
| 18 |
+
|
| 19 |
+
jobs:
|
| 20 |
+
deploy:
|
| 21 |
+
runs-on: ubuntu-latest
|
| 22 |
+
steps:
|
| 23 |
+
- uses: actions/checkout@v4
|
| 24 |
+
with:
|
| 25 |
+
fetch-depth: 0 # Required for mike versioning
|
| 26 |
+
|
| 27 |
+
- name: Set up Python
|
| 28 |
+
uses: actions/setup-python@v5
|
| 29 |
+
with:
|
| 30 |
+
python-version: "3.12"
|
| 31 |
+
|
| 32 |
+
- name: Install docs dependencies
|
| 33 |
+
run: pip install mkdocs-material mike
|
| 34 |
+
|
| 35 |
+
- name: Configure git
|
| 36 |
+
run: |
|
| 37 |
+
git config user.name "github-actions[bot]"
|
| 38 |
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
| 39 |
+
|
| 40 |
+
- name: Deploy versioned docs (on tag)
|
| 41 |
+
if: startsWith(github.ref, 'refs/tags/v')
|
| 42 |
+
run: |
|
| 43 |
+
VERSION=${GITHUB_REF#refs/tags/v}
|
| 44 |
+
mike deploy --push --update-aliases $VERSION latest
|
| 45 |
+
mike set-default --push latest
|
| 46 |
+
|
| 47 |
+
- name: Deploy dev docs (on main push)
|
| 48 |
+
if: github.ref == 'refs/heads/main'
|
| 49 |
+
run: mike deploy --push dev
|
| 50 |
+
|
| 51 |
+
- name: Deploy manually triggered version
|
| 52 |
+
if: github.event_name == 'workflow_dispatch'
|
| 53 |
+
run: |
|
| 54 |
+
mike deploy --push --update-aliases ${{ github.event.inputs.version }} latest
|
| 55 |
+
mike set-default --push latest
|
.github/workflows/publish.yml
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Publish Packages
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
release:
|
| 5 |
+
types: [published]
|
| 6 |
+
workflow_dispatch:
|
| 7 |
+
inputs:
|
| 8 |
+
test_pypi:
|
| 9 |
+
description: 'Publish to TestPyPI instead of PyPI'
|
| 10 |
+
required: false
|
| 11 |
+
default: 'false'
|
| 12 |
+
type: choice
|
| 13 |
+
options:
|
| 14 |
+
- 'true'
|
| 15 |
+
- 'false'
|
| 16 |
+
|
| 17 |
+
jobs:
|
| 18 |
+
# ── ace-framework (Python) ──────────────────────────────────────────
|
| 19 |
+
|
| 20 |
+
build-ace:
|
| 21 |
+
name: Build ace-framework
|
| 22 |
+
runs-on: ubuntu-latest
|
| 23 |
+
steps:
|
| 24 |
+
- uses: actions/checkout@v4
|
| 25 |
+
|
| 26 |
+
- name: Set up Python
|
| 27 |
+
uses: actions/setup-python@v4
|
| 28 |
+
with:
|
| 29 |
+
python-version: '3.12'
|
| 30 |
+
|
| 31 |
+
- name: Install build dependencies
|
| 32 |
+
run: |
|
| 33 |
+
python -m pip install --upgrade pip
|
| 34 |
+
pip install build
|
| 35 |
+
|
| 36 |
+
- name: Build package
|
| 37 |
+
run: python -m build
|
| 38 |
+
|
| 39 |
+
- name: Store the distribution packages
|
| 40 |
+
uses: actions/upload-artifact@v4
|
| 41 |
+
with:
|
| 42 |
+
name: ace-framework-dist
|
| 43 |
+
path: dist/
|
| 44 |
+
|
| 45 |
+
# ── kayba-tracing (Python) ─────────────────────────────────────────
|
| 46 |
+
|
| 47 |
+
build-kayba-tracing:
|
| 48 |
+
name: Build kayba-tracing
|
| 49 |
+
runs-on: ubuntu-latest
|
| 50 |
+
steps:
|
| 51 |
+
- uses: actions/checkout@v4
|
| 52 |
+
|
| 53 |
+
- name: Set up Python
|
| 54 |
+
uses: actions/setup-python@v4
|
| 55 |
+
with:
|
| 56 |
+
python-version: '3.12'
|
| 57 |
+
|
| 58 |
+
- name: Install build dependencies
|
| 59 |
+
run: |
|
| 60 |
+
python -m pip install --upgrade pip
|
| 61 |
+
pip install build
|
| 62 |
+
|
| 63 |
+
- name: Build package
|
| 64 |
+
run: python -m build sdk/python
|
| 65 |
+
|
| 66 |
+
- name: Store the distribution packages
|
| 67 |
+
uses: actions/upload-artifact@v4
|
| 68 |
+
with:
|
| 69 |
+
name: kayba-tracing-dist
|
| 70 |
+
path: sdk/python/dist/
|
| 71 |
+
|
| 72 |
+
# ── @kayba_ai/tracing (TypeScript) ────────────────────────────────────
|
| 73 |
+
|
| 74 |
+
build-kayba-tracing-ts:
|
| 75 |
+
name: Build @kayba_ai/tracing
|
| 76 |
+
runs-on: ubuntu-latest
|
| 77 |
+
steps:
|
| 78 |
+
- uses: actions/checkout@v4
|
| 79 |
+
|
| 80 |
+
- name: Set up Node.js
|
| 81 |
+
uses: actions/setup-node@v4
|
| 82 |
+
with:
|
| 83 |
+
node-version: '20'
|
| 84 |
+
registry-url: 'https://registry.npmjs.org'
|
| 85 |
+
|
| 86 |
+
- name: Install dependencies
|
| 87 |
+
run: npm ci
|
| 88 |
+
working-directory: sdk/typescript
|
| 89 |
+
|
| 90 |
+
- name: Build
|
| 91 |
+
run: npm run build
|
| 92 |
+
working-directory: sdk/typescript
|
| 93 |
+
|
| 94 |
+
- name: Store the distribution packages
|
| 95 |
+
uses: actions/upload-artifact@v4
|
| 96 |
+
with:
|
| 97 |
+
name: kayba-tracing-ts-dist
|
| 98 |
+
path: |
|
| 99 |
+
sdk/typescript/dist/
|
| 100 |
+
sdk/typescript/package.json
|
| 101 |
+
|
| 102 |
+
# ── @kayba_ai/openclaw-tracing (TypeScript) ───────────────────────────
|
| 103 |
+
|
| 104 |
+
build-openclaw-tracing:
|
| 105 |
+
name: Build @kayba_ai/openclaw-tracing
|
| 106 |
+
runs-on: ubuntu-latest
|
| 107 |
+
steps:
|
| 108 |
+
- uses: actions/checkout@v4
|
| 109 |
+
|
| 110 |
+
- name: Set up Node.js
|
| 111 |
+
uses: actions/setup-node@v4
|
| 112 |
+
with:
|
| 113 |
+
node-version: '22'
|
| 114 |
+
registry-url: 'https://registry.npmjs.org'
|
| 115 |
+
|
| 116 |
+
- name: Install dependencies
|
| 117 |
+
run: npm ci
|
| 118 |
+
working-directory: sdk/openclaw
|
| 119 |
+
|
| 120 |
+
- name: Build
|
| 121 |
+
run: npm run build
|
| 122 |
+
working-directory: sdk/openclaw
|
| 123 |
+
|
| 124 |
+
- name: Store the distribution packages
|
| 125 |
+
uses: actions/upload-artifact@v4
|
| 126 |
+
with:
|
| 127 |
+
name: openclaw-tracing-dist
|
| 128 |
+
path: |
|
| 129 |
+
sdk/openclaw/dist/
|
| 130 |
+
sdk/openclaw/package.json
|
| 131 |
+
sdk/openclaw/openclaw.plugin.json
|
| 132 |
+
sdk/openclaw/README.md
|
| 133 |
+
|
| 134 |
+
# ── Publish to TestPyPI ────────────────────────────────────────────
|
| 135 |
+
|
| 136 |
+
publish-to-testpypi:
|
| 137 |
+
name: Publish ace-framework to TestPyPI
|
| 138 |
+
if: github.event.inputs.test_pypi == 'true' || github.event_name == 'workflow_dispatch'
|
| 139 |
+
needs: [build-ace]
|
| 140 |
+
runs-on: ubuntu-latest
|
| 141 |
+
environment:
|
| 142 |
+
name: testpypi
|
| 143 |
+
url: https://test.pypi.org/project/ace-framework/
|
| 144 |
+
permissions:
|
| 145 |
+
id-token: write
|
| 146 |
+
steps:
|
| 147 |
+
- name: Download all the dists
|
| 148 |
+
uses: actions/download-artifact@v4
|
| 149 |
+
with:
|
| 150 |
+
name: ace-framework-dist
|
| 151 |
+
path: dist/
|
| 152 |
+
|
| 153 |
+
- name: Publish to TestPyPI
|
| 154 |
+
uses: pypa/gh-action-pypi-publish@release/v1
|
| 155 |
+
with:
|
| 156 |
+
repository-url: https://test.pypi.org/legacy/
|
| 157 |
+
skip-existing: true
|
| 158 |
+
|
| 159 |
+
publish-kayba-tracing-to-testpypi:
|
| 160 |
+
name: Publish kayba-tracing to TestPyPI
|
| 161 |
+
if: github.event.inputs.test_pypi == 'true' || github.event_name == 'workflow_dispatch'
|
| 162 |
+
needs: [build-kayba-tracing]
|
| 163 |
+
runs-on: ubuntu-latest
|
| 164 |
+
environment:
|
| 165 |
+
name: testpypi
|
| 166 |
+
url: https://test.pypi.org/project/kayba-tracing/
|
| 167 |
+
permissions:
|
| 168 |
+
id-token: write
|
| 169 |
+
steps:
|
| 170 |
+
- name: Download all the dists
|
| 171 |
+
uses: actions/download-artifact@v4
|
| 172 |
+
with:
|
| 173 |
+
name: kayba-tracing-dist
|
| 174 |
+
path: dist/
|
| 175 |
+
|
| 176 |
+
- name: Publish to TestPyPI
|
| 177 |
+
uses: pypa/gh-action-pypi-publish@release/v1
|
| 178 |
+
with:
|
| 179 |
+
repository-url: https://test.pypi.org/legacy/
|
| 180 |
+
skip-existing: true
|
| 181 |
+
|
| 182 |
+
# ── Publish to PyPI ────────────────────────────────────────────────
|
| 183 |
+
|
| 184 |
+
publish-to-pypi:
|
| 185 |
+
name: Publish ace-framework to PyPI
|
| 186 |
+
if: github.event_name == 'release'
|
| 187 |
+
needs: [build-ace]
|
| 188 |
+
runs-on: ubuntu-latest
|
| 189 |
+
environment:
|
| 190 |
+
name: pypi
|
| 191 |
+
url: https://pypi.org/project/ace-framework/
|
| 192 |
+
permissions:
|
| 193 |
+
id-token: write
|
| 194 |
+
steps:
|
| 195 |
+
- name: Download all the dists
|
| 196 |
+
uses: actions/download-artifact@v4
|
| 197 |
+
with:
|
| 198 |
+
name: ace-framework-dist
|
| 199 |
+
path: dist/
|
| 200 |
+
|
| 201 |
+
- name: Publish to PyPI
|
| 202 |
+
uses: pypa/gh-action-pypi-publish@release/v1
|
| 203 |
+
|
| 204 |
+
publish-kayba-tracing-to-pypi:
|
| 205 |
+
name: Publish kayba-tracing to PyPI
|
| 206 |
+
if: github.event_name == 'release'
|
| 207 |
+
needs: [build-kayba-tracing]
|
| 208 |
+
runs-on: ubuntu-latest
|
| 209 |
+
environment:
|
| 210 |
+
name: pypi
|
| 211 |
+
url: https://pypi.org/project/kayba-tracing/
|
| 212 |
+
permissions:
|
| 213 |
+
id-token: write
|
| 214 |
+
steps:
|
| 215 |
+
- name: Download all the dists
|
| 216 |
+
uses: actions/download-artifact@v4
|
| 217 |
+
with:
|
| 218 |
+
name: kayba-tracing-dist
|
| 219 |
+
path: dist/
|
| 220 |
+
|
| 221 |
+
- name: Publish to PyPI
|
| 222 |
+
uses: pypa/gh-action-pypi-publish@release/v1
|
| 223 |
+
|
| 224 |
+
# ── Publish to npm ─────────────────────────────────────────────────
|
| 225 |
+
|
| 226 |
+
publish-to-npm:
|
| 227 |
+
name: Publish @kayba_ai/tracing to npm
|
| 228 |
+
if: github.event_name == 'release'
|
| 229 |
+
needs: [build-kayba-tracing-ts]
|
| 230 |
+
runs-on: ubuntu-latest
|
| 231 |
+
environment:
|
| 232 |
+
name: npm
|
| 233 |
+
url: https://www.npmjs.com/package/@kayba_ai/tracing
|
| 234 |
+
permissions:
|
| 235 |
+
contents: read
|
| 236 |
+
steps:
|
| 237 |
+
- uses: actions/checkout@v4
|
| 238 |
+
|
| 239 |
+
- name: Set up Node.js
|
| 240 |
+
uses: actions/setup-node@v4
|
| 241 |
+
with:
|
| 242 |
+
node-version: '22'
|
| 243 |
+
registry-url: 'https://registry.npmjs.org'
|
| 244 |
+
|
| 245 |
+
- name: Install dependencies
|
| 246 |
+
run: npm ci
|
| 247 |
+
working-directory: sdk/typescript
|
| 248 |
+
|
| 249 |
+
- name: Build
|
| 250 |
+
run: npm run build
|
| 251 |
+
working-directory: sdk/typescript
|
| 252 |
+
|
| 253 |
+
- name: Publish to npm
|
| 254 |
+
run: npm publish --access public
|
| 255 |
+
working-directory: sdk/typescript
|
| 256 |
+
env:
|
| 257 |
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
| 258 |
+
|
| 259 |
+
publish-openclaw-tracing-to-npm:
|
| 260 |
+
name: Publish @kayba_ai/openclaw-tracing to npm
|
| 261 |
+
if: github.event_name == 'release'
|
| 262 |
+
needs: [build-openclaw-tracing]
|
| 263 |
+
runs-on: ubuntu-latest
|
| 264 |
+
environment:
|
| 265 |
+
name: npm
|
| 266 |
+
url: https://www.npmjs.com/package/@kayba_ai/openclaw-tracing
|
| 267 |
+
permissions:
|
| 268 |
+
contents: read
|
| 269 |
+
steps:
|
| 270 |
+
- uses: actions/checkout@v4
|
| 271 |
+
|
| 272 |
+
- name: Set up Node.js
|
| 273 |
+
uses: actions/setup-node@v4
|
| 274 |
+
with:
|
| 275 |
+
node-version: '22'
|
| 276 |
+
registry-url: 'https://registry.npmjs.org'
|
| 277 |
+
|
| 278 |
+
- name: Install dependencies
|
| 279 |
+
run: npm ci
|
| 280 |
+
working-directory: sdk/openclaw
|
| 281 |
+
|
| 282 |
+
- name: Build
|
| 283 |
+
run: npm run build
|
| 284 |
+
working-directory: sdk/openclaw
|
| 285 |
+
|
| 286 |
+
- name: Publish to npm
|
| 287 |
+
run: npm publish --access public
|
| 288 |
+
working-directory: sdk/openclaw
|
| 289 |
+
env:
|
| 290 |
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
.github/workflows/test.yml
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Tests
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches: [ main, develop, lanzelot-dev ]
|
| 6 |
+
pull_request:
|
| 7 |
+
branches: [ main ]
|
| 8 |
+
workflow_dispatch: # Allow manual triggering
|
| 9 |
+
|
| 10 |
+
jobs:
|
| 11 |
+
test:
|
| 12 |
+
runs-on: ${{ matrix.os }}
|
| 13 |
+
strategy:
|
| 14 |
+
matrix:
|
| 15 |
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
| 16 |
+
python-version: ['3.12'] # Matches pyproject.toml requires-python == 3.12.*
|
| 17 |
+
|
| 18 |
+
steps:
|
| 19 |
+
- uses: actions/checkout@v4
|
| 20 |
+
|
| 21 |
+
- name: Set up Python ${{ matrix.python-version }}
|
| 22 |
+
uses: actions/setup-python@v4
|
| 23 |
+
with:
|
| 24 |
+
python-version: ${{ matrix.python-version }}
|
| 25 |
+
|
| 26 |
+
- name: Install uv
|
| 27 |
+
uses: astral-sh/setup-uv@v7
|
| 28 |
+
|
| 29 |
+
- name: Install dependencies
|
| 30 |
+
run: uv sync --extra mcp --extra tracing
|
| 31 |
+
|
| 32 |
+
- name: Run tests with coverage
|
| 33 |
+
run: |
|
| 34 |
+
uv run pytest -m "not requires_api"
|
| 35 |
+
|
| 36 |
+
- name: Upload coverage reports (Linux only)
|
| 37 |
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
|
| 38 |
+
uses: actions/upload-artifact@v4
|
| 39 |
+
with:
|
| 40 |
+
name: coverage-report
|
| 41 |
+
path: htmlcov/
|
| 42 |
+
retention-days: 30
|
| 43 |
+
|
| 44 |
+
- name: Type checking (Linux only)
|
| 45 |
+
if: matrix.os == 'ubuntu-latest'
|
| 46 |
+
run: |
|
| 47 |
+
uv run mypy ace/ --ignore-missing-imports
|
.gitignore
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Byte-compiled / optimized / DLL files
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
|
| 6 |
+
# C extensions
|
| 7 |
+
*.so
|
| 8 |
+
|
| 9 |
+
# Distribution / packaging
|
| 10 |
+
.Python
|
| 11 |
+
build/
|
| 12 |
+
develop-eggs/
|
| 13 |
+
dist/
|
| 14 |
+
downloads/
|
| 15 |
+
eggs/
|
| 16 |
+
.eggs/
|
| 17 |
+
lib/
|
| 18 |
+
lib64/
|
| 19 |
+
parts/
|
| 20 |
+
sdist/
|
| 21 |
+
var/
|
| 22 |
+
wheels/
|
| 23 |
+
*.egg-info/
|
| 24 |
+
.installed.cfg
|
| 25 |
+
*.egg
|
| 26 |
+
|
| 27 |
+
# PyInstaller
|
| 28 |
+
*.manifest
|
| 29 |
+
*.spec
|
| 30 |
+
|
| 31 |
+
# Installer logs
|
| 32 |
+
pip-log.txt
|
| 33 |
+
pip-delete-this-directory.txt
|
| 34 |
+
|
| 35 |
+
# Unit test / coverage reports
|
| 36 |
+
htmlcov/
|
| 37 |
+
.tox/
|
| 38 |
+
.coverage
|
| 39 |
+
.coverage.*
|
| 40 |
+
.cache
|
| 41 |
+
nosetests.xml
|
| 42 |
+
coverage.xml
|
| 43 |
+
*.cover
|
| 44 |
+
.hypothesis/
|
| 45 |
+
.pytest_cache/
|
| 46 |
+
|
| 47 |
+
# Jupyter Notebook
|
| 48 |
+
.ipynb_checkpoints
|
| 49 |
+
|
| 50 |
+
# pyenv
|
| 51 |
+
.python-version
|
| 52 |
+
|
| 53 |
+
# Environments
|
| 54 |
+
.env
|
| 55 |
+
.venv
|
| 56 |
+
env/
|
| 57 |
+
venv/
|
| 58 |
+
ENV/
|
| 59 |
+
env.bak/
|
| 60 |
+
venv.bak/
|
| 61 |
+
|
| 62 |
+
# IDE
|
| 63 |
+
.idea/
|
| 64 |
+
.vscode/
|
| 65 |
+
*.swp
|
| 66 |
+
*.swo
|
| 67 |
+
*~
|
| 68 |
+
.DS_Store
|
| 69 |
+
|
| 70 |
+
# Project specific
|
| 71 |
+
*.pdf
|
| 72 |
+
*.png
|
| 73 |
+
!benchmarks/tasks/tau_bench/*.png
|
| 74 |
+
!examples/browser-use/**/*.png
|
| 75 |
+
!assets/*.png
|
| 76 |
+
ACE_IMPROVEMENTS.md
|
| 77 |
+
ACE_ROADMAP.md
|
| 78 |
+
DEMO_TODO.md
|
| 79 |
+
*.egg-info/
|
| 80 |
+
reports/
|
| 81 |
+
docs/method_outline.md
|
| 82 |
+
logs/
|
| 83 |
+
|
| 84 |
+
# Generated skillbook and result files
|
| 85 |
+
*_skillbook.json
|
| 86 |
+
ace_domain_skillbook.json
|
| 87 |
+
kayba_learned.json
|
| 88 |
+
kayba_test_skillbook.json
|
| 89 |
+
my_agent.json
|
| 90 |
+
my_trained_agent.json
|
| 91 |
+
*.log
|
| 92 |
+
|
| 93 |
+
# Checkpoint files (generated during training)
|
| 94 |
+
**/checkpoints/*.json
|
| 95 |
+
*_checkpoint_*.json
|
| 96 |
+
*_latest.json
|
| 97 |
+
evaluation_results/*.json
|
| 98 |
+
|
| 99 |
+
# Benchmark data and cache
|
| 100 |
+
benchmark_results/
|
| 101 |
+
benchmark_cache/
|
| 102 |
+
tau_benchmark_results/
|
| 103 |
+
results/
|
| 104 |
+
appworld_data/
|
| 105 |
+
*.arrow
|
| 106 |
+
*.parquet
|
| 107 |
+
huggingface_cache/
|
| 108 |
+
|
| 109 |
+
# MkDocs build output
|
| 110 |
+
site/
|
| 111 |
+
|
| 112 |
+
# Sensitive/private data (NEVER commit!)
|
| 113 |
+
.private/
|
| 114 |
+
|
| 115 |
+
# GSD planning artifacts (NEVER commit!)
|
| 116 |
+
.planning/
|
| 117 |
+
|
| 118 |
+
# Node build artifacts
|
| 119 |
+
node_modules/
|
| 120 |
+
|
| 121 |
+
# Local scratch / experiment outputs
|
| 122 |
+
tmp/
|
| 123 |
+
|
| 124 |
+
spyfly-traces
|
.gitmodules
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[submodule "ace-eval"]
|
| 2 |
+
path = ace-eval
|
| 3 |
+
url = git@github.com:kayba-ai/ace-eval.git
|
.pre-commit-config.yaml
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
repos:
|
| 2 |
+
# Black - code formatting (auto-fixes)
|
| 3 |
+
- repo: https://github.com/psf/black
|
| 4 |
+
rev: 24.10.0
|
| 5 |
+
hooks:
|
| 6 |
+
- id: black
|
| 7 |
+
args: [--line-length=88]
|
| 8 |
+
language_version: python3.12
|
| 9 |
+
|
| 10 |
+
# MyPy - type checking (blocks commits on errors)
|
| 11 |
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
| 12 |
+
rev: v1.11.2
|
| 13 |
+
hooks:
|
| 14 |
+
- id: mypy
|
| 15 |
+
args: [--ignore-missing-imports, --warn-unused-configs]
|
| 16 |
+
additional_dependencies:
|
| 17 |
+
- types-requests
|
| 18 |
+
- types-pyyaml
|
| 19 |
+
files: ^ace/
|
| 20 |
+
language_version: python3.12
|
.specify/memory/constitution.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!--
|
| 2 |
+
Sync Impact Report
|
| 3 |
+
==================
|
| 4 |
+
Version change: 1.0.0 → 1.1.0
|
| 5 |
+
Principles added:
|
| 6 |
+
- IV. Clean & Modular Code
|
| 7 |
+
Principles unchanged:
|
| 8 |
+
- I. Ease of Use First
|
| 9 |
+
- II. Practical Value
|
| 10 |
+
- III. Simplicity
|
| 11 |
+
Sections unchanged:
|
| 12 |
+
- Development Standards
|
| 13 |
+
- Quality Gates
|
| 14 |
+
- Governance
|
| 15 |
+
Removed sections: None
|
| 16 |
+
Templates validated:
|
| 17 |
+
✅ .specify/templates/plan-template.md — Constitution Check section compatible
|
| 18 |
+
✅ .specify/templates/spec-template.md — No conflicts
|
| 19 |
+
✅ .specify/templates/tasks-template.md — No conflicts
|
| 20 |
+
✅ .specify/templates/checklist-template.md — No conflicts
|
| 21 |
+
Follow-up TODOs: None
|
| 22 |
+
-->
|
| 23 |
+
|
| 24 |
+
# ACE Framework Constitution
|
| 25 |
+
|
| 26 |
+
## Core Principles
|
| 27 |
+
|
| 28 |
+
### I. Ease of Use First
|
| 29 |
+
|
| 30 |
+
Every public API, integration, and workflow MUST prioritize developer
|
| 31 |
+
experience above all else.
|
| 32 |
+
|
| 33 |
+
- New users MUST be able to install and run a working example in under
|
| 34 |
+
5 minutes with no more than 3 lines of code.
|
| 35 |
+
- Sensible defaults MUST be provided for every configuration option.
|
| 36 |
+
Users MUST NOT be required to understand internals to get started.
|
| 37 |
+
- Breaking changes to the public API MUST follow deprecation warnings
|
| 38 |
+
for at least one minor release before removal.
|
| 39 |
+
- Documentation MUST include a copy-pasteable quick start for every
|
| 40 |
+
integration (LiteLLM, LangChain, browser-use, Claude Code).
|
| 41 |
+
|
| 42 |
+
### II. Practical Value
|
| 43 |
+
|
| 44 |
+
Every feature MUST solve a real, demonstrable problem for users
|
| 45 |
+
building AI agents.
|
| 46 |
+
|
| 47 |
+
- Features MUST NOT be added speculatively. Each addition MUST have a
|
| 48 |
+
concrete use case tied to agent improvement or developer workflow.
|
| 49 |
+
- Performance claims MUST be backed by reproducible benchmarks or
|
| 50 |
+
examples. No unsubstantiated marketing language in docs or code.
|
| 51 |
+
- Integration wrappers MUST add measurable value (learning, skillbook
|
| 52 |
+
evolution) beyond what the wrapped framework already provides.
|
| 53 |
+
|
| 54 |
+
### III. Simplicity
|
| 55 |
+
|
| 56 |
+
Prefer the simplest solution that works. Complexity MUST be justified.
|
| 57 |
+
|
| 58 |
+
- YAGNI: Do not build for hypothetical future requirements. Three
|
| 59 |
+
similar lines of code are better than a premature abstraction.
|
| 60 |
+
- New abstractions MUST be used in at least two places before
|
| 61 |
+
extraction into a shared utility.
|
| 62 |
+
- Dependencies MUST be kept minimal. Optional extras (observability,
|
| 63 |
+
LangChain, transformers) stay optional — the core install MUST
|
| 64 |
+
remain lightweight.
|
| 65 |
+
|
| 66 |
+
### IV. Clean & Modular Code
|
| 67 |
+
|
| 68 |
+
All code MUST be clean, modular, and extensible.
|
| 69 |
+
|
| 70 |
+
- Modules MUST have a single, clear responsibility. Each file MUST
|
| 71 |
+
do one thing well and expose a well-defined interface.
|
| 72 |
+
- Public APIs MUST be designed for extension without modification.
|
| 73 |
+
New integrations, LLM providers, and adapters MUST be addable
|
| 74 |
+
without changing existing code (open/closed principle).
|
| 75 |
+
- Internal boundaries MUST be respected: core library (`ace/`),
|
| 76 |
+
integrations (`ace/integrations/`), LLM providers
|
| 77 |
+
(`ace/llm_providers/`), and observability (`ace/observability/`)
|
| 78 |
+
MUST NOT have circular dependencies.
|
| 79 |
+
- Functions and classes MUST be small enough to understand at a
|
| 80 |
+
glance. If a function requires scrolling, it MUST be decomposed.
|
| 81 |
+
|
| 82 |
+
## Development Standards
|
| 83 |
+
|
| 84 |
+
- **Language**: Python 3.12 with type hints on all public APIs.
|
| 85 |
+
- **Formatting**: Black (line length 88). All code MUST pass
|
| 86 |
+
`black --check` before merge.
|
| 87 |
+
- **Testing**: pytest with coverage enforcement (`--cov-fail-under=25`).
|
| 88 |
+
New features MUST include tests. Bug fixes MUST include regression
|
| 89 |
+
tests.
|
| 90 |
+
- **Distribution**: PyPI package `ace-framework`. Core install MUST NOT
|
| 91 |
+
exceed ~150MB. Heavy dependencies belong in optional extras.
|
| 92 |
+
- **Commit style**: Conventional Commits (`feat(scope): subject`).
|
| 93 |
+
|
| 94 |
+
## Quality Gates
|
| 95 |
+
|
| 96 |
+
- All PRs MUST pass CI (formatting, type checks, test suite) before
|
| 97 |
+
merge.
|
| 98 |
+
- Public API changes MUST update relevant documentation (README,
|
| 99 |
+
docstrings, quick start guides).
|
| 100 |
+
- Benchmark results MUST NOT regress without explicit justification in
|
| 101 |
+
the PR description.
|
| 102 |
+
- Skillbook format changes MUST maintain backward compatibility with
|
| 103 |
+
existing saved skillbooks or provide a migration path.
|
| 104 |
+
|
| 105 |
+
## Governance
|
| 106 |
+
|
| 107 |
+
This constitution is the highest-authority document for the ACE
|
| 108 |
+
Framework project. All design decisions, PRs, and code reviews MUST
|
| 109 |
+
verify compliance with these principles.
|
| 110 |
+
|
| 111 |
+
- **Amendments**: Any change to this constitution MUST be documented
|
| 112 |
+
with a version bump, rationale, and updated `LAST_AMENDED_DATE`.
|
| 113 |
+
- **Versioning**: MAJOR for principle removals or redefinitions, MINOR
|
| 114 |
+
for new principles or material expansions, PATCH for clarifications.
|
| 115 |
+
- **Compliance**: Use `CLAUDE.md` for runtime development guidance.
|
| 116 |
+
This constitution defines the non-negotiable rules that `CLAUDE.md`
|
| 117 |
+
guidance MUST NOT contradict.
|
| 118 |
+
- **Review**: Constitution compliance SHOULD be checked at the start
|
| 119 |
+
of each feature planning cycle (`/speckit.plan` Constitution Check).
|
| 120 |
+
|
| 121 |
+
**Version**: 1.1.0 | **Ratified**: 2026-02-25 | **Last Amended**: 2026-02-25
|
.specify/scripts/bash/check-prerequisites.sh
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
|
| 3 |
+
# Consolidated prerequisite checking script
|
| 4 |
+
#
|
| 5 |
+
# This script provides unified prerequisite checking for Spec-Driven Development workflow.
|
| 6 |
+
# It replaces the functionality previously spread across multiple scripts.
|
| 7 |
+
#
|
| 8 |
+
# Usage: ./check-prerequisites.sh [OPTIONS]
|
| 9 |
+
#
|
| 10 |
+
# OPTIONS:
|
| 11 |
+
# --json Output in JSON format
|
| 12 |
+
# --require-tasks Require tasks.md to exist (for implementation phase)
|
| 13 |
+
# --include-tasks Include tasks.md in AVAILABLE_DOCS list
|
| 14 |
+
# --paths-only Only output path variables (no validation)
|
| 15 |
+
# --help, -h Show help message
|
| 16 |
+
#
|
| 17 |
+
# OUTPUTS:
|
| 18 |
+
# JSON mode: {"FEATURE_DIR":"...", "AVAILABLE_DOCS":["..."]}
|
| 19 |
+
# Text mode: FEATURE_DIR:... \n AVAILABLE_DOCS: \n ✓/✗ file.md
|
| 20 |
+
# Paths only: REPO_ROOT: ... \n BRANCH: ... \n FEATURE_DIR: ... etc.
|
| 21 |
+
|
| 22 |
+
set -e
|
| 23 |
+
|
| 24 |
+
# Parse command line arguments
|
| 25 |
+
JSON_MODE=false
|
| 26 |
+
REQUIRE_TASKS=false
|
| 27 |
+
INCLUDE_TASKS=false
|
| 28 |
+
PATHS_ONLY=false
|
| 29 |
+
|
| 30 |
+
for arg in "$@"; do
|
| 31 |
+
case "$arg" in
|
| 32 |
+
--json)
|
| 33 |
+
JSON_MODE=true
|
| 34 |
+
;;
|
| 35 |
+
--require-tasks)
|
| 36 |
+
REQUIRE_TASKS=true
|
| 37 |
+
;;
|
| 38 |
+
--include-tasks)
|
| 39 |
+
INCLUDE_TASKS=true
|
| 40 |
+
;;
|
| 41 |
+
--paths-only)
|
| 42 |
+
PATHS_ONLY=true
|
| 43 |
+
;;
|
| 44 |
+
--help|-h)
|
| 45 |
+
cat << 'EOF'
|
| 46 |
+
Usage: check-prerequisites.sh [OPTIONS]
|
| 47 |
+
|
| 48 |
+
Consolidated prerequisite checking for Spec-Driven Development workflow.
|
| 49 |
+
|
| 50 |
+
OPTIONS:
|
| 51 |
+
--json Output in JSON format
|
| 52 |
+
--require-tasks Require tasks.md to exist (for implementation phase)
|
| 53 |
+
--include-tasks Include tasks.md in AVAILABLE_DOCS list
|
| 54 |
+
--paths-only Only output path variables (no prerequisite validation)
|
| 55 |
+
--help, -h Show this help message
|
| 56 |
+
|
| 57 |
+
EXAMPLES:
|
| 58 |
+
# Check task prerequisites (plan.md required)
|
| 59 |
+
./check-prerequisites.sh --json
|
| 60 |
+
|
| 61 |
+
# Check implementation prerequisites (plan.md + tasks.md required)
|
| 62 |
+
./check-prerequisites.sh --json --require-tasks --include-tasks
|
| 63 |
+
|
| 64 |
+
# Get feature paths only (no validation)
|
| 65 |
+
./check-prerequisites.sh --paths-only
|
| 66 |
+
|
| 67 |
+
EOF
|
| 68 |
+
exit 0
|
| 69 |
+
;;
|
| 70 |
+
*)
|
| 71 |
+
echo "ERROR: Unknown option '$arg'. Use --help for usage information." >&2
|
| 72 |
+
exit 1
|
| 73 |
+
;;
|
| 74 |
+
esac
|
| 75 |
+
done
|
| 76 |
+
|
| 77 |
+
# Source common functions
|
| 78 |
+
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 79 |
+
source "$SCRIPT_DIR/common.sh"
|
| 80 |
+
|
| 81 |
+
# Get feature paths and validate branch
|
| 82 |
+
eval $(get_feature_paths)
|
| 83 |
+
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
|
| 84 |
+
|
| 85 |
+
# If paths-only mode, output paths and exit (support JSON + paths-only combined)
|
| 86 |
+
if $PATHS_ONLY; then
|
| 87 |
+
if $JSON_MODE; then
|
| 88 |
+
# Minimal JSON paths payload (no validation performed)
|
| 89 |
+
printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS":"%s"}\n' \
|
| 90 |
+
"$REPO_ROOT" "$CURRENT_BRANCH" "$FEATURE_DIR" "$FEATURE_SPEC" "$IMPL_PLAN" "$TASKS"
|
| 91 |
+
else
|
| 92 |
+
echo "REPO_ROOT: $REPO_ROOT"
|
| 93 |
+
echo "BRANCH: $CURRENT_BRANCH"
|
| 94 |
+
echo "FEATURE_DIR: $FEATURE_DIR"
|
| 95 |
+
echo "FEATURE_SPEC: $FEATURE_SPEC"
|
| 96 |
+
echo "IMPL_PLAN: $IMPL_PLAN"
|
| 97 |
+
echo "TASKS: $TASKS"
|
| 98 |
+
fi
|
| 99 |
+
exit 0
|
| 100 |
+
fi
|
| 101 |
+
|
| 102 |
+
# Validate required directories and files
|
| 103 |
+
if [[ ! -d "$FEATURE_DIR" ]]; then
|
| 104 |
+
echo "ERROR: Feature directory not found: $FEATURE_DIR" >&2
|
| 105 |
+
echo "Run /speckit.specify first to create the feature structure." >&2
|
| 106 |
+
exit 1
|
| 107 |
+
fi
|
| 108 |
+
|
| 109 |
+
if [[ ! -f "$IMPL_PLAN" ]]; then
|
| 110 |
+
echo "ERROR: plan.md not found in $FEATURE_DIR" >&2
|
| 111 |
+
echo "Run /speckit.plan first to create the implementation plan." >&2
|
| 112 |
+
exit 1
|
| 113 |
+
fi
|
| 114 |
+
|
| 115 |
+
# Check for tasks.md if required
|
| 116 |
+
if $REQUIRE_TASKS && [[ ! -f "$TASKS" ]]; then
|
| 117 |
+
echo "ERROR: tasks.md not found in $FEATURE_DIR" >&2
|
| 118 |
+
echo "Run /speckit.tasks first to create the task list." >&2
|
| 119 |
+
exit 1
|
| 120 |
+
fi
|
| 121 |
+
|
| 122 |
+
# Build list of available documents
|
| 123 |
+
docs=()
|
| 124 |
+
|
| 125 |
+
# Always check these optional docs
|
| 126 |
+
[[ -f "$RESEARCH" ]] && docs+=("research.md")
|
| 127 |
+
[[ -f "$DATA_MODEL" ]] && docs+=("data-model.md")
|
| 128 |
+
|
| 129 |
+
# Check contracts directory (only if it exists and has files)
|
| 130 |
+
if [[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]; then
|
| 131 |
+
docs+=("contracts/")
|
| 132 |
+
fi
|
| 133 |
+
|
| 134 |
+
[[ -f "$QUICKSTART" ]] && docs+=("quickstart.md")
|
| 135 |
+
|
| 136 |
+
# Include tasks.md if requested and it exists
|
| 137 |
+
if $INCLUDE_TASKS && [[ -f "$TASKS" ]]; then
|
| 138 |
+
docs+=("tasks.md")
|
| 139 |
+
fi
|
| 140 |
+
|
| 141 |
+
# Output results
|
| 142 |
+
if $JSON_MODE; then
|
| 143 |
+
# Build JSON array of documents
|
| 144 |
+
if [[ ${#docs[@]} -eq 0 ]]; then
|
| 145 |
+
json_docs="[]"
|
| 146 |
+
else
|
| 147 |
+
json_docs=$(printf '"%s",' "${docs[@]}")
|
| 148 |
+
json_docs="[${json_docs%,}]"
|
| 149 |
+
fi
|
| 150 |
+
|
| 151 |
+
printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$FEATURE_DIR" "$json_docs"
|
| 152 |
+
else
|
| 153 |
+
# Text output
|
| 154 |
+
echo "FEATURE_DIR:$FEATURE_DIR"
|
| 155 |
+
echo "AVAILABLE_DOCS:"
|
| 156 |
+
|
| 157 |
+
# Show status of each potential document
|
| 158 |
+
check_file "$RESEARCH" "research.md"
|
| 159 |
+
check_file "$DATA_MODEL" "data-model.md"
|
| 160 |
+
check_dir "$CONTRACTS_DIR" "contracts/"
|
| 161 |
+
check_file "$QUICKSTART" "quickstart.md"
|
| 162 |
+
|
| 163 |
+
if $INCLUDE_TASKS; then
|
| 164 |
+
check_file "$TASKS" "tasks.md"
|
| 165 |
+
fi
|
| 166 |
+
fi
|
.specify/scripts/bash/common.sh
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# Common functions and variables for all scripts
|
| 3 |
+
|
| 4 |
+
# Get repository root, with fallback for non-git repositories
|
| 5 |
+
get_repo_root() {
|
| 6 |
+
if git rev-parse --show-toplevel >/dev/null 2>&1; then
|
| 7 |
+
git rev-parse --show-toplevel
|
| 8 |
+
else
|
| 9 |
+
# Fall back to script location for non-git repos
|
| 10 |
+
local script_dir="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 11 |
+
(cd "$script_dir/../../.." && pwd)
|
| 12 |
+
fi
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
# Get current branch, with fallback for non-git repositories
|
| 16 |
+
get_current_branch() {
|
| 17 |
+
# First check if SPECIFY_FEATURE environment variable is set
|
| 18 |
+
if [[ -n "${SPECIFY_FEATURE:-}" ]]; then
|
| 19 |
+
echo "$SPECIFY_FEATURE"
|
| 20 |
+
return
|
| 21 |
+
fi
|
| 22 |
+
|
| 23 |
+
# Then check git if available
|
| 24 |
+
if git rev-parse --abbrev-ref HEAD >/dev/null 2>&1; then
|
| 25 |
+
git rev-parse --abbrev-ref HEAD
|
| 26 |
+
return
|
| 27 |
+
fi
|
| 28 |
+
|
| 29 |
+
# For non-git repos, try to find the latest feature directory
|
| 30 |
+
local repo_root=$(get_repo_root)
|
| 31 |
+
local specs_dir="$repo_root/specs"
|
| 32 |
+
|
| 33 |
+
if [[ -d "$specs_dir" ]]; then
|
| 34 |
+
local latest_feature=""
|
| 35 |
+
local highest=0
|
| 36 |
+
|
| 37 |
+
for dir in "$specs_dir"/*; do
|
| 38 |
+
if [[ -d "$dir" ]]; then
|
| 39 |
+
local dirname=$(basename "$dir")
|
| 40 |
+
if [[ "$dirname" =~ ^([0-9]{3})- ]]; then
|
| 41 |
+
local number=${BASH_REMATCH[1]}
|
| 42 |
+
number=$((10#$number))
|
| 43 |
+
if [[ "$number" -gt "$highest" ]]; then
|
| 44 |
+
highest=$number
|
| 45 |
+
latest_feature=$dirname
|
| 46 |
+
fi
|
| 47 |
+
fi
|
| 48 |
+
fi
|
| 49 |
+
done
|
| 50 |
+
|
| 51 |
+
if [[ -n "$latest_feature" ]]; then
|
| 52 |
+
echo "$latest_feature"
|
| 53 |
+
return
|
| 54 |
+
fi
|
| 55 |
+
fi
|
| 56 |
+
|
| 57 |
+
echo "main" # Final fallback
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
# Check if we have git available
|
| 61 |
+
has_git() {
|
| 62 |
+
git rev-parse --show-toplevel >/dev/null 2>&1
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
check_feature_branch() {
|
| 66 |
+
local branch="$1"
|
| 67 |
+
local has_git_repo="$2"
|
| 68 |
+
|
| 69 |
+
# For non-git repos, we can't enforce branch naming but still provide output
|
| 70 |
+
if [[ "$has_git_repo" != "true" ]]; then
|
| 71 |
+
echo "[specify] Warning: Git repository not detected; skipped branch validation" >&2
|
| 72 |
+
return 0
|
| 73 |
+
fi
|
| 74 |
+
|
| 75 |
+
if [[ ! "$branch" =~ ^[0-9]{3}- ]]; then
|
| 76 |
+
echo "ERROR: Not on a feature branch. Current branch: $branch" >&2
|
| 77 |
+
echo "Feature branches should be named like: 001-feature-name" >&2
|
| 78 |
+
return 1
|
| 79 |
+
fi
|
| 80 |
+
|
| 81 |
+
return 0
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
get_feature_dir() { echo "$1/specs/$2"; }
|
| 85 |
+
|
| 86 |
+
# Find feature directory by numeric prefix instead of exact branch match
|
| 87 |
+
# This allows multiple branches to work on the same spec (e.g., 004-fix-bug, 004-add-feature)
|
| 88 |
+
find_feature_dir_by_prefix() {
|
| 89 |
+
local repo_root="$1"
|
| 90 |
+
local branch_name="$2"
|
| 91 |
+
local specs_dir="$repo_root/specs"
|
| 92 |
+
|
| 93 |
+
# Extract numeric prefix from branch (e.g., "004" from "004-whatever")
|
| 94 |
+
if [[ ! "$branch_name" =~ ^([0-9]{3})- ]]; then
|
| 95 |
+
# If branch doesn't have numeric prefix, fall back to exact match
|
| 96 |
+
echo "$specs_dir/$branch_name"
|
| 97 |
+
return
|
| 98 |
+
fi
|
| 99 |
+
|
| 100 |
+
local prefix="${BASH_REMATCH[1]}"
|
| 101 |
+
|
| 102 |
+
# Search for directories in specs/ that start with this prefix
|
| 103 |
+
local matches=()
|
| 104 |
+
if [[ -d "$specs_dir" ]]; then
|
| 105 |
+
for dir in "$specs_dir"/"$prefix"-*; do
|
| 106 |
+
if [[ -d "$dir" ]]; then
|
| 107 |
+
matches+=("$(basename "$dir")")
|
| 108 |
+
fi
|
| 109 |
+
done
|
| 110 |
+
fi
|
| 111 |
+
|
| 112 |
+
# Handle results
|
| 113 |
+
if [[ ${#matches[@]} -eq 0 ]]; then
|
| 114 |
+
# No match found - return the branch name path (will fail later with clear error)
|
| 115 |
+
echo "$specs_dir/$branch_name"
|
| 116 |
+
elif [[ ${#matches[@]} -eq 1 ]]; then
|
| 117 |
+
# Exactly one match - perfect!
|
| 118 |
+
echo "$specs_dir/${matches[0]}"
|
| 119 |
+
else
|
| 120 |
+
# Multiple matches - this shouldn't happen with proper naming convention
|
| 121 |
+
echo "ERROR: Multiple spec directories found with prefix '$prefix': ${matches[*]}" >&2
|
| 122 |
+
echo "Please ensure only one spec directory exists per numeric prefix." >&2
|
| 123 |
+
echo "$specs_dir/$branch_name" # Return something to avoid breaking the script
|
| 124 |
+
fi
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
get_feature_paths() {
|
| 128 |
+
local repo_root=$(get_repo_root)
|
| 129 |
+
local current_branch=$(get_current_branch)
|
| 130 |
+
local has_git_repo="false"
|
| 131 |
+
|
| 132 |
+
if has_git; then
|
| 133 |
+
has_git_repo="true"
|
| 134 |
+
fi
|
| 135 |
+
|
| 136 |
+
# Use prefix-based lookup to support multiple branches per spec
|
| 137 |
+
local feature_dir=$(find_feature_dir_by_prefix "$repo_root" "$current_branch")
|
| 138 |
+
|
| 139 |
+
cat <<EOF
|
| 140 |
+
REPO_ROOT='$repo_root'
|
| 141 |
+
CURRENT_BRANCH='$current_branch'
|
| 142 |
+
HAS_GIT='$has_git_repo'
|
| 143 |
+
FEATURE_DIR='$feature_dir'
|
| 144 |
+
FEATURE_SPEC='$feature_dir/spec.md'
|
| 145 |
+
IMPL_PLAN='$feature_dir/plan.md'
|
| 146 |
+
TASKS='$feature_dir/tasks.md'
|
| 147 |
+
RESEARCH='$feature_dir/research.md'
|
| 148 |
+
DATA_MODEL='$feature_dir/data-model.md'
|
| 149 |
+
QUICKSTART='$feature_dir/quickstart.md'
|
| 150 |
+
CONTRACTS_DIR='$feature_dir/contracts'
|
| 151 |
+
EOF
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
check_file() { [[ -f "$1" ]] && echo " ✓ $2" || echo " ✗ $2"; }
|
| 155 |
+
check_dir() { [[ -d "$1" && -n $(ls -A "$1" 2>/dev/null) ]] && echo " ✓ $2" || echo " ✗ $2"; }
|
| 156 |
+
|
.specify/scripts/bash/create-new-feature.sh
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
|
| 3 |
+
set -e
|
| 4 |
+
|
| 5 |
+
JSON_MODE=false
|
| 6 |
+
SHORT_NAME=""
|
| 7 |
+
BRANCH_NUMBER=""
|
| 8 |
+
ARGS=()
|
| 9 |
+
i=1
|
| 10 |
+
while [ $i -le $# ]; do
|
| 11 |
+
arg="${!i}"
|
| 12 |
+
case "$arg" in
|
| 13 |
+
--json)
|
| 14 |
+
JSON_MODE=true
|
| 15 |
+
;;
|
| 16 |
+
--short-name)
|
| 17 |
+
if [ $((i + 1)) -gt $# ]; then
|
| 18 |
+
echo 'Error: --short-name requires a value' >&2
|
| 19 |
+
exit 1
|
| 20 |
+
fi
|
| 21 |
+
i=$((i + 1))
|
| 22 |
+
next_arg="${!i}"
|
| 23 |
+
# Check if the next argument is another option (starts with --)
|
| 24 |
+
if [[ "$next_arg" == --* ]]; then
|
| 25 |
+
echo 'Error: --short-name requires a value' >&2
|
| 26 |
+
exit 1
|
| 27 |
+
fi
|
| 28 |
+
SHORT_NAME="$next_arg"
|
| 29 |
+
;;
|
| 30 |
+
--number)
|
| 31 |
+
if [ $((i + 1)) -gt $# ]; then
|
| 32 |
+
echo 'Error: --number requires a value' >&2
|
| 33 |
+
exit 1
|
| 34 |
+
fi
|
| 35 |
+
i=$((i + 1))
|
| 36 |
+
next_arg="${!i}"
|
| 37 |
+
if [[ "$next_arg" == --* ]]; then
|
| 38 |
+
echo 'Error: --number requires a value' >&2
|
| 39 |
+
exit 1
|
| 40 |
+
fi
|
| 41 |
+
BRANCH_NUMBER="$next_arg"
|
| 42 |
+
;;
|
| 43 |
+
--help|-h)
|
| 44 |
+
echo "Usage: $0 [--json] [--short-name <name>] [--number N] <feature_description>"
|
| 45 |
+
echo ""
|
| 46 |
+
echo "Options:"
|
| 47 |
+
echo " --json Output in JSON format"
|
| 48 |
+
echo " --short-name <name> Provide a custom short name (2-4 words) for the branch"
|
| 49 |
+
echo " --number N Specify branch number manually (overrides auto-detection)"
|
| 50 |
+
echo " --help, -h Show this help message"
|
| 51 |
+
echo ""
|
| 52 |
+
echo "Examples:"
|
| 53 |
+
echo " $0 'Add user authentication system' --short-name 'user-auth'"
|
| 54 |
+
echo " $0 'Implement OAuth2 integration for API' --number 5"
|
| 55 |
+
exit 0
|
| 56 |
+
;;
|
| 57 |
+
*)
|
| 58 |
+
ARGS+=("$arg")
|
| 59 |
+
;;
|
| 60 |
+
esac
|
| 61 |
+
i=$((i + 1))
|
| 62 |
+
done
|
| 63 |
+
|
| 64 |
+
FEATURE_DESCRIPTION="${ARGS[*]}"
|
| 65 |
+
if [ -z "$FEATURE_DESCRIPTION" ]; then
|
| 66 |
+
echo "Usage: $0 [--json] [--short-name <name>] [--number N] <feature_description>" >&2
|
| 67 |
+
exit 1
|
| 68 |
+
fi
|
| 69 |
+
|
| 70 |
+
# Function to find the repository root by searching for existing project markers
|
| 71 |
+
find_repo_root() {
|
| 72 |
+
local dir="$1"
|
| 73 |
+
while [ "$dir" != "/" ]; do
|
| 74 |
+
if [ -d "$dir/.git" ] || [ -d "$dir/.specify" ]; then
|
| 75 |
+
echo "$dir"
|
| 76 |
+
return 0
|
| 77 |
+
fi
|
| 78 |
+
dir="$(dirname "$dir")"
|
| 79 |
+
done
|
| 80 |
+
return 1
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
# Function to get highest number from specs directory
|
| 84 |
+
get_highest_from_specs() {
|
| 85 |
+
local specs_dir="$1"
|
| 86 |
+
local highest=0
|
| 87 |
+
|
| 88 |
+
if [ -d "$specs_dir" ]; then
|
| 89 |
+
for dir in "$specs_dir"/*; do
|
| 90 |
+
[ -d "$dir" ] || continue
|
| 91 |
+
dirname=$(basename "$dir")
|
| 92 |
+
number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0")
|
| 93 |
+
number=$((10#$number))
|
| 94 |
+
if [ "$number" -gt "$highest" ]; then
|
| 95 |
+
highest=$number
|
| 96 |
+
fi
|
| 97 |
+
done
|
| 98 |
+
fi
|
| 99 |
+
|
| 100 |
+
echo "$highest"
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
# Function to get highest number from git branches
|
| 104 |
+
get_highest_from_branches() {
|
| 105 |
+
local highest=0
|
| 106 |
+
|
| 107 |
+
# Get all branches (local and remote)
|
| 108 |
+
branches=$(git branch -a 2>/dev/null || echo "")
|
| 109 |
+
|
| 110 |
+
if [ -n "$branches" ]; then
|
| 111 |
+
while IFS= read -r branch; do
|
| 112 |
+
# Clean branch name: remove leading markers and remote prefixes
|
| 113 |
+
clean_branch=$(echo "$branch" | sed 's/^[* ]*//; s|^remotes/[^/]*/||')
|
| 114 |
+
|
| 115 |
+
# Extract feature number if branch matches pattern ###-*
|
| 116 |
+
if echo "$clean_branch" | grep -q '^[0-9]\{3\}-'; then
|
| 117 |
+
number=$(echo "$clean_branch" | grep -o '^[0-9]\{3\}' || echo "0")
|
| 118 |
+
number=$((10#$number))
|
| 119 |
+
if [ "$number" -gt "$highest" ]; then
|
| 120 |
+
highest=$number
|
| 121 |
+
fi
|
| 122 |
+
fi
|
| 123 |
+
done <<< "$branches"
|
| 124 |
+
fi
|
| 125 |
+
|
| 126 |
+
echo "$highest"
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
# Function to check existing branches (local and remote) and return next available number
|
| 130 |
+
check_existing_branches() {
|
| 131 |
+
local specs_dir="$1"
|
| 132 |
+
|
| 133 |
+
# Fetch all remotes to get latest branch info (suppress errors if no remotes)
|
| 134 |
+
git fetch --all --prune 2>/dev/null || true
|
| 135 |
+
|
| 136 |
+
# Get highest number from ALL branches (not just matching short name)
|
| 137 |
+
local highest_branch=$(get_highest_from_branches)
|
| 138 |
+
|
| 139 |
+
# Get highest number from ALL specs (not just matching short name)
|
| 140 |
+
local highest_spec=$(get_highest_from_specs "$specs_dir")
|
| 141 |
+
|
| 142 |
+
# Take the maximum of both
|
| 143 |
+
local max_num=$highest_branch
|
| 144 |
+
if [ "$highest_spec" -gt "$max_num" ]; then
|
| 145 |
+
max_num=$highest_spec
|
| 146 |
+
fi
|
| 147 |
+
|
| 148 |
+
# Return next number
|
| 149 |
+
echo $((max_num + 1))
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
# Function to clean and format a branch name
|
| 153 |
+
clean_branch_name() {
|
| 154 |
+
local name="$1"
|
| 155 |
+
echo "$name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//'
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
# Resolve repository root. Prefer git information when available, but fall back
|
| 159 |
+
# to searching for repository markers so the workflow still functions in repositories that
|
| 160 |
+
# were initialised with --no-git.
|
| 161 |
+
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 162 |
+
|
| 163 |
+
if git rev-parse --show-toplevel >/dev/null 2>&1; then
|
| 164 |
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
| 165 |
+
HAS_GIT=true
|
| 166 |
+
else
|
| 167 |
+
REPO_ROOT="$(find_repo_root "$SCRIPT_DIR")"
|
| 168 |
+
if [ -z "$REPO_ROOT" ]; then
|
| 169 |
+
echo "Error: Could not determine repository root. Please run this script from within the repository." >&2
|
| 170 |
+
exit 1
|
| 171 |
+
fi
|
| 172 |
+
HAS_GIT=false
|
| 173 |
+
fi
|
| 174 |
+
|
| 175 |
+
cd "$REPO_ROOT"
|
| 176 |
+
|
| 177 |
+
SPECS_DIR="$REPO_ROOT/specs"
|
| 178 |
+
mkdir -p "$SPECS_DIR"
|
| 179 |
+
|
| 180 |
+
# Function to generate branch name with stop word filtering and length filtering
|
| 181 |
+
generate_branch_name() {
|
| 182 |
+
local description="$1"
|
| 183 |
+
|
| 184 |
+
# Common stop words to filter out
|
| 185 |
+
local stop_words="^(i|a|an|the|to|for|of|in|on|at|by|with|from|is|are|was|were|be|been|being|have|has|had|do|does|did|will|would|should|could|can|may|might|must|shall|this|that|these|those|my|your|our|their|want|need|add|get|set)$"
|
| 186 |
+
|
| 187 |
+
# Convert to lowercase and split into words
|
| 188 |
+
local clean_name=$(echo "$description" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/ /g')
|
| 189 |
+
|
| 190 |
+
# Filter words: remove stop words and words shorter than 3 chars (unless they're uppercase acronyms in original)
|
| 191 |
+
local meaningful_words=()
|
| 192 |
+
for word in $clean_name; do
|
| 193 |
+
# Skip empty words
|
| 194 |
+
[ -z "$word" ] && continue
|
| 195 |
+
|
| 196 |
+
# Keep words that are NOT stop words AND (length >= 3 OR are potential acronyms)
|
| 197 |
+
if ! echo "$word" | grep -qiE "$stop_words"; then
|
| 198 |
+
if [ ${#word} -ge 3 ]; then
|
| 199 |
+
meaningful_words+=("$word")
|
| 200 |
+
elif echo "$description" | grep -q "\b${word^^}\b"; then
|
| 201 |
+
# Keep short words if they appear as uppercase in original (likely acronyms)
|
| 202 |
+
meaningful_words+=("$word")
|
| 203 |
+
fi
|
| 204 |
+
fi
|
| 205 |
+
done
|
| 206 |
+
|
| 207 |
+
# If we have meaningful words, use first 3-4 of them
|
| 208 |
+
if [ ${#meaningful_words[@]} -gt 0 ]; then
|
| 209 |
+
local max_words=3
|
| 210 |
+
if [ ${#meaningful_words[@]} -eq 4 ]; then max_words=4; fi
|
| 211 |
+
|
| 212 |
+
local result=""
|
| 213 |
+
local count=0
|
| 214 |
+
for word in "${meaningful_words[@]}"; do
|
| 215 |
+
if [ $count -ge $max_words ]; then break; fi
|
| 216 |
+
if [ -n "$result" ]; then result="$result-"; fi
|
| 217 |
+
result="$result$word"
|
| 218 |
+
count=$((count + 1))
|
| 219 |
+
done
|
| 220 |
+
echo "$result"
|
| 221 |
+
else
|
| 222 |
+
# Fallback to original logic if no meaningful words found
|
| 223 |
+
local cleaned=$(clean_branch_name "$description")
|
| 224 |
+
echo "$cleaned" | tr '-' '\n' | grep -v '^$' | head -3 | tr '\n' '-' | sed 's/-$//'
|
| 225 |
+
fi
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
# Generate branch name
|
| 229 |
+
if [ -n "$SHORT_NAME" ]; then
|
| 230 |
+
# Use provided short name, just clean it up
|
| 231 |
+
BRANCH_SUFFIX=$(clean_branch_name "$SHORT_NAME")
|
| 232 |
+
else
|
| 233 |
+
# Generate from description with smart filtering
|
| 234 |
+
BRANCH_SUFFIX=$(generate_branch_name "$FEATURE_DESCRIPTION")
|
| 235 |
+
fi
|
| 236 |
+
|
| 237 |
+
# Determine branch number
|
| 238 |
+
if [ -z "$BRANCH_NUMBER" ]; then
|
| 239 |
+
if [ "$HAS_GIT" = true ]; then
|
| 240 |
+
# Check existing branches on remotes
|
| 241 |
+
BRANCH_NUMBER=$(check_existing_branches "$SPECS_DIR")
|
| 242 |
+
else
|
| 243 |
+
# Fall back to local directory check
|
| 244 |
+
HIGHEST=$(get_highest_from_specs "$SPECS_DIR")
|
| 245 |
+
BRANCH_NUMBER=$((HIGHEST + 1))
|
| 246 |
+
fi
|
| 247 |
+
fi
|
| 248 |
+
|
| 249 |
+
# Force base-10 interpretation to prevent octal conversion (e.g., 010 → 8 in octal, but should be 10 in decimal)
|
| 250 |
+
FEATURE_NUM=$(printf "%03d" "$((10#$BRANCH_NUMBER))")
|
| 251 |
+
BRANCH_NAME="${FEATURE_NUM}-${BRANCH_SUFFIX}"
|
| 252 |
+
|
| 253 |
+
# GitHub enforces a 244-byte limit on branch names
|
| 254 |
+
# Validate and truncate if necessary
|
| 255 |
+
MAX_BRANCH_LENGTH=244
|
| 256 |
+
if [ ${#BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then
|
| 257 |
+
# Calculate how much we need to trim from suffix
|
| 258 |
+
# Account for: feature number (3) + hyphen (1) = 4 chars
|
| 259 |
+
MAX_SUFFIX_LENGTH=$((MAX_BRANCH_LENGTH - 4))
|
| 260 |
+
|
| 261 |
+
# Truncate suffix at word boundary if possible
|
| 262 |
+
TRUNCATED_SUFFIX=$(echo "$BRANCH_SUFFIX" | cut -c1-$MAX_SUFFIX_LENGTH)
|
| 263 |
+
# Remove trailing hyphen if truncation created one
|
| 264 |
+
TRUNCATED_SUFFIX=$(echo "$TRUNCATED_SUFFIX" | sed 's/-$//')
|
| 265 |
+
|
| 266 |
+
ORIGINAL_BRANCH_NAME="$BRANCH_NAME"
|
| 267 |
+
BRANCH_NAME="${FEATURE_NUM}-${TRUNCATED_SUFFIX}"
|
| 268 |
+
|
| 269 |
+
>&2 echo "[specify] Warning: Branch name exceeded GitHub's 244-byte limit"
|
| 270 |
+
>&2 echo "[specify] Original: $ORIGINAL_BRANCH_NAME (${#ORIGINAL_BRANCH_NAME} bytes)"
|
| 271 |
+
>&2 echo "[specify] Truncated to: $BRANCH_NAME (${#BRANCH_NAME} bytes)"
|
| 272 |
+
fi
|
| 273 |
+
|
| 274 |
+
if [ "$HAS_GIT" = true ]; then
|
| 275 |
+
git checkout -b "$BRANCH_NAME"
|
| 276 |
+
else
|
| 277 |
+
>&2 echo "[specify] Warning: Git repository not detected; skipped branch creation for $BRANCH_NAME"
|
| 278 |
+
fi
|
| 279 |
+
|
| 280 |
+
FEATURE_DIR="$SPECS_DIR/$BRANCH_NAME"
|
| 281 |
+
mkdir -p "$FEATURE_DIR"
|
| 282 |
+
|
| 283 |
+
TEMPLATE="$REPO_ROOT/.specify/templates/spec-template.md"
|
| 284 |
+
SPEC_FILE="$FEATURE_DIR/spec.md"
|
| 285 |
+
if [ -f "$TEMPLATE" ]; then cp "$TEMPLATE" "$SPEC_FILE"; else touch "$SPEC_FILE"; fi
|
| 286 |
+
|
| 287 |
+
# Set the SPECIFY_FEATURE environment variable for the current session
|
| 288 |
+
export SPECIFY_FEATURE="$BRANCH_NAME"
|
| 289 |
+
|
| 290 |
+
if $JSON_MODE; then
|
| 291 |
+
printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM"
|
| 292 |
+
else
|
| 293 |
+
echo "BRANCH_NAME: $BRANCH_NAME"
|
| 294 |
+
echo "SPEC_FILE: $SPEC_FILE"
|
| 295 |
+
echo "FEATURE_NUM: $FEATURE_NUM"
|
| 296 |
+
echo "SPECIFY_FEATURE environment variable set to: $BRANCH_NAME"
|
| 297 |
+
fi
|
.specify/scripts/bash/setup-plan.sh
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
|
| 3 |
+
set -e
|
| 4 |
+
|
| 5 |
+
# Parse command line arguments
|
| 6 |
+
JSON_MODE=false
|
| 7 |
+
ARGS=()
|
| 8 |
+
|
| 9 |
+
for arg in "$@"; do
|
| 10 |
+
case "$arg" in
|
| 11 |
+
--json)
|
| 12 |
+
JSON_MODE=true
|
| 13 |
+
;;
|
| 14 |
+
--help|-h)
|
| 15 |
+
echo "Usage: $0 [--json]"
|
| 16 |
+
echo " --json Output results in JSON format"
|
| 17 |
+
echo " --help Show this help message"
|
| 18 |
+
exit 0
|
| 19 |
+
;;
|
| 20 |
+
*)
|
| 21 |
+
ARGS+=("$arg")
|
| 22 |
+
;;
|
| 23 |
+
esac
|
| 24 |
+
done
|
| 25 |
+
|
| 26 |
+
# Get script directory and load common functions
|
| 27 |
+
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 28 |
+
source "$SCRIPT_DIR/common.sh"
|
| 29 |
+
|
| 30 |
+
# Get all paths and variables from common functions
|
| 31 |
+
eval $(get_feature_paths)
|
| 32 |
+
|
| 33 |
+
# Check if we're on a proper feature branch (only for git repos)
|
| 34 |
+
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
|
| 35 |
+
|
| 36 |
+
# Ensure the feature directory exists
|
| 37 |
+
mkdir -p "$FEATURE_DIR"
|
| 38 |
+
|
| 39 |
+
# Copy plan template if it exists
|
| 40 |
+
TEMPLATE="$REPO_ROOT/.specify/templates/plan-template.md"
|
| 41 |
+
if [[ -f "$TEMPLATE" ]]; then
|
| 42 |
+
cp "$TEMPLATE" "$IMPL_PLAN"
|
| 43 |
+
echo "Copied plan template to $IMPL_PLAN"
|
| 44 |
+
else
|
| 45 |
+
echo "Warning: Plan template not found at $TEMPLATE"
|
| 46 |
+
# Create a basic plan file if template doesn't exist
|
| 47 |
+
touch "$IMPL_PLAN"
|
| 48 |
+
fi
|
| 49 |
+
|
| 50 |
+
# Output results
|
| 51 |
+
if $JSON_MODE; then
|
| 52 |
+
printf '{"FEATURE_SPEC":"%s","IMPL_PLAN":"%s","SPECS_DIR":"%s","BRANCH":"%s","HAS_GIT":"%s"}\n' \
|
| 53 |
+
"$FEATURE_SPEC" "$IMPL_PLAN" "$FEATURE_DIR" "$CURRENT_BRANCH" "$HAS_GIT"
|
| 54 |
+
else
|
| 55 |
+
echo "FEATURE_SPEC: $FEATURE_SPEC"
|
| 56 |
+
echo "IMPL_PLAN: $IMPL_PLAN"
|
| 57 |
+
echo "SPECS_DIR: $FEATURE_DIR"
|
| 58 |
+
echo "BRANCH: $CURRENT_BRANCH"
|
| 59 |
+
echo "HAS_GIT: $HAS_GIT"
|
| 60 |
+
fi
|
| 61 |
+
|
.specify/scripts/bash/update-agent-context.sh
ADDED
|
@@ -0,0 +1,810 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
|
| 3 |
+
# Update agent context files with information from plan.md
|
| 4 |
+
#
|
| 5 |
+
# This script maintains AI agent context files by parsing feature specifications
|
| 6 |
+
# and updating agent-specific configuration files with project information.
|
| 7 |
+
#
|
| 8 |
+
# MAIN FUNCTIONS:
|
| 9 |
+
# 1. Environment Validation
|
| 10 |
+
# - Verifies git repository structure and branch information
|
| 11 |
+
# - Checks for required plan.md files and templates
|
| 12 |
+
# - Validates file permissions and accessibility
|
| 13 |
+
#
|
| 14 |
+
# 2. Plan Data Extraction
|
| 15 |
+
# - Parses plan.md files to extract project metadata
|
| 16 |
+
# - Identifies language/version, frameworks, databases, and project types
|
| 17 |
+
# - Handles missing or incomplete specification data gracefully
|
| 18 |
+
#
|
| 19 |
+
# 3. Agent File Management
|
| 20 |
+
# - Creates new agent context files from templates when needed
|
| 21 |
+
# - Updates existing agent files with new project information
|
| 22 |
+
# - Preserves manual additions and custom configurations
|
| 23 |
+
# - Supports multiple AI agent formats and directory structures
|
| 24 |
+
#
|
| 25 |
+
# 4. Content Generation
|
| 26 |
+
# - Generates language-specific build/test commands
|
| 27 |
+
# - Creates appropriate project directory structures
|
| 28 |
+
# - Updates technology stacks and recent changes sections
|
| 29 |
+
# - Maintains consistent formatting and timestamps
|
| 30 |
+
#
|
| 31 |
+
# 5. Multi-Agent Support
|
| 32 |
+
# - Handles agent-specific file paths and naming conventions
|
| 33 |
+
# - Supports: Claude, Gemini, Copilot, Cursor, Qwen, opencode, Codex, Windsurf, Kilo Code, Auggie CLI, Roo Code, CodeBuddy CLI, Qoder CLI, Amp, SHAI, Amazon Q Developer CLI, or Antigravity
|
| 34 |
+
# - Can update single agents or all existing agent files
|
| 35 |
+
# - Creates default Claude file if no agent files exist
|
| 36 |
+
#
|
| 37 |
+
# Usage: ./update-agent-context.sh [agent_type]
|
| 38 |
+
# Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli
|
| 39 |
+
# Leave empty to update all existing agent files
|
| 40 |
+
|
| 41 |
+
set -e
|
| 42 |
+
|
| 43 |
+
# Enable strict error handling
|
| 44 |
+
set -u
|
| 45 |
+
set -o pipefail
|
| 46 |
+
|
| 47 |
+
#==============================================================================
|
| 48 |
+
# Configuration and Global Variables
|
| 49 |
+
#==============================================================================
|
| 50 |
+
|
| 51 |
+
# Get script directory and load common functions
|
| 52 |
+
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 53 |
+
source "$SCRIPT_DIR/common.sh"
|
| 54 |
+
|
| 55 |
+
# Get all paths and variables from common functions
|
| 56 |
+
eval $(get_feature_paths)
|
| 57 |
+
|
| 58 |
+
NEW_PLAN="$IMPL_PLAN" # Alias for compatibility with existing code
|
| 59 |
+
AGENT_TYPE="${1:-}"
|
| 60 |
+
|
| 61 |
+
# Agent-specific file paths
|
| 62 |
+
CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"
|
| 63 |
+
GEMINI_FILE="$REPO_ROOT/GEMINI.md"
|
| 64 |
+
COPILOT_FILE="$REPO_ROOT/.github/agents/copilot-instructions.md"
|
| 65 |
+
CURSOR_FILE="$REPO_ROOT/.cursor/rules/specify-rules.mdc"
|
| 66 |
+
QWEN_FILE="$REPO_ROOT/QWEN.md"
|
| 67 |
+
AGENTS_FILE="$REPO_ROOT/AGENTS.md"
|
| 68 |
+
WINDSURF_FILE="$REPO_ROOT/.windsurf/rules/specify-rules.md"
|
| 69 |
+
KILOCODE_FILE="$REPO_ROOT/.kilocode/rules/specify-rules.md"
|
| 70 |
+
AUGGIE_FILE="$REPO_ROOT/.augment/rules/specify-rules.md"
|
| 71 |
+
ROO_FILE="$REPO_ROOT/.roo/rules/specify-rules.md"
|
| 72 |
+
CODEBUDDY_FILE="$REPO_ROOT/CODEBUDDY.md"
|
| 73 |
+
QODER_FILE="$REPO_ROOT/QODER.md"
|
| 74 |
+
AMP_FILE="$REPO_ROOT/AGENTS.md"
|
| 75 |
+
SHAI_FILE="$REPO_ROOT/SHAI.md"
|
| 76 |
+
Q_FILE="$REPO_ROOT/AGENTS.md"
|
| 77 |
+
AGY_FILE="$REPO_ROOT/.agent/rules/specify-rules.md"
|
| 78 |
+
BOB_FILE="$REPO_ROOT/AGENTS.md"
|
| 79 |
+
|
| 80 |
+
# Template file
|
| 81 |
+
TEMPLATE_FILE="$REPO_ROOT/.specify/templates/agent-file-template.md"
|
| 82 |
+
|
| 83 |
+
# Global variables for parsed plan data
|
| 84 |
+
NEW_LANG=""
|
| 85 |
+
NEW_FRAMEWORK=""
|
| 86 |
+
NEW_DB=""
|
| 87 |
+
NEW_PROJECT_TYPE=""
|
| 88 |
+
|
| 89 |
+
#==============================================================================
|
| 90 |
+
# Utility Functions
|
| 91 |
+
#==============================================================================
|
| 92 |
+
|
| 93 |
+
log_info() {
|
| 94 |
+
echo "INFO: $1"
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
log_success() {
|
| 98 |
+
echo "✓ $1"
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
log_error() {
|
| 102 |
+
echo "ERROR: $1" >&2
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
log_warning() {
|
| 106 |
+
echo "WARNING: $1" >&2
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
# Cleanup function for temporary files
|
| 110 |
+
cleanup() {
|
| 111 |
+
local exit_code=$?
|
| 112 |
+
rm -f /tmp/agent_update_*_$$
|
| 113 |
+
rm -f /tmp/manual_additions_$$
|
| 114 |
+
exit $exit_code
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
# Set up cleanup trap
|
| 118 |
+
trap cleanup EXIT INT TERM
|
| 119 |
+
|
| 120 |
+
#==============================================================================
|
| 121 |
+
# Validation Functions
|
| 122 |
+
#==============================================================================
|
| 123 |
+
|
| 124 |
+
validate_environment() {
|
| 125 |
+
# Check if we have a current branch/feature (git or non-git)
|
| 126 |
+
if [[ -z "$CURRENT_BRANCH" ]]; then
|
| 127 |
+
log_error "Unable to determine current feature"
|
| 128 |
+
if [[ "$HAS_GIT" == "true" ]]; then
|
| 129 |
+
log_info "Make sure you're on a feature branch"
|
| 130 |
+
else
|
| 131 |
+
log_info "Set SPECIFY_FEATURE environment variable or create a feature first"
|
| 132 |
+
fi
|
| 133 |
+
exit 1
|
| 134 |
+
fi
|
| 135 |
+
|
| 136 |
+
# Check if plan.md exists
|
| 137 |
+
if [[ ! -f "$NEW_PLAN" ]]; then
|
| 138 |
+
log_error "No plan.md found at $NEW_PLAN"
|
| 139 |
+
log_info "Make sure you're working on a feature with a corresponding spec directory"
|
| 140 |
+
if [[ "$HAS_GIT" != "true" ]]; then
|
| 141 |
+
log_info "Use: export SPECIFY_FEATURE=your-feature-name or create a new feature first"
|
| 142 |
+
fi
|
| 143 |
+
exit 1
|
| 144 |
+
fi
|
| 145 |
+
|
| 146 |
+
# Check if template exists (needed for new files)
|
| 147 |
+
if [[ ! -f "$TEMPLATE_FILE" ]]; then
|
| 148 |
+
log_warning "Template file not found at $TEMPLATE_FILE"
|
| 149 |
+
log_warning "Creating new agent files will fail"
|
| 150 |
+
fi
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
#==============================================================================
|
| 154 |
+
# Plan Parsing Functions
|
| 155 |
+
#==============================================================================
|
| 156 |
+
|
| 157 |
+
extract_plan_field() {
|
| 158 |
+
local field_pattern="$1"
|
| 159 |
+
local plan_file="$2"
|
| 160 |
+
|
| 161 |
+
grep "^\*\*${field_pattern}\*\*: " "$plan_file" 2>/dev/null | \
|
| 162 |
+
head -1 | \
|
| 163 |
+
sed "s|^\*\*${field_pattern}\*\*: ||" | \
|
| 164 |
+
sed 's/^[ \t]*//;s/[ \t]*$//' | \
|
| 165 |
+
grep -v "NEEDS CLARIFICATION" | \
|
| 166 |
+
grep -v "^N/A$" || echo ""
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
parse_plan_data() {
|
| 170 |
+
local plan_file="$1"
|
| 171 |
+
|
| 172 |
+
if [[ ! -f "$plan_file" ]]; then
|
| 173 |
+
log_error "Plan file not found: $plan_file"
|
| 174 |
+
return 1
|
| 175 |
+
fi
|
| 176 |
+
|
| 177 |
+
if [[ ! -r "$plan_file" ]]; then
|
| 178 |
+
log_error "Plan file is not readable: $plan_file"
|
| 179 |
+
return 1
|
| 180 |
+
fi
|
| 181 |
+
|
| 182 |
+
log_info "Parsing plan data from $plan_file"
|
| 183 |
+
|
| 184 |
+
NEW_LANG=$(extract_plan_field "Language/Version" "$plan_file")
|
| 185 |
+
NEW_FRAMEWORK=$(extract_plan_field "Primary Dependencies" "$plan_file")
|
| 186 |
+
NEW_DB=$(extract_plan_field "Storage" "$plan_file")
|
| 187 |
+
NEW_PROJECT_TYPE=$(extract_plan_field "Project Type" "$plan_file")
|
| 188 |
+
|
| 189 |
+
# Log what we found
|
| 190 |
+
if [[ -n "$NEW_LANG" ]]; then
|
| 191 |
+
log_info "Found language: $NEW_LANG"
|
| 192 |
+
else
|
| 193 |
+
log_warning "No language information found in plan"
|
| 194 |
+
fi
|
| 195 |
+
|
| 196 |
+
if [[ -n "$NEW_FRAMEWORK" ]]; then
|
| 197 |
+
log_info "Found framework: $NEW_FRAMEWORK"
|
| 198 |
+
fi
|
| 199 |
+
|
| 200 |
+
if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then
|
| 201 |
+
log_info "Found database: $NEW_DB"
|
| 202 |
+
fi
|
| 203 |
+
|
| 204 |
+
if [[ -n "$NEW_PROJECT_TYPE" ]]; then
|
| 205 |
+
log_info "Found project type: $NEW_PROJECT_TYPE"
|
| 206 |
+
fi
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
format_technology_stack() {
|
| 210 |
+
local lang="$1"
|
| 211 |
+
local framework="$2"
|
| 212 |
+
local parts=()
|
| 213 |
+
|
| 214 |
+
# Add non-empty parts
|
| 215 |
+
[[ -n "$lang" && "$lang" != "NEEDS CLARIFICATION" ]] && parts+=("$lang")
|
| 216 |
+
[[ -n "$framework" && "$framework" != "NEEDS CLARIFICATION" && "$framework" != "N/A" ]] && parts+=("$framework")
|
| 217 |
+
|
| 218 |
+
# Join with proper formatting
|
| 219 |
+
if [[ ${#parts[@]} -eq 0 ]]; then
|
| 220 |
+
echo ""
|
| 221 |
+
elif [[ ${#parts[@]} -eq 1 ]]; then
|
| 222 |
+
echo "${parts[0]}"
|
| 223 |
+
else
|
| 224 |
+
# Join multiple parts with " + "
|
| 225 |
+
local result="${parts[0]}"
|
| 226 |
+
for ((i=1; i<${#parts[@]}; i++)); do
|
| 227 |
+
result="$result + ${parts[i]}"
|
| 228 |
+
done
|
| 229 |
+
echo "$result"
|
| 230 |
+
fi
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
#==============================================================================
|
| 234 |
+
# Template and Content Generation Functions
|
| 235 |
+
#==============================================================================
|
| 236 |
+
|
| 237 |
+
get_project_structure() {
|
| 238 |
+
local project_type="$1"
|
| 239 |
+
|
| 240 |
+
if [[ "$project_type" == *"web"* ]]; then
|
| 241 |
+
echo "backend/\\nfrontend/\\ntests/"
|
| 242 |
+
else
|
| 243 |
+
echo "src/\\ntests/"
|
| 244 |
+
fi
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
get_commands_for_language() {
|
| 248 |
+
local lang="$1"
|
| 249 |
+
|
| 250 |
+
case "$lang" in
|
| 251 |
+
*"Python"*)
|
| 252 |
+
echo "cd src && pytest && ruff check ."
|
| 253 |
+
;;
|
| 254 |
+
*"Rust"*)
|
| 255 |
+
echo "cargo test && cargo clippy"
|
| 256 |
+
;;
|
| 257 |
+
*"JavaScript"*|*"TypeScript"*)
|
| 258 |
+
echo "npm test \\&\\& npm run lint"
|
| 259 |
+
;;
|
| 260 |
+
*)
|
| 261 |
+
echo "# Add commands for $lang"
|
| 262 |
+
;;
|
| 263 |
+
esac
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
get_language_conventions() {
|
| 267 |
+
local lang="$1"
|
| 268 |
+
echo "$lang: Follow standard conventions"
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
create_new_agent_file() {
|
| 272 |
+
local target_file="$1"
|
| 273 |
+
local temp_file="$2"
|
| 274 |
+
local project_name="$3"
|
| 275 |
+
local current_date="$4"
|
| 276 |
+
|
| 277 |
+
if [[ ! -f "$TEMPLATE_FILE" ]]; then
|
| 278 |
+
log_error "Template not found at $TEMPLATE_FILE"
|
| 279 |
+
return 1
|
| 280 |
+
fi
|
| 281 |
+
|
| 282 |
+
if [[ ! -r "$TEMPLATE_FILE" ]]; then
|
| 283 |
+
log_error "Template file is not readable: $TEMPLATE_FILE"
|
| 284 |
+
return 1
|
| 285 |
+
fi
|
| 286 |
+
|
| 287 |
+
log_info "Creating new agent context file from template..."
|
| 288 |
+
|
| 289 |
+
if ! cp "$TEMPLATE_FILE" "$temp_file"; then
|
| 290 |
+
log_error "Failed to copy template file"
|
| 291 |
+
return 1
|
| 292 |
+
fi
|
| 293 |
+
|
| 294 |
+
# Replace template placeholders
|
| 295 |
+
local project_structure
|
| 296 |
+
project_structure=$(get_project_structure "$NEW_PROJECT_TYPE")
|
| 297 |
+
|
| 298 |
+
local commands
|
| 299 |
+
commands=$(get_commands_for_language "$NEW_LANG")
|
| 300 |
+
|
| 301 |
+
local language_conventions
|
| 302 |
+
language_conventions=$(get_language_conventions "$NEW_LANG")
|
| 303 |
+
|
| 304 |
+
# Perform substitutions with error checking using safer approach
|
| 305 |
+
# Escape special characters for sed by using a different delimiter or escaping
|
| 306 |
+
local escaped_lang=$(printf '%s\n' "$NEW_LANG" | sed 's/[\[\.*^$()+{}|]/\\&/g')
|
| 307 |
+
local escaped_framework=$(printf '%s\n' "$NEW_FRAMEWORK" | sed 's/[\[\.*^$()+{}|]/\\&/g')
|
| 308 |
+
local escaped_branch=$(printf '%s\n' "$CURRENT_BRANCH" | sed 's/[\[\.*^$()+{}|]/\\&/g')
|
| 309 |
+
|
| 310 |
+
# Build technology stack and recent change strings conditionally
|
| 311 |
+
local tech_stack
|
| 312 |
+
if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then
|
| 313 |
+
tech_stack="- $escaped_lang + $escaped_framework ($escaped_branch)"
|
| 314 |
+
elif [[ -n "$escaped_lang" ]]; then
|
| 315 |
+
tech_stack="- $escaped_lang ($escaped_branch)"
|
| 316 |
+
elif [[ -n "$escaped_framework" ]]; then
|
| 317 |
+
tech_stack="- $escaped_framework ($escaped_branch)"
|
| 318 |
+
else
|
| 319 |
+
tech_stack="- ($escaped_branch)"
|
| 320 |
+
fi
|
| 321 |
+
|
| 322 |
+
local recent_change
|
| 323 |
+
if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then
|
| 324 |
+
recent_change="- $escaped_branch: Added $escaped_lang + $escaped_framework"
|
| 325 |
+
elif [[ -n "$escaped_lang" ]]; then
|
| 326 |
+
recent_change="- $escaped_branch: Added $escaped_lang"
|
| 327 |
+
elif [[ -n "$escaped_framework" ]]; then
|
| 328 |
+
recent_change="- $escaped_branch: Added $escaped_framework"
|
| 329 |
+
else
|
| 330 |
+
recent_change="- $escaped_branch: Added"
|
| 331 |
+
fi
|
| 332 |
+
|
| 333 |
+
local substitutions=(
|
| 334 |
+
"s|\[PROJECT NAME\]|$project_name|"
|
| 335 |
+
"s|\[DATE\]|$current_date|"
|
| 336 |
+
"s|\[EXTRACTED FROM ALL PLAN.MD FILES\]|$tech_stack|"
|
| 337 |
+
"s|\[ACTUAL STRUCTURE FROM PLANS\]|$project_structure|g"
|
| 338 |
+
"s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$commands|"
|
| 339 |
+
"s|\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]|$language_conventions|"
|
| 340 |
+
"s|\[LAST 3 FEATURES AND WHAT THEY ADDED\]|$recent_change|"
|
| 341 |
+
)
|
| 342 |
+
|
| 343 |
+
for substitution in "${substitutions[@]}"; do
|
| 344 |
+
if ! sed -i.bak -e "$substitution" "$temp_file"; then
|
| 345 |
+
log_error "Failed to perform substitution: $substitution"
|
| 346 |
+
rm -f "$temp_file" "$temp_file.bak"
|
| 347 |
+
return 1
|
| 348 |
+
fi
|
| 349 |
+
done
|
| 350 |
+
|
| 351 |
+
# Convert \n sequences to actual newlines
|
| 352 |
+
newline=$(printf '\n')
|
| 353 |
+
sed -i.bak2 "s/\\\\n/${newline}/g" "$temp_file"
|
| 354 |
+
|
| 355 |
+
# Clean up backup files
|
| 356 |
+
rm -f "$temp_file.bak" "$temp_file.bak2"
|
| 357 |
+
|
| 358 |
+
return 0
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
|
| 363 |
+
|
| 364 |
+
update_existing_agent_file() {
|
| 365 |
+
local target_file="$1"
|
| 366 |
+
local current_date="$2"
|
| 367 |
+
|
| 368 |
+
log_info "Updating existing agent context file..."
|
| 369 |
+
|
| 370 |
+
# Use a single temporary file for atomic update
|
| 371 |
+
local temp_file
|
| 372 |
+
temp_file=$(mktemp) || {
|
| 373 |
+
log_error "Failed to create temporary file"
|
| 374 |
+
return 1
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
# Process the file in one pass
|
| 378 |
+
local tech_stack=$(format_technology_stack "$NEW_LANG" "$NEW_FRAMEWORK")
|
| 379 |
+
local new_tech_entries=()
|
| 380 |
+
local new_change_entry=""
|
| 381 |
+
|
| 382 |
+
# Prepare new technology entries
|
| 383 |
+
if [[ -n "$tech_stack" ]] && ! grep -q "$tech_stack" "$target_file"; then
|
| 384 |
+
new_tech_entries+=("- $tech_stack ($CURRENT_BRANCH)")
|
| 385 |
+
fi
|
| 386 |
+
|
| 387 |
+
if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]] && ! grep -q "$NEW_DB" "$target_file"; then
|
| 388 |
+
new_tech_entries+=("- $NEW_DB ($CURRENT_BRANCH)")
|
| 389 |
+
fi
|
| 390 |
+
|
| 391 |
+
# Prepare new change entry
|
| 392 |
+
if [[ -n "$tech_stack" ]]; then
|
| 393 |
+
new_change_entry="- $CURRENT_BRANCH: Added $tech_stack"
|
| 394 |
+
elif [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]]; then
|
| 395 |
+
new_change_entry="- $CURRENT_BRANCH: Added $NEW_DB"
|
| 396 |
+
fi
|
| 397 |
+
|
| 398 |
+
# Check if sections exist in the file
|
| 399 |
+
local has_active_technologies=0
|
| 400 |
+
local has_recent_changes=0
|
| 401 |
+
|
| 402 |
+
if grep -q "^## Active Technologies" "$target_file" 2>/dev/null; then
|
| 403 |
+
has_active_technologies=1
|
| 404 |
+
fi
|
| 405 |
+
|
| 406 |
+
if grep -q "^## Recent Changes" "$target_file" 2>/dev/null; then
|
| 407 |
+
has_recent_changes=1
|
| 408 |
+
fi
|
| 409 |
+
|
| 410 |
+
# Process file line by line
|
| 411 |
+
local in_tech_section=false
|
| 412 |
+
local in_changes_section=false
|
| 413 |
+
local tech_entries_added=false
|
| 414 |
+
local changes_entries_added=false
|
| 415 |
+
local existing_changes_count=0
|
| 416 |
+
local file_ended=false
|
| 417 |
+
|
| 418 |
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
| 419 |
+
# Handle Active Technologies section
|
| 420 |
+
if [[ "$line" == "## Active Technologies" ]]; then
|
| 421 |
+
echo "$line" >> "$temp_file"
|
| 422 |
+
in_tech_section=true
|
| 423 |
+
continue
|
| 424 |
+
elif [[ $in_tech_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then
|
| 425 |
+
# Add new tech entries before closing the section
|
| 426 |
+
if [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
|
| 427 |
+
printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
|
| 428 |
+
tech_entries_added=true
|
| 429 |
+
fi
|
| 430 |
+
echo "$line" >> "$temp_file"
|
| 431 |
+
in_tech_section=false
|
| 432 |
+
continue
|
| 433 |
+
elif [[ $in_tech_section == true ]] && [[ -z "$line" ]]; then
|
| 434 |
+
# Add new tech entries before empty line in tech section
|
| 435 |
+
if [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
|
| 436 |
+
printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
|
| 437 |
+
tech_entries_added=true
|
| 438 |
+
fi
|
| 439 |
+
echo "$line" >> "$temp_file"
|
| 440 |
+
continue
|
| 441 |
+
fi
|
| 442 |
+
|
| 443 |
+
# Handle Recent Changes section
|
| 444 |
+
if [[ "$line" == "## Recent Changes" ]]; then
|
| 445 |
+
echo "$line" >> "$temp_file"
|
| 446 |
+
# Add new change entry right after the heading
|
| 447 |
+
if [[ -n "$new_change_entry" ]]; then
|
| 448 |
+
echo "$new_change_entry" >> "$temp_file"
|
| 449 |
+
fi
|
| 450 |
+
in_changes_section=true
|
| 451 |
+
changes_entries_added=true
|
| 452 |
+
continue
|
| 453 |
+
elif [[ $in_changes_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then
|
| 454 |
+
echo "$line" >> "$temp_file"
|
| 455 |
+
in_changes_section=false
|
| 456 |
+
continue
|
| 457 |
+
elif [[ $in_changes_section == true ]] && [[ "$line" == "- "* ]]; then
|
| 458 |
+
# Keep only first 2 existing changes
|
| 459 |
+
if [[ $existing_changes_count -lt 2 ]]; then
|
| 460 |
+
echo "$line" >> "$temp_file"
|
| 461 |
+
((existing_changes_count++))
|
| 462 |
+
fi
|
| 463 |
+
continue
|
| 464 |
+
fi
|
| 465 |
+
|
| 466 |
+
# Update timestamp
|
| 467 |
+
if [[ "$line" =~ \*\*Last\ updated\*\*:.*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] ]]; then
|
| 468 |
+
echo "$line" | sed "s/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/$current_date/" >> "$temp_file"
|
| 469 |
+
else
|
| 470 |
+
echo "$line" >> "$temp_file"
|
| 471 |
+
fi
|
| 472 |
+
done < "$target_file"
|
| 473 |
+
|
| 474 |
+
# Post-loop check: if we're still in the Active Technologies section and haven't added new entries
|
| 475 |
+
if [[ $in_tech_section == true ]] && [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
|
| 476 |
+
printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
|
| 477 |
+
tech_entries_added=true
|
| 478 |
+
fi
|
| 479 |
+
|
| 480 |
+
# If sections don't exist, add them at the end of the file
|
| 481 |
+
if [[ $has_active_technologies -eq 0 ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
|
| 482 |
+
echo "" >> "$temp_file"
|
| 483 |
+
echo "## Active Technologies" >> "$temp_file"
|
| 484 |
+
printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
|
| 485 |
+
tech_entries_added=true
|
| 486 |
+
fi
|
| 487 |
+
|
| 488 |
+
if [[ $has_recent_changes -eq 0 ]] && [[ -n "$new_change_entry" ]]; then
|
| 489 |
+
echo "" >> "$temp_file"
|
| 490 |
+
echo "## Recent Changes" >> "$temp_file"
|
| 491 |
+
echo "$new_change_entry" >> "$temp_file"
|
| 492 |
+
changes_entries_added=true
|
| 493 |
+
fi
|
| 494 |
+
|
| 495 |
+
# Move temp file to target atomically
|
| 496 |
+
if ! mv "$temp_file" "$target_file"; then
|
| 497 |
+
log_error "Failed to update target file"
|
| 498 |
+
rm -f "$temp_file"
|
| 499 |
+
return 1
|
| 500 |
+
fi
|
| 501 |
+
|
| 502 |
+
return 0
|
| 503 |
+
}
|
| 504 |
+
#==============================================================================
|
| 505 |
+
# Main Agent File Update Function
|
| 506 |
+
#==============================================================================
|
| 507 |
+
|
| 508 |
+
update_agent_file() {
|
| 509 |
+
local target_file="$1"
|
| 510 |
+
local agent_name="$2"
|
| 511 |
+
|
| 512 |
+
if [[ -z "$target_file" ]] || [[ -z "$agent_name" ]]; then
|
| 513 |
+
log_error "update_agent_file requires target_file and agent_name parameters"
|
| 514 |
+
return 1
|
| 515 |
+
fi
|
| 516 |
+
|
| 517 |
+
log_info "Updating $agent_name context file: $target_file"
|
| 518 |
+
|
| 519 |
+
local project_name
|
| 520 |
+
project_name=$(basename "$REPO_ROOT")
|
| 521 |
+
local current_date
|
| 522 |
+
current_date=$(date +%Y-%m-%d)
|
| 523 |
+
|
| 524 |
+
# Create directory if it doesn't exist
|
| 525 |
+
local target_dir
|
| 526 |
+
target_dir=$(dirname "$target_file")
|
| 527 |
+
if [[ ! -d "$target_dir" ]]; then
|
| 528 |
+
if ! mkdir -p "$target_dir"; then
|
| 529 |
+
log_error "Failed to create directory: $target_dir"
|
| 530 |
+
return 1
|
| 531 |
+
fi
|
| 532 |
+
fi
|
| 533 |
+
|
| 534 |
+
if [[ ! -f "$target_file" ]]; then
|
| 535 |
+
# Create new file from template
|
| 536 |
+
local temp_file
|
| 537 |
+
temp_file=$(mktemp) || {
|
| 538 |
+
log_error "Failed to create temporary file"
|
| 539 |
+
return 1
|
| 540 |
+
}
|
| 541 |
+
|
| 542 |
+
if create_new_agent_file "$target_file" "$temp_file" "$project_name" "$current_date"; then
|
| 543 |
+
if mv "$temp_file" "$target_file"; then
|
| 544 |
+
log_success "Created new $agent_name context file"
|
| 545 |
+
else
|
| 546 |
+
log_error "Failed to move temporary file to $target_file"
|
| 547 |
+
rm -f "$temp_file"
|
| 548 |
+
return 1
|
| 549 |
+
fi
|
| 550 |
+
else
|
| 551 |
+
log_error "Failed to create new agent file"
|
| 552 |
+
rm -f "$temp_file"
|
| 553 |
+
return 1
|
| 554 |
+
fi
|
| 555 |
+
else
|
| 556 |
+
# Update existing file
|
| 557 |
+
if [[ ! -r "$target_file" ]]; then
|
| 558 |
+
log_error "Cannot read existing file: $target_file"
|
| 559 |
+
return 1
|
| 560 |
+
fi
|
| 561 |
+
|
| 562 |
+
if [[ ! -w "$target_file" ]]; then
|
| 563 |
+
log_error "Cannot write to existing file: $target_file"
|
| 564 |
+
return 1
|
| 565 |
+
fi
|
| 566 |
+
|
| 567 |
+
if update_existing_agent_file "$target_file" "$current_date"; then
|
| 568 |
+
log_success "Updated existing $agent_name context file"
|
| 569 |
+
else
|
| 570 |
+
log_error "Failed to update existing agent file"
|
| 571 |
+
return 1
|
| 572 |
+
fi
|
| 573 |
+
fi
|
| 574 |
+
|
| 575 |
+
return 0
|
| 576 |
+
}
|
| 577 |
+
|
| 578 |
+
#==============================================================================
|
| 579 |
+
# Agent Selection and Processing
|
| 580 |
+
#==============================================================================
|
| 581 |
+
|
| 582 |
+
update_specific_agent() {
|
| 583 |
+
local agent_type="$1"
|
| 584 |
+
|
| 585 |
+
case "$agent_type" in
|
| 586 |
+
claude)
|
| 587 |
+
update_agent_file "$CLAUDE_FILE" "Claude Code"
|
| 588 |
+
;;
|
| 589 |
+
gemini)
|
| 590 |
+
update_agent_file "$GEMINI_FILE" "Gemini CLI"
|
| 591 |
+
;;
|
| 592 |
+
copilot)
|
| 593 |
+
update_agent_file "$COPILOT_FILE" "GitHub Copilot"
|
| 594 |
+
;;
|
| 595 |
+
cursor-agent)
|
| 596 |
+
update_agent_file "$CURSOR_FILE" "Cursor IDE"
|
| 597 |
+
;;
|
| 598 |
+
qwen)
|
| 599 |
+
update_agent_file "$QWEN_FILE" "Qwen Code"
|
| 600 |
+
;;
|
| 601 |
+
opencode)
|
| 602 |
+
update_agent_file "$AGENTS_FILE" "opencode"
|
| 603 |
+
;;
|
| 604 |
+
codex)
|
| 605 |
+
update_agent_file "$AGENTS_FILE" "Codex CLI"
|
| 606 |
+
;;
|
| 607 |
+
windsurf)
|
| 608 |
+
update_agent_file "$WINDSURF_FILE" "Windsurf"
|
| 609 |
+
;;
|
| 610 |
+
kilocode)
|
| 611 |
+
update_agent_file "$KILOCODE_FILE" "Kilo Code"
|
| 612 |
+
;;
|
| 613 |
+
auggie)
|
| 614 |
+
update_agent_file "$AUGGIE_FILE" "Auggie CLI"
|
| 615 |
+
;;
|
| 616 |
+
roo)
|
| 617 |
+
update_agent_file "$ROO_FILE" "Roo Code"
|
| 618 |
+
;;
|
| 619 |
+
codebuddy)
|
| 620 |
+
update_agent_file "$CODEBUDDY_FILE" "CodeBuddy CLI"
|
| 621 |
+
;;
|
| 622 |
+
qodercli)
|
| 623 |
+
update_agent_file "$QODER_FILE" "Qoder CLI"
|
| 624 |
+
;;
|
| 625 |
+
amp)
|
| 626 |
+
update_agent_file "$AMP_FILE" "Amp"
|
| 627 |
+
;;
|
| 628 |
+
shai)
|
| 629 |
+
update_agent_file "$SHAI_FILE" "SHAI"
|
| 630 |
+
;;
|
| 631 |
+
q)
|
| 632 |
+
update_agent_file "$Q_FILE" "Amazon Q Developer CLI"
|
| 633 |
+
;;
|
| 634 |
+
agy)
|
| 635 |
+
update_agent_file "$AGY_FILE" "Antigravity"
|
| 636 |
+
;;
|
| 637 |
+
bob)
|
| 638 |
+
update_agent_file "$BOB_FILE" "IBM Bob"
|
| 639 |
+
;;
|
| 640 |
+
generic)
|
| 641 |
+
log_info "Generic agent: no predefined context file. Use the agent-specific update script for your agent."
|
| 642 |
+
;;
|
| 643 |
+
*)
|
| 644 |
+
log_error "Unknown agent type '$agent_type'"
|
| 645 |
+
log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli|generic"
|
| 646 |
+
exit 1
|
| 647 |
+
;;
|
| 648 |
+
esac
|
| 649 |
+
}
|
| 650 |
+
|
| 651 |
+
update_all_existing_agents() {
|
| 652 |
+
local found_agent=false
|
| 653 |
+
|
| 654 |
+
# Check each possible agent file and update if it exists
|
| 655 |
+
if [[ -f "$CLAUDE_FILE" ]]; then
|
| 656 |
+
update_agent_file "$CLAUDE_FILE" "Claude Code"
|
| 657 |
+
found_agent=true
|
| 658 |
+
fi
|
| 659 |
+
|
| 660 |
+
if [[ -f "$GEMINI_FILE" ]]; then
|
| 661 |
+
update_agent_file "$GEMINI_FILE" "Gemini CLI"
|
| 662 |
+
found_agent=true
|
| 663 |
+
fi
|
| 664 |
+
|
| 665 |
+
if [[ -f "$COPILOT_FILE" ]]; then
|
| 666 |
+
update_agent_file "$COPILOT_FILE" "GitHub Copilot"
|
| 667 |
+
found_agent=true
|
| 668 |
+
fi
|
| 669 |
+
|
| 670 |
+
if [[ -f "$CURSOR_FILE" ]]; then
|
| 671 |
+
update_agent_file "$CURSOR_FILE" "Cursor IDE"
|
| 672 |
+
found_agent=true
|
| 673 |
+
fi
|
| 674 |
+
|
| 675 |
+
if [[ -f "$QWEN_FILE" ]]; then
|
| 676 |
+
update_agent_file "$QWEN_FILE" "Qwen Code"
|
| 677 |
+
found_agent=true
|
| 678 |
+
fi
|
| 679 |
+
|
| 680 |
+
if [[ -f "$AGENTS_FILE" ]]; then
|
| 681 |
+
update_agent_file "$AGENTS_FILE" "Codex/opencode"
|
| 682 |
+
found_agent=true
|
| 683 |
+
fi
|
| 684 |
+
|
| 685 |
+
if [[ -f "$WINDSURF_FILE" ]]; then
|
| 686 |
+
update_agent_file "$WINDSURF_FILE" "Windsurf"
|
| 687 |
+
found_agent=true
|
| 688 |
+
fi
|
| 689 |
+
|
| 690 |
+
if [[ -f "$KILOCODE_FILE" ]]; then
|
| 691 |
+
update_agent_file "$KILOCODE_FILE" "Kilo Code"
|
| 692 |
+
found_agent=true
|
| 693 |
+
fi
|
| 694 |
+
|
| 695 |
+
if [[ -f "$AUGGIE_FILE" ]]; then
|
| 696 |
+
update_agent_file "$AUGGIE_FILE" "Auggie CLI"
|
| 697 |
+
found_agent=true
|
| 698 |
+
fi
|
| 699 |
+
|
| 700 |
+
if [[ -f "$ROO_FILE" ]]; then
|
| 701 |
+
update_agent_file "$ROO_FILE" "Roo Code"
|
| 702 |
+
found_agent=true
|
| 703 |
+
fi
|
| 704 |
+
|
| 705 |
+
if [[ -f "$CODEBUDDY_FILE" ]]; then
|
| 706 |
+
update_agent_file "$CODEBUDDY_FILE" "CodeBuddy CLI"
|
| 707 |
+
found_agent=true
|
| 708 |
+
fi
|
| 709 |
+
|
| 710 |
+
if [[ -f "$SHAI_FILE" ]]; then
|
| 711 |
+
update_agent_file "$SHAI_FILE" "SHAI"
|
| 712 |
+
found_agent=true
|
| 713 |
+
fi
|
| 714 |
+
|
| 715 |
+
if [[ -f "$QODER_FILE" ]]; then
|
| 716 |
+
update_agent_file "$QODER_FILE" "Qoder CLI"
|
| 717 |
+
found_agent=true
|
| 718 |
+
fi
|
| 719 |
+
|
| 720 |
+
if [[ -f "$Q_FILE" ]]; then
|
| 721 |
+
update_agent_file "$Q_FILE" "Amazon Q Developer CLI"
|
| 722 |
+
found_agent=true
|
| 723 |
+
fi
|
| 724 |
+
|
| 725 |
+
if [[ -f "$AGY_FILE" ]]; then
|
| 726 |
+
update_agent_file "$AGY_FILE" "Antigravity"
|
| 727 |
+
found_agent=true
|
| 728 |
+
fi
|
| 729 |
+
if [[ -f "$BOB_FILE" ]]; then
|
| 730 |
+
update_agent_file "$BOB_FILE" "IBM Bob"
|
| 731 |
+
found_agent=true
|
| 732 |
+
fi
|
| 733 |
+
|
| 734 |
+
# If no agent files exist, create a default Claude file
|
| 735 |
+
if [[ "$found_agent" == false ]]; then
|
| 736 |
+
log_info "No existing agent files found, creating default Claude file..."
|
| 737 |
+
update_agent_file "$CLAUDE_FILE" "Claude Code"
|
| 738 |
+
fi
|
| 739 |
+
}
|
| 740 |
+
print_summary() {
|
| 741 |
+
echo
|
| 742 |
+
log_info "Summary of changes:"
|
| 743 |
+
|
| 744 |
+
if [[ -n "$NEW_LANG" ]]; then
|
| 745 |
+
echo " - Added language: $NEW_LANG"
|
| 746 |
+
fi
|
| 747 |
+
|
| 748 |
+
if [[ -n "$NEW_FRAMEWORK" ]]; then
|
| 749 |
+
echo " - Added framework: $NEW_FRAMEWORK"
|
| 750 |
+
fi
|
| 751 |
+
|
| 752 |
+
if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then
|
| 753 |
+
echo " - Added database: $NEW_DB"
|
| 754 |
+
fi
|
| 755 |
+
|
| 756 |
+
echo
|
| 757 |
+
|
| 758 |
+
log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli]"
|
| 759 |
+
}
|
| 760 |
+
|
| 761 |
+
#==============================================================================
|
| 762 |
+
# Main Execution
|
| 763 |
+
#==============================================================================
|
| 764 |
+
|
| 765 |
+
main() {
|
| 766 |
+
# Validate environment before proceeding
|
| 767 |
+
validate_environment
|
| 768 |
+
|
| 769 |
+
log_info "=== Updating agent context files for feature $CURRENT_BRANCH ==="
|
| 770 |
+
|
| 771 |
+
# Parse the plan file to extract project information
|
| 772 |
+
if ! parse_plan_data "$NEW_PLAN"; then
|
| 773 |
+
log_error "Failed to parse plan data"
|
| 774 |
+
exit 1
|
| 775 |
+
fi
|
| 776 |
+
|
| 777 |
+
# Process based on agent type argument
|
| 778 |
+
local success=true
|
| 779 |
+
|
| 780 |
+
if [[ -z "$AGENT_TYPE" ]]; then
|
| 781 |
+
# No specific agent provided - update all existing agent files
|
| 782 |
+
log_info "No agent specified, updating all existing agent files..."
|
| 783 |
+
if ! update_all_existing_agents; then
|
| 784 |
+
success=false
|
| 785 |
+
fi
|
| 786 |
+
else
|
| 787 |
+
# Specific agent provided - update only that agent
|
| 788 |
+
log_info "Updating specific agent: $AGENT_TYPE"
|
| 789 |
+
if ! update_specific_agent "$AGENT_TYPE"; then
|
| 790 |
+
success=false
|
| 791 |
+
fi
|
| 792 |
+
fi
|
| 793 |
+
|
| 794 |
+
# Print summary
|
| 795 |
+
print_summary
|
| 796 |
+
|
| 797 |
+
if [[ "$success" == true ]]; then
|
| 798 |
+
log_success "Agent context update completed successfully"
|
| 799 |
+
exit 0
|
| 800 |
+
else
|
| 801 |
+
log_error "Agent context update completed with errors"
|
| 802 |
+
exit 1
|
| 803 |
+
fi
|
| 804 |
+
}
|
| 805 |
+
|
| 806 |
+
# Execute main function if script is run directly
|
| 807 |
+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
| 808 |
+
main "$@"
|
| 809 |
+
fi
|
| 810 |
+
|
.specify/templates/agent-file-template.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# [PROJECT NAME] Development Guidelines
|
| 2 |
+
|
| 3 |
+
Auto-generated from all feature plans. Last updated: [DATE]
|
| 4 |
+
|
| 5 |
+
## Active Technologies
|
| 6 |
+
|
| 7 |
+
[EXTRACTED FROM ALL PLAN.MD FILES]
|
| 8 |
+
|
| 9 |
+
## Project Structure
|
| 10 |
+
|
| 11 |
+
```text
|
| 12 |
+
[ACTUAL STRUCTURE FROM PLANS]
|
| 13 |
+
```
|
| 14 |
+
|
| 15 |
+
## Commands
|
| 16 |
+
|
| 17 |
+
[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES]
|
| 18 |
+
|
| 19 |
+
## Code Style
|
| 20 |
+
|
| 21 |
+
[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE]
|
| 22 |
+
|
| 23 |
+
## Recent Changes
|
| 24 |
+
|
| 25 |
+
[LAST 3 FEATURES AND WHAT THEY ADDED]
|
| 26 |
+
|
| 27 |
+
<!-- MANUAL ADDITIONS START -->
|
| 28 |
+
<!-- MANUAL ADDITIONS END -->
|
.specify/templates/checklist-template.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# [CHECKLIST TYPE] Checklist: [FEATURE NAME]
|
| 2 |
+
|
| 3 |
+
**Purpose**: [Brief description of what this checklist covers]
|
| 4 |
+
**Created**: [DATE]
|
| 5 |
+
**Feature**: [Link to spec.md or relevant documentation]
|
| 6 |
+
|
| 7 |
+
**Note**: This checklist is generated by the `/speckit.checklist` command based on feature context and requirements.
|
| 8 |
+
|
| 9 |
+
<!--
|
| 10 |
+
============================================================================
|
| 11 |
+
IMPORTANT: The checklist items below are SAMPLE ITEMS for illustration only.
|
| 12 |
+
|
| 13 |
+
The /speckit.checklist command MUST replace these with actual items based on:
|
| 14 |
+
- User's specific checklist request
|
| 15 |
+
- Feature requirements from spec.md
|
| 16 |
+
- Technical context from plan.md
|
| 17 |
+
- Implementation details from tasks.md
|
| 18 |
+
|
| 19 |
+
DO NOT keep these sample items in the generated checklist file.
|
| 20 |
+
============================================================================
|
| 21 |
+
-->
|
| 22 |
+
|
| 23 |
+
## [Category 1]
|
| 24 |
+
|
| 25 |
+
- [ ] CHK001 First checklist item with clear action
|
| 26 |
+
- [ ] CHK002 Second checklist item
|
| 27 |
+
- [ ] CHK003 Third checklist item
|
| 28 |
+
|
| 29 |
+
## [Category 2]
|
| 30 |
+
|
| 31 |
+
- [ ] CHK004 Another category item
|
| 32 |
+
- [ ] CHK005 Item with specific criteria
|
| 33 |
+
- [ ] CHK006 Final item in this category
|
| 34 |
+
|
| 35 |
+
## Notes
|
| 36 |
+
|
| 37 |
+
- Check items off as completed: `[x]`
|
| 38 |
+
- Add comments or findings inline
|
| 39 |
+
- Link to relevant resources or documentation
|
| 40 |
+
- Items are numbered sequentially for easy reference
|
.specify/templates/constitution-template.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# [PROJECT_NAME] Constitution
|
| 2 |
+
<!-- Example: Spec Constitution, TaskFlow Constitution, etc. -->
|
| 3 |
+
|
| 4 |
+
## Core Principles
|
| 5 |
+
|
| 6 |
+
### [PRINCIPLE_1_NAME]
|
| 7 |
+
<!-- Example: I. Library-First -->
|
| 8 |
+
[PRINCIPLE_1_DESCRIPTION]
|
| 9 |
+
<!-- Example: Every feature starts as a standalone library; Libraries must be self-contained, independently testable, documented; Clear purpose required - no organizational-only libraries -->
|
| 10 |
+
|
| 11 |
+
### [PRINCIPLE_2_NAME]
|
| 12 |
+
<!-- Example: II. CLI Interface -->
|
| 13 |
+
[PRINCIPLE_2_DESCRIPTION]
|
| 14 |
+
<!-- Example: Every library exposes functionality via CLI; Text in/out protocol: stdin/args → stdout, errors → stderr; Support JSON + human-readable formats -->
|
| 15 |
+
|
| 16 |
+
### [PRINCIPLE_3_NAME]
|
| 17 |
+
<!-- Example: III. Test-First (NON-NEGOTIABLE) -->
|
| 18 |
+
[PRINCIPLE_3_DESCRIPTION]
|
| 19 |
+
<!-- Example: TDD mandatory: Tests written → User approved → Tests fail → Then implement; Red-Green-Refactor cycle strictly enforced -->
|
| 20 |
+
|
| 21 |
+
### [PRINCIPLE_4_NAME]
|
| 22 |
+
<!-- Example: IV. Integration Testing -->
|
| 23 |
+
[PRINCIPLE_4_DESCRIPTION]
|
| 24 |
+
<!-- Example: Focus areas requiring integration tests: New library contract tests, Contract changes, Inter-service communication, Shared schemas -->
|
| 25 |
+
|
| 26 |
+
### [PRINCIPLE_5_NAME]
|
| 27 |
+
<!-- Example: V. Observability, VI. Versioning & Breaking Changes, VII. Simplicity -->
|
| 28 |
+
[PRINCIPLE_5_DESCRIPTION]
|
| 29 |
+
<!-- Example: Text I/O ensures debuggability; Structured logging required; Or: MAJOR.MINOR.BUILD format; Or: Start simple, YAGNI principles -->
|
| 30 |
+
|
| 31 |
+
## [SECTION_2_NAME]
|
| 32 |
+
<!-- Example: Additional Constraints, Security Requirements, Performance Standards, etc. -->
|
| 33 |
+
|
| 34 |
+
[SECTION_2_CONTENT]
|
| 35 |
+
<!-- Example: Technology stack requirements, compliance standards, deployment policies, etc. -->
|
| 36 |
+
|
| 37 |
+
## [SECTION_3_NAME]
|
| 38 |
+
<!-- Example: Development Workflow, Review Process, Quality Gates, etc. -->
|
| 39 |
+
|
| 40 |
+
[SECTION_3_CONTENT]
|
| 41 |
+
<!-- Example: Code review requirements, testing gates, deployment approval process, etc. -->
|
| 42 |
+
|
| 43 |
+
## Governance
|
| 44 |
+
<!-- Example: Constitution supersedes all other practices; Amendments require documentation, approval, migration plan -->
|
| 45 |
+
|
| 46 |
+
[GOVERNANCE_RULES]
|
| 47 |
+
<!-- Example: All PRs/reviews must verify compliance; Complexity must be justified; Use [GUIDANCE_FILE] for runtime development guidance -->
|
| 48 |
+
|
| 49 |
+
**Version**: [CONSTITUTION_VERSION] | **Ratified**: [RATIFICATION_DATE] | **Last Amended**: [LAST_AMENDED_DATE]
|
| 50 |
+
<!-- Example: Version: 2.1.1 | Ratified: 2025-06-13 | Last Amended: 2025-07-16 -->
|
.specify/templates/plan-template.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Implementation Plan: [FEATURE]
|
| 2 |
+
|
| 3 |
+
**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
|
| 4 |
+
**Input**: Feature specification from `/specs/[###-feature-name]/spec.md`
|
| 5 |
+
|
| 6 |
+
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/plan-template.md` for the execution workflow.
|
| 7 |
+
|
| 8 |
+
## Summary
|
| 9 |
+
|
| 10 |
+
[Extract from feature spec: primary requirement + technical approach from research]
|
| 11 |
+
|
| 12 |
+
## Technical Context
|
| 13 |
+
|
| 14 |
+
<!--
|
| 15 |
+
ACTION REQUIRED: Replace the content in this section with the technical details
|
| 16 |
+
for the project. The structure here is presented in advisory capacity to guide
|
| 17 |
+
the iteration process.
|
| 18 |
+
-->
|
| 19 |
+
|
| 20 |
+
**Language/Version**: [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION]
|
| 21 |
+
**Primary Dependencies**: [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION]
|
| 22 |
+
**Storage**: [if applicable, e.g., PostgreSQL, CoreData, files or N/A]
|
| 23 |
+
**Testing**: [e.g., pytest, XCTest, cargo test or NEEDS CLARIFICATION]
|
| 24 |
+
**Target Platform**: [e.g., Linux server, iOS 15+, WASM or NEEDS CLARIFICATION]
|
| 25 |
+
**Project Type**: [e.g., library/cli/web-service/mobile-app/compiler/desktop-app or NEEDS CLARIFICATION]
|
| 26 |
+
**Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION]
|
| 27 |
+
**Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION]
|
| 28 |
+
**Scale/Scope**: [domain-specific, e.g., 10k users, 1M LOC, 50 screens or NEEDS CLARIFICATION]
|
| 29 |
+
|
| 30 |
+
## Constitution Check
|
| 31 |
+
|
| 32 |
+
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
| 33 |
+
|
| 34 |
+
[Gates determined based on constitution file]
|
| 35 |
+
|
| 36 |
+
## Project Structure
|
| 37 |
+
|
| 38 |
+
### Documentation (this feature)
|
| 39 |
+
|
| 40 |
+
```text
|
| 41 |
+
specs/[###-feature]/
|
| 42 |
+
├── plan.md # This file (/speckit.plan command output)
|
| 43 |
+
├── research.md # Phase 0 output (/speckit.plan command)
|
| 44 |
+
├── data-model.md # Phase 1 output (/speckit.plan command)
|
| 45 |
+
├── quickstart.md # Phase 1 output (/speckit.plan command)
|
| 46 |
+
├── contracts/ # Phase 1 output (/speckit.plan command)
|
| 47 |
+
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
### Source Code (repository root)
|
| 51 |
+
<!--
|
| 52 |
+
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
|
| 53 |
+
for this feature. Delete unused options and expand the chosen structure with
|
| 54 |
+
real paths (e.g., apps/admin, packages/something). The delivered plan must
|
| 55 |
+
not include Option labels.
|
| 56 |
+
-->
|
| 57 |
+
|
| 58 |
+
```text
|
| 59 |
+
# [REMOVE IF UNUSED] Option 1: Single project (DEFAULT)
|
| 60 |
+
src/
|
| 61 |
+
├── models/
|
| 62 |
+
├── services/
|
| 63 |
+
├── cli/
|
| 64 |
+
└── lib/
|
| 65 |
+
|
| 66 |
+
tests/
|
| 67 |
+
├── contract/
|
| 68 |
+
├── integration/
|
| 69 |
+
└── unit/
|
| 70 |
+
|
| 71 |
+
# [REMOVE IF UNUSED] Option 2: Web application (when "frontend" + "backend" detected)
|
| 72 |
+
backend/
|
| 73 |
+
├── src/
|
| 74 |
+
│ ├── models/
|
| 75 |
+
│ ├── services/
|
| 76 |
+
│ └── api/
|
| 77 |
+
└── tests/
|
| 78 |
+
|
| 79 |
+
frontend/
|
| 80 |
+
├── src/
|
| 81 |
+
│ ├── components/
|
| 82 |
+
│ ├── pages/
|
| 83 |
+
│ └── services/
|
| 84 |
+
└── tests/
|
| 85 |
+
|
| 86 |
+
# [REMOVE IF UNUSED] Option 3: Mobile + API (when "iOS/Android" detected)
|
| 87 |
+
api/
|
| 88 |
+
└── [same as backend above]
|
| 89 |
+
|
| 90 |
+
ios/ or android/
|
| 91 |
+
└── [platform-specific structure: feature modules, UI flows, platform tests]
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
**Structure Decision**: [Document the selected structure and reference the real
|
| 95 |
+
directories captured above]
|
| 96 |
+
|
| 97 |
+
## Complexity Tracking
|
| 98 |
+
|
| 99 |
+
> **Fill ONLY if Constitution Check has violations that must be justified**
|
| 100 |
+
|
| 101 |
+
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
| 102 |
+
|-----------|------------|-------------------------------------|
|
| 103 |
+
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
|
| 104 |
+
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |
|
.specify/templates/spec-template.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Feature Specification: [FEATURE NAME]
|
| 2 |
+
|
| 3 |
+
**Feature Branch**: `[###-feature-name]`
|
| 4 |
+
**Created**: [DATE]
|
| 5 |
+
**Status**: Draft
|
| 6 |
+
**Input**: User description: "$ARGUMENTS"
|
| 7 |
+
|
| 8 |
+
## User Scenarios & Testing *(mandatory)*
|
| 9 |
+
|
| 10 |
+
<!--
|
| 11 |
+
IMPORTANT: User stories should be PRIORITIZED as user journeys ordered by importance.
|
| 12 |
+
Each user story/journey must be INDEPENDENTLY TESTABLE - meaning if you implement just ONE of them,
|
| 13 |
+
you should still have a viable MVP (Minimum Viable Product) that delivers value.
|
| 14 |
+
|
| 15 |
+
Assign priorities (P1, P2, P3, etc.) to each story, where P1 is the most critical.
|
| 16 |
+
Think of each story as a standalone slice of functionality that can be:
|
| 17 |
+
- Developed independently
|
| 18 |
+
- Tested independently
|
| 19 |
+
- Deployed independently
|
| 20 |
+
- Demonstrated to users independently
|
| 21 |
+
-->
|
| 22 |
+
|
| 23 |
+
### User Story 1 - [Brief Title] (Priority: P1)
|
| 24 |
+
|
| 25 |
+
[Describe this user journey in plain language]
|
| 26 |
+
|
| 27 |
+
**Why this priority**: [Explain the value and why it has this priority level]
|
| 28 |
+
|
| 29 |
+
**Independent Test**: [Describe how this can be tested independently - e.g., "Can be fully tested by [specific action] and delivers [specific value]"]
|
| 30 |
+
|
| 31 |
+
**Acceptance Scenarios**:
|
| 32 |
+
|
| 33 |
+
1. **Given** [initial state], **When** [action], **Then** [expected outcome]
|
| 34 |
+
2. **Given** [initial state], **When** [action], **Then** [expected outcome]
|
| 35 |
+
|
| 36 |
+
---
|
| 37 |
+
|
| 38 |
+
### User Story 2 - [Brief Title] (Priority: P2)
|
| 39 |
+
|
| 40 |
+
[Describe this user journey in plain language]
|
| 41 |
+
|
| 42 |
+
**Why this priority**: [Explain the value and why it has this priority level]
|
| 43 |
+
|
| 44 |
+
**Independent Test**: [Describe how this can be tested independently]
|
| 45 |
+
|
| 46 |
+
**Acceptance Scenarios**:
|
| 47 |
+
|
| 48 |
+
1. **Given** [initial state], **When** [action], **Then** [expected outcome]
|
| 49 |
+
|
| 50 |
+
---
|
| 51 |
+
|
| 52 |
+
### User Story 3 - [Brief Title] (Priority: P3)
|
| 53 |
+
|
| 54 |
+
[Describe this user journey in plain language]
|
| 55 |
+
|
| 56 |
+
**Why this priority**: [Explain the value and why it has this priority level]
|
| 57 |
+
|
| 58 |
+
**Independent Test**: [Describe how this can be tested independently]
|
| 59 |
+
|
| 60 |
+
**Acceptance Scenarios**:
|
| 61 |
+
|
| 62 |
+
1. **Given** [initial state], **When** [action], **Then** [expected outcome]
|
| 63 |
+
|
| 64 |
+
---
|
| 65 |
+
|
| 66 |
+
[Add more user stories as needed, each with an assigned priority]
|
| 67 |
+
|
| 68 |
+
### Edge Cases
|
| 69 |
+
|
| 70 |
+
<!--
|
| 71 |
+
ACTION REQUIRED: The content in this section represents placeholders.
|
| 72 |
+
Fill them out with the right edge cases.
|
| 73 |
+
-->
|
| 74 |
+
|
| 75 |
+
- What happens when [boundary condition]?
|
| 76 |
+
- How does system handle [error scenario]?
|
| 77 |
+
|
| 78 |
+
## Requirements *(mandatory)*
|
| 79 |
+
|
| 80 |
+
<!--
|
| 81 |
+
ACTION REQUIRED: The content in this section represents placeholders.
|
| 82 |
+
Fill them out with the right functional requirements.
|
| 83 |
+
-->
|
| 84 |
+
|
| 85 |
+
### Functional Requirements
|
| 86 |
+
|
| 87 |
+
- **FR-001**: System MUST [specific capability, e.g., "allow users to create accounts"]
|
| 88 |
+
- **FR-002**: System MUST [specific capability, e.g., "validate email addresses"]
|
| 89 |
+
- **FR-003**: Users MUST be able to [key interaction, e.g., "reset their password"]
|
| 90 |
+
- **FR-004**: System MUST [data requirement, e.g., "persist user preferences"]
|
| 91 |
+
- **FR-005**: System MUST [behavior, e.g., "log all security events"]
|
| 92 |
+
|
| 93 |
+
*Example of marking unclear requirements:*
|
| 94 |
+
|
| 95 |
+
- **FR-006**: System MUST authenticate users via [NEEDS CLARIFICATION: auth method not specified - email/password, SSO, OAuth?]
|
| 96 |
+
- **FR-007**: System MUST retain user data for [NEEDS CLARIFICATION: retention period not specified]
|
| 97 |
+
|
| 98 |
+
### Key Entities *(include if feature involves data)*
|
| 99 |
+
|
| 100 |
+
- **[Entity 1]**: [What it represents, key attributes without implementation]
|
| 101 |
+
- **[Entity 2]**: [What it represents, relationships to other entities]
|
| 102 |
+
|
| 103 |
+
## Success Criteria *(mandatory)*
|
| 104 |
+
|
| 105 |
+
<!--
|
| 106 |
+
ACTION REQUIRED: Define measurable success criteria.
|
| 107 |
+
These must be technology-agnostic and measurable.
|
| 108 |
+
-->
|
| 109 |
+
|
| 110 |
+
### Measurable Outcomes
|
| 111 |
+
|
| 112 |
+
- **SC-001**: [Measurable metric, e.g., "Users can complete account creation in under 2 minutes"]
|
| 113 |
+
- **SC-002**: [Measurable metric, e.g., "System handles 1000 concurrent users without degradation"]
|
| 114 |
+
- **SC-003**: [User satisfaction metric, e.g., "90% of users successfully complete primary task on first attempt"]
|
| 115 |
+
- **SC-004**: [Business metric, e.g., "Reduce support tickets related to [X] by 50%"]
|
.specify/templates/tasks-template.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
|
| 3 |
+
description: "Task list template for feature implementation"
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# Tasks: [FEATURE NAME]
|
| 7 |
+
|
| 8 |
+
**Input**: Design documents from `/specs/[###-feature-name]/`
|
| 9 |
+
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
|
| 10 |
+
|
| 11 |
+
**Tests**: The examples below include test tasks. Tests are OPTIONAL - only include them if explicitly requested in the feature specification.
|
| 12 |
+
|
| 13 |
+
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
|
| 14 |
+
|
| 15 |
+
## Format: `[ID] [P?] [Story] Description`
|
| 16 |
+
|
| 17 |
+
- **[P]**: Can run in parallel (different files, no dependencies)
|
| 18 |
+
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
|
| 19 |
+
- Include exact file paths in descriptions
|
| 20 |
+
|
| 21 |
+
## Path Conventions
|
| 22 |
+
|
| 23 |
+
- **Single project**: `src/`, `tests/` at repository root
|
| 24 |
+
- **Web app**: `backend/src/`, `frontend/src/`
|
| 25 |
+
- **Mobile**: `api/src/`, `ios/src/` or `android/src/`
|
| 26 |
+
- Paths shown below assume single project - adjust based on plan.md structure
|
| 27 |
+
|
| 28 |
+
<!--
|
| 29 |
+
============================================================================
|
| 30 |
+
IMPORTANT: The tasks below are SAMPLE TASKS for illustration purposes only.
|
| 31 |
+
|
| 32 |
+
The /speckit.tasks command MUST replace these with actual tasks based on:
|
| 33 |
+
- User stories from spec.md (with their priorities P1, P2, P3...)
|
| 34 |
+
- Feature requirements from plan.md
|
| 35 |
+
- Entities from data-model.md
|
| 36 |
+
- Endpoints from contracts/
|
| 37 |
+
|
| 38 |
+
Tasks MUST be organized by user story so each story can be:
|
| 39 |
+
- Implemented independently
|
| 40 |
+
- Tested independently
|
| 41 |
+
- Delivered as an MVP increment
|
| 42 |
+
|
| 43 |
+
DO NOT keep these sample tasks in the generated tasks.md file.
|
| 44 |
+
============================================================================
|
| 45 |
+
-->
|
| 46 |
+
|
| 47 |
+
## Phase 1: Setup (Shared Infrastructure)
|
| 48 |
+
|
| 49 |
+
**Purpose**: Project initialization and basic structure
|
| 50 |
+
|
| 51 |
+
- [ ] T001 Create project structure per implementation plan
|
| 52 |
+
- [ ] T002 Initialize [language] project with [framework] dependencies
|
| 53 |
+
- [ ] T003 [P] Configure linting and formatting tools
|
| 54 |
+
|
| 55 |
+
---
|
| 56 |
+
|
| 57 |
+
## Phase 2: Foundational (Blocking Prerequisites)
|
| 58 |
+
|
| 59 |
+
**Purpose**: Core infrastructure that MUST be complete before ANY user story can be implemented
|
| 60 |
+
|
| 61 |
+
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
|
| 62 |
+
|
| 63 |
+
Examples of foundational tasks (adjust based on your project):
|
| 64 |
+
|
| 65 |
+
- [ ] T004 Setup database schema and migrations framework
|
| 66 |
+
- [ ] T005 [P] Implement authentication/authorization framework
|
| 67 |
+
- [ ] T006 [P] Setup API routing and middleware structure
|
| 68 |
+
- [ ] T007 Create base models/entities that all stories depend on
|
| 69 |
+
- [ ] T008 Configure error handling and logging infrastructure
|
| 70 |
+
- [ ] T009 Setup environment configuration management
|
| 71 |
+
|
| 72 |
+
**Checkpoint**: Foundation ready - user story implementation can now begin in parallel
|
| 73 |
+
|
| 74 |
+
---
|
| 75 |
+
|
| 76 |
+
## Phase 3: User Story 1 - [Title] (Priority: P1) 🎯 MVP
|
| 77 |
+
|
| 78 |
+
**Goal**: [Brief description of what this story delivers]
|
| 79 |
+
|
| 80 |
+
**Independent Test**: [How to verify this story works on its own]
|
| 81 |
+
|
| 82 |
+
### Tests for User Story 1 (OPTIONAL - only if tests requested) ⚠️
|
| 83 |
+
|
| 84 |
+
> **NOTE: Write these tests FIRST, ensure they FAIL before implementation**
|
| 85 |
+
|
| 86 |
+
- [ ] T010 [P] [US1] Contract test for [endpoint] in tests/contract/test_[name].py
|
| 87 |
+
- [ ] T011 [P] [US1] Integration test for [user journey] in tests/integration/test_[name].py
|
| 88 |
+
|
| 89 |
+
### Implementation for User Story 1
|
| 90 |
+
|
| 91 |
+
- [ ] T012 [P] [US1] Create [Entity1] model in src/models/[entity1].py
|
| 92 |
+
- [ ] T013 [P] [US1] Create [Entity2] model in src/models/[entity2].py
|
| 93 |
+
- [ ] T014 [US1] Implement [Service] in src/services/[service].py (depends on T012, T013)
|
| 94 |
+
- [ ] T015 [US1] Implement [endpoint/feature] in src/[location]/[file].py
|
| 95 |
+
- [ ] T016 [US1] Add validation and error handling
|
| 96 |
+
- [ ] T017 [US1] Add logging for user story 1 operations
|
| 97 |
+
|
| 98 |
+
**Checkpoint**: At this point, User Story 1 should be fully functional and testable independently
|
| 99 |
+
|
| 100 |
+
---
|
| 101 |
+
|
| 102 |
+
## Phase 4: User Story 2 - [Title] (Priority: P2)
|
| 103 |
+
|
| 104 |
+
**Goal**: [Brief description of what this story delivers]
|
| 105 |
+
|
| 106 |
+
**Independent Test**: [How to verify this story works on its own]
|
| 107 |
+
|
| 108 |
+
### Tests for User Story 2 (OPTIONAL - only if tests requested) ⚠️
|
| 109 |
+
|
| 110 |
+
- [ ] T018 [P] [US2] Contract test for [endpoint] in tests/contract/test_[name].py
|
| 111 |
+
- [ ] T019 [P] [US2] Integration test for [user journey] in tests/integration/test_[name].py
|
| 112 |
+
|
| 113 |
+
### Implementation for User Story 2
|
| 114 |
+
|
| 115 |
+
- [ ] T020 [P] [US2] Create [Entity] model in src/models/[entity].py
|
| 116 |
+
- [ ] T021 [US2] Implement [Service] in src/services/[service].py
|
| 117 |
+
- [ ] T022 [US2] Implement [endpoint/feature] in src/[location]/[file].py
|
| 118 |
+
- [ ] T023 [US2] Integrate with User Story 1 components (if needed)
|
| 119 |
+
|
| 120 |
+
**Checkpoint**: At this point, User Stories 1 AND 2 should both work independently
|
| 121 |
+
|
| 122 |
+
---
|
| 123 |
+
|
| 124 |
+
## Phase 5: User Story 3 - [Title] (Priority: P3)
|
| 125 |
+
|
| 126 |
+
**Goal**: [Brief description of what this story delivers]
|
| 127 |
+
|
| 128 |
+
**Independent Test**: [How to verify this story works on its own]
|
| 129 |
+
|
| 130 |
+
### Tests for User Story 3 (OPTIONAL - only if tests requested) ⚠️
|
| 131 |
+
|
| 132 |
+
- [ ] T024 [P] [US3] Contract test for [endpoint] in tests/contract/test_[name].py
|
| 133 |
+
- [ ] T025 [P] [US3] Integration test for [user journey] in tests/integration/test_[name].py
|
| 134 |
+
|
| 135 |
+
### Implementation for User Story 3
|
| 136 |
+
|
| 137 |
+
- [ ] T026 [P] [US3] Create [Entity] model in src/models/[entity].py
|
| 138 |
+
- [ ] T027 [US3] Implement [Service] in src/services/[service].py
|
| 139 |
+
- [ ] T028 [US3] Implement [endpoint/feature] in src/[location]/[file].py
|
| 140 |
+
|
| 141 |
+
**Checkpoint**: All user stories should now be independently functional
|
| 142 |
+
|
| 143 |
+
---
|
| 144 |
+
|
| 145 |
+
[Add more user story phases as needed, following the same pattern]
|
| 146 |
+
|
| 147 |
+
---
|
| 148 |
+
|
| 149 |
+
## Phase N: Polish & Cross-Cutting Concerns
|
| 150 |
+
|
| 151 |
+
**Purpose**: Improvements that affect multiple user stories
|
| 152 |
+
|
| 153 |
+
- [ ] TXXX [P] Documentation updates in docs/
|
| 154 |
+
- [ ] TXXX Code cleanup and refactoring
|
| 155 |
+
- [ ] TXXX Performance optimization across all stories
|
| 156 |
+
- [ ] TXXX [P] Additional unit tests (if requested) in tests/unit/
|
| 157 |
+
- [ ] TXXX Security hardening
|
| 158 |
+
- [ ] TXXX Run quickstart.md validation
|
| 159 |
+
|
| 160 |
+
---
|
| 161 |
+
|
| 162 |
+
## Dependencies & Execution Order
|
| 163 |
+
|
| 164 |
+
### Phase Dependencies
|
| 165 |
+
|
| 166 |
+
- **Setup (Phase 1)**: No dependencies - can start immediately
|
| 167 |
+
- **Foundational (Phase 2)**: Depends on Setup completion - BLOCKS all user stories
|
| 168 |
+
- **User Stories (Phase 3+)**: All depend on Foundational phase completion
|
| 169 |
+
- User stories can then proceed in parallel (if staffed)
|
| 170 |
+
- Or sequentially in priority order (P1 → P2 → P3)
|
| 171 |
+
- **Polish (Final Phase)**: Depends on all desired user stories being complete
|
| 172 |
+
|
| 173 |
+
### User Story Dependencies
|
| 174 |
+
|
| 175 |
+
- **User Story 1 (P1)**: Can start after Foundational (Phase 2) - No dependencies on other stories
|
| 176 |
+
- **User Story 2 (P2)**: Can start after Foundational (Phase 2) - May integrate with US1 but should be independently testable
|
| 177 |
+
- **User Story 3 (P3)**: Can start after Foundational (Phase 2) - May integrate with US1/US2 but should be independently testable
|
| 178 |
+
|
| 179 |
+
### Within Each User Story
|
| 180 |
+
|
| 181 |
+
- Tests (if included) MUST be written and FAIL before implementation
|
| 182 |
+
- Models before services
|
| 183 |
+
- Services before endpoints
|
| 184 |
+
- Core implementation before integration
|
| 185 |
+
- Story complete before moving to next priority
|
| 186 |
+
|
| 187 |
+
### Parallel Opportunities
|
| 188 |
+
|
| 189 |
+
- All Setup tasks marked [P] can run in parallel
|
| 190 |
+
- All Foundational tasks marked [P] can run in parallel (within Phase 2)
|
| 191 |
+
- Once Foundational phase completes, all user stories can start in parallel (if team capacity allows)
|
| 192 |
+
- All tests for a user story marked [P] can run in parallel
|
| 193 |
+
- Models within a story marked [P] can run in parallel
|
| 194 |
+
- Different user stories can be worked on in parallel by different team members
|
| 195 |
+
|
| 196 |
+
---
|
| 197 |
+
|
| 198 |
+
## Parallel Example: User Story 1
|
| 199 |
+
|
| 200 |
+
```bash
|
| 201 |
+
# Launch all tests for User Story 1 together (if tests requested):
|
| 202 |
+
Task: "Contract test for [endpoint] in tests/contract/test_[name].py"
|
| 203 |
+
Task: "Integration test for [user journey] in tests/integration/test_[name].py"
|
| 204 |
+
|
| 205 |
+
# Launch all models for User Story 1 together:
|
| 206 |
+
Task: "Create [Entity1] model in src/models/[entity1].py"
|
| 207 |
+
Task: "Create [Entity2] model in src/models/[entity2].py"
|
| 208 |
+
```
|
| 209 |
+
|
| 210 |
+
---
|
| 211 |
+
|
| 212 |
+
## Implementation Strategy
|
| 213 |
+
|
| 214 |
+
### MVP First (User Story 1 Only)
|
| 215 |
+
|
| 216 |
+
1. Complete Phase 1: Setup
|
| 217 |
+
2. Complete Phase 2: Foundational (CRITICAL - blocks all stories)
|
| 218 |
+
3. Complete Phase 3: User Story 1
|
| 219 |
+
4. **STOP and VALIDATE**: Test User Story 1 independently
|
| 220 |
+
5. Deploy/demo if ready
|
| 221 |
+
|
| 222 |
+
### Incremental Delivery
|
| 223 |
+
|
| 224 |
+
1. Complete Setup + Foundational → Foundation ready
|
| 225 |
+
2. Add User Story 1 → Test independently → Deploy/Demo (MVP!)
|
| 226 |
+
3. Add User Story 2 → Test independently → Deploy/Demo
|
| 227 |
+
4. Add User Story 3 → Test independently → Deploy/Demo
|
| 228 |
+
5. Each story adds value without breaking previous stories
|
| 229 |
+
|
| 230 |
+
### Parallel Team Strategy
|
| 231 |
+
|
| 232 |
+
With multiple developers:
|
| 233 |
+
|
| 234 |
+
1. Team completes Setup + Foundational together
|
| 235 |
+
2. Once Foundational is done:
|
| 236 |
+
- Developer A: User Story 1
|
| 237 |
+
- Developer B: User Story 2
|
| 238 |
+
- Developer C: User Story 3
|
| 239 |
+
3. Stories complete and integrate independently
|
| 240 |
+
|
| 241 |
+
---
|
| 242 |
+
|
| 243 |
+
## Notes
|
| 244 |
+
|
| 245 |
+
- [P] tasks = different files, no dependencies
|
| 246 |
+
- [Story] label maps task to specific user story for traceability
|
| 247 |
+
- Each user story should be independently completable and testable
|
| 248 |
+
- Verify tests fail before implementing
|
| 249 |
+
- Commit after each task or logical group
|
| 250 |
+
- Stop at any checkpoint to validate story independently
|
| 251 |
+
- Avoid: vague tasks, same file conflicts, cross-story dependencies that break independence
|
AGENTS.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# AGENTS.md
|
| 2 |
+
|
| 3 |
+
This file provides guidance to coding agents working in this repository.
|
| 4 |
+
|
| 5 |
+
## Repository Guidelines
|
| 6 |
+
|
| 7 |
+
### Pipeline-First Development (MANDATORY)
|
| 8 |
+
**All new functionality MUST be implemented as pipeline Steps composed via the Pipeline engine.** Do NOT write standalone scripts, ad-hoc loops, or inline logic that bypasses the pipeline. Before writing any code:
|
| 9 |
+
|
| 10 |
+
1. Read `docs/design/PIPELINE_DESIGN.md` to understand the Step → Pipeline → Branch model.
|
| 11 |
+
2. Implement logic as a `Step` class with `requires`/`provides` declarations and a `__call__(self, ctx) -> ctx` method.
|
| 12 |
+
3. Compose steps using `Pipeline().then(...)` and `.branch(...)` — never manual for-loops or direct function chaining.
|
| 13 |
+
4. Use `StepContext.replace()` for immutable context updates — never mutate context directly.
|
| 14 |
+
5. Put integration-specific data in `metadata`, not new context fields, unless the field is shared across multiple pipelines.
|
| 15 |
+
|
| 16 |
+
**Anti-patterns to reject:**
|
| 17 |
+
- Writing a function that calls multiple steps manually instead of composing them in a Pipeline
|
| 18 |
+
- Inline reflection/evaluation logic instead of creating a ReflectStep or EvaluateStep
|
| 19 |
+
- Ad-hoc `ThreadPoolExecutor` usage instead of `async_boundary` and `max_workers` on steps
|
| 20 |
+
- Standalone scripts that duplicate pipeline functionality without using the pipeline engine
|
| 21 |
+
- Bypassing `requires`/`provides` contracts by accessing context fields not declared in `requires`
|
| 22 |
+
|
| 23 |
+
If a task seems like it cannot fit the pipeline model, explain why to the user before proceeding — do not silently circumvent it.
|
| 24 |
+
|
| 25 |
+
### Core Code Protection
|
| 26 |
+
**Do NOT modify core modules (`ace/core/`, `pipeline/`) without explicit user approval.** Before proposing any change to these directories:
|
| 27 |
+
1. Read the relevant design docs (`docs/design/ACE_ARCHITECTURE.md`, `docs/design/PIPELINE_DESIGN.md`) thoroughly.
|
| 28 |
+
2. Evaluate whether the change is truly required or if it can be achieved outside the core (e.g., in an integration, step, or example).
|
| 29 |
+
3. Clearly explain the proposed change and its justification to the user **before** making any edits.
|
| 30 |
+
4. Wait for the user to explicitly accept before proceeding.
|
| 31 |
+
|
| 32 |
+
### Documentation Maintenance
|
| 33 |
+
Before working on code in `ace/`, read `docs/design/ACE_ARCHITECTURE.md` to understand the current architecture.
|
| 34 |
+
Before working on code in `pipeline/` or `ace/core/`, read `docs/design/PIPELINE_DESIGN.md` to understand the pipeline engine.
|
| 35 |
+
|
| 36 |
+
**Docs MUST be kept in sync with code.** Any change that alters a public API, renames a concept, adds/removes a module, or changes execution flow **requires** a corresponding update to the relevant docs. Do not merge code changes that make the documentation inaccurate.
|
| 37 |
+
|
| 38 |
+
Key design docs:
|
| 39 |
+
- `docs/design/ACE_ARCHITECTURE.md` — ACE architecture: layers, core concepts, roles, steps, runners, integrations
|
| 40 |
+
- `docs/design/ACE_REFERENCE.md` — ACE code reference: full implementations, API signatures, usage examples
|
| 41 |
+
- `docs/design/ACE_DECISIONS.md` — design decisions and rejected alternatives (ACE, pipeline, migration)
|
| 42 |
+
- `docs/design/PIPELINE_DESIGN.md` — pipeline engine: steps, StepProtocol, Pipeline, Branch, concurrency
|
| 43 |
+
- If you need to work with collected traces from Logfire, read `agent-guides/logfire.md`
|
| 44 |
+
|
| 45 |
+
### Project Structure
|
| 46 |
+
- `ace/` — core library: roles (PydanticAI-backed), skillbook, steps, runners, providers, RR, integrations, observability
|
| 47 |
+
- `pipeline/` — generic pipeline engine that `ace` is built on (see `docs/design/PIPELINE_DESIGN.md`)
|
| 48 |
+
- `ace-eval/` — evaluation framework (submodule, separate repo)
|
| 49 |
+
- `tests/` — unit/integration tests (pytest)
|
| 50 |
+
- `examples/` — runnable demos grouped by integration
|
| 51 |
+
- `agent-guides/` — internal development guides for LLM agents; not part of the public docs site
|
| 52 |
+
- `docs/` — guides and reference material
|
| 53 |
+
- `docs/design/ACE_ARCHITECTURE.md` — architecture and concepts (keep in sync with code)
|
| 54 |
+
- `docs/design/ACE_REFERENCE.md` — code reference and examples (keep in sync with code)
|
| 55 |
+
- `docs/design/ACE_DECISIONS.md` — design decisions and rejected alternatives
|
| 56 |
+
- `docs/design/PIPELINE_DESIGN.md` — pipeline engine design doc (keep in sync with code)
|
| 57 |
+
|
| 58 |
+
### Commands
|
| 59 |
+
- `uv sync` — install all dependencies
|
| 60 |
+
- `uv run pytest` — run tests (coverage enforced `--cov-fail-under=25`)
|
| 61 |
+
- `uv run pytest -m unit` / `-m integration` / `-m slow` — run by marker
|
| 62 |
+
- `uv run black ace/ tests/ examples/` — format code
|
| 63 |
+
- `uv run mypy ace/` — type check
|
| 64 |
+
|
| 65 |
+
### Coding Style
|
| 66 |
+
- PEP 8 with Black formatting (line length 88)
|
| 67 |
+
- Type hints and docstrings for public APIs
|
| 68 |
+
- Python 3.12 target
|
| 69 |
+
- Test files: `tests/test_*.py`; functions: `test_*`; classes: `Test*`
|
| 70 |
+
|
| 71 |
+
### Testing
|
| 72 |
+
- Pytest is the primary runner
|
| 73 |
+
- Add tests for new features; include regression tests for bug fixes
|
| 74 |
+
|
| 75 |
+
### Commits
|
| 76 |
+
- Conventional Commits: `feat(scope): subject`, `fix(scope): subject`
|
| 77 |
+
- Do NOT add `Co-Authored-By` trailers to commit messages
|
| 78 |
+
- PRs should include description, test results, and relevant docs updates
|
| 79 |
+
|
| 80 |
+
### ACE Roles (quick reference)
|
| 81 |
+
|
| 82 |
+
| Role | Responsibility | Key Class |
|
| 83 |
+
|------|---------------|-----------|
|
| 84 |
+
| **Agent** | Executes tasks using skillbook strategies | `Agent` |
|
| 85 |
+
| **Reflector** | Analyzes execution results | `Reflector` |
|
| 86 |
+
| **SkillManager** | Updates the skillbook with new strategies | `SkillManager` |
|
| 87 |
+
|
| 88 |
+
### Integration Runners
|
| 89 |
+
|
| 90 |
+
| Runner | Framework | Use Case |
|
| 91 |
+
|--------|-----------|----------|
|
| 92 |
+
| `ACELiteLLM` | LiteLLM (100+ providers) | Simple self-improving agent |
|
| 93 |
+
| `ACELangChain` | LangChain | Wrap chains/agents with learning |
|
| 94 |
+
| `ACEBrowserUse` | browser-use | Browser automation with learning |
|
| 95 |
+
| `ACEClaudeCode` | Claude Code CLI | Coding tasks with learning |
|
| 96 |
+
|
| 97 |
+
NEVER USE FALLBACKS OR IMPLEMENT THINGS I NEVER ASKED FOR.
|
| 98 |
+
IF IT'S STRAIGHFORWARD, IMPLEMENT IT STRAIGHFORWARD.
|
CHANGELOG.md
ADDED
|
@@ -0,0 +1,445 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Changelog
|
| 2 |
+
|
| 3 |
+
All notable changes to ACE Framework will be documented in this file.
|
| 4 |
+
|
| 5 |
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
| 6 |
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
| 7 |
+
|
| 8 |
+
## [Unreleased]
|
| 9 |
+
|
| 10 |
+
## [0.12.0] - 2026-05-06
|
| 11 |
+
|
| 12 |
+
### Added
|
| 13 |
+
- **Cross-trace generalization gate** for the SkillManager — four-criterion check
|
| 14 |
+
(≥3 instances across ≥2 domains, named slot, no API-specific params in the
|
| 15 |
+
action, verifiable runtime trigger) that constrains when SM may write a broad
|
| 16 |
+
skill subsuming existing narrow ones. Backed by [skill_generalization.md](ace-eval/research/skill_generalization.md)
|
| 17 |
+
(14 cited sources).
|
| 18 |
+
- **Action-equivalence rule** for within-run skill writing — splits on action,
|
| 19 |
+
not on trigger surface. Prevents over-decomposition of structurally identical
|
| 20 |
+
rules.
|
| 21 |
+
- **Atomicity rule** in `insight` formatting — one trigger + one action per
|
| 22 |
+
skill, with explicit good/bad shape examples in the prompt.
|
| 23 |
+
- **Insight format guidance** in the SM prompt sourced from the in-context-
|
| 24 |
+
learning research doc ([icl_skill_formatting.md](ace-eval/research/icl_skill_formatting.md)) — 15-50 word cap, imperative
|
| 25 |
+
voice, positive framing default, examples only for format/shape rules.
|
| 26 |
+
- **Evidence-only tagging** — SM tags only skills the reflection actually
|
| 27 |
+
implicates, instead of iterating over every injected_skill_id.
|
| 28 |
+
- **Broaden-via-comparison rule** for UPDATE — when two skills target the same
|
| 29 |
+
root cause in different niches, broaden `issue` rather than adding a duplicate.
|
| 30 |
+
- **Prompt caching for SM** via `CachePoint(ttl="5m")` mirroring RR's caching;
|
| 31 |
+
cache_read/write tokens forwarded in run metadata.
|
| 32 |
+
- **SM behavior spec + harness** — `ace-eval/scripts/sm_behavior_check.py`,
|
| 33 |
+
`sm_iterative_check.py`, `sm_stability_check.py` and matching scenario
|
| 34 |
+
fixtures cover replay stability, convergence, scope expansion, and the
|
| 35 |
+
below-threshold gate boundary.
|
| 36 |
+
|
| 37 |
+
### Changed
|
| 38 |
+
- **`update_skills` signature** — `source` is now optional; `SkillbookView`
|
| 39 |
+
was dropped from the parameter list (callers pass the real `Skillbook`
|
| 40 |
+
directly).
|
| 41 |
+
- **Hard removal cap removed** — SM no longer auto-removes skills whose
|
| 42 |
+
`harmful_count >= 3`. Heavily-used skills can legitimately accumulate
|
| 43 |
+
harmful tags without being net-negative; REMOVE now requires explicit
|
| 44 |
+
reflection evidence.
|
| 45 |
+
- **TauBench evaluator** — `evaluation_type=ALL_WITH_NL_ASSERTIONS` on both
|
| 46 |
+
`run_task` and `run_tasks` call sites in
|
| 47 |
+
`ace-eval/src/ace_eval/e2e/benchmarks/tau_bench.py`. Retail (and any future
|
| 48 |
+
benchmark with `NL_ASSERTION` in `reward_basis`) now produces real reward
|
| 49 |
+
numbers instead of crashing on every task during reward computation.
|
| 50 |
+
|
| 51 |
+
### Removed
|
| 52 |
+
- **Skillbook v1 legacy aliases** on `Skill` and `UpdateOperation` — v2 schema
|
| 53 |
+
is now the only schema.
|
| 54 |
+
|
| 55 |
+
## [0.11.0] - 2026-04-29
|
| 56 |
+
|
| 57 |
+
### Added
|
| 58 |
+
- **`RecursiveAgent` core abstraction** — extracted from RR into `ace/core/recursive_agent.py`; provides a generic recursive PydanticAI agent with sandbox, microcompaction, default tool set, and depth-aware sub-agent registration. Reusable across roles beyond the Reflector.
|
| 59 |
+
- **Skillbook v2 schema** — full rewrite of `ace/core/skillbook.py` with section-grouped storage, richer `InsightSource` provenance, and BM25-backed retrieval (`rank-bm25` runtime dependency).
|
| 60 |
+
- **Agentic SkillManager** — `SkillManager` rewritten as a tool-calling loop (`ace/implementations/sm_tools.py`). Provenance is now populated by the SkillManager agent directly rather than a dedicated step.
|
| 61 |
+
- **RR skillbook tools for the Reflector** — Reflector can introspect and propose updates to the skillbook from inside the recursive loop.
|
| 62 |
+
- **Anthropic prompt caching enabled by default** for RR agents; `cache_read_tokens` and `cache_write_tokens` are forwarded in run metadata for cost accounting.
|
| 63 |
+
- **Logfire spans around recursive agent sessions** for end-to-end observability of nested RR runs.
|
| 64 |
+
- **Online / offline mode** in the ACE runner.
|
| 65 |
+
- **`nest-asyncio`** added to the dev extra to support nested loops in notebooks and live test scripts.
|
| 66 |
+
|
| 67 |
+
### Changed
|
| 68 |
+
- **RR collapsed into a single `RRStep`** — the orchestrator/worker split, batch machinery, and `AttachInsightSourcesStep` have been removed. RR now runs as a true recursive loop with depth-bounded sub-agent delegation and microcompaction of stale tool results.
|
| 69 |
+
- **Reflector prompts** simplified, deduplicated, and made input-agnostic; added early-skillbook-skim and parallel-tool guidance.
|
| 70 |
+
- **`record_observation` tool renamed to `think`** to clarify it is a scratch reasoning channel, not persistent storage.
|
| 71 |
+
- **Native evidence summaries** are produced inside RR before final synthesis.
|
| 72 |
+
- **Skillbook prompt format is now markdown** — `Skillbook.as_prompt()` returns a section-grouped markdown list instead of TOON. The `python-toon` dependency has been dropped.
|
| 73 |
+
- **`metered_model` and `sandbox`** moved from `ace/rr/` into `ace/core/` to reflect their cross-role use.
|
| 74 |
+
- **Pytest defaults** — `uv run pytest` now excludes `integration` and `requires_api` markers by default; coverage flags removed from `addopts` (run with `--cov` explicitly when needed).
|
| 75 |
+
- **Observability** — `tool_arguments` and `tool_response` are no longer scrubbed by the Logfire callback so tool I/O remains inspectable.
|
| 76 |
+
|
| 77 |
+
### Removed
|
| 78 |
+
- `ace/rr/` legacy package layout (`agent.py`, `runner.py`, `trace_context.py`, `message_trimming.py`, batch helpers). Functionality is now in `ace/core/recursive_agent.py` and `ace/implementations/rr/`.
|
| 79 |
+
- `AttachInsightSourcesStep` and its pipeline wiring — provenance is attached by the SkillManager agent.
|
| 80 |
+
- `python-toon` runtime dependency.
|
| 81 |
+
- TAG handling from the SkillManager.
|
| 82 |
+
- Citation scanning from the Reflector.
|
| 83 |
+
|
| 84 |
+
## [0.10.0] - 2026-04-13
|
| 85 |
+
|
| 86 |
+
### Added
|
| 87 |
+
- **Usage metering hook** — `RecursiveConfig.usage_callback: (RequestUsage, model_id) -> None` fires once per pydantic-ai model request (orchestrator turns, sub-agent runs, tool-call follow-ups). Implemented via `ace.rr.MeteredModel`, a `pydantic_ai.models.wrapper.WrapperModel` subclass, so metering lives at the framework's own model boundary — no per-call-site plumbing. Callback exceptions are caught and logged so metering never crashes the pipeline.
|
| 88 |
+
- **Pre-built model instance support** — `RRStep`, `create_rr_agent`, `create_sub_agent`, and `RecursiveConfig.subagent_model` now accept either a model-id string or a pre-built `pydantic_ai.models.Model` instance. Enables callers that need a custom provider (e.g. cross-account Bedrock with STS-assumed credentials) to inject a fully-configured model rather than resolving from a string.
|
| 89 |
+
- **Sub-agent `model_settings`** — `create_sub_agent` now threads an explicit `ModelSettings` parameter into its `PydanticAgent` constructor.
|
| 90 |
+
|
| 91 |
+
### Notes
|
| 92 |
+
- Back-compat: existing `RRStep(model="...")` callers continue to work unchanged. The widened type signature is additive.
|
| 93 |
+
|
| 94 |
+
## [0.9.4] - 2026-04-11
|
| 95 |
+
|
| 96 |
+
### Added
|
| 97 |
+
- **Kayba tracing SDK** — `ace.tracing` module wraps MLflow tracing with Kayba-native configuration, folder organization, and input sanitization (`pip install ace-framework[tracing]`)
|
| 98 |
+
|
| 99 |
+
## [0.9.3] - 2026-04-01
|
| 100 |
+
|
| 101 |
+
### Added
|
| 102 |
+
- **Structured design docs** — split ACE_DESIGN.md into architecture, reference, and decisions docs under docs/design/
|
| 103 |
+
- **Simplified Skill model** — removed unused tag counters (helpful/harmful/neutral) and TagStep from the pipeline
|
| 104 |
+
- **Cleaner InsightSource provenance** — restored error_identification and learning_text fields
|
| 105 |
+
|
| 106 |
+
## [0.9.2] - 2026-03-31
|
| 107 |
+
|
| 108 |
+
### Added
|
| 109 |
+
- **Insight source provenance** — `InsightSource` typed model captures the origin of each skillbook update (trace ID, sample question, epoch/step, reflection summary, integration metadata); provenance is now populated by the SkillManager agent directly
|
| 110 |
+
- **Claude SDK step** — `ClaudeSDKStep` integration for running Claude Code sub-agents from within ACE pipelines
|
| 111 |
+
- **RR sub-agent code execution** — Recursive Reflector can now delegate to code-execution sub-agents at runtime
|
| 112 |
+
- **RR raw trace batch helpers** — `build_raw_trace_batches` and related runtime utilities for feeding raw traces directly into the RR pipeline
|
| 113 |
+
|
| 114 |
+
### Fixed
|
| 115 |
+
- **Logfire scrubbing** — added scrubbing callback to stop Logfire over-redacting trace content (reasoning, answers, messages now visible in Logfire UI)
|
| 116 |
+
- **RR combined-batch normalization** — fixed ordering/deduplication of combined task batches in multi-sample runs
|
| 117 |
+
|
| 118 |
+
### Docs
|
| 119 |
+
- Logfire query API guide clarifications
|
| 120 |
+
- MCP client setup guide and compatibility tests
|
| 121 |
+
- Design docs updated to reflect insight source provenance model
|
| 122 |
+
|
| 123 |
+
## [0.9.1] - 2026-03-26
|
| 124 |
+
|
| 125 |
+
### Fixed
|
| 126 |
+
- **CLI packaging** — include .md data files in wheel so `kayba setup` and skill install work on pip/uv-installed packages
|
| 127 |
+
|
| 128 |
+
## [0.9.0] - 2026-03-26
|
| 129 |
+
|
| 130 |
+
### Added
|
| 131 |
+
- **PydanticAI migration** — ACE roles (Agent, Reflector, SkillManager) rebuilt on PydanticAI agents with structured output, replacing the legacy role system
|
| 132 |
+
- **Recursive Reflector** — PydanticAI-powered trace analysis agent with sandboxed code execution, sub-agent delegation, and working memory (`save_notes` tool)
|
| 133 |
+
- **Kayba CLI** — full hosted API client with trace upload/management, interactive run, insights, prompts, batch processing, materialization, and integration commands (`kayba` entry point)
|
| 134 |
+
|
| 135 |
+
## [0.8.8] - 2026-03-17
|
| 136 |
+
|
| 137 |
+
### Added
|
| 138 |
+
- **Pipeline hooks & cancellation** — `PipelineHook` protocol and `CancellationToken` for observing and controlling pipeline execution
|
| 139 |
+
- **Kayba pipeline skills for Claude Code** — 7-stage dynamic evaluation pipeline that generates custom benchmarks tailored to your agent's domain. Instead of static test suites, the skills analyze your API, build domain-aware metrics and rubrics, create action plans, and run human-in-the-loop validation — all as composable Claude Code skills
|
| 140 |
+
- **`kayba setup` command** — one command to install the full evaluation skill pipeline into your `.claude/skills/` directory, ready to use inside Claude Code out of the box
|
| 141 |
+
|
| 142 |
+
### Docs
|
| 143 |
+
- Documented `kayba setup` skills installation
|
| 144 |
+
|
| 145 |
+
### Try it free
|
| 146 |
+
**7-day free trial** — Try the full Kayba evaluation pipeline on our hosted solution with zero setup. Sign up at [kayba.ai](https://kayba.ai) and run `kayba setup` to start building dynamic evals for your agents today.
|
| 147 |
+
|
| 148 |
+
## [0.8.7] - 2026-03-17
|
| 149 |
+
|
| 150 |
+
### Added
|
| 151 |
+
- **Improved Opik trace naming** — traces now display the question text (first 80 chars) instead of generic names like "ace_pipeline" or "rr_reflect"
|
| 152 |
+
- **Thread ID support for Opik** — `OpikStep` and `RROpikStep` accept an optional `thread_id` parameter for grouping related traces
|
| 153 |
+
|
| 154 |
+
## [0.8.5] - 2026-03-04
|
| 155 |
+
|
| 156 |
+
### Added
|
| 157 |
+
- **Self-contained RR module** (`ace/rr/`) — sandbox, subagent, trace_context, config, code_extraction, message_trimming extracted from `ace/reflector/` into a standalone package
|
| 158 |
+
- **v5.6 prompt promoted as default** — new prompt evolution (v4 → v5.1–v5.6) for the `ace` RR pipeline
|
| 159 |
+
- **`build_steps()` API** — all runners gain a `build_steps()` classmethod for pipeline customization
|
| 160 |
+
- **Shared `CallBudget`** — single budget instance shared across RR pipeline steps
|
| 161 |
+
- **ACE MCP server (optional)** — stdio MCP server in `ace.integrations.mcp` with tools: `ace.ask`, `ace.learn.sample`, `ace.learn.feedback`, `ace.skillbook.get`, `ace.skillbook.save`, `ace.skillbook.load`
|
| 162 |
+
- **Session-scoped state management** — in-memory `session_id` registry with TTL cleanup and per-session async locking
|
| 163 |
+
- **MCP packaging + CLI** — optional `mcp` extra and `ace-mcp` entrypoint
|
| 164 |
+
- **MCP docs and demo client** — integration guide and stdio client example
|
| 165 |
+
- **Composing pipelines guide** — new `docs/guides/composing-pipelines.md`
|
| 166 |
+
- **RR examples** — `rr_demo.py`, `rr_opik_demo.py`, `compose_custom_pipeline.py`
|
| 167 |
+
|
| 168 |
+
### Changed
|
| 169 |
+
- **RR backward-compat shims** — original `ace/reflector/` files now re-export from `ace.rr` (no duplication)
|
| 170 |
+
- **`RRStep` dual protocol** — implements both `StepProtocol` and `ReflectorLike`
|
| 171 |
+
- **Sandbox hardening** — hardened `getattr` in sandbox execution environment
|
| 172 |
+
- **Opik made opt-in** — moved `opik` from hard dependency to `observability` extra
|
| 173 |
+
- **Safety controls** — runtime request limits (`max_prompt_chars`, `max_samples_per_call`) and optional root-bound path enforcement for save/load via `ACE_MCP_SKILLBOOK_ROOT`
|
| 174 |
+
- **Schema-driven validation** — MCP request/response models aligned to `specs/002-ace-mcp-server/contracts/tool-schemas.md`
|
| 175 |
+
- **`learn_from_feedback` routed through pipeline** — feedback learning now uses the pipeline engine
|
| 176 |
+
|
| 177 |
+
### Testing
|
| 178 |
+
- Added MCP test suite: models, registry, handlers, and server registration/startup smoke tests
|
| 179 |
+
- Added optional-dependency boundary checks for the MCP integration
|
| 180 |
+
- RR steps at 94%, sandbox at 92%, runner at 74%, MCP models at 100%
|
| 181 |
+
|
| 182 |
+
## [0.8.4] - 2026-02-27
|
| 183 |
+
|
| 184 |
+
### Added
|
| 185 |
+
- **OpenClaw integration** — learn from OpenClaw session transcripts (JSONL) via new `OpenClawToTraceStep` and `LoadTracesStep` pipeline steps (#86)
|
| 186 |
+
- **ExportSkillbookMarkdownStep** — export skillbook to markdown file
|
| 187 |
+
- OpenClaw example script and integration docs
|
| 188 |
+
|
| 189 |
+
## [0.8.3] - 2026-02-21
|
| 190 |
+
|
| 191 |
+
### Added
|
| 192 |
+
- **Pipeline engine** — generic pipeline framework with branching, async boundaries, and parallel execution (#78)
|
| 193 |
+
- **Trace passthrough** — `_build_traces()` helper and raw trace data passed to RecursiveReflector sandbox
|
| 194 |
+
|
| 195 |
+
## [0.8.2] - 2026-02-18
|
| 196 |
+
|
| 197 |
+
### Added
|
| 198 |
+
- **RecursiveReflector None-response guard** — gracefully handles empty/None LLM responses (e.g. from Gemini) with retry prompt instead of crashing
|
| 199 |
+
- **`LiteLLMClient.complete_messages()`** — native multi-turn completion that preserves structured message lists
|
| 200 |
+
|
| 201 |
+
## [0.8.1] - 2026-02-18
|
| 202 |
+
|
| 203 |
+
### Added
|
| 204 |
+
- **Insight source tracing** — `InsightSource` dataclass tracks skill provenance (epoch, sample, trace refs, error identification, learning text)
|
| 205 |
+
- **Sample.id** promoted to first-class field with UUID auto-generation
|
| 206 |
+
- **Skillbook query API** — `source_map()`, `source_summary()`, `source_filter()` for skill lineage
|
| 207 |
+
- Insight sources wired through `OfflineACE`, `OnlineACE`, and async learning pipelines
|
| 208 |
+
- `UpdateOperation.learning_index` for linking operations to reflector learnings
|
| 209 |
+
- Bedrock e2e example (`examples/litellm/bedrock_insight_source_test.py`)
|
| 210 |
+
- `docs/INSIGHT_SOURCES.md` guide
|
| 211 |
+
|
| 212 |
+
## [0.8.0] - 2026-02-17
|
| 213 |
+
|
| 214 |
+
### Added
|
| 215 |
+
- **Recursive reflector** with sandboxed code execution for validation
|
| 216 |
+
- **TAU-bench integration** with config-driven YAML profiles, prompt sweep, capture/replay, and label support
|
| 217 |
+
- **v3 prompt templates** for agent, reflector, and skill manager roles
|
| 218 |
+
- **Trace context module** exposing agent system prompt and execution context to reflector
|
| 219 |
+
|
| 220 |
+
### Fixed
|
| 221 |
+
- Opik cloud mode support when `OPIK_API_KEY` is set
|
| 222 |
+
- Bedrock/SageMaker API key lookup skipped for managed providers
|
| 223 |
+
- Reflector trace quality improvements (user messages, turn separators)
|
| 224 |
+
|
| 225 |
+
### Changed
|
| 226 |
+
- v3 prompts set as default prompt version
|
| 227 |
+
- Reflector now includes agent system prompt in trace context
|
| 228 |
+
|
| 229 |
+
## [0.7.3] - 2026-02-04
|
| 230 |
+
|
| 231 |
+
### Added
|
| 232 |
+
- ACE learning for Claude Code via `/ace-learn` (transcript-based learning and skillbook updates).
|
| 233 |
+
- CLI patching to minimize Claude Code system prompt overhead for learning runs.
|
| 234 |
+
|
| 235 |
+
### Fixed
|
| 236 |
+
- Claude Code transcript parsing for feedback and last-prompt extraction edge cases.
|
| 237 |
+
|
| 238 |
+
### Changed
|
| 239 |
+
- Unified agent guidance into `AGENTS.md` with `CLAUDE.md` symlink.
|
| 240 |
+
|
| 241 |
+
## [0.7.0] - 2025-12-04
|
| 242 |
+
|
| 243 |
+
### ⚠️ Breaking Changes
|
| 244 |
+
- **Complete terminology rename** - Playbook → Skillbook, Bullet → Skill
|
| 245 |
+
- `Playbook` → `Skillbook`
|
| 246 |
+
- `Bullet` → `Skill`
|
| 247 |
+
- `Generator` → `Agent`
|
| 248 |
+
- `Curator` → `SkillManager`
|
| 249 |
+
- `OfflineAdapter` → `OfflineACE`
|
| 250 |
+
- `OnlineAdapter` → `OnlineACE`
|
| 251 |
+
- `DeltaOperation` → `UpdateOperation`
|
| 252 |
+
- `DeltaBatch` → `UpdateBatch`
|
| 253 |
+
- **Migration**: Update imports and method calls to use new names
|
| 254 |
+
- **JSON files**: Change `"bullets"` key to `"skills"` in saved skillbooks
|
| 255 |
+
|
| 256 |
+
### Added
|
| 257 |
+
- **Deduplication consolidation_operations field** - SkillManagerOutput now properly captures consolidation operations from LLM responses
|
| 258 |
+
|
| 259 |
+
### Fixed
|
| 260 |
+
- **Deduplication not working** - Added `consolidation_operations` field to SkillManagerOutput Pydantic model. Previously, Instructor was silently dropping these operations.
|
| 261 |
+
|
| 262 |
+
## [0.5.0] - 2025-11-20
|
| 263 |
+
|
| 264 |
+
### ⚠️ Breaking Changes
|
| 265 |
+
- **Playbook format changed to TOON (Token-Oriented Object Notation)**
|
| 266 |
+
- `Playbook.as_prompt()` now returns TOON format instead of markdown
|
| 267 |
+
- **Reason**: 16-62% token savings for improved scalability and reduced inference costs
|
| 268 |
+
- **Migration**: No action needed if using playbook with Generator/Curator/Reflector
|
| 269 |
+
- **Debugging**: Use `playbook._as_markdown_debug()` or `str(playbook)` for human-readable output
|
| 270 |
+
- **Details**: Uses tab delimiters and excludes internal metadata (created_at, updated_at)
|
| 271 |
+
|
| 272 |
+
### Added
|
| 273 |
+
- **ACELiteLLM integration** - Simple conversational agent with automatic learning
|
| 274 |
+
- **ACELangChain integration** - Wrap LangChain Runnables with ACE learning
|
| 275 |
+
- **Custom integration pattern** - Wrap ANY agentic system with ACE learning
|
| 276 |
+
- Base utilities in `ace/integrations/base.py` with `wrap_playbook_context()` helper
|
| 277 |
+
- Complete working example in `examples/custom_integration_example.py`
|
| 278 |
+
- Integration Pattern: Inject playbook → Execute agent → Learn from results
|
| 279 |
+
- **Integration exports** - Import ACEAgent, ACELiteLLM, ACELangChain from `ace` package root
|
| 280 |
+
- **TOON compression for playbooks** - 16-62% token reduction vs markdown
|
| 281 |
+
- **Citation-based tracking** - Strategies cited inline as `[section-00001]`, auto-extracted from reasoning
|
| 282 |
+
- **Enhanced browser traces** - Full execution logs (2200+ chars) passed to Reflector
|
| 283 |
+
- **Test coverage** - Improved from 28% to 70% (241 tests total)
|
| 284 |
+
|
| 285 |
+
### Changed
|
| 286 |
+
- **Renamed SimpleAgent → ACELiteLLM** - Clearer naming for conversational agent integration
|
| 287 |
+
- `Playbook.__str__()` returns markdown (TOON reserved for LLM consumption via `as_prompt()`)
|
| 288 |
+
|
| 289 |
+
### Fixed
|
| 290 |
+
- **Browser-use trace integration** - Reflector now receives complete execution traces
|
| 291 |
+
- Fixed initial query duplication (task appeared in both question and reasoning)
|
| 292 |
+
- Fixed missing trace data (reasoning field now contains 2200+ chars vs 154 chars)
|
| 293 |
+
- Fixed screenshot attribute bug causing AttributeError on step.state.screenshot
|
| 294 |
+
- Fixed invalid bullet ID filtering - hallucinated/malformed citations now filtered out
|
| 295 |
+
- Added comprehensive regression tests to catch these issues
|
| 296 |
+
- Impact: Reflector can now properly analyze browser agent's thought process
|
| 297 |
+
- Test coverage improved: 69% → 79% for browser_use.py
|
| 298 |
+
- Prompt v2.1 test assertions updated to match current format
|
| 299 |
+
- All 206 tests now pass (was 189)
|
| 300 |
+
|
| 301 |
+
## [0.4.0] - 2025-10-26
|
| 302 |
+
|
| 303 |
+
### Added
|
| 304 |
+
- **Production Observability** with Opik integration
|
| 305 |
+
- Enterprise-grade monitoring and tracing
|
| 306 |
+
- Automatic token usage and cost tracking for all LLM calls
|
| 307 |
+
- Real-time cost monitoring via Opik dashboard
|
| 308 |
+
- Graceful degradation when Opik is not installed
|
| 309 |
+
- **Browser Automation Demos** showing ACE vs baseline performance
|
| 310 |
+
- Domain checker demo with learning capabilities
|
| 311 |
+
- Form filler demo with adaptive strategies
|
| 312 |
+
- Side-by-side comparison of baseline vs ACE-enhanced automation
|
| 313 |
+
- Support for UV package manager (10-100x faster than pip)
|
| 314 |
+
- Added uv.lock for reproducible builds
|
| 315 |
+
- UV-specific installation and development instructions
|
| 316 |
+
- Improved documentation structure with multiple guides
|
| 317 |
+
- QUICK_START.md for 5-minute quickstart
|
| 318 |
+
- API_REFERENCE.md for complete API documentation
|
| 319 |
+
- PROMPT_ENGINEERING.md for advanced techniques
|
| 320 |
+
- SETUP_GUIDE.md for development setup
|
| 321 |
+
- TESTING_GUIDE.md for testing procedures
|
| 322 |
+
- Optional dependency groups for modular installation
|
| 323 |
+
- `observability` for Opik integration
|
| 324 |
+
- `demos` for browser automation examples
|
| 325 |
+
- `langchain` for LangChain support
|
| 326 |
+
- `transformers` for local model support
|
| 327 |
+
- `dev` for development tools
|
| 328 |
+
- `all` for all features combined
|
| 329 |
+
|
| 330 |
+
### Changed
|
| 331 |
+
- **Replaced explainability module with observability**
|
| 332 |
+
- Removed empty ace/explainability directory
|
| 333 |
+
- Migrated to production-grade Opik monitoring
|
| 334 |
+
- Updated all documentation to reflect this change
|
| 335 |
+
- Improved Python version requirements consistency (3.12 everywhere)
|
| 336 |
+
- Enhanced README with clearer examples and installation options
|
| 337 |
+
- Reorganized examples directory for better discoverability
|
| 338 |
+
- Updated CLAUDE.md with comprehensive codebase guidance
|
| 339 |
+
|
| 340 |
+
### Fixed
|
| 341 |
+
- Package configuration in pyproject.toml
|
| 342 |
+
- Documentation references to non-existent explainability module
|
| 343 |
+
- Python version inconsistencies across documentation files
|
| 344 |
+
|
| 345 |
+
### Removed
|
| 346 |
+
- Empty ace/explainability module (replaced by observability)
|
| 347 |
+
- Outdated references to explainability features in documentation
|
| 348 |
+
|
| 349 |
+
## [0.3.0] - 2025-10-16
|
| 350 |
+
|
| 351 |
+
### Added
|
| 352 |
+
- **Experimental v2 Prompts** with state-of-the-art prompt engineering
|
| 353 |
+
- Confidence scoring at bullet and answer levels
|
| 354 |
+
- Domain-specific variants for math and code generation
|
| 355 |
+
- Hierarchical structure with identity headers and metadata
|
| 356 |
+
- Concrete examples and anti-patterns for better guidance
|
| 357 |
+
- PromptManager for version control and A/B testing
|
| 358 |
+
- Comprehensive prompt engineering documentation (`docs/PROMPT_ENGINEERING.md`)
|
| 359 |
+
- Advanced examples demonstrating v2 prompts (`examples/advanced_prompts_v2.py`)
|
| 360 |
+
- Comparison script for v1 vs v2 prompts (`examples/compare_v1_v2_prompts.py`)
|
| 361 |
+
- Playbook persistence with `save_to_file()` and `load_from_file()` methods
|
| 362 |
+
- Example demonstrating playbook save/load functionality (`examples/playbook_persistence.py`)
|
| 363 |
+
- py.typed file for PEP 561 type hint support
|
| 364 |
+
- Mermaid flowchart visualization in README showing ACE learning loop
|
| 365 |
+
|
| 366 |
+
### Changed
|
| 367 |
+
- Enhanced docstrings with comprehensive examples throughout codebase
|
| 368 |
+
- Improved README with v2 prompts section and visual diagrams
|
| 369 |
+
- Updated formatting to comply with Black code style
|
| 370 |
+
|
| 371 |
+
### Fixed
|
| 372 |
+
- README incorrectly referenced non-existent docs/ directory
|
| 373 |
+
- Test badge URL in README (test.yml → tests.yml)
|
| 374 |
+
- Code formatting issues detected by GitHub Actions
|
| 375 |
+
|
| 376 |
+
## [0.2.0] - 2025-10-15
|
| 377 |
+
|
| 378 |
+
### Added
|
| 379 |
+
- LangChain integration via `LangChainLiteLLMClient` for advanced workflows
|
| 380 |
+
- Router support for load balancing across multiple model deployments
|
| 381 |
+
- Comprehensive example for LangChain usage (`examples/langchain_example.py`)
|
| 382 |
+
- Optional installation group: `pip install ace-framework[langchain]`
|
| 383 |
+
- PyPI badges and Quick Links section in README
|
| 384 |
+
- CHANGELOG.md for version tracking
|
| 385 |
+
|
| 386 |
+
### Fixed
|
| 387 |
+
- Parameter filtering in LiteLLM and LangChain clients (refinement_round, max_refinement_rounds)
|
| 388 |
+
- GitHub Actions workflow using deprecated artifact actions v3 → v4
|
| 389 |
+
|
| 390 |
+
### Changed
|
| 391 |
+
- Improved README with better structure and badges
|
| 392 |
+
- Updated .gitignore to exclude build artifacts and development files
|
| 393 |
+
|
| 394 |
+
### Removed
|
| 395 |
+
- Unnecessary development files from repository
|
| 396 |
+
|
| 397 |
+
## [0.1.1] - 2025-10-15
|
| 398 |
+
|
| 399 |
+
### Fixed
|
| 400 |
+
- GitHub Actions workflow for PyPI publishing
|
| 401 |
+
- Updated artifact upload/download actions from v3 to v4
|
| 402 |
+
|
| 403 |
+
## [0.1.0] - 2025-10-15
|
| 404 |
+
|
| 405 |
+
### Added
|
| 406 |
+
- Initial release of ACE Framework
|
| 407 |
+
- Core ACE implementation based on paper (arXiv:2510.04618)
|
| 408 |
+
- Three-role architecture: Generator, Reflector, and Curator
|
| 409 |
+
- Playbook system for storing and evolving strategies
|
| 410 |
+
- LiteLLM integration supporting 100+ LLM providers
|
| 411 |
+
- Offline and Online adaptation modes
|
| 412 |
+
- Async and streaming support
|
| 413 |
+
- Example scripts for quick start
|
| 414 |
+
- Comprehensive test suite
|
| 415 |
+
- PyPI packaging and GitHub Actions CI/CD
|
| 416 |
+
|
| 417 |
+
### Features
|
| 418 |
+
- Self-improving agents that learn from experience
|
| 419 |
+
- Delta operations for incremental playbook updates
|
| 420 |
+
- Support for OpenAI, Anthropic, Google, and more via LiteLLM
|
| 421 |
+
- Type hints and modern Python practices
|
| 422 |
+
- MIT licensed for open source use
|
| 423 |
+
|
| 424 |
+
[0.9.4]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.9.3...v0.9.4
|
| 425 |
+
[0.9.3]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.9.2...v0.9.3
|
| 426 |
+
[0.9.2]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.9.1...v0.9.2
|
| 427 |
+
[0.9.1]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.9.0...v0.9.1
|
| 428 |
+
[0.9.0]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.8.9...v0.9.0
|
| 429 |
+
[0.8.8]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.8.7...v0.8.8
|
| 430 |
+
[0.8.7]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.8.6...v0.8.7
|
| 431 |
+
[0.8.5]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.8.4...v0.8.5
|
| 432 |
+
[0.8.4]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.8.3...v0.8.4
|
| 433 |
+
[0.8.3]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.8.2...v0.8.3
|
| 434 |
+
[0.8.2]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.8.1...v0.8.2
|
| 435 |
+
[0.8.1]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.8.0...v0.8.1
|
| 436 |
+
[0.8.0]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.7.3...v0.8.0
|
| 437 |
+
[0.7.3]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.7.0...v0.7.3
|
| 438 |
+
[0.7.0]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.6.0...v0.7.0
|
| 439 |
+
[0.6.0]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.5.0...v0.6.0
|
| 440 |
+
[0.5.0]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.4.0...v0.5.0
|
| 441 |
+
[0.4.0]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.3.0...v0.4.0
|
| 442 |
+
[0.3.0]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.2.0...v0.3.0
|
| 443 |
+
[0.2.0]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.1.1...v0.2.0
|
| 444 |
+
[0.1.1]: https://github.com/Kayba-ai/agentic-context-engine/compare/v0.1.0...v0.1.1
|
| 445 |
+
[0.1.0]: https://github.com/Kayba-ai/agentic-context-engine/releases/tag/v0.1.0
|
CLAUDE.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CLAUDE.md
|
| 2 |
+
|
| 3 |
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
| 4 |
+
|
| 5 |
+
## Repository Guidelines
|
| 6 |
+
|
| 7 |
+
### Pipeline-First Development (MANDATORY)
|
| 8 |
+
**All new functionality MUST be implemented as pipeline Steps composed via the Pipeline engine.** Do NOT write standalone scripts, ad-hoc loops, or inline logic that bypasses the pipeline. Before writing any code:
|
| 9 |
+
|
| 10 |
+
1. Read `docs/design/PIPELINE_DESIGN.md` to understand the Step → Pipeline → Branch model.
|
| 11 |
+
2. Implement logic as a `Step` class with `requires`/`provides` declarations and a `__call__(self, ctx) -> ctx` method.
|
| 12 |
+
3. Compose steps using `Pipeline().then(...)` and `.branch(...)` — never manual for-loops or direct function chaining.
|
| 13 |
+
4. Use `StepContext.replace()` for immutable context updates — never mutate context directly.
|
| 14 |
+
5. Put integration-specific data in `metadata`, not new context fields, unless the field is shared across multiple pipelines.
|
| 15 |
+
|
| 16 |
+
**Anti-patterns to reject:**
|
| 17 |
+
- Writing a function that calls multiple steps manually instead of composing them in a Pipeline
|
| 18 |
+
- Inline reflection/evaluation logic instead of creating a ReflectStep or EvaluateStep
|
| 19 |
+
- Ad-hoc `ThreadPoolExecutor` usage instead of `async_boundary` and `max_workers` on steps
|
| 20 |
+
- Standalone scripts that duplicate pipeline functionality without using the pipeline engine
|
| 21 |
+
- Bypassing `requires`/`provides` contracts by accessing context fields not declared in `requires`
|
| 22 |
+
|
| 23 |
+
If a task seems like it cannot fit the pipeline model, explain why to the user before proceeding — do not silently circumvent it.
|
| 24 |
+
|
| 25 |
+
### Core Code Protection
|
| 26 |
+
**Do NOT modify core modules (`ace/core/`, `pipeline/`) without explicit user approval.** Before proposing any change to these directories:
|
| 27 |
+
1. Read the relevant design docs (`docs/design/ACE_ARCHITECTURE.md`, `docs/design/PIPELINE_DESIGN.md`) thoroughly.
|
| 28 |
+
2. Evaluate whether the change is truly required or if it can be achieved outside the core (e.g., in an integration, step, or example).
|
| 29 |
+
3. Clearly explain the proposed change and its justification to the user **before** making any edits.
|
| 30 |
+
4. Wait for the user to explicitly accept before proceeding.
|
| 31 |
+
|
| 32 |
+
### Documentation Maintenance
|
| 33 |
+
Before working on code in `ace/`, read `docs/design/ACE_ARCHITECTURE.md` to understand the current architecture.
|
| 34 |
+
Before working on code in `pipeline/` or `ace/core/`, read `docs/design/PIPELINE_DESIGN.md` to understand the pipeline engine.
|
| 35 |
+
|
| 36 |
+
**Docs MUST be kept in sync with code.** Any change that alters a public API, renames a concept, adds/removes a module, or changes execution flow **requires** a corresponding update to the relevant docs. Do not merge code changes that make the documentation inaccurate.
|
| 37 |
+
|
| 38 |
+
Key design docs:
|
| 39 |
+
- `docs/design/ACE_ARCHITECTURE.md` — ACE architecture: layers, core concepts, roles, steps, runners, integrations
|
| 40 |
+
- `docs/design/ACE_REFERENCE.md` — ACE code reference: full implementations, API signatures, usage examples
|
| 41 |
+
- `docs/design/ACE_DECISIONS.md` — design decisions and rejected alternatives (ACE, pipeline, migration)
|
| 42 |
+
- `docs/design/PIPELINE_DESIGN.md` — pipeline engine: steps, StepProtocol, Pipeline, Branch, concurrency
|
| 43 |
+
- If you need to work with collected traces from Logfire, read `agent-guides/logfire.md`
|
| 44 |
+
|
| 45 |
+
### Project Structure
|
| 46 |
+
- `ace/` — core library: roles (PydanticAI-backed), skillbook, steps, runners, providers, RR, integrations, observability
|
| 47 |
+
- `pipeline/` — generic pipeline engine that `ace` is built on (see `docs/design/PIPELINE_DESIGN.md`)
|
| 48 |
+
- `ace-eval/` — evaluation framework (submodule, separate repo)
|
| 49 |
+
- `tests/` — unit/integration tests (pytest)
|
| 50 |
+
- `examples/` — runnable demos grouped by integration
|
| 51 |
+
- `agent-guides/` — internal development guides for LLM agents; not part of the public docs site
|
| 52 |
+
- `docs/` — guides and reference material
|
| 53 |
+
- `docs/design/ACE_ARCHITECTURE.md` — architecture and concepts (keep in sync with code)
|
| 54 |
+
- `docs/design/ACE_REFERENCE.md` — code reference and examples (keep in sync with code)
|
| 55 |
+
- `docs/design/ACE_DECISIONS.md` — design decisions and rejected alternatives
|
| 56 |
+
- `docs/design/PIPELINE_DESIGN.md` — pipeline engine design doc (keep in sync with code)
|
| 57 |
+
|
| 58 |
+
### Commands
|
| 59 |
+
- `uv sync` — install all dependencies
|
| 60 |
+
- `uv run pytest` — run tests (excludes `integration` and `requires_api` markers by default)
|
| 61 |
+
- `uv run pytest -m unit` / `-m integration` / `-m slow` — run by marker
|
| 62 |
+
- `uv run black ace/ tests/ examples/` — format code
|
| 63 |
+
- `uv run mypy ace/` — type check
|
| 64 |
+
|
| 65 |
+
### Coding Style
|
| 66 |
+
- PEP 8 with Black formatting (line length 88)
|
| 67 |
+
- Type hints and docstrings for public APIs
|
| 68 |
+
- Python 3.12 target
|
| 69 |
+
- Test files: `tests/test_*.py`; functions: `test_*`; classes: `Test*`
|
| 70 |
+
|
| 71 |
+
### Testing
|
| 72 |
+
- Pytest is the primary runner
|
| 73 |
+
- Add tests for new features; include regression tests for bug fixes
|
| 74 |
+
|
| 75 |
+
### Commits
|
| 76 |
+
- Conventional Commits: `feat(scope): subject`, `fix(scope): subject`
|
| 77 |
+
- Do NOT add `Co-Authored-By` trailers to commit messages
|
| 78 |
+
- PRs should include description, test results, and relevant docs updates
|
| 79 |
+
|
| 80 |
+
### ACE Roles (quick reference)
|
| 81 |
+
|
| 82 |
+
| Role | Responsibility | Key Class |
|
| 83 |
+
|------|---------------|-----------|
|
| 84 |
+
| **Agent** | Executes tasks using skillbook strategies | `Agent` |
|
| 85 |
+
| **Reflector** | Analyzes execution results | `Reflector` |
|
| 86 |
+
| **SkillManager** | Updates the skillbook with new strategies | `SkillManager` |
|
| 87 |
+
|
| 88 |
+
### Integration Runners
|
| 89 |
+
|
| 90 |
+
| Runner | Framework | Use Case |
|
| 91 |
+
|--------|-----------|----------|
|
| 92 |
+
| `ACELiteLLM` | LiteLLM (100+ providers) | Simple self-improving agent |
|
| 93 |
+
| `ACELangChain` | LangChain | Wrap chains/agents with learning |
|
| 94 |
+
| `ACEBrowserUse` | browser-use | Browser automation with learning |
|
| 95 |
+
| `ACEClaudeCode` | Claude Code CLI | Coding tasks with learning |
|
| 96 |
+
|
| 97 |
+
NEVER USE FALLBACKS OR IMPLEMENT THINGS I NEVER ASKED FOR.
|
| 98 |
+
|
| 99 |
+
Keep your answers concise and to the point. If you don't know something, say you don't know instead of making assumptions or fabricating information. Always ask clarifying questions if the user's request is ambiguous or lacks necessary details.
|
CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
**By submitting a pull request to this repository, you agree to the terms below.**
|
| 2 |
+
|
| 3 |
+
## Contributor Terms
|
| 4 |
+
|
| 5 |
+
(a) The contribution is your original work and you have the right to submit it.
|
| 6 |
+
(b) You license your contribution under the project's current license (Apache-2.0).
|
| 7 |
+
(c) You grant the maintainers the right to relicense your contribution as part of the project under any future open-source or commercial license.
|
| 8 |
+
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
# Contributing to ACE Framework
|
| 12 |
+
|
| 13 |
+
Thank you for your interest in contributing to the Agentic Context Engine! We welcome contributions from the community.
|
| 14 |
+
|
| 15 |
+
## How to Contribute
|
| 16 |
+
|
| 17 |
+
### Reporting Bugs
|
| 18 |
+
|
| 19 |
+
Before creating bug reports, please check existing issues to avoid duplicates. When creating a bug report, include:
|
| 20 |
+
|
| 21 |
+
- A clear and descriptive title
|
| 22 |
+
- Steps to reproduce the issue
|
| 23 |
+
- Expected behavior vs actual behavior
|
| 24 |
+
- Environment details (OS, Python version, package versions)
|
| 25 |
+
- Any relevant error messages or logs
|
| 26 |
+
|
| 27 |
+
### Suggesting Enhancements
|
| 28 |
+
|
| 29 |
+
Enhancement suggestions are welcome! Please provide:
|
| 30 |
+
|
| 31 |
+
- A clear description of the enhancement
|
| 32 |
+
- Use cases and benefits
|
| 33 |
+
- Possible implementation approach (optional)
|
| 34 |
+
- Any potential drawbacks or considerations
|
| 35 |
+
|
| 36 |
+
### Pull Requests
|
| 37 |
+
|
| 38 |
+
1. Fork the repository
|
| 39 |
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
| 40 |
+
3. Make your changes
|
| 41 |
+
4. Run tests to ensure nothing breaks
|
| 42 |
+
5. Commit your changes using conventional commits (see below)
|
| 43 |
+
6. Push to your branch
|
| 44 |
+
7. Open a Pull Request
|
| 45 |
+
|
| 46 |
+
## Branch Naming Convention
|
| 47 |
+
|
| 48 |
+
Use consistent prefixes for branch names:
|
| 49 |
+
|
| 50 |
+
| Prefix | Purpose | Example |
|
| 51 |
+
|--------|---------|---------|
|
| 52 |
+
| `feature/` | New features | `feature/john/benchmarks` |
|
| 53 |
+
| `fix/` | Bug fixes | `fix/jane/memory-leak` |
|
| 54 |
+
| `docs/` | Documentation changes | `docs/john/api-reference` |
|
| 55 |
+
| `refactor/` | Code refactoring | `refactor/jane/llm-client` |
|
| 56 |
+
| `test/` | Test additions/fixes | `test/john/integration-suite` |
|
| 57 |
+
| `chore/` | Maintenance tasks | `chore/jane/update-deps` |
|
| 58 |
+
|
| 59 |
+
**Format:** `<type>/<developer>/<description>`
|
| 60 |
+
|
| 61 |
+
**Rules:**
|
| 62 |
+
- Use lowercase with hyphens (kebab-case)
|
| 63 |
+
- Use your GitHub username or first name as developer identifier
|
| 64 |
+
- Keep descriptions short but descriptive
|
| 65 |
+
- Include issue number if applicable: `fix/john/123-login-error`
|
| 66 |
+
- Never push directly to `main` - always use feature branches
|
| 67 |
+
|
| 68 |
+
## Worktree Workflow
|
| 69 |
+
|
| 70 |
+
We use git worktrees to work on multiple branches simultaneously without switching. Each branch gets its own directory.
|
| 71 |
+
|
| 72 |
+
### Claude Code Commands
|
| 73 |
+
|
| 74 |
+
| Command | Description | Example |
|
| 75 |
+
|---------|-------------|---------|
|
| 76 |
+
| `/create-branch` | Create branch + worktree | `/create-branch feature add-caching` |
|
| 77 |
+
| `/checkout-branch` | Switch to branch (creates worktree if needed) | `/checkout-branch add-caching` |
|
| 78 |
+
| `/list-branches` | List branches with worktree status | `/list-branches` or `/list-branches feature` |
|
| 79 |
+
| `/remove-branch` | Remove branch + worktree | `/remove-branch feature/john/add-caching` |
|
| 80 |
+
|
| 81 |
+
### Worktree Path Convention
|
| 82 |
+
|
| 83 |
+
Worktrees are created as siblings to the main worktree:
|
| 84 |
+
- Branch: `feature/john/add-caching`
|
| 85 |
+
- Worktree: `../feature-john-add-caching`
|
| 86 |
+
|
| 87 |
+
### Manual Worktree Commands
|
| 88 |
+
|
| 89 |
+
```bash
|
| 90 |
+
# List all worktrees
|
| 91 |
+
git worktree list
|
| 92 |
+
|
| 93 |
+
# Add worktree for existing branch
|
| 94 |
+
git worktree add ../path-name branch-name
|
| 95 |
+
|
| 96 |
+
# Add worktree with new branch
|
| 97 |
+
git worktree add -b new-branch ../path-name
|
| 98 |
+
|
| 99 |
+
# Remove worktree
|
| 100 |
+
git worktree remove ../path-name
|
| 101 |
+
|
| 102 |
+
# Prune stale worktree references
|
| 103 |
+
git worktree prune
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
### Benefits
|
| 107 |
+
|
| 108 |
+
- **Parallel development**: Work on multiple features without stashing
|
| 109 |
+
- **Faster context switching**: No need to rebuild dependencies
|
| 110 |
+
- **Cleaner git history**: No accidental commits to wrong branch
|
| 111 |
+
- **IDE-friendly**: Open each worktree in separate IDE windows
|
| 112 |
+
|
| 113 |
+
## Development Setup
|
| 114 |
+
|
| 115 |
+
```bash
|
| 116 |
+
# Clone your fork
|
| 117 |
+
git clone https://github.com/your-username/agentic-context-engine.git
|
| 118 |
+
cd agentic-context-engine
|
| 119 |
+
|
| 120 |
+
# Install all dependencies (uses UV - 10-100x faster than pip)
|
| 121 |
+
uv sync
|
| 122 |
+
|
| 123 |
+
# Run tests
|
| 124 |
+
uv run pytest
|
| 125 |
+
|
| 126 |
+
# Run linting and formatting
|
| 127 |
+
uv run black ace/ tests/ examples/
|
| 128 |
+
uv run mypy ace/
|
| 129 |
+
|
| 130 |
+
# Run specific test files
|
| 131 |
+
uv run pytest tests/test_skillbook.py
|
| 132 |
+
uv run pytest -m unit # Only unit tests
|
| 133 |
+
uv run pytest -m integration # Only integration tests
|
| 134 |
+
```
|
| 135 |
+
|
| 136 |
+
## Commit Message Format
|
| 137 |
+
|
| 138 |
+
We use [Conventional Commits](https://www.conventionalcommits.org/) for clear commit history and automatic changelog generation.
|
| 139 |
+
|
| 140 |
+
Format: `<type>(<scope>): <subject>`
|
| 141 |
+
|
| 142 |
+
Types:
|
| 143 |
+
- `feat`: New feature
|
| 144 |
+
- `fix`: Bug fix
|
| 145 |
+
- `docs`: Documentation only
|
| 146 |
+
- `style`: Code style changes (formatting, etc.)
|
| 147 |
+
- `refactor`: Code refactoring
|
| 148 |
+
- `test`: Adding tests
|
| 149 |
+
- `chore`: Maintenance tasks
|
| 150 |
+
|
| 151 |
+
Examples:
|
| 152 |
+
```
|
| 153 |
+
feat(llm): add support for new LLM provider
|
| 154 |
+
fix(adapter): resolve memory leak in online mode
|
| 155 |
+
docs(readme): update installation instructions
|
| 156 |
+
```
|
| 157 |
+
|
| 158 |
+
## Code Style
|
| 159 |
+
|
| 160 |
+
- Follow PEP 8
|
| 161 |
+
- Use type hints where possible
|
| 162 |
+
- Add docstrings to all public functions and classes
|
| 163 |
+
- Keep line length under 100 characters
|
| 164 |
+
- Use Black for automatic formatting
|
| 165 |
+
|
| 166 |
+
## Testing
|
| 167 |
+
|
| 168 |
+
- Write tests for new features
|
| 169 |
+
- Ensure all tests pass before submitting PR
|
| 170 |
+
- Aim for good test coverage
|
| 171 |
+
- Use meaningful test names
|
| 172 |
+
|
| 173 |
+
## Documentation
|
| 174 |
+
|
| 175 |
+
- Update README.md if adding new features
|
| 176 |
+
- Add docstrings to new code
|
| 177 |
+
- Update CHANGELOG.md following Keep a Changelog format
|
| 178 |
+
- Include examples for new functionality
|
| 179 |
+
|
| 180 |
+
## Questions?
|
| 181 |
+
|
| 182 |
+
Feel free to open an issue for any questions or join the discussion in [GitHub Discussions](https://github.com/Kayba-ai/agentic-context-engine/discussions).
|
| 183 |
+
|
Dockerfile
CHANGED
|
@@ -1,19 +1,20 @@
|
|
| 1 |
-
FROM
|
| 2 |
|
| 3 |
WORKDIR /app
|
| 4 |
|
| 5 |
-
# Install
|
| 6 |
-
RUN
|
| 7 |
|
| 8 |
-
|
| 9 |
-
|
| 10 |
|
| 11 |
-
# Install
|
| 12 |
-
|
| 13 |
-
RUN
|
| 14 |
-
|
| 15 |
-
|
| 16 |
|
| 17 |
EXPOSE 7860
|
| 18 |
|
|
|
|
| 19 |
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
|
|
|
|
| 1 |
+
FROM python:3.10-slim
|
| 2 |
|
| 3 |
WORKDIR /app
|
| 4 |
|
| 5 |
+
# Install uv for fast dependency resolution as recommended by ACE
|
| 6 |
+
RUN pip install uv
|
| 7 |
|
| 8 |
+
# Copy the ACE repository and our FastAPI files
|
| 9 |
+
COPY . /app
|
| 10 |
|
| 11 |
+
# Install ACE framework using uv (referencing the local pyproject.toml in the cloned repo)
|
| 12 |
+
# and install FastAPI components
|
| 13 |
+
RUN uv pip install --system fastapi uvicorn pydantic litellm
|
| 14 |
+
# Since the cloned directory has pyproject.toml, we can install the local package
|
| 15 |
+
RUN uv pip install --system -e .
|
| 16 |
|
| 17 |
EXPOSE 7860
|
| 18 |
|
| 19 |
+
# We need the user to pass API keys in Space Secrets (e.g. OPENAI_API_KEY, GROQ_API_KEY)
|
| 20 |
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
|
LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Apache License
|
| 2 |
+
Version 2.0, January 2004
|
| 3 |
+
http://www.apache.org/licenses/
|
| 4 |
+
|
| 5 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 6 |
+
|
| 7 |
+
1. Definitions.
|
| 8 |
+
|
| 9 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
| 10 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
| 11 |
+
|
| 12 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
| 13 |
+
the copyright owner that is granting the License.
|
| 14 |
+
|
| 15 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
| 16 |
+
other entities that control, are controlled by, or are under common
|
| 17 |
+
control with that entity. For the purposes of this definition,
|
| 18 |
+
"control" means (i) the power, direct or indirect, to cause the
|
| 19 |
+
direction or management of such entity, whether by contract or
|
| 20 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 21 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 22 |
+
|
| 23 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
| 24 |
+
exercising permissions granted by this License.
|
| 25 |
+
|
| 26 |
+
"Source" form shall mean the preferred form for making modifications,
|
| 27 |
+
including but not limited to software source code, documentation
|
| 28 |
+
source, and configuration files.
|
| 29 |
+
|
| 30 |
+
"Object" form shall mean any form resulting from mechanical
|
| 31 |
+
transformation or translation of a Source form, including but
|
| 32 |
+
not limited to compiled object code, generated documentation,
|
| 33 |
+
and conversions to other media types.
|
| 34 |
+
|
| 35 |
+
"Work" shall mean the work of authorship, whether in Source or
|
| 36 |
+
Object form, made available under the License, as indicated by a
|
| 37 |
+
copyright notice that is included in or attached to the work
|
| 38 |
+
(an example is provided in the Appendix below).
|
| 39 |
+
|
| 40 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
| 41 |
+
form, that is based on (or derived from) the Work and for which the
|
| 42 |
+
editorial revisions, annotations, elaborations, or other modifications
|
| 43 |
+
represent, as a whole, an original work of authorship. For the purposes
|
| 44 |
+
of this License, Derivative Works shall not include works that remain
|
| 45 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
| 46 |
+
the Work and Derivative Works thereof.
|
| 47 |
+
|
| 48 |
+
"Contribution" shall mean any work of authorship, including
|
| 49 |
+
the original version of the Work and any modifications or additions
|
| 50 |
+
to that Work or Derivative Works thereof, that is intentionally
|
| 51 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 52 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
| 53 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
| 54 |
+
means any form of electronic, verbal, or written communication sent
|
| 55 |
+
to the Licensor or its representatives, including but not limited to
|
| 56 |
+
communication on electronic mailing lists, source code control systems,
|
| 57 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
| 58 |
+
Licensor for the purpose of discussing and improving the Work, but
|
| 59 |
+
excluding communication that is conspicuously marked or otherwise
|
| 60 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 61 |
+
|
| 62 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 63 |
+
on behalf of whom a Contribution has been received by Licensor and
|
| 64 |
+
subsequently incorporated within the Work.
|
| 65 |
+
|
| 66 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 67 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 68 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 69 |
+
copyright license to reproduce, prepare Derivative Works of,
|
| 70 |
+
publicly display, publicly perform, sublicense, and distribute the
|
| 71 |
+
Work and such Derivative Works in Source or Object form.
|
| 72 |
+
|
| 73 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
| 74 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 75 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 76 |
+
(except as stated in this section) patent license to make, have made,
|
| 77 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 78 |
+
where such license applies only to those patent claims licensable
|
| 79 |
+
by such Contributor that are necessarily infringed by their
|
| 80 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
| 81 |
+
with the Work to which such Contribution(s) was submitted. If You
|
| 82 |
+
institute patent litigation against any entity (including a
|
| 83 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 84 |
+
or a Contribution incorporated within the Work constitutes direct
|
| 85 |
+
or contributory patent infringement, then any patent licenses
|
| 86 |
+
granted to You under this License for that Work shall terminate
|
| 87 |
+
as of the date such litigation is filed.
|
| 88 |
+
|
| 89 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
| 90 |
+
Work or Derivative Works thereof in any medium, with or without
|
| 91 |
+
modifications, and in Source or Object form, provided that You
|
| 92 |
+
meet the following conditions:
|
| 93 |
+
|
| 94 |
+
(a) You must give any other recipients of the Work or
|
| 95 |
+
Derivative Works a copy of this License; and
|
| 96 |
+
|
| 97 |
+
(b) You must cause any modified files to carry prominent notices
|
| 98 |
+
stating that You changed the files; and
|
| 99 |
+
|
| 100 |
+
(c) You must retain, in the Source form of any Derivative Works
|
| 101 |
+
that You distribute, all copyright, patent, trademark, and
|
| 102 |
+
attribution notices from the Source form of the Work,
|
| 103 |
+
excluding those notices that do not pertain to any part of
|
| 104 |
+
the Derivative Works; and
|
| 105 |
+
|
| 106 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
| 107 |
+
distribution, then any Derivative Works that You distribute must
|
| 108 |
+
include a readable copy of the attribution notices contained
|
| 109 |
+
within such NOTICE file, excluding those notices that do not
|
| 110 |
+
pertain to any part of the Derivative Works, in at least one
|
| 111 |
+
of the following places: within a NOTICE text file distributed
|
| 112 |
+
as part of the Derivative Works; within the Source form or
|
| 113 |
+
documentation, if provided along with the Derivative Works; or,
|
| 114 |
+
within a display generated by the Derivative Works, if and
|
| 115 |
+
wherever such third-party notices normally appear. The contents
|
| 116 |
+
of the NOTICE file are for informational purposes only and
|
| 117 |
+
do not modify the License. You may add Your own attribution
|
| 118 |
+
notices within Derivative Works that You distribute, alongside
|
| 119 |
+
or as an addendum to the NOTICE text from the Work, provided
|
| 120 |
+
that such additional attribution notices cannot be construed
|
| 121 |
+
as modifying the License.
|
| 122 |
+
|
| 123 |
+
You may add Your own copyright statement to Your modifications and
|
| 124 |
+
may provide additional or different license terms and conditions
|
| 125 |
+
for use, reproduction, or distribution of Your modifications, or
|
| 126 |
+
for any such Derivative Works as a whole, provided Your use,
|
| 127 |
+
reproduction, and distribution of the Work otherwise complies with
|
| 128 |
+
the conditions stated in this License.
|
| 129 |
+
|
| 130 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 131 |
+
any Contribution intentionally submitted for inclusion in the Work
|
| 132 |
+
by You to the Licensor shall be under the terms and conditions of
|
| 133 |
+
this License, without any additional terms or conditions.
|
| 134 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
| 135 |
+
the terms of any separate license agreement you may have executed
|
| 136 |
+
with Licensor regarding such Contributions.
|
| 137 |
+
|
| 138 |
+
6. Trademarks. This License does not grant permission to use the trade
|
| 139 |
+
names, trademarks, service marks, or product names of the Licensor,
|
| 140 |
+
except as required for reasonable and customary use in describing the
|
| 141 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
| 142 |
+
|
| 143 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 144 |
+
agreed to in writing, Licensor provides the Work (and each
|
| 145 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 146 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 147 |
+
implied, including, without limitation, any warranties or conditions
|
| 148 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 149 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 150 |
+
appropriateness of using or redistributing the Work and assume any
|
| 151 |
+
risks associated with Your exercise of permissions under this License.
|
| 152 |
+
|
| 153 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
| 154 |
+
whether in tort (including negligence), contract, or otherwise,
|
| 155 |
+
unless required by applicable law (such as deliberate and grossly
|
| 156 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
| 157 |
+
liable to You for damages, including any direct, indirect, special,
|
| 158 |
+
incidental, or consequential damages of any character arising as a
|
| 159 |
+
result of this License or out of the use or inability to use the
|
| 160 |
+
Work (including but not limited to damages for loss of goodwill,
|
| 161 |
+
work stoppage, computer failure or malfunction, or any and all
|
| 162 |
+
other commercial damages or losses), even if such Contributor
|
| 163 |
+
has been advised of the possibility of such damages.
|
| 164 |
+
|
| 165 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
| 166 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
| 167 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 168 |
+
or other liability obligations and/or rights consistent with this
|
| 169 |
+
License. However, in accepting such obligations, You may act only
|
| 170 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
| 171 |
+
of any other Contributor, and only if You agree to indemnify,
|
| 172 |
+
defend, and hold each Contributor harmless for any liability
|
| 173 |
+
incurred by, or claims asserted against, such Contributor by reason
|
| 174 |
+
of your accepting any such warranty or additional liability.
|
| 175 |
+
|
| 176 |
+
END OF TERMS AND CONDITIONS
|
| 177 |
+
|
| 178 |
+
APPENDIX: How to apply the Apache License to your work.
|
| 179 |
+
|
| 180 |
+
To apply the Apache License to your work, attach the following
|
| 181 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
| 182 |
+
replaced with your own identifying information. (Don't include
|
| 183 |
+
the brackets!) The text should be enclosed in the appropriate
|
| 184 |
+
comment syntax for the file format. We also recommend that a
|
| 185 |
+
file or class name and description of purpose be included on the
|
| 186 |
+
same "printed page" as the copyright notice for easier
|
| 187 |
+
identification within third-party archives.
|
| 188 |
+
|
| 189 |
+
Copyright [yyyy] [name of copyright owner]
|
| 190 |
+
|
| 191 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 192 |
+
you may not use this file except in compliance with the License.
|
| 193 |
+
You may obtain a copy of the License at
|
| 194 |
+
|
| 195 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 196 |
+
|
| 197 |
+
Unless required by applicable law or agreed to in writing, software
|
| 198 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 199 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 200 |
+
See the License for the specific language governing permissions and
|
| 201 |
+
limitations under the License.
|
README.md
CHANGED
|
@@ -1,10 +1,224 @@
|
|
| 1 |
-
--
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<a href="https://kayba.ai"><img src="assets/kayba-banner.png" alt="Kayba - Stop fixing agents by hand" width="1080"/></a>
|
| 2 |
+
|
| 3 |
+
# Agentic Context Engine (ACE)
|
| 4 |
+
|
| 5 |
+
[](https://github.com/kayba-ai/agentic-context-engine/stargazers)
|
| 6 |
+
[](https://kayba.ai)
|
| 7 |
+
[](https://discord.gg/mqCqH7sTyK)
|
| 8 |
+
[](https://twitter.com/kaybaai)
|
| 9 |
+
[](https://kayba-ai.github.io/agentic-context-engine/latest/)
|
| 10 |
+
|
| 11 |
+
> [!TIP]
|
| 12 |
+
> ACE is the open-source engine behind [Kayba](https://kayba.ai). If you'd rather have the whole loop managed for you, from failure investigation to fixes shipped as PRs, [get a demo](https://kayba.ai).
|
| 13 |
+
|
| 14 |
+
---
|
| 15 |
+
|
| 16 |
+
**AI agents don't learn from experience.** They repeat the same mistakes every session, forget what worked, and ignore what failed. ACE is the open-source engine that adds a persistent learning loop. It also powers [Kayba](https://kayba.ai), the managed service that does this for your production agents automatically.
|
| 17 |
+
|
| 18 |
+
<img src="examples/seahorse-emoji-ace.gif" alt="ACE learns from mistakes in real time" width="70%"/>
|
| 19 |
+
|
| 20 |
+
> The agent claims a seahorse emoji exists. ACE reflects on the error, and on the next attempt, the agent responds correctly — without human intervention.
|
| 21 |
+
|
| 22 |
+
---
|
| 23 |
+
|
| 24 |
+
## Proven Results
|
| 25 |
+
|
| 26 |
+
| Metric | Result | Context |
|
| 27 |
+
|:-------|:-------|:--------|
|
| 28 |
+
| **2x consistency** | Doubles pass^4 on Tau2 airline benchmark | 15 learned strategies, no reward signals |
|
| 29 |
+
| **49% token reduction** | Browser automation costs cut nearly in half | 10-run learning curve |
|
| 30 |
+
| **$1.50 learning cost** | Claude Code translated 14k lines to TypeScript | Zero build errors, all tests passing |
|
| 31 |
+
|
| 32 |
+
---
|
| 33 |
+
|
| 34 |
+
## Quick Start
|
| 35 |
+
|
| 36 |
+
```bash
|
| 37 |
+
uv add ace-framework
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
**Option A** — Interactive setup (recommended):
|
| 41 |
+
|
| 42 |
+
```bash
|
| 43 |
+
ace setup # Walks you through model selection, API keys, and connection validation
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
**Option B** — Manual configuration:
|
| 47 |
+
|
| 48 |
+
```bash
|
| 49 |
+
export OPENAI_API_KEY="your-key" # or ANTHROPIC_API_KEY, or any of 100+ supported providers
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
Then use it:
|
| 53 |
+
|
| 54 |
+
```python
|
| 55 |
+
from ace import ACELiteLLM
|
| 56 |
+
|
| 57 |
+
agent = ACELiteLLM(model="gpt-4o-mini")
|
| 58 |
+
|
| 59 |
+
# First attempt — the agent may hallucinate
|
| 60 |
+
answer = agent.ask("Is there a seahorse emoji?")
|
| 61 |
+
|
| 62 |
+
# Feed a correction — ACE extracts a strategy and updates the Skillbook
|
| 63 |
+
agent.learn_from_feedback("There is no seahorse emoji in Unicode.")
|
| 64 |
+
|
| 65 |
+
# Subsequent calls benefit from the learned strategy
|
| 66 |
+
answer = agent.ask("Is there a seahorse emoji?")
|
| 67 |
+
|
| 68 |
+
# Inspect what the agent has learned
|
| 69 |
+
print(agent.get_strategies())
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
No fine-tuning, no training data, no vector database.
|
| 73 |
+
|
| 74 |
+
[-> Quick Start Guide](https://kayba-ai.github.io/agentic-context-engine/latest/getting-started/quick-start/) | [-> Setup Guide](https://kayba-ai.github.io/agentic-context-engine/latest/getting-started/setup/) | [-> Hosted API: Where Do Traces Come From?](https://kayba-ai.github.io/agentic-context-engine/latest/integrations/hosted-api/#where-do-traces-come-from)
|
| 75 |
+
|
| 76 |
+
---
|
| 77 |
+
|
| 78 |
+
## How It Works
|
| 79 |
+
|
| 80 |
+
ACE maintains a **Skillbook** — a persistent collection of strategies that evolves with every task. Three specialized roles manage the learning loop:
|
| 81 |
+
|
| 82 |
+
| Role | Responsibility |
|
| 83 |
+
|:-----|:---------------|
|
| 84 |
+
| **Agent** | Executes tasks, enhanced with Skillbook strategies |
|
| 85 |
+
| **Reflector** | Analyzes execution traces to extract what worked and what failed |
|
| 86 |
+
| **SkillManager** | Curates the Skillbook — adds, refines, and removes strategies |
|
| 87 |
+
|
| 88 |
+
The **Recursive Reflector** is the key innovation: instead of summarizing traces in a single pass, it writes and executes Python code in a sandboxed environment to programmatically search for patterns, isolate errors, and iterate until it finds actionable insights.
|
| 89 |
+
|
| 90 |
+
```mermaid
|
| 91 |
+
flowchart LR
|
| 92 |
+
Skillbook[(Skillbook)]
|
| 93 |
+
Start([Task]) --> Agent[Agent]
|
| 94 |
+
Agent <--> Environment[Environment]
|
| 95 |
+
Environment -- Trace --> Reflector[Reflector]
|
| 96 |
+
Reflector --> SkillManager[SkillManager]
|
| 97 |
+
SkillManager -- Updates --> Skillbook
|
| 98 |
+
Skillbook -. Strategies .-> Agent
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
All roles are backed by [PydanticAI](https://ai.pydantic.dev/) agents with structured output validation. PydanticAI routes to 100+ LLM providers through its LiteLLM integration, with native support for OpenAI, Anthropic, Google, Bedrock, Groq, and more.
|
| 102 |
+
|
| 103 |
+
*Based on the [ACE paper](https://arxiv.org/abs/2510.04618) (Stanford & SambaNova) and [Dynamic Cheatsheet](https://arxiv.org/abs/2504.07952).*
|
| 104 |
+
|
| 105 |
+
---
|
| 106 |
+
|
| 107 |
+
## Runners
|
| 108 |
+
|
| 109 |
+
| Runner | Class | Description |
|
| 110 |
+
|:-------|:------|:------------|
|
| 111 |
+
| **LiteLLM** | `ACELiteLLM` | Batteries-included agent with `.ask()`, `.learn()`, `.save()` — accepts any [LiteLLM model string](https://docs.litellm.ai/docs/providers) |
|
| 112 |
+
| **Core** | `ACE` | Full learning loop with batch epochs and evaluation |
|
| 113 |
+
| **Trace Analyser** | `TraceAnalyser` | Learn from pre-recorded traces without re-running tasks |
|
| 114 |
+
| **browser-use** | `BrowserUse` | Browser automation that improves with each run |
|
| 115 |
+
| **LangChain** | `LangChain` | Wrap any LangChain chain or agent with learning |
|
| 116 |
+
| **Claude Code** | `ClaudeCode` | Claude Code CLI tasks with learning |
|
| 117 |
+
|
| 118 |
+
```bash
|
| 119 |
+
uv add 'ace-framework[browser-use]' # Browser automation
|
| 120 |
+
uv add 'ace-framework[langchain]' # LangChain
|
| 121 |
+
uv add 'ace-framework[logfire]' # Observability (auto-instruments PydanticAI)
|
| 122 |
+
uv add 'ace-framework[mcp]' # MCP server for IDE integration
|
| 123 |
+
uv add 'ace-framework[deduplication]' # Embedding-based skill deduplication
|
| 124 |
+
```
|
| 125 |
+
|
| 126 |
+
Have existing agent logs? Extract strategies from them directly:
|
| 127 |
+
|
| 128 |
+
```python
|
| 129 |
+
from ace import ACELiteLLM
|
| 130 |
+
|
| 131 |
+
agent = ACELiteLLM(model="gpt-4o-mini")
|
| 132 |
+
agent.learn_from_traces(your_existing_traces)
|
| 133 |
+
print(agent.get_strategies())
|
| 134 |
+
```
|
| 135 |
+
|
| 136 |
+
[-> Examples](examples/)
|
| 137 |
+
|
| 138 |
+
---
|
| 139 |
+
|
| 140 |
+
## Benchmarks
|
| 141 |
+
|
| 142 |
+
### Tau2 — Multi-Step Agentic Tasks
|
| 143 |
+
|
| 144 |
+
[tau2-bench](https://github.com/sierra-research/tau2-bench) by Sierra Research: airline domain tasks requiring tool use and policy adherence. Claude Haiku 4.5 agent, strategies learned on the train split with no reward signals, evaluated on the held-out test split.
|
| 145 |
+
|
| 146 |
+
<img src="benchmarks/tasks/tau_bench/Tau2Benchmark Result Haiku4.5.png" alt="Tau2 Benchmark — ACE doubles consistency at pass^4" width="35%"/>
|
| 147 |
+
|
| 148 |
+
*pass^k = probability all k independent attempts succeed. ACE doubles consistency at pass^4 with 15 learned strategies.*
|
| 149 |
+
|
| 150 |
+
### Claude Code — Autonomous Translation
|
| 151 |
+
|
| 152 |
+
ACE + Claude Code translated this library from Python to TypeScript with zero supervision:
|
| 153 |
+
|
| 154 |
+
| Metric | Result |
|
| 155 |
+
|:-------|:-------|
|
| 156 |
+
| Duration | ~4 hours |
|
| 157 |
+
| Commits | 119 |
|
| 158 |
+
| Lines written | ~14,000 |
|
| 159 |
+
| Build errors | 0 |
|
| 160 |
+
| Tests | All passing |
|
| 161 |
+
| Learning cost | ~$1.50 |
|
| 162 |
+
|
| 163 |
+
---
|
| 164 |
+
|
| 165 |
+
## Pipeline Architecture
|
| 166 |
+
|
| 167 |
+
ACE is built on a composable pipeline engine. Each step declares what it requires and what it produces:
|
| 168 |
+
|
| 169 |
+
```
|
| 170 |
+
AgentStep -> EvaluateStep -> ReflectStep -> UpdateStep -> DeduplicateStep
|
| 171 |
+
```
|
| 172 |
+
|
| 173 |
+
Use `learning_tail()` for the standard learning sequence, or compose custom pipelines:
|
| 174 |
+
|
| 175 |
+
```python
|
| 176 |
+
from ace import Pipeline, AgentStep, EvaluateStep, learning_tail
|
| 177 |
+
|
| 178 |
+
steps = [AgentStep(agent, skillbook), EvaluateStep(env)] + learning_tail(reflector, skill_manager, skillbook)
|
| 179 |
+
pipeline = Pipeline(steps)
|
| 180 |
+
```
|
| 181 |
+
|
| 182 |
+
The pipeline engine ([`pipeline/`](pipeline/)) is framework-agnostic with `requires`/`provides` contracts, immutable context, and error isolation. See [Pipeline Design](docs/design/PIPELINE_DESIGN.md) and [Architecture](docs/design/ACE_ARCHITECTURE.md).
|
| 183 |
+
|
| 184 |
+
---
|
| 185 |
+
|
| 186 |
+
## CLI
|
| 187 |
+
|
| 188 |
+
| Command | Description |
|
| 189 |
+
|:--------|:------------|
|
| 190 |
+
| `ace setup` | Interactive setup — model selection, API keys, connection validation |
|
| 191 |
+
| `ace models <query>` | Search available models with pricing |
|
| 192 |
+
| `ace validate <model>` | Test a model connection |
|
| 193 |
+
| `ace config` | Show current configuration |
|
| 194 |
+
| `kayba` | Cloud CLI — upload traces, fetch insights, manage prompts |
|
| 195 |
+
| `ace-mcp` | MCP server for IDE integration |
|
| 196 |
+
|
| 197 |
+
---
|
| 198 |
+
|
| 199 |
+
## Documentation
|
| 200 |
+
|
| 201 |
+
- [Full Documentation](https://kayba-ai.github.io/agentic-context-engine/latest/) — Guides, API reference, examples
|
| 202 |
+
- [Quick Start](https://kayba-ai.github.io/agentic-context-engine/latest/getting-started/quick-start/) — 5-minute setup
|
| 203 |
+
- [Setup Guide](https://kayba-ai.github.io/agentic-context-engine/latest/getting-started/setup/) — Configuration and providers
|
| 204 |
+
- [Hosted API Guide](https://kayba-ai.github.io/agentic-context-engine/latest/integrations/hosted-api/) — Hosted CLI, trace upload, prompt install
|
| 205 |
+
- [Architecture](docs/design/ACE_ARCHITECTURE.md) — Core concepts and system design
|
| 206 |
+
- [Code Reference](docs/design/ACE_REFERENCE.md) — Implementations, API, usage examples
|
| 207 |
+
- [Design Decisions](docs/design/ACE_DECISIONS.md) — Rejected alternatives and rationale
|
| 208 |
+
- [Pipeline Engine](docs/design/PIPELINE_DESIGN.md) — Step composition and context flow
|
| 209 |
+
- [Examples](examples/) — Runnable demos
|
| 210 |
+
- [Changelog](CHANGELOG.md) — Version history
|
| 211 |
+
|
| 212 |
+
---
|
| 213 |
+
|
| 214 |
+
## Contributing
|
| 215 |
+
|
| 216 |
+
Contributions are welcome. See [Contributing Guidelines](CONTRIBUTING.md).
|
| 217 |
+
|
| 218 |
+
---
|
| 219 |
+
|
| 220 |
+
<div align="center">
|
| 221 |
+
|
| 222 |
+
**Built by [Kayba](https://kayba.ai) and the open-source community.**
|
| 223 |
+
|
| 224 |
+
</div>
|
ace.toml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[default]
|
| 2 |
+
model = "us.writer.palmyra-x5-v1:0"
|
ace/__init__.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""ACE — Agentic Context Engine.
|
| 2 |
+
|
| 3 |
+
All public symbols are lazily imported to keep ``import ace`` fast.
|
| 4 |
+
Direct attribute access (``ace.ACE``, ``from ace import ACE``)
|
| 5 |
+
works — the underlying module is loaded on first use.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
from __future__ import annotations
|
| 9 |
+
|
| 10 |
+
from typing import TYPE_CHECKING
|
| 11 |
+
|
| 12 |
+
if TYPE_CHECKING:
|
| 13 |
+
# Static analysis / IDE autocomplete — never executed at runtime.
|
| 14 |
+
from pipeline import Branch, MergeStrategy, Pipeline, SampleResult, StepProtocol
|
| 15 |
+
|
| 16 |
+
from .core import (
|
| 17 |
+
ACEStepContext,
|
| 18 |
+
EnvironmentResult,
|
| 19 |
+
InsightSource,
|
| 20 |
+
Sample,
|
| 21 |
+
SimpleEnvironment,
|
| 22 |
+
Skill,
|
| 23 |
+
Skillbook,
|
| 24 |
+
SkillbookView,
|
| 25 |
+
TaskEnvironment,
|
| 26 |
+
TraceIdentity,
|
| 27 |
+
UpdateBatch,
|
| 28 |
+
UpdateOperation,
|
| 29 |
+
)
|
| 30 |
+
from .deduplication import DeduplicationManager, SimilarityDetector
|
| 31 |
+
from .implementations import Agent, Reflector, SkillManager
|
| 32 |
+
from .integrations import wrap_skillbook_context
|
| 33 |
+
from .protocols import DeduplicationConfig
|
| 34 |
+
from .providers import ACEModelConfig, ModelConfig
|
| 35 |
+
from .steps.rr_step import RRConfig, RRStep
|
| 36 |
+
from .tracing import configure as configure_tracing
|
| 37 |
+
from .runners import (
|
| 38 |
+
ACE,
|
| 39 |
+
ACELiteLLM,
|
| 40 |
+
ACERunner,
|
| 41 |
+
BrowserUse,
|
| 42 |
+
ClaudeCode,
|
| 43 |
+
LangChain,
|
| 44 |
+
TraceAnalyser,
|
| 45 |
+
)
|
| 46 |
+
from .steps import (
|
| 47 |
+
AgentStep,
|
| 48 |
+
CheckpointStep,
|
| 49 |
+
DeduplicateStep,
|
| 50 |
+
EvaluateStep,
|
| 51 |
+
ExportSkillbookMarkdownStep,
|
| 52 |
+
LoadTracesStep,
|
| 53 |
+
ObservabilityStep,
|
| 54 |
+
PersistStep,
|
| 55 |
+
ReflectStep,
|
| 56 |
+
UpdateStep,
|
| 57 |
+
learning_tail,
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
# ---- lazy import mapping: name -> (module_path, attribute) ----------------
|
| 61 |
+
|
| 62 |
+
_LAZY_IMPORTS: dict[str, tuple[str, str]] = {
|
| 63 |
+
# Pipeline engine (re-exported from pipeline/)
|
| 64 |
+
"Pipeline": ("pipeline", "Pipeline"),
|
| 65 |
+
"Branch": ("pipeline", "Branch"),
|
| 66 |
+
"MergeStrategy": ("pipeline", "MergeStrategy"),
|
| 67 |
+
"StepProtocol": ("pipeline", "StepProtocol"),
|
| 68 |
+
"SampleResult": ("pipeline", "SampleResult"),
|
| 69 |
+
# ACE context
|
| 70 |
+
"ACEStepContext": ("ace.core", "ACEStepContext"),
|
| 71 |
+
"SkillbookView": ("ace.core", "SkillbookView"),
|
| 72 |
+
# Core data types
|
| 73 |
+
"InsightSource": ("ace.core", "InsightSource"),
|
| 74 |
+
"Skill": ("ace.core", "Skill"),
|
| 75 |
+
"Skillbook": ("ace.core", "Skillbook"),
|
| 76 |
+
"TraceIdentity": ("ace.core", "TraceIdentity"),
|
| 77 |
+
"UpdateOperation": ("ace.core", "UpdateOperation"),
|
| 78 |
+
"UpdateBatch": ("ace.core", "UpdateBatch"),
|
| 79 |
+
"Sample": ("ace.core", "Sample"),
|
| 80 |
+
"EnvironmentResult": ("ace.core", "EnvironmentResult"),
|
| 81 |
+
"TaskEnvironment": ("ace.core", "TaskEnvironment"),
|
| 82 |
+
"SimpleEnvironment": ("ace.core", "SimpleEnvironment"),
|
| 83 |
+
# Implementations
|
| 84 |
+
"Agent": ("ace.implementations", "Agent"),
|
| 85 |
+
"Reflector": ("ace.implementations", "Reflector"),
|
| 86 |
+
"SkillManager": ("ace.implementations", "SkillManager"),
|
| 87 |
+
# Deduplication
|
| 88 |
+
"DeduplicationConfig": ("ace.protocols", "DeduplicationConfig"),
|
| 89 |
+
"DeduplicationManager": ("ace.deduplication", "DeduplicationManager"),
|
| 90 |
+
"SimilarityDetector": ("ace.deduplication", "SimilarityDetector"),
|
| 91 |
+
# Integrations
|
| 92 |
+
"wrap_skillbook_context": ("ace.integrations", "wrap_skillbook_context"),
|
| 93 |
+
# Config
|
| 94 |
+
"ModelConfig": ("ace.providers", "ModelConfig"),
|
| 95 |
+
"ACEModelConfig": ("ace.providers", "ACEModelConfig"),
|
| 96 |
+
# Runners
|
| 97 |
+
"ACE": ("ace.runners", "ACE"),
|
| 98 |
+
"ACELiteLLM": ("ace.runners", "ACELiteLLM"),
|
| 99 |
+
"ACERunner": ("ace.runners", "ACERunner"),
|
| 100 |
+
"BrowserUse": ("ace.runners", "BrowserUse"),
|
| 101 |
+
"ClaudeCode": ("ace.runners", "ClaudeCode"),
|
| 102 |
+
"LangChain": ("ace.runners", "LangChain"),
|
| 103 |
+
"TraceAnalyser": ("ace.runners", "TraceAnalyser"),
|
| 104 |
+
# Steps
|
| 105 |
+
"AgentStep": ("ace.steps", "AgentStep"),
|
| 106 |
+
"EvaluateStep": ("ace.steps", "EvaluateStep"),
|
| 107 |
+
"ReflectStep": ("ace.steps", "ReflectStep"),
|
| 108 |
+
"UpdateStep": ("ace.steps", "UpdateStep"),
|
| 109 |
+
"DeduplicateStep": ("ace.steps", "DeduplicateStep"),
|
| 110 |
+
"CheckpointStep": ("ace.steps", "CheckpointStep"),
|
| 111 |
+
"LoadTracesStep": ("ace.steps", "LoadTracesStep"),
|
| 112 |
+
"ExportSkillbookMarkdownStep": ("ace.steps", "ExportSkillbookMarkdownStep"),
|
| 113 |
+
"ObservabilityStep": ("ace.steps", "ObservabilityStep"),
|
| 114 |
+
"PersistStep": ("ace.steps", "PersistStep"),
|
| 115 |
+
"learning_tail": ("ace.steps", "learning_tail"),
|
| 116 |
+
# Recursive Reflector
|
| 117 |
+
"RRStep": ("ace.steps.rr_step", "RRStep"),
|
| 118 |
+
"RRConfig": ("ace.steps.rr_step", "RRConfig"),
|
| 119 |
+
# Tracing
|
| 120 |
+
"configure_tracing": ("ace.tracing", "configure"),
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
def __getattr__(name: str) -> object:
|
| 125 |
+
if name in _LAZY_IMPORTS:
|
| 126 |
+
module_path, attr = _LAZY_IMPORTS[name]
|
| 127 |
+
import importlib
|
| 128 |
+
|
| 129 |
+
module = importlib.import_module(module_path)
|
| 130 |
+
value = getattr(module, attr)
|
| 131 |
+
# Cache on the module so __getattr__ is only called once per name.
|
| 132 |
+
globals()[name] = value
|
| 133 |
+
return value
|
| 134 |
+
raise AttributeError(f"module 'ace' has no attribute {name!r}")
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
__all__ = [
|
| 138 |
+
# Pipeline composition
|
| 139 |
+
"Pipeline",
|
| 140 |
+
"Branch",
|
| 141 |
+
"MergeStrategy",
|
| 142 |
+
"StepProtocol",
|
| 143 |
+
"SampleResult",
|
| 144 |
+
# ACE context
|
| 145 |
+
"ACEStepContext",
|
| 146 |
+
"SkillbookView",
|
| 147 |
+
# Core data types
|
| 148 |
+
"InsightSource",
|
| 149 |
+
"Skill",
|
| 150 |
+
"Skillbook",
|
| 151 |
+
"TraceIdentity",
|
| 152 |
+
"UpdateOperation",
|
| 153 |
+
"UpdateBatch",
|
| 154 |
+
# Environments
|
| 155 |
+
"Sample",
|
| 156 |
+
"EnvironmentResult",
|
| 157 |
+
"TaskEnvironment",
|
| 158 |
+
"SimpleEnvironment",
|
| 159 |
+
# Implementations
|
| 160 |
+
"Agent",
|
| 161 |
+
"Reflector",
|
| 162 |
+
"SkillManager",
|
| 163 |
+
# Config
|
| 164 |
+
"ModelConfig",
|
| 165 |
+
"ACEModelConfig",
|
| 166 |
+
# Runners
|
| 167 |
+
"ACE",
|
| 168 |
+
"ACELiteLLM",
|
| 169 |
+
"ACERunner",
|
| 170 |
+
"BrowserUse",
|
| 171 |
+
"ClaudeCode",
|
| 172 |
+
"LangChain",
|
| 173 |
+
"TraceAnalyser",
|
| 174 |
+
# Steps
|
| 175 |
+
"AgentStep",
|
| 176 |
+
"EvaluateStep",
|
| 177 |
+
"ReflectStep",
|
| 178 |
+
"UpdateStep",
|
| 179 |
+
"DeduplicateStep",
|
| 180 |
+
"CheckpointStep",
|
| 181 |
+
"LoadTracesStep",
|
| 182 |
+
"ExportSkillbookMarkdownStep",
|
| 183 |
+
"ObservabilityStep",
|
| 184 |
+
"PersistStep",
|
| 185 |
+
"learning_tail",
|
| 186 |
+
# Recursive Reflector
|
| 187 |
+
"RRStep",
|
| 188 |
+
"RRConfig",
|
| 189 |
+
# Deduplication
|
| 190 |
+
"DeduplicationConfig",
|
| 191 |
+
"DeduplicationManager",
|
| 192 |
+
"SimilarityDetector",
|
| 193 |
+
# Tracing
|
| 194 |
+
"configure_tracing",
|
| 195 |
+
# Utilities
|
| 196 |
+
"wrap_skillbook_context",
|
| 197 |
+
]
|
ace/cli/__init__.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Kayba CLI."""
|
| 2 |
+
|
| 3 |
+
import click
|
| 4 |
+
|
| 5 |
+
from ace.cli.cloud import (
|
| 6 |
+
upload,
|
| 7 |
+
traces,
|
| 8 |
+
run,
|
| 9 |
+
insights,
|
| 10 |
+
prompts,
|
| 11 |
+
status,
|
| 12 |
+
materialize,
|
| 13 |
+
batch,
|
| 14 |
+
setup,
|
| 15 |
+
integrations,
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
@click.group()
|
| 20 |
+
@click.version_option(package_name="ace-framework")
|
| 21 |
+
def cli():
|
| 22 |
+
"""Kayba CLI."""
|
| 23 |
+
pass
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
cli.add_command(upload)
|
| 27 |
+
cli.add_command(traces)
|
| 28 |
+
cli.add_command(run)
|
| 29 |
+
cli.add_command(insights)
|
| 30 |
+
cli.add_command(prompts)
|
| 31 |
+
cli.add_command(status)
|
| 32 |
+
cli.add_command(materialize)
|
| 33 |
+
cli.add_command(batch)
|
| 34 |
+
cli.add_command(setup)
|
| 35 |
+
cli.add_command(integrations)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def main():
|
| 39 |
+
cli()
|
ace/cli/client.py
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""HTTP client for the Kayba hosted API."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import json
|
| 6 |
+
import os
|
| 7 |
+
import re
|
| 8 |
+
from typing import Any, Dict, List, Optional
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class KaybaAPIError(Exception):
|
| 12 |
+
"""Structured error from the Kayba API."""
|
| 13 |
+
|
| 14 |
+
def __init__(self, code: str, message: str, status_code: int = 0):
|
| 15 |
+
self.code = code
|
| 16 |
+
self.message = message
|
| 17 |
+
self.status_code = status_code
|
| 18 |
+
super().__init__(f"[{code}] {message}")
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
DEFAULT_BASE_URL = "https://use.kayba.ai/api"
|
| 22 |
+
MAX_TRACE_UPLOAD_BODY_BYTES = 900_000
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def _chunk_trace_uploads(
|
| 26 |
+
traces: List[Dict[str, Any]],
|
| 27 |
+
) -> List[List[Dict[str, Any]]]:
|
| 28 |
+
"""Split uploads into request-sized batches under the body size cap."""
|
| 29 |
+
batches: List[List[Dict[str, Any]]] = []
|
| 30 |
+
current: List[Dict[str, Any]] = []
|
| 31 |
+
current_size = len('{"traces":[]}')
|
| 32 |
+
|
| 33 |
+
for trace in traces:
|
| 34 |
+
trace_size = len(
|
| 35 |
+
json.dumps(trace, ensure_ascii=False, separators=(",", ":")).encode(
|
| 36 |
+
"utf-8"
|
| 37 |
+
)
|
| 38 |
+
)
|
| 39 |
+
separator_size = 1 if current else 0
|
| 40 |
+
candidate_size = current_size + separator_size + trace_size
|
| 41 |
+
|
| 42 |
+
if current and candidate_size > MAX_TRACE_UPLOAD_BODY_BYTES:
|
| 43 |
+
batches.append(current)
|
| 44 |
+
current = [trace]
|
| 45 |
+
current_size = len('{"traces":[]}') + trace_size
|
| 46 |
+
continue
|
| 47 |
+
|
| 48 |
+
current.append(trace)
|
| 49 |
+
current_size = candidate_size
|
| 50 |
+
|
| 51 |
+
if current:
|
| 52 |
+
batches.append(current)
|
| 53 |
+
|
| 54 |
+
return batches
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class KaybaClient:
|
| 58 |
+
"""HTTP client for the Kayba hosted API.
|
| 59 |
+
|
| 60 |
+
Args:
|
| 61 |
+
api_key: Kayba API key. Falls back to KAYBA_API_KEY env var.
|
| 62 |
+
base_url: API base URL. Falls back to KAYBA_API_URL env var,
|
| 63 |
+
then to https://use.kayba.ai/api.
|
| 64 |
+
"""
|
| 65 |
+
|
| 66 |
+
def __init__(
|
| 67 |
+
self,
|
| 68 |
+
api_key: Optional[str] = None,
|
| 69 |
+
base_url: Optional[str] = None,
|
| 70 |
+
):
|
| 71 |
+
try:
|
| 72 |
+
import requests
|
| 73 |
+
except ImportError as exc:
|
| 74 |
+
raise KaybaAPIError(
|
| 75 |
+
"DEPENDENCY_MISSING",
|
| 76 |
+
"The hosted Kayba CLI requires the cloud extra. Install with "
|
| 77 |
+
"`uv add \"ace-framework[cloud]\"` or "
|
| 78 |
+
"`pip install 'ace-framework[cloud]'`.",
|
| 79 |
+
) from exc
|
| 80 |
+
|
| 81 |
+
self.api_key = api_key or os.environ.get("KAYBA_API_KEY", "")
|
| 82 |
+
if not self.api_key:
|
| 83 |
+
raise KaybaAPIError(
|
| 84 |
+
"AUTH_MISSING",
|
| 85 |
+
"No API key provided. Set KAYBA_API_KEY or pass --api-key.",
|
| 86 |
+
)
|
| 87 |
+
self.base_url = (
|
| 88 |
+
base_url or os.environ.get("KAYBA_API_URL") or DEFAULT_BASE_URL
|
| 89 |
+
).rstrip("/")
|
| 90 |
+
self.session: Any = requests.Session()
|
| 91 |
+
self.session.headers["Authorization"] = f"Bearer {self.api_key}"
|
| 92 |
+
|
| 93 |
+
@staticmethod
|
| 94 |
+
def _summarize_http_body(body: str, limit: int = 240) -> str:
|
| 95 |
+
"""Collapse whitespace so raw HTML and proxy errors stay readable."""
|
| 96 |
+
snippet = re.sub(r"\s+", " ", body or "").strip()
|
| 97 |
+
if not snippet:
|
| 98 |
+
return "Unexpected non-JSON error from the Kayba API."
|
| 99 |
+
if len(snippet) <= limit:
|
| 100 |
+
return snippet
|
| 101 |
+
return snippet[: limit - 3] + "..."
|
| 102 |
+
|
| 103 |
+
def _request(
|
| 104 |
+
self,
|
| 105 |
+
method: str,
|
| 106 |
+
path: str,
|
| 107 |
+
*,
|
| 108 |
+
json: Optional[Dict[str, Any]] = None,
|
| 109 |
+
params: Optional[Dict[str, str]] = None,
|
| 110 |
+
) -> Any:
|
| 111 |
+
"""Send a request and return parsed JSON, raising on API errors."""
|
| 112 |
+
url = f"{self.base_url}{path}"
|
| 113 |
+
resp = self.session.request(method, url, json=json, params=params)
|
| 114 |
+
|
| 115 |
+
if resp.status_code >= 400:
|
| 116 |
+
try:
|
| 117 |
+
body = resp.json()
|
| 118 |
+
err = body.get("error", {})
|
| 119 |
+
if isinstance(err, str):
|
| 120 |
+
raise KaybaAPIError(
|
| 121 |
+
code="API_ERROR",
|
| 122 |
+
message=err,
|
| 123 |
+
status_code=resp.status_code,
|
| 124 |
+
)
|
| 125 |
+
message = err.get("message", resp.text)
|
| 126 |
+
if (
|
| 127 |
+
resp.status_code == 413
|
| 128 |
+
or "maximum content size" in message.lower()
|
| 129 |
+
or "too large" in message.lower()
|
| 130 |
+
):
|
| 131 |
+
raise KaybaAPIError(
|
| 132 |
+
code="PAYLOAD_TOO_LARGE",
|
| 133 |
+
message=message,
|
| 134 |
+
status_code=resp.status_code,
|
| 135 |
+
)
|
| 136 |
+
raise KaybaAPIError(
|
| 137 |
+
code=err.get("code", "UNKNOWN"),
|
| 138 |
+
message=message,
|
| 139 |
+
status_code=resp.status_code,
|
| 140 |
+
)
|
| 141 |
+
except (ValueError, KeyError, AttributeError):
|
| 142 |
+
message = self._summarize_http_body(resp.text)
|
| 143 |
+
if resp.status_code == 413:
|
| 144 |
+
message = (
|
| 145 |
+
"Upload rejected because the request body is too large. "
|
| 146 |
+
"Try smaller traces or upload fewer files at once."
|
| 147 |
+
)
|
| 148 |
+
elif resp.status_code in (401, 403):
|
| 149 |
+
message = "Authentication failed; check KAYBA_API_KEY"
|
| 150 |
+
else:
|
| 151 |
+
message = f"HTTP {resp.status_code} from Kayba API: {message}"
|
| 152 |
+
raise KaybaAPIError(
|
| 153 |
+
code="HTTP_ERROR",
|
| 154 |
+
message=message,
|
| 155 |
+
status_code=resp.status_code,
|
| 156 |
+
)
|
| 157 |
+
|
| 158 |
+
if resp.status_code == 204:
|
| 159 |
+
return {}
|
| 160 |
+
return resp.json()
|
| 161 |
+
|
| 162 |
+
# -- Traces --
|
| 163 |
+
|
| 164 |
+
def upload_traces(self, traces: List[Dict[str, Any]]) -> Dict[str, Any]:
|
| 165 |
+
"""Upload trace files.
|
| 166 |
+
|
| 167 |
+
Args:
|
| 168 |
+
traces: List of dicts with keys: filename, content, fileType.
|
| 169 |
+
"""
|
| 170 |
+
batches = _chunk_trace_uploads(traces)
|
| 171 |
+
if len(batches) == 1:
|
| 172 |
+
return self._request("POST", "/traces", json={"traces": traces})
|
| 173 |
+
|
| 174 |
+
combined: Dict[str, Any] = {"count": 0, "traces": []}
|
| 175 |
+
for batch in batches:
|
| 176 |
+
result = self._request("POST", "/traces", json={"traces": batch})
|
| 177 |
+
uploaded = result.get("traces", [])
|
| 178 |
+
combined["count"] += result.get("count", len(uploaded) or len(batch))
|
| 179 |
+
combined["traces"].extend(uploaded)
|
| 180 |
+
for key, value in result.items():
|
| 181 |
+
if key not in {"count", "traces"} and key not in combined:
|
| 182 |
+
combined[key] = value
|
| 183 |
+
return combined
|
| 184 |
+
|
| 185 |
+
def list_traces(self) -> Dict[str, Any]:
|
| 186 |
+
"""List all traces (metadata only, no content)."""
|
| 187 |
+
return self._request("GET", "/traces")
|
| 188 |
+
|
| 189 |
+
def get_trace(self, trace_id: str) -> Dict[str, Any]:
|
| 190 |
+
"""Get a single trace with full content."""
|
| 191 |
+
return self._request("GET", f"/traces/{trace_id}")
|
| 192 |
+
|
| 193 |
+
def get_traces(self, trace_ids: List[str]) -> Dict[str, Any]:
|
| 194 |
+
"""Batch get traces by IDs (with content)."""
|
| 195 |
+
return self._request("POST", "/traces/batch", json={"ids": trace_ids})
|
| 196 |
+
|
| 197 |
+
def delete_trace(self, trace_id: str) -> Dict[str, Any]:
|
| 198 |
+
"""Delete a single trace."""
|
| 199 |
+
return self._request("DELETE", f"/traces/{trace_id}")
|
| 200 |
+
|
| 201 |
+
def delete_traces(self, trace_ids: List[str]) -> Dict[str, Any]:
|
| 202 |
+
"""Delete multiple traces."""
|
| 203 |
+
results = []
|
| 204 |
+
errors = []
|
| 205 |
+
for tid in trace_ids:
|
| 206 |
+
try:
|
| 207 |
+
self.delete_trace(tid)
|
| 208 |
+
results.append(tid)
|
| 209 |
+
except KaybaAPIError as e:
|
| 210 |
+
errors.append({"id": tid, "error": str(e)})
|
| 211 |
+
return {"deleted": results, "errors": errors}
|
| 212 |
+
|
| 213 |
+
# -- Insights --
|
| 214 |
+
|
| 215 |
+
def generate_insights(
|
| 216 |
+
self,
|
| 217 |
+
*,
|
| 218 |
+
trace_ids: Optional[List[str]] = None,
|
| 219 |
+
model: Optional[str] = None,
|
| 220 |
+
epochs: Optional[int] = None,
|
| 221 |
+
reflector_mode: Optional[str] = None,
|
| 222 |
+
anthropic_key: Optional[str] = None,
|
| 223 |
+
) -> Dict[str, Any]:
|
| 224 |
+
"""Start async insight generation."""
|
| 225 |
+
body: Dict[str, Any] = {}
|
| 226 |
+
if trace_ids:
|
| 227 |
+
body["traceIds"] = trace_ids
|
| 228 |
+
if model:
|
| 229 |
+
body["model"] = model
|
| 230 |
+
if epochs is not None:
|
| 231 |
+
body["epochs"] = epochs
|
| 232 |
+
if reflector_mode:
|
| 233 |
+
body["reflectorMode"] = reflector_mode
|
| 234 |
+
if anthropic_key:
|
| 235 |
+
body["anthropicApiKey"] = anthropic_key
|
| 236 |
+
return self._request("POST", "/insights/generate", json=body)
|
| 237 |
+
|
| 238 |
+
def list_insights(
|
| 239 |
+
self,
|
| 240 |
+
*,
|
| 241 |
+
status: Optional[str] = None,
|
| 242 |
+
section: Optional[str] = None,
|
| 243 |
+
) -> Dict[str, Any]:
|
| 244 |
+
"""List insights, optionally filtered."""
|
| 245 |
+
params: Dict[str, str] = {}
|
| 246 |
+
if status:
|
| 247 |
+
params["status"] = status
|
| 248 |
+
if section:
|
| 249 |
+
params["section"] = section
|
| 250 |
+
return self._request("GET", "/insights", params=params or None)
|
| 251 |
+
|
| 252 |
+
def triage_insight(
|
| 253 |
+
self,
|
| 254 |
+
insight_id: str,
|
| 255 |
+
status: str,
|
| 256 |
+
note: Optional[str] = None,
|
| 257 |
+
) -> Dict[str, Any]:
|
| 258 |
+
"""Accept or reject a single insight."""
|
| 259 |
+
body: Dict[str, Any] = {"status": status}
|
| 260 |
+
if note:
|
| 261 |
+
body["note"] = note
|
| 262 |
+
return self._request("PATCH", f"/insights/{insight_id}", json=body)
|
| 263 |
+
|
| 264 |
+
# -- Jobs --
|
| 265 |
+
|
| 266 |
+
def get_job(self, job_id: str) -> Dict[str, Any]:
|
| 267 |
+
"""Get job status."""
|
| 268 |
+
return self._request("GET", f"/jobs/{job_id}")
|
| 269 |
+
|
| 270 |
+
def materialize_job(self, job_id: str) -> Dict[str, Any]:
|
| 271 |
+
"""Materialize completed job results into the skillbook."""
|
| 272 |
+
return self._request("POST", f"/jobs/{job_id}")
|
| 273 |
+
|
| 274 |
+
# -- Prompts --
|
| 275 |
+
|
| 276 |
+
def generate_prompt(
|
| 277 |
+
self,
|
| 278 |
+
*,
|
| 279 |
+
insight_ids: Optional[List[str]] = None,
|
| 280 |
+
label: Optional[str] = None,
|
| 281 |
+
) -> Dict[str, Any]:
|
| 282 |
+
"""Generate a prompt from accepted insights."""
|
| 283 |
+
body: Dict[str, Any] = {}
|
| 284 |
+
if insight_ids:
|
| 285 |
+
body["insightIds"] = insight_ids
|
| 286 |
+
if label:
|
| 287 |
+
body["label"] = label
|
| 288 |
+
return self._request("POST", "/prompts/generate", json=body)
|
| 289 |
+
|
| 290 |
+
def list_prompts(self) -> Dict[str, Any]:
|
| 291 |
+
"""List all prompt versions."""
|
| 292 |
+
return self._request("GET", "/prompts")
|
| 293 |
+
|
| 294 |
+
def get_prompt(self, prompt_id: str) -> Dict[str, Any]:
|
| 295 |
+
"""Get a specific prompt by ID."""
|
| 296 |
+
return self._request("GET", f"/prompts/{prompt_id}")
|
| 297 |
+
|
| 298 |
+
# -- Integrations --
|
| 299 |
+
|
| 300 |
+
def get_integrations(self) -> Dict[str, Any]:
|
| 301 |
+
"""Get current integration settings."""
|
| 302 |
+
return self._request("GET", "/integrations")
|
| 303 |
+
|
| 304 |
+
def update_integration(self, name: str, config: Dict[str, Any]) -> Dict[str, Any]:
|
| 305 |
+
"""Update an integration's config."""
|
| 306 |
+
return self._request("PUT", f"/integrations/{name}", json=config)
|
| 307 |
+
|
| 308 |
+
def test_integration(self, name: str) -> Dict[str, Any]:
|
| 309 |
+
"""Test an integration connection."""
|
| 310 |
+
return self._request("POST", f"/integrations/{name}/test")
|