@kody-ade/kody-engine 0.4.18 → 0.4.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/kody.js +225 -542
- package/dist/executables/fix/profile.json +1 -1
- package/dist/executables/fix/prompt.md +1 -1
- package/dist/executables/goal-scheduler/scheduler.sh +0 -0
- package/dist/executables/goal-tick/tick.sh +94 -15
- package/dist/executables/job-tick/prompt.md +12 -1
- package/dist/executables/release-deploy/deploy.sh +0 -0
- package/dist/executables/release-prepare/prepare.sh +0 -0
- package/dist/executables/release-publish/publish.sh +0 -0
- package/dist/executables/resolve/apply-prefer.sh +0 -0
- package/dist/executables/resolve/profile.json +1 -1
- package/dist/executables/resolve/prompt.md +1 -1
- package/dist/executables/revert/revert.sh +0 -0
- package/dist/executables/run/profile.json +1 -1
- package/dist/executables/run/prompt.md +1 -1
- package/dist/jobs/watch-stale-prs.md +86 -0
- package/package.json +15 -14
- package/dist/executables/memorize/profile.json +0 -48
- package/dist/executables/memorize/prompt.md +0 -59
- package/dist/executables/watch-stale-prs/profile.json +0 -30
|
@@ -21,7 +21,7 @@ You are Kody, an autonomous engineer. Apply the feedback below to the existing P
|
|
|
21
21
|
|
|
22
22
|
If a prior-art block is present above, scan it before editing — those are earlier attempts (possibly by you, possibly by a human) at the same fix. Note what was rejected and why; do not repeat a discarded approach.
|
|
23
23
|
|
|
24
|
-
{{
|
|
24
|
+
{{memoryContext}}
|
|
25
25
|
|
|
26
26
|
# Required steps
|
|
27
27
|
1. **Extract** every actionable item from the feedback. A structured review uses headings like `### Concerns`, `### Suggestions`, and `### Bugs`; each bullet under those headings is a distinct item. `### Strengths`, `### Summary`, and `### Bottom line` are NOT items — skip them. If the feedback has no headings (plain inline feedback), treat the whole feedback as one item.
|
|
File without changes
|
|
@@ -196,6 +196,68 @@ with open(path, "w") as f:
|
|
|
196
196
|
PY
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
ensure_goal_pr() {
|
|
200
|
+
# Open a draft goal PR (`goal-<id>` → default branch) early in the goal's
|
|
201
|
+
# life so the dashboard has a single anchor that ties together the umbrella
|
|
202
|
+
# issue, the goal branch, and the Vercel preview deploy. Without this PR,
|
|
203
|
+
# the umbrella issue is just a label-tagged issue with no link to its
|
|
204
|
+
# branch, so the dashboard can't surface preview/CI/branch on the umbrella
|
|
205
|
+
# row.
|
|
206
|
+
#
|
|
207
|
+
# Lifecycle:
|
|
208
|
+
# - Created here as DRAFT on every active tick once origin/<goal_branch>
|
|
209
|
+
# exists. Body carries `Closes #<umbrellaNumber>` so the umbrella
|
|
210
|
+
# auto-closes on merge.
|
|
211
|
+
# - Promoted to ready-for-review by the finalize path when all child
|
|
212
|
+
# tasks close (see below).
|
|
213
|
+
#
|
|
214
|
+
# Lookup order:
|
|
215
|
+
# 1. state.json `goalPrUrl` — fast path; skip if already populated.
|
|
216
|
+
# 2. `gh pr list --head <goal_branch>` — recovery path when state.json
|
|
217
|
+
# lost the field (e.g. older goals from before this change).
|
|
218
|
+
# 3. Create a fresh draft PR.
|
|
219
|
+
local existing_url existing_num
|
|
220
|
+
existing_url=$(read_state_field "goalPrUrl")
|
|
221
|
+
if [ -n "$existing_url" ]; then
|
|
222
|
+
return 0
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
# Goal branch must exist on origin before we can open a PR.
|
|
226
|
+
if ! git ls-remote --exit-code --heads origin "$goal_branch" >/dev/null 2>&1; then
|
|
227
|
+
return 0
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
# Recovery: PR may already exist from a prior tick that didn't persist the
|
|
231
|
+
# URL. Match by head ref.
|
|
232
|
+
existing_num=$(gh pr list --head "$goal_branch" --state open --json number --jq '.[0].number // empty' 2>/dev/null || echo "")
|
|
233
|
+
if [ -n "$existing_num" ] && [[ "$existing_num" =~ ^[0-9]+$ ]]; then
|
|
234
|
+
existing_url=$(gh pr view "$existing_num" --json url --jq .url 2>/dev/null || echo "")
|
|
235
|
+
else
|
|
236
|
+
local title body goal_issue_number
|
|
237
|
+
title="goal: ${goal_id}"
|
|
238
|
+
goal_issue_number=$(read_state_field "goalIssueNumber")
|
|
239
|
+
if [ -n "$goal_issue_number" ] && [ "$goal_issue_number" != "0" ]; then
|
|
240
|
+
body=$(printf "Tracking integration PR for goal **%s**.\n\nChild task PRs merge into \`%s\`. This PR is held in **draft** until every task is complete, then promoted to ready-for-review by goal-tick.\n\nCloses #%s\n" "$goal_id" "$goal_branch" "$goal_issue_number")
|
|
241
|
+
else
|
|
242
|
+
body=$(printf "Tracking integration PR for goal **%s**.\n\nChild task PRs merge into \`%s\`. Held in **draft** until every task is complete.\n" "$goal_id" "$goal_branch")
|
|
243
|
+
fi
|
|
244
|
+
existing_url=$(gh pr create \
|
|
245
|
+
--draft \
|
|
246
|
+
--head "$goal_branch" \
|
|
247
|
+
--base "$default_branch" \
|
|
248
|
+
--title "$title" \
|
|
249
|
+
--body "$body" 2>/dev/null || echo "")
|
|
250
|
+
if [ -z "$existing_url" ]; then
|
|
251
|
+
echo "[goal-tick] ensure_goal_pr: gh pr create failed (continuing without goal PR)"
|
|
252
|
+
return 0
|
|
253
|
+
fi
|
|
254
|
+
echo "[goal-tick] opened draft goal PR ${existing_url} for ${goal_id}"
|
|
255
|
+
fi
|
|
256
|
+
|
|
257
|
+
# Persist URL into state.json so subsequent ticks skip the lookup.
|
|
258
|
+
set_state_field "goalPrUrl" "$existing_url"
|
|
259
|
+
}
|
|
260
|
+
|
|
199
261
|
list_goal_issues() {
|
|
200
262
|
# Up to 100 goal-labelled issues. PRs filtered out. Also filters out the
|
|
201
263
|
# umbrella goal issue (if any) — it shares the `goal:<id>` label so the
|
|
@@ -348,31 +410,43 @@ open_count=$(echo "$issues_json" | python3 -c "import json,sys; print(sum(1 for
|
|
|
348
410
|
if [ "$open_count" = "0" ]; then
|
|
349
411
|
echo "[goal-tick] all $total task(s) closed — finalising goal"
|
|
350
412
|
|
|
351
|
-
#
|
|
352
|
-
# the goal branch
|
|
353
|
-
#
|
|
413
|
+
# Promote (or open) the goal PR. The active path opens this PR as a draft
|
|
414
|
+
# once the goal branch exists, so by finalize it almost always already
|
|
415
|
+
# exists — we just mark it ready-for-review and refresh the body. Older
|
|
416
|
+
# goals from before the early-PR change may still need first-time creation
|
|
417
|
+
# here as a fallback.
|
|
354
418
|
goal_pr_url=""
|
|
355
419
|
if git ls-remote --exit-code --heads origin "$goal_branch" >/dev/null 2>&1; then
|
|
356
|
-
existing_pr=$(gh pr list --head "$goal_branch" --state open --json number,url --jq '.[0]' 2>/dev/null || echo "")
|
|
420
|
+
existing_pr=$(gh pr list --head "$goal_branch" --state open --json number,url,isDraft --jq '.[0]' 2>/dev/null || echo "")
|
|
421
|
+
title="goal: ${goal_id}"
|
|
422
|
+
goal_issue_number=$(read_state_field "goalIssueNumber")
|
|
423
|
+
# `Closes #N` auto-closes the umbrella goal issue on PR merge — that's
|
|
424
|
+
# how the dashboard learns the goal is done. Skip the line gracefully
|
|
425
|
+
# if no umbrella issue was ever opened (older goals from before this
|
|
426
|
+
# change, or `gh issue create` failed silently during a tick).
|
|
427
|
+
if [ -n "$goal_issue_number" ] && [ "$goal_issue_number" != "0" ]; then
|
|
428
|
+
body=$(printf "Final integration PR for goal **%s**.\n\nAll task issues are closed and merged into \`%s\`. Ready for review.\n\nCloses #%s\n" "$goal_id" "$goal_branch" "$goal_issue_number")
|
|
429
|
+
else
|
|
430
|
+
body=$(printf "Final integration PR for goal **%s**.\n\nAll task issues are closed and merged into \`%s\`. Ready for review.\n" "$goal_id" "$goal_branch")
|
|
431
|
+
fi
|
|
357
432
|
if [ -z "$existing_pr" ] || [ "$existing_pr" = "null" ]; then
|
|
358
|
-
title="goal: ${goal_id}"
|
|
359
|
-
goal_issue_number=$(read_state_field "goalIssueNumber")
|
|
360
|
-
# `Closes #N` auto-closes the umbrella goal issue on PR merge — that's
|
|
361
|
-
# how the dashboard learns the goal is done. Skip the line gracefully
|
|
362
|
-
# if no umbrella issue was ever opened (older goals from before this
|
|
363
|
-
# change, or `gh issue create` failed silently during a tick).
|
|
364
|
-
if [ -n "$goal_issue_number" ] && [ "$goal_issue_number" != "0" ]; then
|
|
365
|
-
body=$(printf "Final integration PR for goal **%s**.\n\nAll task issues are closed and merged into \`%s\`. Ready for review.\n\nCloses #%s\n" "$goal_id" "$goal_branch" "$goal_issue_number")
|
|
366
|
-
else
|
|
367
|
-
body=$(printf "Final integration PR for goal **%s**.\n\nAll task issues are closed and merged into \`%s\`. Ready for review.\n" "$goal_id" "$goal_branch")
|
|
368
|
-
fi
|
|
369
433
|
goal_pr_url=$(gh pr create \
|
|
370
434
|
--head "$goal_branch" \
|
|
371
435
|
--base "$default_branch" \
|
|
372
436
|
--title "$title" \
|
|
373
437
|
--body "$body" 2>/dev/null || echo "")
|
|
374
438
|
else
|
|
439
|
+
existing_num=$(echo "$existing_pr" | python3 -c "import json,sys; print(json.load(sys.stdin).get('number',''))")
|
|
375
440
|
goal_pr_url=$(echo "$existing_pr" | python3 -c "import json,sys; print(json.load(sys.stdin).get('url',''))")
|
|
441
|
+
is_draft=$(echo "$existing_pr" | python3 -c "import json,sys; print('true' if json.load(sys.stdin).get('isDraft') else 'false')")
|
|
442
|
+
# Refresh the body with the finalize copy so reviewers see the right
|
|
443
|
+
# framing. Best-effort — failure is non-fatal.
|
|
444
|
+
gh pr edit "$existing_num" --body "$body" >/dev/null 2>&1 || true
|
|
445
|
+
if [ "$is_draft" = "true" ]; then
|
|
446
|
+
echo "[goal-tick] promoting draft goal PR #${existing_num} to ready-for-review"
|
|
447
|
+
gh pr ready "$existing_num" >/dev/null 2>&1 \
|
|
448
|
+
|| echo "[goal-tick] failed to mark PR #${existing_num} ready (continuing)"
|
|
449
|
+
fi
|
|
376
450
|
fi
|
|
377
451
|
else
|
|
378
452
|
echo "[goal-tick] goal branch ${goal_branch} not found on origin — skipping final PR"
|
|
@@ -470,6 +544,11 @@ else
|
|
|
470
544
|
fi
|
|
471
545
|
fi
|
|
472
546
|
|
|
547
|
+
# Open the draft goal PR now that the branch exists. The PR is the dashboard's
|
|
548
|
+
# single anchor for the goal's branch + preview + CI; finalize promotes it
|
|
549
|
+
# from draft to ready-for-review when every task has closed.
|
|
550
|
+
ensure_goal_pr
|
|
551
|
+
|
|
473
552
|
echo "[goal-tick] dispatching @kody on task #$next_issue (--base $goal_branch)"
|
|
474
553
|
gh issue comment "$next_issue" --body "@kody --base ${goal_branch}"
|
|
475
554
|
gh issue edit "$next_issue" --add-label "$dispatched_label"
|
|
@@ -47,8 +47,19 @@ If you fail to emit this block, or the JSON is invalid, the tick fails and the g
|
|
|
47
47
|
## Rules
|
|
48
48
|
|
|
49
49
|
- Never edit, create, or delete files in the working tree.
|
|
50
|
-
- Never commit or push.
|
|
50
|
+
- Never commit or push via `git`. The only permitted commit path is `gh api -X PUT` against the report file (see exception below).
|
|
51
51
|
- Only shell calls allowed: `gh`. Everything must go through it.
|
|
52
52
|
- Keep each tick focused: do one action per candidate per wake. The cron will call you again.
|
|
53
53
|
- If state says you're waiting on something, just check and re-emit — don't spawn a duplicate.
|
|
54
54
|
- Honour the job body's `## Restrictions` over any inferred shortcut.
|
|
55
|
+
|
|
56
|
+
### Single permitted write: the job's report file
|
|
57
|
+
|
|
58
|
+
A job MAY (optionally — only if its body asks for it) write a single
|
|
59
|
+
markdown report file at the canonical path:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
.kody/reports/{{jobSlug}}.md
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Only that exact path. Only via `gh api -X PUT /repos/<owner>/<repo>/contents/.kody/reports/{{jobSlug}}.md` (with base64 content + `sha` of the existing file when updating). All other writes — code files, other report paths, other slugs — remain forbidden. The dashboard's `/reports` page surfaces these files automatically; this is the canonical channel for a job's diagnostic output when an issue comment isn't expressive enough.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -9,7 +9,7 @@ You are Kody, an autonomous engineer. A `git merge origin/{{baseBranch}}` into P
|
|
|
9
9
|
|
|
10
10
|
{{conflictedFiles}}
|
|
11
11
|
|
|
12
|
-
{{preferBlock}}{{conventionsBlock}}{{
|
|
12
|
+
{{preferBlock}}{{conventionsBlock}}{{memoryContext}}{{toolsUsage}}# Working-tree conflict markers (truncated)
|
|
13
13
|
|
|
14
14
|
{{conflictMarkersPreview}}
|
|
15
15
|
|
|
File without changes
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
{ "script": "loadTaskState" },
|
|
54
54
|
{ "script": "resolveArtifacts" },
|
|
55
55
|
{ "script": "loadPriorArt" },
|
|
56
|
-
{ "script": "
|
|
56
|
+
{ "script": "loadMemoryContext" },
|
|
57
57
|
{ "script": "loadConventions" },
|
|
58
58
|
{ "script": "loadCoverageRules" },
|
|
59
59
|
{ "script": "composePrompt" }
|
|
@@ -25,7 +25,7 @@ If the plan above is non-empty, TREAT IT AS AUTHORITATIVE — follow its file li
|
|
|
25
25
|
|
|
26
26
|
If a prior-art block is present above, READ THE DIFFS — those are failed or superseded attempts at this same issue. Identify what went wrong (review comments, the fact they were closed without merging, or behavioural gaps in the diff itself) and pick a different approach. Repeating a prior failed attempt is a hard failure even if your tests pass locally.
|
|
27
27
|
|
|
28
|
-
{{
|
|
28
|
+
{{memoryContext}}
|
|
29
29
|
|
|
30
30
|
# Required steps (all in this one session — no handoff)
|
|
31
31
|
1. **Research** — read the issue carefully, then meet the research floor below before any Edit/Write. Use Grep/Glob/Read to investigate.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# watch-stale-prs
|
|
2
|
+
|
|
3
|
+
> Weekly digest of open PRs that haven't been touched in a while. Writes a
|
|
4
|
+
> markdown report at `.kody/reports/watch-stale-prs.md` (surfaced by the
|
|
5
|
+
> dashboard's `/reports` page).
|
|
6
|
+
|
|
7
|
+
## Job
|
|
8
|
+
|
|
9
|
+
Find every open PR untouched for **≥ 7 days** and write a report listing
|
|
10
|
+
them, sorted by staleness (oldest first). When there are no stale PRs,
|
|
11
|
+
write a short "all clear" report so operators know the check ran.
|
|
12
|
+
|
|
13
|
+
**Cadence guard.** Skip this tick unless `data.lastRunAt` is null or older
|
|
14
|
+
than 7 days from now. When skipping, emit the same state back unchanged
|
|
15
|
+
with no `gh` calls.
|
|
16
|
+
|
|
17
|
+
### What "stale" means
|
|
18
|
+
|
|
19
|
+
A PR is stale if:
|
|
20
|
+
|
|
21
|
+
- `state` is `OPEN`, AND
|
|
22
|
+
- `updatedAt` is more than 7 days before now.
|
|
23
|
+
|
|
24
|
+
Use `gh pr list --state open --limit 100 --json number,title,url,updatedAt,author`
|
|
25
|
+
to enumerate. Filter and sort client-side; do not call `gh` once per PR.
|
|
26
|
+
|
|
27
|
+
### Report shape
|
|
28
|
+
|
|
29
|
+
Write to `.kody/reports/watch-stale-prs.md`. Overwrite each run.
|
|
30
|
+
|
|
31
|
+
When stale PRs exist:
|
|
32
|
+
|
|
33
|
+
```markdown
|
|
34
|
+
# Stale PRs — <ISO date>
|
|
35
|
+
|
|
36
|
+
🟡 <N> PR(s) untouched for > 7 days.
|
|
37
|
+
|
|
38
|
+
| # | Title | Author | Days stale | Updated |
|
|
39
|
+
|---|-------|--------|------------|---------|
|
|
40
|
+
| [#123](url) | <title> | @user | 14 | 2026-04-25 |
|
|
41
|
+
| ... | | | | |
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
When none:
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
# Stale PRs — <ISO date>
|
|
48
|
+
|
|
49
|
+
🟢 No open PRs untouched for more than 7 days.
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Truncate to the 50 oldest if the list is longer; append a final line
|
|
53
|
+
`> … and N more not shown`.
|
|
54
|
+
|
|
55
|
+
## Allowed Commands
|
|
56
|
+
|
|
57
|
+
- `gh pr list --state open --limit 100 --json number,title,url,updatedAt,author`
|
|
58
|
+
- `gh api -X GET /repos/{owner}/{repo}/contents/.kody/reports/watch-stale-prs.md`
|
|
59
|
+
— only to fetch the existing file's `sha` for an update.
|
|
60
|
+
- `gh api -X PUT /repos/{owner}/{repo}/contents/.kody/reports/watch-stale-prs.md`
|
|
61
|
+
— to write the report (base64-encoded `content`, `message`, and `sha`
|
|
62
|
+
when updating). This is the **only** permitted write path for this job.
|
|
63
|
+
|
|
64
|
+
## Restrictions
|
|
65
|
+
|
|
66
|
+
- Never edit, create, or delete any other file in the working tree.
|
|
67
|
+
- Never `git commit`, `git push`, or open a PR.
|
|
68
|
+
- Never post comments on PRs or issues; the report file is the only
|
|
69
|
+
output channel.
|
|
70
|
+
- Never call `gh` per-PR — one `pr list` is enough.
|
|
71
|
+
|
|
72
|
+
## State
|
|
73
|
+
|
|
74
|
+
`cursor`:
|
|
75
|
+
|
|
76
|
+
- `"idle"` — between runs (cadence guard skipped this tick or the run
|
|
77
|
+
finished cleanly).
|
|
78
|
+
|
|
79
|
+
`data`:
|
|
80
|
+
|
|
81
|
+
- `lastRunAt` (string, ISO) — when the report was last written. Used by
|
|
82
|
+
the cadence guard.
|
|
83
|
+
- `lastStaleCount` (number) — how many stale PRs were in the most recent
|
|
84
|
+
report. Diagnostic only.
|
|
85
|
+
|
|
86
|
+
`done`: always `false` — this job is evergreen.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.20",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -12,6 +12,18 @@
|
|
|
12
12
|
"templates",
|
|
13
13
|
"kody.config.schema.json"
|
|
14
14
|
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"kody": "tsx bin/kody.ts",
|
|
17
|
+
"build": "tsup && node scripts/copy-assets.cjs",
|
|
18
|
+
"test": "vitest run tests/unit tests/int --no-coverage",
|
|
19
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
20
|
+
"test:all": "vitest run tests --no-coverage",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"lint": "biome check",
|
|
23
|
+
"lint:fix": "biome check --write",
|
|
24
|
+
"format": "biome format --write",
|
|
25
|
+
"prepublishOnly": "pnpm build"
|
|
26
|
+
},
|
|
15
27
|
"dependencies": {
|
|
16
28
|
"@actions/cache": "^6.0.0",
|
|
17
29
|
"@anthropic-ai/claude-agent-sdk": "0.2.119"
|
|
@@ -32,16 +44,5 @@
|
|
|
32
44
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
33
45
|
},
|
|
34
46
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
35
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
36
|
-
|
|
37
|
-
"kody": "tsx bin/kody.ts",
|
|
38
|
-
"build": "tsup && node scripts/copy-assets.cjs",
|
|
39
|
-
"test": "vitest run tests/unit tests/int --no-coverage",
|
|
40
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
41
|
-
"test:all": "vitest run tests --no-coverage",
|
|
42
|
-
"typecheck": "tsc --noEmit",
|
|
43
|
-
"lint": "biome check",
|
|
44
|
-
"lint:fix": "biome check --write",
|
|
45
|
-
"format": "biome format --write"
|
|
46
|
-
}
|
|
47
|
-
}
|
|
47
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
48
|
+
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "memorize",
|
|
3
|
-
"role": "watch",
|
|
4
|
-
"describe": "Scheduled: synthesize recently merged PRs into the project's .kody/vault/ markdown wiki and open a PR with the changes.",
|
|
5
|
-
"kind": "scheduled",
|
|
6
|
-
"schedule": "0 3 * * *",
|
|
7
|
-
"inputs": [],
|
|
8
|
-
"claudeCode": {
|
|
9
|
-
"model": "inherit",
|
|
10
|
-
"permissionMode": "acceptEdits",
|
|
11
|
-
"maxTurns": null,
|
|
12
|
-
"maxThinkingTokens": null,
|
|
13
|
-
"systemPromptAppend": null,
|
|
14
|
-
"tools": ["Read", "Write", "Edit", "Bash", "Grep", "Glob"],
|
|
15
|
-
"hooks": ["block-git"],
|
|
16
|
-
"skills": [],
|
|
17
|
-
"commands": [],
|
|
18
|
-
"subagents": [],
|
|
19
|
-
"plugins": [],
|
|
20
|
-
"mcpServers": []
|
|
21
|
-
},
|
|
22
|
-
"cliTools": [
|
|
23
|
-
{
|
|
24
|
-
"name": "gh",
|
|
25
|
-
"install": {
|
|
26
|
-
"required": true,
|
|
27
|
-
"checkCommand": "command -v gh"
|
|
28
|
-
},
|
|
29
|
-
"verify": "gh auth status",
|
|
30
|
-
"usage": "Use `gh` only for read-only inspection (`gh pr view`, `gh pr list`, `gh api`) when you need extra context on a referenced PR. Never use it to commit, push, or open PRs — the wrapper does that.",
|
|
31
|
-
"allowedUses": ["pr", "api", "issue"]
|
|
32
|
-
}
|
|
33
|
-
],
|
|
34
|
-
"inputArtifacts": [],
|
|
35
|
-
"outputArtifacts": [],
|
|
36
|
-
"scripts": {
|
|
37
|
-
"preflight": [
|
|
38
|
-
{ "script": "memorizeFlow" },
|
|
39
|
-
{ "script": "composePrompt" }
|
|
40
|
-
],
|
|
41
|
-
"postflight": [
|
|
42
|
-
{ "script": "parseAgentResult" },
|
|
43
|
-
{ "script": "abortUnfinishedGitOps" },
|
|
44
|
-
{ "script": "commitAndPush" },
|
|
45
|
-
{ "script": "ensureMemorizePr" }
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
You are **kody memorize**, the project's long-term memory keeper. You synthesize recently merged work into a markdown knowledge base at `.kody/vault/` so future kody runs can recall decisions, conventions, and component knowledge.
|
|
2
|
-
|
|
3
|
-
## What you have
|
|
4
|
-
|
|
5
|
-
### Recent merged PRs (since {{vaultSinceIso}})
|
|
6
|
-
|
|
7
|
-
{{recentPrs}}
|
|
8
|
-
|
|
9
|
-
### Existing vault index
|
|
10
|
-
|
|
11
|
-
Vault root: `.kody/vault/`
|
|
12
|
-
|
|
13
|
-
{{vaultIndex}}
|
|
14
|
-
|
|
15
|
-
## What to do
|
|
16
|
-
|
|
17
|
-
1. **Read each recent PR's title, body, and (if useful) diff via `gh pr view <n>` / `gh pr diff <n>`.**
|
|
18
|
-
2. **Map each PR to the concept pages it affects** — files like `architecture/<area>.md`, `conventions/<topic>.md`, `decisions/<slug>.md`, `components/<name>.md`, or whatever organization the existing vault uses. If the vault is empty, start with a small set of pages reflecting what you actually learned.
|
|
19
|
-
3. **Update or create those pages.** Each page is a concept (e.g. "executor", "release flow"), NOT a per-PR log. A PR contributes one or more updates — small additions, edits to keep current, links back to the PR URL.
|
|
20
|
-
4. **Cross-link** related pages with relative markdown links so the vault forms a connected graph.
|
|
21
|
-
5. **Be terse.** Each page is reference material, not a story. One short paragraph per fact, bullet lists where useful, links instead of recapping.
|
|
22
|
-
6. **Don't duplicate the codebase.** Capture *what was decided* and *why*, not *how* the code looks — the code is authoritative for that.
|
|
23
|
-
7. **Don't invent.** If a PR's intent isn't clear, skip it rather than guessing.
|
|
24
|
-
|
|
25
|
-
## Page conventions
|
|
26
|
-
|
|
27
|
-
- Filename: `kebab-case.md`.
|
|
28
|
-
- Frontmatter (YAML) on every page:
|
|
29
|
-
```yaml
|
|
30
|
-
---
|
|
31
|
-
title: <Human Title>
|
|
32
|
-
type: architecture | convention | decision | component | runbook
|
|
33
|
-
updated: {{vaultUpdatedIso}}
|
|
34
|
-
sources:
|
|
35
|
-
- <PR URL or file path>
|
|
36
|
-
---
|
|
37
|
-
```
|
|
38
|
-
- Body: one short intro paragraph, then sections.
|
|
39
|
-
- Cross-references via relative links: `[executor](../architecture/executor.md)`.
|
|
40
|
-
|
|
41
|
-
## Rules
|
|
42
|
-
|
|
43
|
-
- Edit files only under `.kody/vault/`. Do not touch any other path.
|
|
44
|
-
- Do not commit or push. The wrapper does it.
|
|
45
|
-
- Do not run `git` or `gh` for anything except read-only inspection of referenced PRs.
|
|
46
|
-
- If there is nothing meaningful to add (PRs are trivial chores, all already captured, etc.), say so and emit `DONE` with `COMMIT_MSG: chore(vault): no updates`. The wrapper will detect no changes and skip the PR.
|
|
47
|
-
|
|
48
|
-
## Output contract (MANDATORY)
|
|
49
|
-
|
|
50
|
-
End your response with these lines, exactly:
|
|
51
|
-
|
|
52
|
-
```
|
|
53
|
-
DONE
|
|
54
|
-
COMMIT_MSG: chore(vault): <one-line summary>
|
|
55
|
-
PR_SUMMARY:
|
|
56
|
-
<2–6 line summary of what changed in the vault and why>
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
If you decide to abort with no changes, emit `DONE` with the no-updates `COMMIT_MSG` and a brief `PR_SUMMARY` saying so.
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "watch-stale-prs",
|
|
3
|
-
"role": "watch",
|
|
4
|
-
"describe": "Scheduled: list open PRs untouched for N days and report. No agent invocation.",
|
|
5
|
-
"kind": "scheduled",
|
|
6
|
-
"schedule": "0 8 * * MON",
|
|
7
|
-
"inputs": [],
|
|
8
|
-
"claudeCode": {
|
|
9
|
-
"model": "inherit",
|
|
10
|
-
"permissionMode": "default",
|
|
11
|
-
"maxTurns": null,
|
|
12
|
-
"systemPromptAppend": null,
|
|
13
|
-
"tools": [],
|
|
14
|
-
"hooks": [],
|
|
15
|
-
"skills": [],
|
|
16
|
-
"commands": [],
|
|
17
|
-
"subagents": [],
|
|
18
|
-
"plugins": [],
|
|
19
|
-
"mcpServers": []
|
|
20
|
-
},
|
|
21
|
-
"cliTools": [],
|
|
22
|
-
"scripts": {
|
|
23
|
-
"preflight": [
|
|
24
|
-
{
|
|
25
|
-
"script": "watchStalePrsFlow"
|
|
26
|
-
}
|
|
27
|
-
],
|
|
28
|
-
"postflight": []
|
|
29
|
-
}
|
|
30
|
-
}
|