@kody-ade/kody-engine 0.4.19 → 0.4.21
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 +101 -15
- 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 +89 -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
|
|
@@ -273,6 +335,16 @@ ensure_label "$failed_label" "b60205" "kody goal-runner: task failed; needs huma
|
|
|
273
335
|
# counting child tasks, so list_goal_issues can filter it out cleanly.
|
|
274
336
|
ensure_goal_issue
|
|
275
337
|
|
|
338
|
+
# Open the draft goal PR if the goal branch already exists. Must run BEFORE
|
|
339
|
+
# any of the early exits below (in_flight check, no-undispatched-task idle,
|
|
340
|
+
# etc.) — otherwise active goals that always have a task in flight would
|
|
341
|
+
# never get past the in_flight gate to reach the late call site, leaving
|
|
342
|
+
# the umbrella row without its branch + preview anchor in the dashboard.
|
|
343
|
+
# `ensure_goal_pr` is a safe no-op when the branch hasn't been created yet
|
|
344
|
+
# (the lazy-branch-creation block at the dispatch site handles that case;
|
|
345
|
+
# the next tick picks up the PR creation here).
|
|
346
|
+
ensure_goal_pr
|
|
347
|
+
|
|
276
348
|
# Merge ready goal-task PRs into the goal branch. We own the merge here
|
|
277
349
|
# instead of relying on GitHub's `--auto` flag (which requires the repo's
|
|
278
350
|
# "Allow auto-merge" setting and silently no-ops when disabled). Only merge
|
|
@@ -348,31 +420,43 @@ open_count=$(echo "$issues_json" | python3 -c "import json,sys; print(sum(1 for
|
|
|
348
420
|
if [ "$open_count" = "0" ]; then
|
|
349
421
|
echo "[goal-tick] all $total task(s) closed — finalising goal"
|
|
350
422
|
|
|
351
|
-
#
|
|
352
|
-
# the goal branch
|
|
353
|
-
#
|
|
423
|
+
# Promote (or open) the goal PR. The active path opens this PR as a draft
|
|
424
|
+
# once the goal branch exists, so by finalize it almost always already
|
|
425
|
+
# exists — we just mark it ready-for-review and refresh the body. Older
|
|
426
|
+
# goals from before the early-PR change may still need first-time creation
|
|
427
|
+
# here as a fallback.
|
|
354
428
|
goal_pr_url=""
|
|
355
429
|
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 "")
|
|
430
|
+
existing_pr=$(gh pr list --head "$goal_branch" --state open --json number,url,isDraft --jq '.[0]' 2>/dev/null || echo "")
|
|
431
|
+
title="goal: ${goal_id}"
|
|
432
|
+
goal_issue_number=$(read_state_field "goalIssueNumber")
|
|
433
|
+
# `Closes #N` auto-closes the umbrella goal issue on PR merge — that's
|
|
434
|
+
# how the dashboard learns the goal is done. Skip the line gracefully
|
|
435
|
+
# if no umbrella issue was ever opened (older goals from before this
|
|
436
|
+
# change, or `gh issue create` failed silently during a tick).
|
|
437
|
+
if [ -n "$goal_issue_number" ] && [ "$goal_issue_number" != "0" ]; then
|
|
438
|
+
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")
|
|
439
|
+
else
|
|
440
|
+
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")
|
|
441
|
+
fi
|
|
357
442
|
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
443
|
goal_pr_url=$(gh pr create \
|
|
370
444
|
--head "$goal_branch" \
|
|
371
445
|
--base "$default_branch" \
|
|
372
446
|
--title "$title" \
|
|
373
447
|
--body "$body" 2>/dev/null || echo "")
|
|
374
448
|
else
|
|
449
|
+
existing_num=$(echo "$existing_pr" | python3 -c "import json,sys; print(json.load(sys.stdin).get('number',''))")
|
|
375
450
|
goal_pr_url=$(echo "$existing_pr" | python3 -c "import json,sys; print(json.load(sys.stdin).get('url',''))")
|
|
451
|
+
is_draft=$(echo "$existing_pr" | python3 -c "import json,sys; print('true' if json.load(sys.stdin).get('isDraft') else 'false')")
|
|
452
|
+
# Refresh the body with the finalize copy so reviewers see the right
|
|
453
|
+
# framing. Best-effort — failure is non-fatal.
|
|
454
|
+
gh pr edit "$existing_num" --body "$body" >/dev/null 2>&1 || true
|
|
455
|
+
if [ "$is_draft" = "true" ]; then
|
|
456
|
+
echo "[goal-tick] promoting draft goal PR #${existing_num} to ready-for-review"
|
|
457
|
+
gh pr ready "$existing_num" >/dev/null 2>&1 \
|
|
458
|
+
|| echo "[goal-tick] failed to mark PR #${existing_num} ready (continuing)"
|
|
459
|
+
fi
|
|
376
460
|
fi
|
|
377
461
|
else
|
|
378
462
|
echo "[goal-tick] goal branch ${goal_branch} not found on origin — skipping final PR"
|
|
@@ -469,6 +553,8 @@ else
|
|
|
469
553
|
fi
|
|
470
554
|
fi
|
|
471
555
|
fi
|
|
556
|
+
# (`ensure_goal_pr` runs at the top of the active path so it's reached even
|
|
557
|
+
# when this tick exits early via the in_flight gate; not duplicated here.)
|
|
472
558
|
|
|
473
559
|
echo "[goal-tick] dispatching @kody on task #$next_issue (--base $goal_branch)"
|
|
474
560
|
gh issue comment "$next_issue" --body "@kody --base ${goal_branch}"
|
|
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,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
every: 7d
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# watch-stale-prs
|
|
6
|
+
|
|
7
|
+
> Weekly digest of open PRs that haven't been touched in a while. Writes a
|
|
8
|
+
> markdown report at `.kody/reports/watch-stale-prs.md` (surfaced by the
|
|
9
|
+
> dashboard's `/reports` page).
|
|
10
|
+
>
|
|
11
|
+
> Cadence is enforced by the engine via the `every: 7d` frontmatter — this
|
|
12
|
+
> file only fires once per 7 days regardless of how often `job-scheduler`
|
|
13
|
+
> wakes. No prose cadence guard needed.
|
|
14
|
+
|
|
15
|
+
## Job
|
|
16
|
+
|
|
17
|
+
Find every open PR untouched for **≥ 7 days** and write a report listing
|
|
18
|
+
them, sorted by staleness (oldest first). When there are no stale PRs,
|
|
19
|
+
write a short "all clear" report so operators know the check ran.
|
|
20
|
+
|
|
21
|
+
### What "stale" means
|
|
22
|
+
|
|
23
|
+
A PR is stale if:
|
|
24
|
+
|
|
25
|
+
- `state` is `OPEN`, AND
|
|
26
|
+
- `updatedAt` is more than 7 days before now.
|
|
27
|
+
|
|
28
|
+
Use `gh pr list --state open --limit 100 --json number,title,url,updatedAt,author`
|
|
29
|
+
to enumerate. Filter and sort client-side; do not call `gh` once per PR.
|
|
30
|
+
|
|
31
|
+
### Report shape
|
|
32
|
+
|
|
33
|
+
Write to `.kody/reports/watch-stale-prs.md`. Overwrite each run.
|
|
34
|
+
|
|
35
|
+
When stale PRs exist:
|
|
36
|
+
|
|
37
|
+
```markdown
|
|
38
|
+
# Stale PRs — <ISO date>
|
|
39
|
+
|
|
40
|
+
🟡 <N> PR(s) untouched for > 7 days.
|
|
41
|
+
|
|
42
|
+
| # | Title | Author | Days stale | Updated |
|
|
43
|
+
|---|-------|--------|------------|---------|
|
|
44
|
+
| [#123](url) | <title> | @user | 14 | 2026-04-25 |
|
|
45
|
+
| ... | | | | |
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
When none:
|
|
49
|
+
|
|
50
|
+
```markdown
|
|
51
|
+
# Stale PRs — <ISO date>
|
|
52
|
+
|
|
53
|
+
🟢 No open PRs untouched for more than 7 days.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Truncate to the 50 oldest if the list is longer; append a final line
|
|
57
|
+
`> … and N more not shown`.
|
|
58
|
+
|
|
59
|
+
## Allowed Commands
|
|
60
|
+
|
|
61
|
+
- `gh pr list --state open --limit 100 --json number,title,url,updatedAt,author`
|
|
62
|
+
- `gh api -X GET /repos/{owner}/{repo}/contents/.kody/reports/watch-stale-prs.md`
|
|
63
|
+
— only to fetch the existing file's `sha` for an update.
|
|
64
|
+
- `gh api -X PUT /repos/{owner}/{repo}/contents/.kody/reports/watch-stale-prs.md`
|
|
65
|
+
— to write the report (base64-encoded `content`, `message`, and `sha`
|
|
66
|
+
when updating). This is the **only** permitted write path for this job.
|
|
67
|
+
|
|
68
|
+
## Restrictions
|
|
69
|
+
|
|
70
|
+
- Never edit, create, or delete any other file in the working tree.
|
|
71
|
+
- Never `git commit`, `git push`, or open a PR.
|
|
72
|
+
- Never post comments on PRs or issues; the report file is the only
|
|
73
|
+
output channel.
|
|
74
|
+
- Never call `gh` per-PR — one `pr list` is enough.
|
|
75
|
+
|
|
76
|
+
## State
|
|
77
|
+
|
|
78
|
+
`cursor`: always `"idle"` — this job has no phases; each fire is a
|
|
79
|
+
one-shot report write.
|
|
80
|
+
|
|
81
|
+
`data`:
|
|
82
|
+
|
|
83
|
+
- `lastStaleCount` (number) — how many stale PRs were in the most recent
|
|
84
|
+
report. Diagnostic only; the engine ignores it.
|
|
85
|
+
|
|
86
|
+
(Engine-managed fields like `lastFiredAt` live under `data` automatically;
|
|
87
|
+
do not write or rely on them from the prompt.)
|
|
88
|
+
|
|
89
|
+
`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.21",
|
|
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
|
-
}
|