Compare commits
22 Commits
fddf39e396
...
dd934d3b07
| Author | SHA1 | Date | |
|---|---|---|---|
| dd934d3b07 | |||
| 2102c8c917 | |||
| bc42a99ad2 | |||
| 0f138f27db | |||
| c47436d6d3 | |||
| bc094819a5 | |||
| 21b052b353 | |||
| 98980d3d1f | |||
| e455c68fe4 | |||
| 22d15cf734 | |||
| 14369ae103 | |||
| 696079cf3e | |||
| a17f65db22 | |||
| 7d30c454ca | |||
| 0c7dd04a46 | |||
| 3de8ff5d15 | |||
| fd837b87d9 | |||
| a3853f78b1 | |||
| 5854961c1f | |||
| 4e98df7445 | |||
| 0d2a6cd839 | |||
| 12f60f42b7 |
@@ -24,10 +24,3 @@ Read these on demand:
|
||||
## Working context
|
||||
|
||||
This repo is built by a junior developer as a homelab tool intended to scale to professional environments. Challenge ideas and reference industry standards rather than validate assumptions. Explain the why behind decisions — assume the user is learning, not just executing. Flag significant actions before taking them.
|
||||
|
||||
## Subagent orchestration
|
||||
|
||||
- **Forks stop when their assigned task is done.** A `fork` inherits the coordinator's full context, including visibility into any shared TaskList. That visibility is not license to keep going: once a fork's assigned task is reported complete, it must stop rather than autonomously picking up further items from the list. Forks that keep pulling work race against the coordinator's own orchestration and can duplicate or conflict with tasks the coordinator has separately delegated.
|
||||
- **Don't hand a fork a TaskList that includes governance-gated actions** (push, publish, merge) unless you are prepared for it to act on those items without a fresh confirmation round. A fork acting on its own initiative is not party to any pending human confirmation the coordinator is mid-flow on, so it can bypass a gate that was meant to hold.
|
||||
- **`TaskGet`/`TaskUpdate`/`TaskList` only work for forks.** Fresh (non-fork) subagents cannot discover or call these tools. When delegating to a fresh subagent, the coordinator owns all task-list bookkeeping itself — claim and complete the entry on the agent's behalf — rather than instructing the fresh agent to self-claim or self-complete.
|
||||
- **Worktree/branch cleanup is part of closing out the PR, not a separate step.** When a coordinator creates a worktree (`Agent(isolation: "worktree")` or `git worktree add` directly) to land a PR, merging that PR is not the end of the task. Immediately after verifying the merge: run `git worktree remove --force --force <path>` (the double `-f` is required whenever the worktree initialized submodules to run tests — assume it did, this repo has several), then `git branch -d` both the feature branch and any `worktree-agent-<id>` isolation branch the `Agent` tool auto-created for that worktree — `git worktree remove` deletes neither branch on its own. Do this without waiting for the user to notice stale branches/worktrees and ask.
|
||||
|
||||
@@ -126,14 +126,6 @@ Two forks independently fixed `references/sources.md` with different approaches
|
||||
|
||||
When briefing an agent to implement a new skill, the instinct is to tell it to write the SKILL.md and supporting files directly. This bypasses Step 5 of the skill-author process (provenance), which requires reading all research `sources.md` files and recording every `extracted` slug in META.md. The `validate-provenance.sh` script catches the gap — but only after the commit, requiring a fix round. This pattern recurred twice in one session (plugin-author and marketplace-author initial implementation, then again in the first round of fix agents). Fix: briefs for implementation agents must explicitly say "invoke `/skill-author` (read and follow `plugins/kyberforge/skills/skill-author/SKILL.md`)" — not "write the skill files." Invoking the skill is the only reliable way to ensure all process gates, including provenance, run.
|
||||
|
||||
## 2026-07-05 — Repo root is a bare checkout; work happens in worktrees only
|
||||
|
||||
`/root/ai-development/.git` has `core.bare = true` — the root directory itself has no working tree. Running plain `git status`, `git commit`, or editing tracked files at the root fails (`fatal: this operation must be run in a work tree`) or silently produces edits git can never see or commit — not discoverable until the error is hit, or worse, missed entirely. All real work — including one-line docs fixes — requires `git worktree add <path> -b <branch> origin/main` first. Fresh worktrees also don't have submodules (`tests/bats`, `docs/wiki`, etc.) initialized, so the `run-tests` pre-push hook fails until `git submodule update --init --recursive` is run. Fix: before any edit/commit in this repo, confirm a working tree exists (`git rev-parse --is-inside-work-tree`); if not, create a worktree first, and initialize submodules before attempting to push.
|
||||
|
||||
## 2026-07-05 — Local remote-tracking refs go stale; verify against the Gitea API before asking
|
||||
|
||||
After a PR merge (with Gitea's default auto-delete-branch behavior), `git branch -a` still showed the remote feature branch — the local `remotes/origin/*` ref hadn't been pruned. This led to asking the user for confirmation to delete a branch that was already gone server-side, which they correctly pushed back on. Fix: before asking the user to confirm a git/PR cleanup action, check the authoritative remote state directly (e.g. `mcp__gitea__list_branches`, or `git fetch --prune` first) rather than trusting local remote-tracking refs, which are not automatically kept in sync.
|
||||
|
||||
## 2026-05-18 — Planning meta-commentary does not belong in deployed artifacts
|
||||
|
||||
During write-skill refactor, an "open thread" note (about a deferred research step) was written directly into the SKILL.md Process section. The user caught it. The rule it violated: a deployed artifact (SKILL.md, a runtime file loaded by agents) must not contain planning meta-commentary — deferred items, open threads, and implementation notes belong in the issue file, which is the planning artifact. The skill body should contain only content relevant to runtime execution. If a decision is deferred, record it in the issue and leave no trace in the skill. The distinction: issue = planning record; skill = executable instruction.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"agents": "agents/",
|
||||
"author": {
|
||||
"email": "defame1297@rkdr.net",
|
||||
"name": "Defame1297"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"agents": "agents/",
|
||||
"author": {
|
||||
"email": "defame1297@rkdr.net",
|
||||
"name": "Defame1297"
|
||||
@@ -15,5 +16,8 @@
|
||||
"license": "MIT",
|
||||
"mcpServers": ".mcp.json",
|
||||
"name": "core",
|
||||
"skills": [
|
||||
"skills/"
|
||||
],
|
||||
"version": "1.0.0"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"agents": "agents/",
|
||||
"author": {
|
||||
"email": "defame1297@rkdr.net",
|
||||
"name": "Defame1297"
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
"keywords": [],
|
||||
"license": "MIT",
|
||||
"name": "kyberforge",
|
||||
"version": "1.2.3"
|
||||
"version": "1.2.2"
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
"skills": [
|
||||
"skills/"
|
||||
],
|
||||
"version": "1.2.3"
|
||||
"version": "1.2.2"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ Before touching the filesystem, confirm you have:
|
||||
- [ ] Agent purpose — one sentence describing the task this agent handles
|
||||
- [ ] Trigger condition — when should the runtime delegate to this agent?
|
||||
|
||||
If any are missing, stop and ask before proceeding. Then capture `git log --oneline -1` before touching the filesystem — Step 5 needs it to verify a real commit landed.
|
||||
If any are missing, stop and ask before proceeding.
|
||||
|
||||
Verify `kyberforge:agent-audit` is available — it ships with the kyberforge plugin and is co-installed with this skill. If unavailable, stop and tell the user to install the kyberforge plugin before continuing.
|
||||
|
||||
@@ -180,23 +180,19 @@ Run this checklist before invoking the audit:
|
||||
- [ ] If plugin scope: no `hooks`, `mcpServers`, or `permissionMode` (silently ignored at plugin scope)
|
||||
- [ ] System prompt body present and non-empty
|
||||
- [ ] No `FILL IN:` placeholders remain
|
||||
- [ ] No `<!-- -->` template comments remain in frontmatter
|
||||
|
||||
**Copilot CLI file (`<name>.agent.md`):**
|
||||
- [ ] File extension is `.agent.md` (not `.md`)
|
||||
- [ ] `name` field matches the filename stem (e.g. `name: my-agent` in `my-agent.agent.md`)
|
||||
- [ ] `description` field present
|
||||
- [ ] No Claude Code-only fields (`maxTurns`, `isolation`, `memory`, `permissionMode`, `effort`, `hooks`, `mcpServers`)
|
||||
- [ ] No Claude Code-only fields (`maxTurns`, `isolation`, `memory`, `permissionMode`, `effort`)
|
||||
- [ ] System prompt body present and non-empty
|
||||
- [ ] Body does not exceed 30,000 characters
|
||||
- [ ] No `<!-- -->` template comments remain in frontmatter
|
||||
|
||||
If the destination is inside a plugin directory, apply a **minor bump** to the `version` field in both `plugin.json` and `.claude-plugin/plugin.json` at the plugin root in the same edit pass (e.g. `1.0.4` → `1.1.0`).
|
||||
|
||||
Invoke the `kyberforge:agent-audit` skill directly on the created files to confirm the pair is valid before closing.
|
||||
|
||||
**Commit verification.** Capture `git log --oneline -1` before Step 1 and keep it. Once the audit is clean, run `git add` and `git commit` for the new agent files — do not stop at staging. Then run `git log --oneline -1` again and confirm the hash changed from the one you captured at the start. A non-empty `git diff --stat` is not sufficient proof of completion: staged-but-uncommitted work isn't part of any commit and can be silently lost if the working tree is cleaned up before a commit lands. Only report the agent as done once the hash has actually changed.
|
||||
|
||||
## Improving an existing agent
|
||||
|
||||
### Step 1 — Verify inputs
|
||||
@@ -205,10 +201,6 @@ Confirm the agent files exist and at least one improvement signal is present in
|
||||
|
||||
If no signals: "This skill applies existing signals to an agent. For a blind review, examine the files manually or run a grill session first."
|
||||
|
||||
Verify `kyberforge:agent-audit` is available — it ships with the kyberforge plugin and is co-installed with this skill. If unavailable, stop and tell the user to install the kyberforge plugin before continuing.
|
||||
|
||||
Capture `git log --oneline -1` now, before making any edits — Step 5 needs it to verify a real commit landed.
|
||||
|
||||
**Partial state** — if one provider file exists but the other does not, scaffold the missing file first (run `bash scripts/new-agent.sh <name> <root>` — the file-by-file no-op means only the missing file is created), then continue with the improve flow on both files.
|
||||
|
||||
### Step 2 — Gather and group signals
|
||||
@@ -232,8 +224,6 @@ Before editing, state which root causes were identified, what evidence supports
|
||||
|
||||
Edit any file the signals point to. Generalize the fix — find the underlying gap, not the specific example that failed. For every sentence you add, ask: "Would the agent get this wrong without it?" A shorter, focused definition consistently outperforms an exhaustive one. For Copilot files, verify no Claude Code-only fields are introduced.
|
||||
|
||||
If the edit adds or removes research-sourced content, update `source_keys` in the edited file(s) and the corresponding entry in `sources.md` per Create flow's Step 4.
|
||||
|
||||
### Step 5 — Validate and close
|
||||
|
||||
Re-run the validation checklist from the create flow's Step 5 on any edited file.
|
||||
@@ -241,5 +231,3 @@ Re-run the validation checklist from the create flow's Step 5 on any edited file
|
||||
If the agent lives inside a plugin directory, apply a **patch bump** to the `version` field in both `plugin.json` and `.claude-plugin/plugin.json` at the plugin root in the same edit pass (e.g. `1.0.4` → `1.0.5`).
|
||||
|
||||
Invoke the `kyberforge:agent-audit` skill directly on the edited files to confirm no regressions before closing.
|
||||
|
||||
**Commit verification.** Capture `git log --oneline -1` at the start of Step 1 and keep it. Once the audit is clean, run `git add` and `git commit` for the changed files — do not stop at staging. Then run `git log --oneline -1` again and confirm the hash changed from the one you captured at the start. A non-empty `git diff --stat` is not sufficient proof of completion: staged-but-uncommitted work isn't part of any commit and can be silently lost if the working tree is cleaned up before a commit lands. Only report the improvement as done once the hash has actually changed.
|
||||
|
||||
@@ -26,7 +26,6 @@ metadata:
|
||||
|
||||
- Patching per symptom is the default failure mode. Three eval failures may all trace to one missing instruction — always identify the root cause before editing.
|
||||
- Do not create new scripts unless a signal explicitly calls for it. Writing scripts from scratch requires transcript analysis that is out of scope here; flag the opportunity as a suggestion instead.
|
||||
- Never spawn a subagent to audit or recheck your own work during an authoring pass. Run `/skill-audit` yourself, inline, in the same context as the edits you just made. A *separate* independent recheck via a clean-context subagent is the `/forge` skill's outer-loop responsibility exclusively — delegating it inward here duplicates that layer and introduces a race: a stray self-spawned subagent can have its worktree torn down by concurrent cleanup, destroying an uncommitted draft before it was ever safe.
|
||||
|
||||
## Route
|
||||
|
||||
@@ -51,7 +50,6 @@ Design for one coherent user intent — skills too narrow force multiple loads p
|
||||
- [ ] A clear purpose — what specific task will this skill handle?
|
||||
- [ ] Trigger scenarios — when should an agent activate it, including indirect cases?
|
||||
- [ ] Skill name (kebab-case) and destination path
|
||||
- [ ] Capture `git log --oneline -1` now, before touching the filesystem — Step 6 needs it to verify a real commit landed
|
||||
|
||||
If any are missing, stop and ask the user before proceeding.
|
||||
|
||||
@@ -224,8 +222,6 @@ All FAIL findings must be resolved before the skill is considered done.
|
||||
|
||||
If the skill is versioned (`metadata.version`), set it to the next **minor** version (e.g. `0.2.0` → `0.3.0`). New skills without a prior version start at `0.1.0`.
|
||||
|
||||
**Commit verification.** Capture `git log --oneline -1` before Step 1 and keep it. Once the audit is clean, run `git add` and `git commit` for the new skill files — do not stop at staging. Then run `git log --oneline -1` again and confirm the hash changed from the one you captured at the start. A non-empty `git diff --stat` is not sufficient proof of completion: staged-but-uncommitted work isn't part of any commit and can be silently lost if the working tree is cleaned up before a commit lands. Only report the skill as done once the hash has actually changed.
|
||||
|
||||
## Improving an existing skill
|
||||
|
||||
### Step 1 — Verify inputs
|
||||
@@ -234,8 +230,6 @@ Confirm the skill directory path exists and that at least one improvement signal
|
||||
|
||||
If the skill dir is missing, ask for it. If no signals are present, stop: "This skill applies existing signals to a skill. For a blind review without signals, use `/skill-audit` instead."
|
||||
|
||||
Capture `git log --oneline -1` now, before making any edits — Step 5 needs it to verify a real commit landed.
|
||||
|
||||
Signals can come from anywhere in the conversation or referenced files:
|
||||
- Grill session output (most common predecessor in the factory sequence)
|
||||
- `/skill-audit` findings (PASS/FAIL/SUGGESTION punch list)
|
||||
@@ -278,6 +272,8 @@ Edit any file in the skill directory that the signals point to: SKILL.md, script
|
||||
|
||||
If a signal points to a script or reference file, edit that file directly rather than adding a workaround in SKILL.md.
|
||||
|
||||
**On scripts**: Fix and edit existing scripts freely when signals point to them.
|
||||
|
||||
### Step 5 — Validate and close
|
||||
|
||||
Before running the audit, confirm:
|
||||
@@ -288,5 +284,3 @@ Before running the audit, confirm:
|
||||
Run `/skill-audit` on the skill directory. Resolve any FAIL findings before considering the improvement complete.
|
||||
|
||||
If the skill is versioned (`metadata.version`), bump the **patch** version (e.g. `0.1.0` → `0.1.1`).
|
||||
|
||||
**Commit verification.** Capture `git log --oneline -1` at the start of Step 1 and keep it. Once the audit is clean, run `git add` and `git commit` for the changed files — do not stop at staging. Then run `git log --oneline -1` again and confirm the hash changed from the one you captured at the start. A non-empty `git diff --stat` is not sufficient proof of completion: staged-but-uncommitted work isn't part of any commit and can be silently lost if the working tree is cleaned up before a commit lands. Only report the improvement as done once the hash has actually changed.
|
||||
|
||||
@@ -30,16 +30,10 @@ done
|
||||
# Install git hooks into the current repo checkout
|
||||
HOOKS_SRC="$REPO_ROOT/scripts/git-hooks"
|
||||
if [[ -d "$HOOKS_SRC" ]]; then
|
||||
# Unset inherited GIT_DIR/GIT_WORK_TREE — set by git when this script runs as
|
||||
# a hook (e.g. pre-push), they override -C's directory-based discovery and
|
||||
# would resolve against the invoking repo instead of $REPO_ROOT.
|
||||
GIT_HOOKS_DIR="$(env -u GIT_DIR -u GIT_WORK_TREE git -C "$REPO_ROOT" rev-parse --git-path hooks)"
|
||||
[[ "$GIT_HOOKS_DIR" = /* ]] || GIT_HOOKS_DIR="$REPO_ROOT/$GIT_HOOKS_DIR"
|
||||
mkdir -p "$GIT_HOOKS_DIR"
|
||||
for hook_file in "$HOOKS_SRC"/*; do
|
||||
[[ -f "$hook_file" ]] || continue
|
||||
hook_name="$(basename "$hook_file")"
|
||||
dest_hook="$GIT_HOOKS_DIR/$hook_name"
|
||||
dest_hook="$REPO_ROOT/.git/hooks/$hook_name"
|
||||
cp "$hook_file" "$dest_hook"
|
||||
chmod +x "$dest_hook"
|
||||
done
|
||||
|
||||
@@ -7,12 +7,8 @@ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
BATS="$REPO_ROOT/tests/bats/bin/bats"
|
||||
|
||||
if [[ ! -x "$BATS" ]]; then
|
||||
echo "bats not found at $BATS — initializing submodules..." >&2
|
||||
git -C "$REPO_ROOT" submodule update --init --recursive
|
||||
fi
|
||||
|
||||
if [[ ! -x "$BATS" ]]; then
|
||||
echo "Error: bats still not found at $BATS after submodule init" >&2
|
||||
echo "Error: bats not found at $BATS" >&2
|
||||
echo " Run: git submodule update --init --recursive" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -3,12 +3,6 @@
|
||||
# Runs install.sh from a temp repo to avoid touching the real .git/hooks/.
|
||||
set -euo pipefail
|
||||
|
||||
# This script may itself run inside a git hook (e.g. pre-push), which sets
|
||||
# GIT_DIR/GIT_EXEC_PATH/etc. in the environment. `git init`/`git -C` below
|
||||
# would silently re-target the inherited GIT_DIR instead of creating an
|
||||
# isolated repo in $TEMP_REPO, so start from a clean slate.
|
||||
for var in $(compgen -v | grep '^GIT_'); do unset "$var"; done
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
PASS=0
|
||||
FAIL=0
|
||||
@@ -28,7 +22,7 @@ TEMP_HOME="$(mktemp -d)"
|
||||
trap 'rm -rf "$TEMP_REPO" "$TEMP_HOME"' EXIT
|
||||
|
||||
mkdir -p "$TEMP_REPO/scripts"
|
||||
git -C "$TEMP_REPO" init -q
|
||||
mkdir -p "$TEMP_REPO/.git/hooks"
|
||||
|
||||
# Minimal deploy-manifest.sh — empty deploy lists so install.sh reaches the
|
||||
# hook-copy block without attempting to copy files that don't exist in the
|
||||
@@ -96,28 +90,6 @@ else
|
||||
fi
|
||||
rmdir "$HOOKS_SRC/not-a-hook"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "--- hook install: resolves correctly when GIT_DIR is inherited (hook context) ---"
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Git sets GIT_DIR/GIT_WORK_TREE for child processes when this script itself
|
||||
# runs as a hook (e.g. pre-push). Simulate that and confirm install.sh still
|
||||
# resolves hooks against $TEMP_REPO, not the inherited GIT_DIR.
|
||||
OTHER_REPO="$(mktemp -d)"
|
||||
git -C "$OTHER_REPO" init -q
|
||||
if HOME="$TEMP_HOME" GIT_DIR="$OTHER_REPO/.git" GIT_WORK_TREE="$OTHER_REPO" \
|
||||
bash "$TEMP_REPO/scripts/install.sh" > /dev/null 2>&1; then
|
||||
if [[ -f "$TEMP_REPO/.git/hooks/post-push" ]]; then
|
||||
pass "resolves \$TEMP_REPO/.git/hooks/ even with inherited GIT_DIR"
|
||||
else
|
||||
fail "installed into inherited GIT_DIR instead of \$TEMP_REPO"
|
||||
fi
|
||||
else
|
||||
fail "install.sh failed when GIT_DIR/GIT_WORK_TREE were inherited"
|
||||
fi
|
||||
rm -rf "$OTHER_REPO"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "--- hook install: idempotent ---"
|
||||
|
||||
Reference in New Issue
Block a user