@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.
Files changed (35) hide show
  1. package/.github/prompts/context-repo.prompt.md +62 -34
  2. package/.github/prompts/retro-analysis.prompt.md +6 -5
  3. package/.kiro/steering/context-repo.md +62 -34
  4. package/.kiro/steering/retro-analysis.md +6 -5
  5. package/.windsurf/rules/context-repo.md +62 -34
  6. package/.windsurf/rules/retro-analysis.md +6 -5
  7. package/README.md +24 -7
  8. package/adapters/claude/olko-reflection/skills/retro-analysis/SKILL.md +6 -5
  9. package/adapters/claude/olko-skill-meta/skills/context-repo/SKILL.md +61 -33
  10. package/adapters/claude/olko-skill-meta/skills/shared-knowledge-artifact/SKILL.md +3 -3
  11. package/adapters/claude/olko-skill-meta/skills/shared-knowledge-artifact/references/prompt.txt +22 -16
  12. package/adapters/cursor/olko-reflection/skills/retro-analysis/SKILL.md +6 -5
  13. package/adapters/cursor/olko-skill-meta/skills/context-repo/SKILL.md +61 -33
  14. package/adapters/grok/olko-reflection/skills/retro-analysis/SKILL.md +6 -5
  15. package/adapters/grok/olko-skill-meta/skills/context-repo/SKILL.md +61 -33
  16. package/catalog/skills.json +1 -1
  17. package/docs/agent-context-store.md +178 -39
  18. package/docs/assets/context-store-card.html +377 -0
  19. package/docs/assets/context-store-card.png +0 -0
  20. package/package.json +1 -1
  21. package/plugins/olko-apple-kit/.claude-plugin/plugin.json +1 -1
  22. package/plugins/olko-creative/.claude-plugin/plugin.json +1 -1
  23. package/plugins/olko-garmin-kit/.claude-plugin/plugin.json +1 -1
  24. package/plugins/olko-git-tools/.claude-plugin/plugin.json +1 -1
  25. package/plugins/olko-github-pr/.claude-plugin/plugin.json +1 -1
  26. package/plugins/olko-obsidian/.claude-plugin/plugin.json +1 -1
  27. package/plugins/olko-product/.claude-plugin/plugin.json +1 -1
  28. package/plugins/olko-reflection/.claude-plugin/plugin.json +1 -1
  29. package/plugins/olko-reflection/skills/retro-analysis/SKILL.md +6 -5
  30. package/plugins/olko-release/.claude-plugin/plugin.json +1 -1
  31. package/plugins/olko-skill-meta/.claude-plugin/plugin.json +1 -1
  32. package/plugins/olko-skill-meta/skills/context-repo/SKILL.md +61 -33
  33. package/plugins/olko-skill-meta/skills/shared-knowledge-artifact/SKILL.md +3 -3
  34. package/plugins/olko-skill-meta/skills/shared-knowledge-artifact/references/prompt.txt +22 -16
  35. 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: "Bootstrap and maintain one private GitHub repository as the durable store for agent-produced context, creating it once with explicit consent and returning a verified receipt."
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, seeded on creation and extended by callers afterward:
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
- retros/<repo-slug>/<YYYY-MM-DD>-<window>.json
54
- retros/<repo-slug>/<YYYY-MM-DD>-<window>.md
55
- knowledge/<artifact-slug>/ledger.json
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
- `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). `retros/` and `knowledge/` start empty aside from a placeholder so git tracks the directories; callers create the dated or slugged subpaths they need.
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>` succeeds.**
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 failure that names the repository as not found, or reports access denied, means the pointer is stale: report the stale state and fall through to step 3 to re-prompt, and never assume a stale pointer still means "yes." A failure caused by no network, a `gh` API outage, or a rate limit is not staleness. In that case keep the pointer and the existing clone, resolve as `READY` with the SHA read locally from `git -C <clone> rev-parse HEAD`, and report that the remote could not be reached. Never prompt to create a store that the pointer says already exists just because GitHub was unreachable, and never create a replacement repository on a failed read.
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>` succeeds, but the local clone directory is missing.**
71
- Re-clone silently into the fixed clone location. Report to the caller that a re-clone happened (this is expected the first time a given machine touches an already-resolved store). Zero prompts.
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
- **3. No pointer, or the pointer is in the refusal shape, or the pointer was found stale in step 1.**
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
- Otherwise check preconditions before offering to create anything:
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-context`.
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`, `retros/`, `knowledge/`).
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 4.
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 `retros/` directory and a `knowledge/` directory at the repository root, and a `README.md` that identifies it as an agent context store), adopt it: skip creation, clone it, and proceed as if step 4 had just run.
100
- - Otherwise it is an unrelated repository. Never write into it. Offer `agent-context-2` (incrementing further only if that also collides) as the name and re-run the consent prompt with the new name.
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
- **4. Create, seed, and push.**
103
- Only reached after explicit `y` consent (or an adopted existing repo with the right layout).
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`, and empty `retros/` and `knowledge/` directories (each holding a placeholder file so git tracks them). Then:
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
- **5. Write the pointer, then verify from a fresh source.**
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 2). Use `CREATED` only after the fresh verification in step 5 succeeded. Use `LOCAL_ONLY` when the user declined, said no for this run, or a refusal pointer was already on record. Use `BLOCKED` only when `gh` is missing or unauthenticated; always include the `gh auth login -s repo` remedy in the surrounding report when this status appears.
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 one named exception: this skill may invoke `context-repo` for a consented store bootstrap, and may make one snapshot commit and push per run into the context store only. Outside that exception, it 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: to the context store's `retros/<repo-slug>/` when the store resolves, otherwise to `.context/retros/` when that directory exists or when persistence is explicitly requested. Never overwrite an existing snapshot; use a date and window-specific filename.
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 in the context store's `retros/<repo-slug>/` first, then in `.context/retros/`. 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
+ 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. If the store pointer resolved, write the snapshot to `<clone>/retros/<repo-slug>/<YYYY-MM-DD>-<window>.json` plus the matching `.md`, then commit and push per the `context-repo` caller contract. Otherwise fall back to `.context/retros/` exactly as today. A snapshot is an aid to future analysis, not a source of truth that overrides current evidence.
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: "Bootstrap and maintain one private GitHub repository as the durable store for agent-produced context, creating it once with explicit consent and returning a verified receipt."
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, seeded on creation and extended by callers afterward:
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
- retros/<repo-slug>/<YYYY-MM-DD>-<window>.json
53
- retros/<repo-slug>/<YYYY-MM-DD>-<window>.md
54
- knowledge/<artifact-slug>/ledger.json
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
- `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). `retros/` and `knowledge/` start empty aside from a placeholder so git tracks the directories; callers create the dated or slugged subpaths they need.
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>` succeeds.**
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 failure that names the repository as not found, or reports access denied, means the pointer is stale: report the stale state and fall through to step 3 to re-prompt, and never assume a stale pointer still means "yes." A failure caused by no network, a `gh` API outage, or a rate limit is not staleness. In that case keep the pointer and the existing clone, resolve as `READY` with the SHA read locally from `git -C <clone> rev-parse HEAD`, and report that the remote could not be reached. Never prompt to create a store that the pointer says already exists just because GitHub was unreachable, and never create a replacement repository on a failed read.
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>` succeeds, but the local clone directory is missing.**
70
- Re-clone silently into the fixed clone location. Report to the caller that a re-clone happened (this is expected the first time a given machine touches an already-resolved store). Zero prompts.
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
- **3. No pointer, or the pointer is in the refusal shape, or the pointer was found stale in step 1.**
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
- Otherwise check preconditions before offering to create anything:
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-context`.
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`, `retros/`, `knowledge/`).
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 4.
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 `retros/` directory and a `knowledge/` directory at the repository root, and a `README.md` that identifies it as an agent context store), adopt it: skip creation, clone it, and proceed as if step 4 had just run.
99
- - Otherwise it is an unrelated repository. Never write into it. Offer `agent-context-2` (incrementing further only if that also collides) as the name and re-run the consent prompt with the new name.
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
- **4. Create, seed, and push.**
102
- Only reached after explicit `y` consent (or an adopted existing repo with the right layout).
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`, and empty `retros/` and `knowledge/` directories (each holding a placeholder file so git tracks them). Then:
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
- **5. Write the pointer, then verify from a fresh source.**
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 2). Use `CREATED` only after the fresh verification in step 5 succeeded. Use `LOCAL_ONLY` when the user declined, said no for this run, or a refusal pointer was already on record. Use `BLOCKED` only when `gh` is missing or unauthenticated; always include the `gh auth login -s repo` remedy in the surrounding report when this status appears.
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 one named exception: this skill may invoke `context-repo` for a consented store bootstrap, and may make one snapshot commit and push per run into the context store only. Outside that exception, it 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: to the context store's `retros/<repo-slug>/` when the store resolves, otherwise to `.context/retros/` when that directory exists or when persistence is explicitly requested. Never overwrite an existing snapshot; use a date and window-specific filename.
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 in the context store's `retros/<repo-slug>/` first, then in `.context/retros/`. 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.
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. If the store pointer resolved, write the snapshot to `<clone>/retros/<repo-slug>/<YYYY-MM-DD>-<window>.json` plus the matching `.md`, then commit and push per the `context-repo` caller contract. Otherwise fall back to `.context/retros/` exactly as today. A snapshot is an aid to future analysis, not a source of truth that overrides current evidence.
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