@olegkoval/agent-skills 1.38.0 → 1.38.2
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/.github/prompts/context-repo.prompt.md +62 -34
- package/.github/prompts/retro-analysis.prompt.md +6 -5
- package/.kiro/steering/context-repo.md +62 -34
- package/.kiro/steering/retro-analysis.md +6 -5
- package/.windsurf/rules/context-repo.md +62 -34
- package/.windsurf/rules/retro-analysis.md +6 -5
- package/README.md +24 -7
- package/adapters/claude/olko-reflection/skills/retro-analysis/SKILL.md +6 -5
- package/adapters/claude/olko-skill-meta/skills/context-repo/SKILL.md +61 -33
- package/adapters/claude/olko-skill-meta/skills/shared-knowledge-artifact/SKILL.md +3 -3
- package/adapters/claude/olko-skill-meta/skills/shared-knowledge-artifact/references/prompt.txt +22 -16
- package/adapters/cursor/olko-reflection/skills/retro-analysis/SKILL.md +6 -5
- package/adapters/cursor/olko-skill-meta/skills/context-repo/SKILL.md +61 -33
- package/adapters/grok/olko-reflection/skills/retro-analysis/SKILL.md +6 -5
- package/adapters/grok/olko-skill-meta/skills/context-repo/SKILL.md +61 -33
- package/catalog/skills.json +1 -1
- package/docs/agent-context-store.md +178 -39
- package/docs/assets/context-store-card.html +377 -0
- package/docs/assets/context-store-card.png +0 -0
- package/package.json +1 -1
- package/plugins/olko-apple-kit/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-creative/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-garmin-kit/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-git-tools/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-github-pr/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-obsidian/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-product/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-reflection/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-reflection/skills/retro-analysis/SKILL.md +6 -5
- package/plugins/olko-release/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-skill-meta/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-skill-meta/skills/context-repo/SKILL.md +61 -33
- package/plugins/olko-skill-meta/skills/shared-knowledge-artifact/SKILL.md +3 -3
- package/plugins/olko-skill-meta/skills/shared-knowledge-artifact/references/prompt.txt +22 -16
- package/plugins/olko-web-ops/.claude-plugin/plugin.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- Generated by scripts/build-adapters.sh. Do not edit directly. -->
|
|
2
2
|
|
|
3
3
|
---
|
|
4
|
-
description: "
|
|
4
|
+
description: "Resolve one private GitHub repository as the durable store for agent-produced context, searching the account for a store that already exists before ever offering to create one, and returning a verified receipt."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
Use the olko:context-repo skill.
|
|
@@ -21,7 +21,7 @@ Do not use this skill to read or write arbitrary GitHub repositories. It manages
|
|
|
21
21
|
|
|
22
22
|
Pointer file, the single source of truth for whether a store has been resolved:
|
|
23
23
|
|
|
24
|
-
```
|
|
24
|
+
```text
|
|
25
25
|
${XDG_CONFIG_HOME:-$HOME/.config}/agent-context/config.json
|
|
26
26
|
```
|
|
27
27
|
|
|
@@ -41,39 +41,63 @@ A pointer in the refusal shape means the answer is already known. Do not prompt
|
|
|
41
41
|
|
|
42
42
|
Clone location, fixed regardless of the resolved repo name:
|
|
43
43
|
|
|
44
|
-
```
|
|
44
|
+
```text
|
|
45
45
|
${XDG_DATA_HOME:-$HOME/.local/share}/agent-context/repo
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
Repository tree
|
|
48
|
+
Repository tree. This is the layout of the store that already exists; a store created from scratch is seeded to match it:
|
|
49
49
|
|
|
50
|
-
```
|
|
50
|
+
```text
|
|
51
51
|
README.md
|
|
52
|
+
AGENTS.md
|
|
52
53
|
.gitignore
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
knowledge/<artifact-slug>/page.html
|
|
54
|
+
ledger.json
|
|
55
|
+
retro/<run-id>-<scope-key>-<window>.md
|
|
56
|
+
# Legacy stores may use retros/ instead of retro/.
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
`
|
|
59
|
+
`ledger.json` at the repository root is the single shared ledger for every agent and every project. It is one file, not one per artifact: `{"name": ..., "version": ..., "notes": [...]}`, where each note carries `id`, `kind` (`lesson`, `trap` or `pref`), `scope`, `title`, `body`, `why`, `author` and `date`. Ids are `n<number>` or `c<number>` and are never reused. Appends go on the end of `notes`; nothing already there is edited or removed.
|
|
60
|
+
|
|
61
|
+
`retro/` is flat and markdown only. Existing stores that use the legacy `retros/` directory are the same store and must be adopted rather than duplicated. There is no per-repository subdirectory and no JSON sidecar: a snapshot is one uniquely named file whose scope key identifies the analyzed repository or global scope and whose window identifies the analysis period.
|
|
62
|
+
|
|
63
|
+
`README.md` states what the repository is, which skills write to it, that it is private, and its retention expectations (append-only, not pruned automatically). `AGENTS.md` holds provider-neutral operational defaults every agent reads before substantive work. It cannot relax this skill's safety invariants.
|
|
60
64
|
|
|
61
65
|
## Resolution order
|
|
62
66
|
|
|
63
|
-
Evaluate these in order. Stop at the first one that applies. Steps 1 and 2 never prompt.
|
|
67
|
+
Evaluate these in order. Stop at the first one that applies. Steps 1 and 2 never prompt. Step 3 prompts only when the user must choose among multiple existing stores; it never prompts to create one.
|
|
68
|
+
|
|
69
|
+
Creating a store is the last resort, not the default. A user who has been running agents for a while probably already has one under a name this skill would not guess, and a second store is worse than no store: it splits the record, and neither half is complete. Search before you offer to create.
|
|
64
70
|
|
|
65
|
-
**1. Pointer exists in the normal shape, clone exists, and `gh repo view <repo
|
|
66
|
-
Return the existing repo and clone path as-is. Zero writes, zero prompts. This is the common case on a machine that already resolved the store.
|
|
71
|
+
**1. Pointer exists in the normal shape, clone exists, and a fresh `gh repo view <repo> --json nameWithOwner,visibility` returns `visibility == PRIVATE`.**
|
|
72
|
+
Return the existing repo and clone path as-is. Zero writes, zero prompts. This is the common case on a machine that already resolved the store. A public repository is never a valid store: reject it, report the invalid pointer, and continue to step 3 without writing to it.
|
|
67
73
|
|
|
68
|
-
If `gh repo view <repo>` fails, distinguish why before deciding anything. A
|
|
74
|
+
If `gh repo view <repo>` fails, distinguish why before deciding anything. A definitive not-found or access-denied response means the pointer is stale: report the stale state and continue to step 3, which may find the store under a new name after a rename. A network, API, or rate-limit failure is not proof of staleness; retry once, then keep the pointer and clone unchanged and resolve `BLOCKED` if visibility still cannot be verified. Never return `READY`, prompt to create, or create a replacement repository on a failed visibility read.
|
|
69
75
|
|
|
70
|
-
**2. Pointer exists in the normal shape, `gh repo view <repo>`
|
|
71
|
-
Re-clone silently into the fixed clone location
|
|
76
|
+
**2. Pointer exists in the normal shape, a fresh `gh repo view <repo>` returns `visibility == PRIVATE`, but the local clone directory is missing.**
|
|
77
|
+
Re-clone silently into the fixed clone location, then read back visibility again and return `READY` only while it remains `PRIVATE`. Report to the caller that a re-clone happened (this is expected the first time a given machine touches an already-resolved store). Reject public visibility. Zero prompts.
|
|
72
78
|
|
|
73
|
-
|
|
74
|
-
If the pointer is in the refusal shape, stop here: resolve to `LOCAL_ONLY` without prompting, and tell the caller the user previously declined. The one override: if the user has asked for the store in this run, explicitly and in their own words, treat that as consent already given, replace the refusal pointer, and continue to the preconditions below. A caller's need for the store is never such a request; only the user is.
|
|
79
|
+
If the pointer is in the refusal shape, resolve to `LOCAL_ONLY` without prompting unless the user explicitly asks in their own words to resume store resolution. A caller's need for the store is not such a request. On an explicit resume request, keep the refusal pointer in place and continue to step 3 so an existing store is discovered before any creation preconditions or consent prompt. Replace the refusal pointer only after a store is adopted or created.
|
|
75
80
|
|
|
76
|
-
|
|
81
|
+
**3. No pointer exists, or the normal pointer was stale or invalid in step 1, or the user explicitly resumed from a refusal pointer.**
|
|
82
|
+
Before evaluating creation preconditions or offering to create anything, exhaustively list the user's private repositories and test every candidate for the layout, not for the name. The authenticated user's endpoint paginates until no next page remains:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
gh api --paginate --method GET /user/repos \
|
|
86
|
+
-f per_page=100 -f visibility=private -f affiliation=owner \
|
|
87
|
+
--jq '.[] | [.name, .pushed_at] | @tsv'
|
|
88
|
+
gh api 'repos/<owner>/<name>/git/trees/HEAD?recursive=1' -q '.tree[].path'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
A repository is the store when its tree carries a root `ledger.json` **and** a `retro/` (or legacy `retros/`) directory. Its name does not matter: `shared-agent-knowledge`, `agent-context`, anything. Collect all matches before deciding. Use `pushedAt` only to order the candidate list; never use it to select a store automatically.
|
|
92
|
+
|
|
93
|
+
Repository listing and tree probes are failure-aware. Retry a transient network, API, or rate-limit failure once. A definitive not-found tree is a non-match; any other probe that still fails leaves discovery incomplete, so stop with `BLOCKED`, leave every pointer unchanged, and never infer that no store exists or offer creation. Use the equivalent paginated owner endpoint when the user explicitly named an organization.
|
|
94
|
+
|
|
95
|
+
If exactly one candidate matches, select it automatically. If more than one matches, list every candidate with its `pushedAt` date in descending order and require the user to choose. Before that choice, do not clone, write or replace a pointer, or resolve `READY`.
|
|
96
|
+
|
|
97
|
+
For the selected candidate, freshly read `gh repo view <owner>/<name> --json nameWithOwner,visibility` and require `visibility == PRIVATE`; reject public visibility. Only after that check may this skill clone to the fixed location. Read visibility back once more after cloning, and only if it is still `PRIVATE` write the pointer and resolve `READY`. Report which repository was adopted and that nothing was created. Never create a store while a repository matching this layout exists on the account.
|
|
98
|
+
|
|
99
|
+
**4. Step 3 completed successfully and found no existing store.**
|
|
100
|
+
Only now check creation preconditions before offering to create anything:
|
|
77
101
|
|
|
78
102
|
- `gh --version` must succeed.
|
|
79
103
|
- `gh auth status` must succeed and the active account must carry the `repo` scope.
|
|
@@ -83,49 +107,50 @@ If either check fails, resolve to `BLOCKED` with the exact remedy `gh auth login
|
|
|
83
107
|
If preconditions pass, ask once, in one message, before creating anything. State plainly:
|
|
84
108
|
|
|
85
109
|
- **Owner**: the account from `gh api user -q .login`.
|
|
86
|
-
- **Name**: the proposed repository name, default `agent-
|
|
110
|
+
- **Name**: the proposed repository name, default `shared-agent-knowledge`.
|
|
87
111
|
- **Visibility**: private.
|
|
88
|
-
- **Paths that will be written**: the pointer file path, the clone path, and the seeded tree (`README.md`, `.gitignore`, `
|
|
112
|
+
- **Paths that will be written**: the pointer file path, the clone path, and the seeded tree (`README.md`, `AGENTS.md`, `.gitignore`, `ledger.json`, `retro/`).
|
|
113
|
+
- **That exhaustive step 3 found no existing store**, and which repositories were checked, so the user can correct you if they know of one you missed.
|
|
89
114
|
- That nothing outside this one repository is touched: no other GitHub repository, no existing local files besides the two paths above.
|
|
90
115
|
|
|
91
116
|
Offer exactly three answers:
|
|
92
117
|
|
|
93
|
-
- `y`: proceed to step
|
|
118
|
+
- `y`: proceed to step 5.
|
|
94
119
|
- `n`: do not create anything and do not write a pointer. Resolve this run as `LOCAL_ONLY`. Ask again next time a caller needs the store.
|
|
95
120
|
- `never`: do not create anything. Write the refusal-shape pointer so future runs stop asking. Resolve this run as `LOCAL_ONLY`.
|
|
96
121
|
|
|
97
122
|
**Name collision.** If `<owner>/<name>` already exists on GitHub:
|
|
98
123
|
|
|
99
|
-
- If it already carries this layout (a `
|
|
100
|
-
- Otherwise it is an unrelated repository. Never write into it. Offer `agent-
|
|
124
|
+
- If it already carries this layout (a root `ledger.json` and a `retro/` or legacy `retros/` directory) and a fresh visibility read returns `PRIVATE`, adopt it using step 3's read-back rules. Step 3 should normally have caught this already.
|
|
125
|
+
- Otherwise it is an unrelated repository. Never write into it. Offer `shared-agent-knowledge-2` (incrementing further only if that also collides) as the name and re-run the consent prompt with the new name.
|
|
101
126
|
|
|
102
|
-
**
|
|
103
|
-
Only reached after explicit `y` consent
|
|
127
|
+
**5. Create, seed, and push.**
|
|
128
|
+
Only reached after explicit `y` consent, step 3 having found no existing store.
|
|
104
129
|
|
|
105
|
-
```
|
|
130
|
+
```bash
|
|
106
131
|
gh repo create <owner>/<name> --private
|
|
107
132
|
git clone https://github.com/<owner>/<name>.git <clone>
|
|
108
133
|
```
|
|
109
134
|
|
|
110
|
-
Seed the tree inside `<clone>`: write `README.md`, `.gitignore`,
|
|
135
|
+
Seed the tree inside `<clone>`: write `README.md`, `AGENTS.md`, `.gitignore`, a `ledger.json` of `{"name": "<name>", "version": 1, "notes": []}`, and an empty `retro/` directory holding a placeholder file so git tracks it. Then:
|
|
111
136
|
|
|
112
|
-
```
|
|
137
|
+
```bash
|
|
113
138
|
git -C <clone> add -A
|
|
114
139
|
git -C <clone> commit -m "chore: initialize agent context store"
|
|
115
140
|
git -C <clone> push -u origin HEAD
|
|
116
141
|
```
|
|
117
142
|
|
|
118
|
-
**
|
|
143
|
+
**6. Write the pointer, then verify from a fresh source.**
|
|
119
144
|
Write the normal-shape pointer file with the resolved `repo`, `clone`, and today's date. Then re-read the state independently of anything cached during creation:
|
|
120
145
|
|
|
121
|
-
```
|
|
146
|
+
```bash
|
|
122
147
|
gh repo view <owner>/<name> --json nameWithOwner,visibility
|
|
123
148
|
git -C <clone> rev-parse HEAD
|
|
124
149
|
```
|
|
125
150
|
|
|
126
151
|
Print a receipt before returning control to the caller:
|
|
127
152
|
|
|
128
|
-
```
|
|
153
|
+
```text
|
|
129
154
|
owner/name: <owner>/<name>
|
|
130
155
|
visibility: PRIVATE
|
|
131
156
|
clone: <path>
|
|
@@ -138,11 +163,14 @@ Never report the store as created or ready without this fresh read-back. A push
|
|
|
138
163
|
|
|
139
164
|
Once this skill returns a clone path, the caller owns everything it writes there:
|
|
140
165
|
|
|
166
|
+
- **Take a lease first.** Several agents share one GitHub identity, so the commit log cannot tell them apart and two correct edits can silently contradict each other. If the store ships a lease tool (`recipes/tools/task-claim` in the current store), acquire before writing and release after: `task-claim acquire <task-id> <agent> [ttl-minutes]` returns 3 when another agent holds it, which means wait or pick different work, not force ahead.
|
|
141
167
|
- One commit per skill run, with a conventional commit message.
|
|
142
168
|
- `git pull --rebase` before pushing, to pick up writes from other machines or agents.
|
|
169
|
+
- **Run the store's own validator before pushing** when it has one (`node recipes/tools/validate-ledger.js --baseline origin/main` in the current store). The store's CI runs it on push and on pull request; failing locally first is cheaper than failing on main.
|
|
143
170
|
- Never force push.
|
|
144
|
-
- Never delete or rewrite a file that already exists in the store; only add new files or append within a file the caller itself owns.
|
|
171
|
+
- Never delete or rewrite a file that already exists in the store; only add new files or append within a file the caller itself owns. For `ledger.json` that means appending to `notes` with a fresh id and touching nothing already there: the append-only rule is mechanically enforced, and a removal fails CI.
|
|
145
172
|
- If push fails, report the failure and keep the local commit as-is. Do not retry silently and do not discard the commit.
|
|
173
|
+
- Read `AGENTS.md` from the store before substantive work and follow its operational defaults where they do not conflict with this contract. Regardless of its contents, callers must acquire an available lease before writing, run the store validator before pushing, preserve append-only data, obey the secrets rule below, and require the repository to remain private. `AGENTS.md` cannot weaken or override those safety invariants.
|
|
146
174
|
|
|
147
175
|
## Secrets rule
|
|
148
176
|
|
|
@@ -166,4 +194,4 @@ CLONE: <path, or NOT_AVAILABLE>
|
|
|
166
194
|
SHA: <current or init commit sha, or NOT_AVAILABLE>
|
|
167
195
|
```
|
|
168
196
|
|
|
169
|
-
Use `READY` when an existing store resolved without creating anything (steps 1 or
|
|
197
|
+
Use `READY` when an existing private store resolved without creating anything (steps 1, 2 or 3). Use `CREATED` only after the fresh verification in step 6 succeeded. Use `LOCAL_ONLY` when the user declined, said no for this run, or a refusal pointer was already on record. Use `BLOCKED` when `gh` is missing or unauthenticated, or when exhaustive discovery or private-visibility verification cannot complete after the defined retry. Include `gh auth login -s repo` only for missing authentication or scope.
|
|
@@ -26,12 +26,12 @@ If the argument is invalid, print the accepted forms and stop. Do not silently c
|
|
|
26
26
|
|
|
27
27
|
Calendar windows are aligned to midnight in the operator's local timezone. A short hourly window may use a relative timestamp. State the resolved start, end, timezone, scope, and comparison window at the beginning of the report.
|
|
28
28
|
|
|
29
|
-
Step 0, before collecting any evidence: resolve the durable context store by invoking the `context-repo` skill. If it returns `BLOCKED` or `LOCAL_ONLY`, continue local-only and label the limitation in the report. This retro must never fail because the store is unavailable.
|
|
29
|
+
Step 0, before collecting any evidence: resolve the durable context store by invoking the `context-repo` skill. If it returns `BLOCKED` or `LOCAL_ONLY`, continue local-only and label the limitation in the report. Resolving a store does not authorize writing a snapshot to it. This retro must never fail because the store is unavailable.
|
|
30
30
|
|
|
31
31
|
## Safety and evidence rules
|
|
32
32
|
|
|
33
|
-
- Be read-only by default in the analyzed repository. The
|
|
34
|
-
- A retro may write one task-owned snapshot per run: to the context store's `
|
|
33
|
+
- Be read-only by default in the analyzed repository. The named exceptions are a `context-repo` bootstrap performed under that skill's own consent flow, and one context-store snapshot commit and push when the user explicitly consented to remote snapshot persistence for this run or through a recorded standing workflow preference. Outside those exceptions, this skill never pushes, merges, deploys, closes issues, edits source, or rewrites history in the analyzed repository.
|
|
34
|
+
- A retro may write one task-owned snapshot per run. Generate one collision-resistant run id and reuse it for the whole run, in the form `<YYYYMMDDTHHMMSSZ>-<short-unique-suffix>`. Derive one scope key: the normalized `<owner>-<repo>` slug in repository mode and the literal `global` in global mode, independent of which repositories were discovered or their order. The filename is `<run-id>-<scope-key>-<window>.md`. Write it to the context store's `retro/` only with explicit remote-persistence consent; otherwise use `.context/retros/` when that directory exists or local persistence was explicitly requested. Create the file only if absent and generate a new run id on collision; never overwrite an existing snapshot.
|
|
35
35
|
- Do not fetch or refresh remote refs unless the user or the surrounding workflow authorized that read-side state change. If refs may be stale, say so and use the available evidence.
|
|
36
36
|
- Preserve dirty work, untracked files, existing snapshots, credentials, and unrelated temporary artifacts.
|
|
37
37
|
- Never infer delivery from a local commit. Treat local Git, remote/PR state, CI, deployment, and device or human QA as separate evidence gates.
|
|
@@ -47,7 +47,7 @@ For repository mode:
|
|
|
47
47
|
2. Preserve and report pre-existing dirty paths; do not include their changes as delivered work unless the evidence links them to the window.
|
|
48
48
|
3. Use the repository's local timezone for calendar boundaries. Use UTC timestamps in stored machine-readable data.
|
|
49
49
|
4. Read only relevant project documentation and task artifacts needed to interpret the changes. Do not invent milestones, objectives, or acceptance criteria.
|
|
50
|
-
5. Locate prior snapshots
|
|
50
|
+
5. Locate prior snapshots by the same scope key and window, newest run timestamp first: the context store's `retro/`, then its legacy `retros/`, then `.context/retros/`. For pre-run-id repository snapshots, fall back to matching the repository slug; never treat a repository snapshot as a global snapshot. Reading the store first is what makes `compare` and `global` work across machines instead of only where the last run happened. Load the immediately preceding comparable snapshot when available.
|
|
51
51
|
|
|
52
52
|
For global mode:
|
|
53
53
|
|
|
@@ -55,6 +55,7 @@ For global mode:
|
|
|
55
55
|
2. For each repository, collect the same bounded evidence as repository mode and skip missing, inaccessible, or non-Git directories.
|
|
56
56
|
3. Optionally include available agent/session summaries or tool telemetry, but only as aggregate, redacted evidence. Do not require a specific agent vendor, plugin, or telemetry format.
|
|
57
57
|
4. Keep per-project results separate before producing cross-project totals. Never hide a repository-level failure in an aggregate.
|
|
58
|
+
5. Use the literal `global` scope key to locate the prior global snapshot with the same store-first ordering as repository mode. Never derive the lookup key from the discovered repository set or its order.
|
|
58
59
|
|
|
59
60
|
## 2. Collect raw evidence
|
|
60
61
|
|
|
@@ -142,7 +143,7 @@ For `compare` or any window with a prior snapshot:
|
|
|
142
143
|
- preserve the same metric definitions between periods; do not compare a repository window to a global window as if they were equivalent
|
|
143
144
|
- report streaks, recurring hotspots, repeated failure modes, and unresolved improvements only when snapshots support them
|
|
144
145
|
|
|
145
|
-
Store a JSON snapshot with stable keys, UTC timestamps, resolved window, scope, repository identity, commit/PR identifiers, metric values, evidence limitations, and a short list of findings. Keep narrative prose out of fields intended for machine comparison.
|
|
146
|
+
Store a JSON snapshot with stable keys, the run id, UTC timestamps, resolved window, scope key, repository identity, commit/PR identifiers, metric values, evidence limitations, and a short list of findings. Keep narrative prose out of fields intended for machine comparison. When the store pointer resolved and the user explicitly consented to remote snapshot persistence for this run or through a recorded standing workflow preference, create `<clone>/retro/<run-id>-<scope-key>-<window>.md`, with the machine-comparable JSON in a fenced block inside that file rather than as a separate sidecar, then commit and push per the `context-repo` caller contract, lease and validator included. Store resolution alone never authorizes the write, commit, or push. Without that consent, or when the store is unavailable, fall back to `.context/retros/` exactly as described above and do not modify the store. A snapshot is an aid to future analysis, not a source of truth that overrides current evidence.
|
|
146
147
|
|
|
147
148
|
## 5. Optionally promote durable lessons
|
|
148
149
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
inclusion: manual
|
|
5
|
-
description: "
|
|
5
|
+
description: "Resolve one private GitHub repository as the durable store for agent-produced context, searching the account for a store that already exists before ever offering to create one, and returning a verified receipt."
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Context Repo
|
|
@@ -20,7 +20,7 @@ Do not use this skill to read or write arbitrary GitHub repositories. It manages
|
|
|
20
20
|
|
|
21
21
|
Pointer file, the single source of truth for whether a store has been resolved:
|
|
22
22
|
|
|
23
|
-
```
|
|
23
|
+
```text
|
|
24
24
|
${XDG_CONFIG_HOME:-$HOME/.config}/agent-context/config.json
|
|
25
25
|
```
|
|
26
26
|
|
|
@@ -40,39 +40,63 @@ A pointer in the refusal shape means the answer is already known. Do not prompt
|
|
|
40
40
|
|
|
41
41
|
Clone location, fixed regardless of the resolved repo name:
|
|
42
42
|
|
|
43
|
-
```
|
|
43
|
+
```text
|
|
44
44
|
${XDG_DATA_HOME:-$HOME/.local/share}/agent-context/repo
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
Repository tree
|
|
47
|
+
Repository tree. This is the layout of the store that already exists; a store created from scratch is seeded to match it:
|
|
48
48
|
|
|
49
|
-
```
|
|
49
|
+
```text
|
|
50
50
|
README.md
|
|
51
|
+
AGENTS.md
|
|
51
52
|
.gitignore
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
knowledge/<artifact-slug>/page.html
|
|
53
|
+
ledger.json
|
|
54
|
+
retro/<run-id>-<scope-key>-<window>.md
|
|
55
|
+
# Legacy stores may use retros/ instead of retro/.
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
`
|
|
58
|
+
`ledger.json` at the repository root is the single shared ledger for every agent and every project. It is one file, not one per artifact: `{"name": ..., "version": ..., "notes": [...]}`, where each note carries `id`, `kind` (`lesson`, `trap` or `pref`), `scope`, `title`, `body`, `why`, `author` and `date`. Ids are `n<number>` or `c<number>` and are never reused. Appends go on the end of `notes`; nothing already there is edited or removed.
|
|
59
|
+
|
|
60
|
+
`retro/` is flat and markdown only. Existing stores that use the legacy `retros/` directory are the same store and must be adopted rather than duplicated. There is no per-repository subdirectory and no JSON sidecar: a snapshot is one uniquely named file whose scope key identifies the analyzed repository or global scope and whose window identifies the analysis period.
|
|
61
|
+
|
|
62
|
+
`README.md` states what the repository is, which skills write to it, that it is private, and its retention expectations (append-only, not pruned automatically). `AGENTS.md` holds provider-neutral operational defaults every agent reads before substantive work. It cannot relax this skill's safety invariants.
|
|
59
63
|
|
|
60
64
|
## Resolution order
|
|
61
65
|
|
|
62
|
-
Evaluate these in order. Stop at the first one that applies. Steps 1 and 2 never prompt.
|
|
66
|
+
Evaluate these in order. Stop at the first one that applies. Steps 1 and 2 never prompt. Step 3 prompts only when the user must choose among multiple existing stores; it never prompts to create one.
|
|
67
|
+
|
|
68
|
+
Creating a store is the last resort, not the default. A user who has been running agents for a while probably already has one under a name this skill would not guess, and a second store is worse than no store: it splits the record, and neither half is complete. Search before you offer to create.
|
|
63
69
|
|
|
64
|
-
**1. Pointer exists in the normal shape, clone exists, and `gh repo view <repo
|
|
65
|
-
Return the existing repo and clone path as-is. Zero writes, zero prompts. This is the common case on a machine that already resolved the store.
|
|
70
|
+
**1. Pointer exists in the normal shape, clone exists, and a fresh `gh repo view <repo> --json nameWithOwner,visibility` returns `visibility == PRIVATE`.**
|
|
71
|
+
Return the existing repo and clone path as-is. Zero writes, zero prompts. This is the common case on a machine that already resolved the store. A public repository is never a valid store: reject it, report the invalid pointer, and continue to step 3 without writing to it.
|
|
66
72
|
|
|
67
|
-
If `gh repo view <repo>` fails, distinguish why before deciding anything. A
|
|
73
|
+
If `gh repo view <repo>` fails, distinguish why before deciding anything. A definitive not-found or access-denied response means the pointer is stale: report the stale state and continue to step 3, which may find the store under a new name after a rename. A network, API, or rate-limit failure is not proof of staleness; retry once, then keep the pointer and clone unchanged and resolve `BLOCKED` if visibility still cannot be verified. Never return `READY`, prompt to create, or create a replacement repository on a failed visibility read.
|
|
68
74
|
|
|
69
|
-
**2. Pointer exists in the normal shape, `gh repo view <repo>`
|
|
70
|
-
Re-clone silently into the fixed clone location
|
|
75
|
+
**2. Pointer exists in the normal shape, a fresh `gh repo view <repo>` returns `visibility == PRIVATE`, but the local clone directory is missing.**
|
|
76
|
+
Re-clone silently into the fixed clone location, then read back visibility again and return `READY` only while it remains `PRIVATE`. Report to the caller that a re-clone happened (this is expected the first time a given machine touches an already-resolved store). Reject public visibility. Zero prompts.
|
|
71
77
|
|
|
72
|
-
|
|
73
|
-
If the pointer is in the refusal shape, stop here: resolve to `LOCAL_ONLY` without prompting, and tell the caller the user previously declined. The one override: if the user has asked for the store in this run, explicitly and in their own words, treat that as consent already given, replace the refusal pointer, and continue to the preconditions below. A caller's need for the store is never such a request; only the user is.
|
|
78
|
+
If the pointer is in the refusal shape, resolve to `LOCAL_ONLY` without prompting unless the user explicitly asks in their own words to resume store resolution. A caller's need for the store is not such a request. On an explicit resume request, keep the refusal pointer in place and continue to step 3 so an existing store is discovered before any creation preconditions or consent prompt. Replace the refusal pointer only after a store is adopted or created.
|
|
74
79
|
|
|
75
|
-
|
|
80
|
+
**3. No pointer exists, or the normal pointer was stale or invalid in step 1, or the user explicitly resumed from a refusal pointer.**
|
|
81
|
+
Before evaluating creation preconditions or offering to create anything, exhaustively list the user's private repositories and test every candidate for the layout, not for the name. The authenticated user's endpoint paginates until no next page remains:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
gh api --paginate --method GET /user/repos \
|
|
85
|
+
-f per_page=100 -f visibility=private -f affiliation=owner \
|
|
86
|
+
--jq '.[] | [.name, .pushed_at] | @tsv'
|
|
87
|
+
gh api 'repos/<owner>/<name>/git/trees/HEAD?recursive=1' -q '.tree[].path'
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
A repository is the store when its tree carries a root `ledger.json` **and** a `retro/` (or legacy `retros/`) directory. Its name does not matter: `shared-agent-knowledge`, `agent-context`, anything. Collect all matches before deciding. Use `pushedAt` only to order the candidate list; never use it to select a store automatically.
|
|
91
|
+
|
|
92
|
+
Repository listing and tree probes are failure-aware. Retry a transient network, API, or rate-limit failure once. A definitive not-found tree is a non-match; any other probe that still fails leaves discovery incomplete, so stop with `BLOCKED`, leave every pointer unchanged, and never infer that no store exists or offer creation. Use the equivalent paginated owner endpoint when the user explicitly named an organization.
|
|
93
|
+
|
|
94
|
+
If exactly one candidate matches, select it automatically. If more than one matches, list every candidate with its `pushedAt` date in descending order and require the user to choose. Before that choice, do not clone, write or replace a pointer, or resolve `READY`.
|
|
95
|
+
|
|
96
|
+
For the selected candidate, freshly read `gh repo view <owner>/<name> --json nameWithOwner,visibility` and require `visibility == PRIVATE`; reject public visibility. Only after that check may this skill clone to the fixed location. Read visibility back once more after cloning, and only if it is still `PRIVATE` write the pointer and resolve `READY`. Report which repository was adopted and that nothing was created. Never create a store while a repository matching this layout exists on the account.
|
|
97
|
+
|
|
98
|
+
**4. Step 3 completed successfully and found no existing store.**
|
|
99
|
+
Only now check creation preconditions before offering to create anything:
|
|
76
100
|
|
|
77
101
|
- `gh --version` must succeed.
|
|
78
102
|
- `gh auth status` must succeed and the active account must carry the `repo` scope.
|
|
@@ -82,49 +106,50 @@ If either check fails, resolve to `BLOCKED` with the exact remedy `gh auth login
|
|
|
82
106
|
If preconditions pass, ask once, in one message, before creating anything. State plainly:
|
|
83
107
|
|
|
84
108
|
- **Owner**: the account from `gh api user -q .login`.
|
|
85
|
-
- **Name**: the proposed repository name, default `agent-
|
|
109
|
+
- **Name**: the proposed repository name, default `shared-agent-knowledge`.
|
|
86
110
|
- **Visibility**: private.
|
|
87
|
-
- **Paths that will be written**: the pointer file path, the clone path, and the seeded tree (`README.md`, `.gitignore`, `
|
|
111
|
+
- **Paths that will be written**: the pointer file path, the clone path, and the seeded tree (`README.md`, `AGENTS.md`, `.gitignore`, `ledger.json`, `retro/`).
|
|
112
|
+
- **That exhaustive step 3 found no existing store**, and which repositories were checked, so the user can correct you if they know of one you missed.
|
|
88
113
|
- That nothing outside this one repository is touched: no other GitHub repository, no existing local files besides the two paths above.
|
|
89
114
|
|
|
90
115
|
Offer exactly three answers:
|
|
91
116
|
|
|
92
|
-
- `y`: proceed to step
|
|
117
|
+
- `y`: proceed to step 5.
|
|
93
118
|
- `n`: do not create anything and do not write a pointer. Resolve this run as `LOCAL_ONLY`. Ask again next time a caller needs the store.
|
|
94
119
|
- `never`: do not create anything. Write the refusal-shape pointer so future runs stop asking. Resolve this run as `LOCAL_ONLY`.
|
|
95
120
|
|
|
96
121
|
**Name collision.** If `<owner>/<name>` already exists on GitHub:
|
|
97
122
|
|
|
98
|
-
- If it already carries this layout (a `
|
|
99
|
-
- Otherwise it is an unrelated repository. Never write into it. Offer `agent-
|
|
123
|
+
- If it already carries this layout (a root `ledger.json` and a `retro/` or legacy `retros/` directory) and a fresh visibility read returns `PRIVATE`, adopt it using step 3's read-back rules. Step 3 should normally have caught this already.
|
|
124
|
+
- Otherwise it is an unrelated repository. Never write into it. Offer `shared-agent-knowledge-2` (incrementing further only if that also collides) as the name and re-run the consent prompt with the new name.
|
|
100
125
|
|
|
101
|
-
**
|
|
102
|
-
Only reached after explicit `y` consent
|
|
126
|
+
**5. Create, seed, and push.**
|
|
127
|
+
Only reached after explicit `y` consent, step 3 having found no existing store.
|
|
103
128
|
|
|
104
|
-
```
|
|
129
|
+
```bash
|
|
105
130
|
gh repo create <owner>/<name> --private
|
|
106
131
|
git clone https://github.com/<owner>/<name>.git <clone>
|
|
107
132
|
```
|
|
108
133
|
|
|
109
|
-
Seed the tree inside `<clone>`: write `README.md`, `.gitignore`,
|
|
134
|
+
Seed the tree inside `<clone>`: write `README.md`, `AGENTS.md`, `.gitignore`, a `ledger.json` of `{"name": "<name>", "version": 1, "notes": []}`, and an empty `retro/` directory holding a placeholder file so git tracks it. Then:
|
|
110
135
|
|
|
111
|
-
```
|
|
136
|
+
```bash
|
|
112
137
|
git -C <clone> add -A
|
|
113
138
|
git -C <clone> commit -m "chore: initialize agent context store"
|
|
114
139
|
git -C <clone> push -u origin HEAD
|
|
115
140
|
```
|
|
116
141
|
|
|
117
|
-
**
|
|
142
|
+
**6. Write the pointer, then verify from a fresh source.**
|
|
118
143
|
Write the normal-shape pointer file with the resolved `repo`, `clone`, and today's date. Then re-read the state independently of anything cached during creation:
|
|
119
144
|
|
|
120
|
-
```
|
|
145
|
+
```bash
|
|
121
146
|
gh repo view <owner>/<name> --json nameWithOwner,visibility
|
|
122
147
|
git -C <clone> rev-parse HEAD
|
|
123
148
|
```
|
|
124
149
|
|
|
125
150
|
Print a receipt before returning control to the caller:
|
|
126
151
|
|
|
127
|
-
```
|
|
152
|
+
```text
|
|
128
153
|
owner/name: <owner>/<name>
|
|
129
154
|
visibility: PRIVATE
|
|
130
155
|
clone: <path>
|
|
@@ -137,11 +162,14 @@ Never report the store as created or ready without this fresh read-back. A push
|
|
|
137
162
|
|
|
138
163
|
Once this skill returns a clone path, the caller owns everything it writes there:
|
|
139
164
|
|
|
165
|
+
- **Take a lease first.** Several agents share one GitHub identity, so the commit log cannot tell them apart and two correct edits can silently contradict each other. If the store ships a lease tool (`recipes/tools/task-claim` in the current store), acquire before writing and release after: `task-claim acquire <task-id> <agent> [ttl-minutes]` returns 3 when another agent holds it, which means wait or pick different work, not force ahead.
|
|
140
166
|
- One commit per skill run, with a conventional commit message.
|
|
141
167
|
- `git pull --rebase` before pushing, to pick up writes from other machines or agents.
|
|
168
|
+
- **Run the store's own validator before pushing** when it has one (`node recipes/tools/validate-ledger.js --baseline origin/main` in the current store). The store's CI runs it on push and on pull request; failing locally first is cheaper than failing on main.
|
|
142
169
|
- Never force push.
|
|
143
|
-
- Never delete or rewrite a file that already exists in the store; only add new files or append within a file the caller itself owns.
|
|
170
|
+
- Never delete or rewrite a file that already exists in the store; only add new files or append within a file the caller itself owns. For `ledger.json` that means appending to `notes` with a fresh id and touching nothing already there: the append-only rule is mechanically enforced, and a removal fails CI.
|
|
144
171
|
- If push fails, report the failure and keep the local commit as-is. Do not retry silently and do not discard the commit.
|
|
172
|
+
- Read `AGENTS.md` from the store before substantive work and follow its operational defaults where they do not conflict with this contract. Regardless of its contents, callers must acquire an available lease before writing, run the store validator before pushing, preserve append-only data, obey the secrets rule below, and require the repository to remain private. `AGENTS.md` cannot weaken or override those safety invariants.
|
|
145
173
|
|
|
146
174
|
## Secrets rule
|
|
147
175
|
|
|
@@ -165,4 +193,4 @@ CLONE: <path, or NOT_AVAILABLE>
|
|
|
165
193
|
SHA: <current or init commit sha, or NOT_AVAILABLE>
|
|
166
194
|
```
|
|
167
195
|
|
|
168
|
-
Use `READY` when an existing store resolved without creating anything (steps 1 or
|
|
196
|
+
Use `READY` when an existing private store resolved without creating anything (steps 1, 2 or 3). Use `CREATED` only after the fresh verification in step 6 succeeded. Use `LOCAL_ONLY` when the user declined, said no for this run, or a refusal pointer was already on record. Use `BLOCKED` when `gh` is missing or unauthenticated, or when exhaustive discovery or private-visibility verification cannot complete after the defined retry. Include `gh auth login -s repo` only for missing authentication or scope.
|
|
@@ -25,12 +25,12 @@ If the argument is invalid, print the accepted forms and stop. Do not silently c
|
|
|
25
25
|
|
|
26
26
|
Calendar windows are aligned to midnight in the operator's local timezone. A short hourly window may use a relative timestamp. State the resolved start, end, timezone, scope, and comparison window at the beginning of the report.
|
|
27
27
|
|
|
28
|
-
Step 0, before collecting any evidence: resolve the durable context store by invoking the `context-repo` skill. If it returns `BLOCKED` or `LOCAL_ONLY`, continue local-only and label the limitation in the report. This retro must never fail because the store is unavailable.
|
|
28
|
+
Step 0, before collecting any evidence: resolve the durable context store by invoking the `context-repo` skill. If it returns `BLOCKED` or `LOCAL_ONLY`, continue local-only and label the limitation in the report. Resolving a store does not authorize writing a snapshot to it. This retro must never fail because the store is unavailable.
|
|
29
29
|
|
|
30
30
|
## Safety and evidence rules
|
|
31
31
|
|
|
32
|
-
- Be read-only by default in the analyzed repository. The
|
|
33
|
-
- A retro may write one task-owned snapshot per run: to the context store's `
|
|
32
|
+
- Be read-only by default in the analyzed repository. The named exceptions are a `context-repo` bootstrap performed under that skill's own consent flow, and one context-store snapshot commit and push when the user explicitly consented to remote snapshot persistence for this run or through a recorded standing workflow preference. Outside those exceptions, this skill never pushes, merges, deploys, closes issues, edits source, or rewrites history in the analyzed repository.
|
|
33
|
+
- A retro may write one task-owned snapshot per run. Generate one collision-resistant run id and reuse it for the whole run, in the form `<YYYYMMDDTHHMMSSZ>-<short-unique-suffix>`. Derive one scope key: the normalized `<owner>-<repo>` slug in repository mode and the literal `global` in global mode, independent of which repositories were discovered or their order. The filename is `<run-id>-<scope-key>-<window>.md`. Write it to the context store's `retro/` only with explicit remote-persistence consent; otherwise use `.context/retros/` when that directory exists or local persistence was explicitly requested. Create the file only if absent and generate a new run id on collision; never overwrite an existing snapshot.
|
|
34
34
|
- Do not fetch or refresh remote refs unless the user or the surrounding workflow authorized that read-side state change. If refs may be stale, say so and use the available evidence.
|
|
35
35
|
- Preserve dirty work, untracked files, existing snapshots, credentials, and unrelated temporary artifacts.
|
|
36
36
|
- Never infer delivery from a local commit. Treat local Git, remote/PR state, CI, deployment, and device or human QA as separate evidence gates.
|
|
@@ -46,7 +46,7 @@ For repository mode:
|
|
|
46
46
|
2. Preserve and report pre-existing dirty paths; do not include their changes as delivered work unless the evidence links them to the window.
|
|
47
47
|
3. Use the repository's local timezone for calendar boundaries. Use UTC timestamps in stored machine-readable data.
|
|
48
48
|
4. Read only relevant project documentation and task artifacts needed to interpret the changes. Do not invent milestones, objectives, or acceptance criteria.
|
|
49
|
-
5. Locate prior snapshots
|
|
49
|
+
5. Locate prior snapshots by the same scope key and window, newest run timestamp first: the context store's `retro/`, then its legacy `retros/`, then `.context/retros/`. For pre-run-id repository snapshots, fall back to matching the repository slug; never treat a repository snapshot as a global snapshot. Reading the store first is what makes `compare` and `global` work across machines instead of only where the last run happened. Load the immediately preceding comparable snapshot when available.
|
|
50
50
|
|
|
51
51
|
For global mode:
|
|
52
52
|
|
|
@@ -54,6 +54,7 @@ For global mode:
|
|
|
54
54
|
2. For each repository, collect the same bounded evidence as repository mode and skip missing, inaccessible, or non-Git directories.
|
|
55
55
|
3. Optionally include available agent/session summaries or tool telemetry, but only as aggregate, redacted evidence. Do not require a specific agent vendor, plugin, or telemetry format.
|
|
56
56
|
4. Keep per-project results separate before producing cross-project totals. Never hide a repository-level failure in an aggregate.
|
|
57
|
+
5. Use the literal `global` scope key to locate the prior global snapshot with the same store-first ordering as repository mode. Never derive the lookup key from the discovered repository set or its order.
|
|
57
58
|
|
|
58
59
|
## 2. Collect raw evidence
|
|
59
60
|
|
|
@@ -141,7 +142,7 @@ For `compare` or any window with a prior snapshot:
|
|
|
141
142
|
- preserve the same metric definitions between periods; do not compare a repository window to a global window as if they were equivalent
|
|
142
143
|
- report streaks, recurring hotspots, repeated failure modes, and unresolved improvements only when snapshots support them
|
|
143
144
|
|
|
144
|
-
Store a JSON snapshot with stable keys, UTC timestamps, resolved window, scope, repository identity, commit/PR identifiers, metric values, evidence limitations, and a short list of findings. Keep narrative prose out of fields intended for machine comparison.
|
|
145
|
+
Store a JSON snapshot with stable keys, the run id, UTC timestamps, resolved window, scope key, repository identity, commit/PR identifiers, metric values, evidence limitations, and a short list of findings. Keep narrative prose out of fields intended for machine comparison. When the store pointer resolved and the user explicitly consented to remote snapshot persistence for this run or through a recorded standing workflow preference, create `<clone>/retro/<run-id>-<scope-key>-<window>.md`, with the machine-comparable JSON in a fenced block inside that file rather than as a separate sidecar, then commit and push per the `context-repo` caller contract, lease and validator included. Store resolution alone never authorizes the write, commit, or push. Without that consent, or when the store is unavailable, fall back to `.context/retros/` exactly as described above and do not modify the store. A snapshot is an aid to future analysis, not a source of truth that overrides current evidence.
|
|
145
146
|
|
|
146
147
|
## 5. Optionally promote durable lessons
|
|
147
148
|
|