@awebai/oats 0.29.4 → 0.30.1

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 (263) hide show
  1. package/README.md +12 -6
  2. package/bin/oats.mjs +194 -50
  3. package/docs/capabilities.md +160 -171
  4. package/docs/capability-manifest.schema.json +6 -11
  5. package/docs/configuration.md +213 -64
  6. package/docs/design/2026-09-16-knowledge-capability-contract.md +36 -50
  7. package/docs/design/2026-09-23-workspace-module-contracts.md +377 -544
  8. package/docs/design/2026-09-26-okf-knowledge-operations.md +132 -357
  9. package/docs/design/2026-09-27-team-model-v2.md +97 -117
  10. package/docs/design/2026-09-28-automations-trust.md +38 -0
  11. package/docs/design/2026-09-28-soul-launch-preference.md +63 -0
  12. package/docs/design/HISTORY.md +65 -0
  13. package/docs/design/README.md +23 -54
  14. package/docs/desktop-cli-api.md +1787 -1777
  15. package/docs/desktop.md +30 -91
  16. package/docs/execution-targets.md +146 -292
  17. package/docs/first-team.md +31 -17
  18. package/docs/implementation.md +77 -288
  19. package/docs/integrations.md +118 -320
  20. package/docs/knowledge-capability-authoring.md +25 -52
  21. package/docs/knowledge-reference/acceptance.md +3 -3
  22. package/docs/knowledge-reference/adoption.md +1 -1
  23. package/docs/knowledge-reference/harvester.md +2 -2
  24. package/docs/knowledge-reference/package-craft.md +3 -3
  25. package/docs/knowledge-reference/provider-mapping.md +3 -6
  26. package/docs/knowledge-reference/reader-capture.md +3 -3
  27. package/docs/knowledge-theory.md +62 -166
  28. package/docs/knowledge.md +225 -404
  29. package/docs/layers.md +42 -97
  30. package/docs/oats-local.schema.json +58 -5
  31. package/docs/oats-membership.schema.json +1 -8
  32. package/docs/oats-package.schema.json +5 -5
  33. package/docs/oats-workspace.schema.json +8 -22
  34. package/docs/official-catalog.md +25 -28
  35. package/docs/packages.md +45 -63
  36. package/docs/plans/0.30-close-out.md +83 -0
  37. package/docs/release-lane.md +82 -0
  38. package/docs/release-notes/oats-framework-v1.1.3.md +10 -8
  39. package/docs/release-notes/v0.19.0.md +48 -147
  40. package/docs/release-notes/v0.19.1.md +2 -3
  41. package/docs/release-notes/v0.19.3.md +2 -15
  42. package/docs/release-notes/v0.20.0.md +0 -15
  43. package/docs/release-notes/v0.22.0.md +71 -138
  44. package/docs/release-notes/v0.22.1.md +42 -90
  45. package/docs/release-notes/v0.22.10.md +1 -1
  46. package/docs/release-notes/v0.22.11.md +1 -47
  47. package/docs/release-notes/v0.22.12.md +4 -13
  48. package/docs/release-notes/v0.22.13.md +1 -42
  49. package/docs/release-notes/v0.22.14.md +3 -11
  50. package/docs/release-notes/v0.22.15.md +1 -46
  51. package/docs/release-notes/v0.22.16.md +6 -8
  52. package/docs/release-notes/v0.22.18.md +1 -99
  53. package/docs/release-notes/v0.22.19.md +3 -14
  54. package/docs/release-notes/v0.22.2.md +6 -15
  55. package/docs/release-notes/v0.22.3.md +0 -1
  56. package/docs/release-notes/v0.22.4.md +1 -14
  57. package/docs/release-notes/v0.22.5.md +2 -12
  58. package/docs/release-notes/v0.22.6.md +0 -3
  59. package/docs/release-notes/v0.23.0.md +9 -25
  60. package/docs/release-notes/v0.23.1.md +9 -25
  61. package/docs/release-notes/v0.23.2.md +2 -4
  62. package/docs/release-notes/v0.24.0.md +56 -97
  63. package/docs/release-notes/v0.24.1.md +7 -11
  64. package/docs/release-notes/v0.24.10.md +34 -45
  65. package/docs/release-notes/v0.24.11.md +12 -20
  66. package/docs/release-notes/v0.24.12.md +35 -48
  67. package/docs/release-notes/v0.24.13.md +34 -41
  68. package/docs/release-notes/v0.24.2.md +9 -13
  69. package/docs/release-notes/v0.24.3.md +7 -11
  70. package/docs/release-notes/v0.24.4.md +6 -6
  71. package/docs/release-notes/v0.24.5.md +6 -10
  72. package/docs/release-notes/v0.24.6.md +2 -5
  73. package/docs/release-notes/v0.24.7.md +46 -75
  74. package/docs/release-notes/v0.24.8.md +58 -96
  75. package/docs/release-notes/v0.24.9.md +38 -54
  76. package/docs/release-notes/v0.25.0.md +59 -76
  77. package/docs/release-notes/v0.25.1.md +57 -81
  78. package/docs/release-notes/v0.25.2.md +51 -70
  79. package/docs/release-notes/v0.25.3.md +11 -13
  80. package/docs/release-notes/v0.25.4.md +9 -13
  81. package/docs/release-notes/v0.25.5.md +3 -5
  82. package/docs/release-notes/v0.25.6.md +20 -29
  83. package/docs/release-notes/v0.25.7.md +5 -7
  84. package/docs/release-notes/v0.25.8.md +26 -39
  85. package/docs/release-notes/v0.26.0.md +175 -646
  86. package/docs/release-notes/v0.27.0.md +4 -5
  87. package/docs/release-notes/v0.27.1.md +4 -6
  88. package/docs/release-notes/v0.27.2.md +1 -1
  89. package/docs/release-notes/v0.28.0.md +57 -124
  90. package/docs/release-notes/v0.29.0.md +89 -208
  91. package/docs/release-notes/v0.29.1.md +1 -1
  92. package/docs/release-notes/v0.29.2.md +3 -4
  93. package/docs/release-notes/v0.30.0.md +205 -0
  94. package/docs/release-notes/v0.30.1.md +123 -0
  95. package/docs/schedules.md +280 -363
  96. package/docs/servers.md +99 -117
  97. package/docs/soul.schema.json +2 -9
  98. package/docs/souls-and-instances.md +145 -158
  99. package/docs/workspaces.md +137 -215
  100. package/lib/automations.mjs +21 -6
  101. package/lib/core.mjs +226 -74
  102. package/lib/instance-events.mjs +1 -1
  103. package/lib/instance-inspect.mjs +109 -34
  104. package/lib/instance-lifecycle.mjs +14 -1
  105. package/lib/instance-resolution.mjs +26 -27
  106. package/lib/launch-preference.mjs +87 -0
  107. package/lib/materialize.mjs +3 -3
  108. package/lib/packages.mjs +1 -1
  109. package/lib/resolve.mjs +30 -88
  110. package/lib/schedule.mjs +1 -1
  111. package/lib/teams-verbs.mjs +195 -0
  112. package/lib/teams.mjs +190 -0
  113. package/lib/triggers.mjs +2 -2
  114. package/lib/workspace.mjs +54 -147
  115. package/package-catalog.json +10 -16
  116. package/package.json +1 -3
  117. package/skills/oats-getting-started/SKILL.md +25 -13
  118. package/capabilities/oats-authoring/LICENSE +0 -21
  119. package/capabilities/oats-authoring/oats-package.json +0 -11
  120. package/capabilities/oats-authoring/oats.json +0 -12
  121. package/capabilities/oats-authoring/skills/integration-authoring/SKILL.md +0 -84
  122. package/capabilities/oats-authoring/skills/skill-craft/SKILL.md +0 -109
  123. package/capabilities/oats-authoring/skills/soul-craft/SKILL.md +0 -116
  124. package/capabilities/oats-aweb/bin/oats-aweb-binding.mjs +0 -11
  125. package/capabilities/oats-aweb/bin/oats-aweb.mjs +0 -1338
  126. package/capabilities/oats-aweb/injects/aweb.md +0 -47
  127. package/capabilities/oats-aweb/lib/binding-wire.mjs +0 -356
  128. package/capabilities/oats-aweb/lib/captured-execution.mjs +0 -91
  129. package/capabilities/oats-aweb/lib/captured-native.mjs +0 -91
  130. package/capabilities/oats-aweb/lib/grant-custody.mjs +0 -38
  131. package/capabilities/oats-aweb/lib/invocation-shape.mjs +0 -135
  132. package/capabilities/oats-aweb/lib/portable-binding.mjs +0 -146
  133. package/capabilities/oats-aweb/lib/session-readiness.mjs +0 -56
  134. package/capabilities/oats-aweb/lib/wake-receive.mjs +0 -56
  135. package/capabilities/oats-aweb/oats.json +0 -208
  136. package/capabilities/oats-aweb/skills/LICENSE +0 -21
  137. package/capabilities/oats-aweb/skills/VENDORED.md +0 -31
  138. package/capabilities/oats-aweb/skills/aweb-identity/SKILL.md +0 -201
  139. package/capabilities/oats-aweb/skills/aweb-messaging/SKILL.md +0 -161
  140. package/capabilities/oats-aweb/skills/aweb-messaging/references/messaging-scenarios.md +0 -61
  141. package/capabilities/oats-aweb/skills/aweb-team-membership/SKILL.md +0 -116
  142. package/capabilities/oats-aweb/skills/aweb-team-membership/references/team-membership-reference.md +0 -74
  143. package/capabilities/oats-aweb/skills/oats-aweb/SKILL.md +0 -216
  144. package/capabilities/oats-jira/bin/oats-jira.mjs +0 -40
  145. package/capabilities/oats-jira/injects/jira.md +0 -10
  146. package/capabilities/oats-jira/oats.json +0 -22
  147. package/capabilities/oats-jira/skills/jira-tasks/SKILL.md +0 -179
  148. package/capabilities/oats-linear/bin/oats-linear-hook.mjs +0 -34
  149. package/capabilities/oats-linear/bin/oats-linear.mjs +0 -344
  150. package/capabilities/oats-linear/injects/linear.md +0 -8
  151. package/capabilities/oats-linear/oats.json +0 -24
  152. package/capabilities/oats-linear/skills/linear-tasks/SKILL.md +0 -223
  153. package/capabilities/oats-okf/bin/oats-okf-binding.mjs +0 -14
  154. package/capabilities/oats-okf/bin/oats-okf.mjs +0 -209
  155. package/capabilities/oats-okf/injects/okf.md +0 -42
  156. package/capabilities/oats-okf/lib/binding-wire.mjs +0 -348
  157. package/capabilities/oats-okf/lib/captured-worker.mjs +0 -109
  158. package/capabilities/oats-okf/lib/config.mjs +0 -124
  159. package/capabilities/oats-okf/lib/consult.mjs +0 -518
  160. package/capabilities/oats-okf/lib/harvest-status.mjs +0 -88
  161. package/capabilities/oats-okf/lib/harvest-switch.mjs +0 -94
  162. package/capabilities/oats-okf/lib/inspection.mjs +0 -119
  163. package/capabilities/oats-okf/lib/invocation-context.mjs +0 -111
  164. package/capabilities/oats-okf/lib/invocation-shape.mjs +0 -135
  165. package/capabilities/oats-okf/lib/io.mjs +0 -118
  166. package/capabilities/oats-okf/lib/migration.mjs +0 -137
  167. package/capabilities/oats-okf/lib/okf-validate.mjs +0 -123
  168. package/capabilities/oats-okf/lib/portable-binding.mjs +0 -199
  169. package/capabilities/oats-okf/lib/source-contract.mjs +0 -46
  170. package/capabilities/oats-okf/lib/sources.mjs +0 -424
  171. package/capabilities/oats-okf/lib/stores.mjs +0 -473
  172. package/capabilities/oats-okf/lib/worker.mjs +0 -497
  173. package/capabilities/oats-okf/oats.json +0 -148
  174. package/capabilities/oats-okf/schemas/okf-base.schema.json +0 -46
  175. package/capabilities/oats-okf/schemas/okf-bindings.schema.json +0 -112
  176. package/capabilities/oats-okf/schemas/okf-portable-declaration.schema.json +0 -87
  177. package/capabilities/oats-okf/schemas/okf-portable-payload.schema.json +0 -113
  178. package/capabilities/oats-okf/schemas/okf-soul.schema.json +0 -37
  179. package/capabilities/oats-okf/skills/okf-consultation/SKILL.md +0 -144
  180. package/capabilities/oats-okf/skills/okf-consultation/references/consult.md +0 -86
  181. package/capabilities/oats-okf/skills/okf-instance-knowledge/SKILL.md +0 -104
  182. package/capabilities/oats-okf-harvest/bin/okf-harvest.mjs +0 -140
  183. package/capabilities/oats-okf-harvest/injects/harvester.md +0 -12
  184. package/capabilities/oats-okf-harvest/oats.json +0 -26
  185. package/capabilities/oats-okf-harvest/skills/knowledge-harvest/SKILL.md +0 -168
  186. package/capabilities/oats-okf-harvest/skills/knowledge-theory/SKILL.md +0 -192
  187. package/capabilities/oats-okf-harvest/skills/okf-authoring/SKILL.md +0 -151
  188. package/capabilities/oats-okf-harvest/skills/okf-authoring/scripts/okf-validate.mjs +0 -123
  189. package/capabilities/oats-okf-maintenance/bin/okf-maintenance.mjs +0 -170
  190. package/capabilities/oats-okf-maintenance/injects/maintainer.md +0 -12
  191. package/capabilities/oats-okf-maintenance/lib/provenance.mjs +0 -50
  192. package/capabilities/oats-okf-maintenance/oats.json +0 -21
  193. package/capabilities/oats-okf-maintenance/skills/knowledge-review/SKILL.md +0 -159
  194. package/capabilities/oats-okf-maintenance/skills/knowledge-theory/SKILL.md +0 -192
  195. package/capabilities/oats-okf-maintenance/skills/okf-authoring/SKILL.md +0 -151
  196. package/capabilities/oats-okf-maintenance/skills/okf-authoring/scripts/okf-validate.mjs +0 -123
  197. package/capabilities/oats-okf-maintenance/skills/okf-trigger-setup/SKILL.md +0 -146
  198. package/capabilities/oats-review/injects/review.md +0 -69
  199. package/capabilities/oats-review/oats.json +0 -10
  200. package/capabilities/oats-review/skills/code-review/SKILL.md +0 -44
  201. package/capabilities/oats-review/skills/security-review/SKILL.md +0 -59
  202. package/docs/conventions.md +0 -90
  203. package/docs/design/2026-09-07-architecture-reassessment.md +0 -131
  204. package/docs/design/2026-09-07-desktop-souls-capabilities.md +0 -50
  205. package/docs/design/2026-09-07-mobile-agent-management-proposal.md +0 -228
  206. package/docs/design/2026-09-08-expert-assisted-deployment-proposal.md +0 -558
  207. package/docs/design/2026-09-13-knowledge-and-memory-direction.md +0 -744
  208. package/docs/design/2026-09-13-knowledge-implementation.md +0 -127
  209. package/docs/design/2026-09-13-knowledge-location-contract.md +0 -340
  210. package/docs/design/2026-09-14-artifact-retention-contract.md +0 -190
  211. package/docs/design/2026-09-14-portable-souls-and-git-workspaces.md +0 -708
  212. package/docs/design/2026-09-14-portable-souls-contract-amendments.md +0 -85
  213. package/docs/design/2026-09-14-portable-souls-explainer.md +0 -750
  214. package/docs/design/2026-09-15-captured-dispatch.md +0 -127
  215. package/docs/design/2026-09-15-captured-resolution-records.md +0 -143
  216. package/docs/design/2026-09-15-package-preparation.md +0 -100
  217. package/docs/design/2026-09-15-portable-data-contract.md +0 -121
  218. package/docs/design/2026-09-15-portable-declarations.md +0 -189
  219. package/docs/design/2026-09-15-portable-souls-handoff.md +0 -150
  220. package/docs/design/2026-09-15-portable-souls-implementation.md +0 -417
  221. package/docs/design/2026-09-15-selection-lock-and-approval.md +0 -122
  222. package/docs/design/2026-09-15-source-observation.md +0 -119
  223. package/docs/design/2026-09-16-captured-admission.md +0 -77
  224. package/docs/design/2026-09-16-captured-helper-dispatch.md +0 -105
  225. package/docs/design/2026-09-16-captured-launch-inputs.md +0 -42
  226. package/docs/design/2026-09-16-command-profile-preparation.md +0 -86
  227. package/docs/design/2026-09-16-fresh-install-first-rollout.md +0 -47
  228. package/docs/design/2026-09-16-fresh-operator-walkthrough.md +0 -282
  229. package/docs/design/2026-09-16-messaging-capability-contract.md +0 -59
  230. package/docs/design/2026-09-16-portable-migration-evidence.md +0 -158
  231. package/docs/design/2026-09-16-portable-onboarding.md +0 -179
  232. package/docs/design/2026-09-16-prepare-request-transport.md +0 -26
  233. package/docs/design/2026-09-16-provider-binding-codecs.md +0 -98
  234. package/docs/design/2026-09-16-provider-binding-wire.md +0 -274
  235. package/docs/design/2026-09-17-capability-helper-input-contract.md +0 -95
  236. package/docs/design/2026-09-17-captured-backend-parity.md +0 -53
  237. package/docs/design/2026-09-17-captured-native-start.md +0 -58
  238. package/docs/design/2026-09-17-portable-boundary-hookup.md +0 -19
  239. package/docs/design/2026-09-17-portable-boundary-resources.md +0 -52
  240. package/docs/design/2026-09-17-public-captured-start.md +0 -108
  241. package/docs/design/2026-09-17-public-prepare-request.md +0 -90
  242. package/docs/design/2026-09-18-captured-pi-host.md +0 -205
  243. package/docs/design/2026-09-18-first-cut-release-checklist.md +0 -131
  244. package/docs/design/2026-09-18-herdr-protocol-compatibility.md +0 -60
  245. package/docs/design/2026-09-20-redesign-program-board.md +0 -142
  246. package/docs/design/2026-09-20-workspace-and-portable-adoption-plan.md +0 -289
  247. package/docs/design/2026-09-20-workspace-onboarding-public.md +0 -207
  248. package/docs/design/2026-09-22-desktop-parity-seams.md +0 -58
  249. package/docs/design/2026-09-23-simplified-workspace-model.md +0 -711
  250. package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +0 -65
  251. package/docs/design/2026-09-24-desktop-phase-f-boundary.md +0 -242
  252. package/docs/design/2026-09-24-phase-d-plan.md +0 -305
  253. package/docs/design/2026-09-25-teams-contract.md +0 -258
  254. package/docs/design/2026-09-26-desktop-design-brief-architecture.md +0 -241
  255. package/docs/design/desktop-ux-plan.md +0 -362
  256. package/docs/design/launch-configurations.md +0 -168
  257. package/docs/design/okf-mirror-provenance.md +0 -105
  258. package/docs/design/operations-contract.md +0 -141
  259. package/docs/oats-member.schema.json +0 -38
  260. package/skills/integration-authoring/SKILL.md +0 -84
  261. package/skills/oats-support/SKILL.md +0 -79
  262. package/skills/skill-craft/SKILL.md +0 -109
  263. package/skills/soul-craft/SKILL.md +0 -116
@@ -1,144 +0,0 @@
1
- ---
2
- name: okf-consultation
3
- description: >-
4
- Consulting your soul's knowledge with the `oats okf` CLI: reading its
5
- external OKF bases remotely at the accepted commit (index, cat, ls, links,
6
- search, bases) with no local copy, then citing what you relied on. Use when
7
- starting a task or resuming after compaction, when looking up a prior
8
- decision, lesson or concept, when asked "what do we know about X" or to
9
- "check the knowledge base", before re-deriving a design decision, when a
10
- question touches your domain, or when an `oats okf` receipt says STALE or a
11
- command errors. What to write in your own notes is the okf-instance-knowledge
12
- skill.
13
- ---
14
-
15
- # Consulting your knowledge with `oats okf`
16
-
17
- Your soul's accumulated judgment — decisions and their rationale, lessons,
18
- rejected alternatives, limits — lives outside the soul, in external OKF
19
- **bases**. You read it remotely; nothing is copied into your home. Consulting
20
- it before you act is how you avoid re-deciding what was already decided.
21
-
22
- ## The model
23
-
24
- - **Base / alias.** Each bound base has an alias (`oats okf bases` lists
25
- them). A base is one OKF bundle and one link namespace.
26
- - **Node.** A subdirectory of a base with its own `index.md`. Your soul
27
- **owns** some nodes (you are responsible for them) and **reads** others
28
- (starting context). Neither is an access list: every bound base is readable.
29
- - **Accepted commit.** `oats okf` serves only a base's accepted state: the
30
- accepted branch of a Git base, the in-place files of a directory base. An
31
- open PR is not accepted knowledge until it is merged.
32
- - **Host cache, no local copy.** A Git base is read from one host-wide cache
33
- that fetches file contents on first read. Your home has no `./knowledge/`
34
- and no view directory. A `./knowledge/` left by okf 2.x is stale; ignore it.
35
- - **Receipts.** Every answer ends with `— alias@<short-oid> (fetched <age>)`.
36
- With `--json`, the result carries `receipt: {base, kind, commit|digest,
37
- fetchedAt, stale}`.
38
-
39
- Run every command from your instance home.
40
-
41
- ## At the start of every task, and after compaction
42
-
43
- 1. `oats okf index` prints your owned then read nodes' indexes, each headed
44
- `## alias/node (owns|reads)`.
45
- 2. Choose the entries relevant to *this* task by their one-line descriptions.
46
- 3. `oats okf cat --base ALIAS /node/path.md` for each of those, and follow
47
- their links only as far as the task needs (see Navigating).
48
- 4. Write down in STATE.md which concepts shaped your plan, with their
49
- citations.
50
-
51
- Do not skip this because the task looks small: prior decisions are cheapest
52
- to find before you have written the code that contradicts them.
53
-
54
- ## Consult again while working
55
-
56
- The start-of-task read is not enough. Consult again:
57
-
58
- - **Before a design decision.** Search for the decision's subject, and read
59
- any prior decision on it before choosing.
60
- - **Before re-deriving something.** If you are about to work out why
61
- something is the way it is, search first; the rationale may be recorded.
62
- - **When a question touches your domain**, including a teammate's question.
63
- - **Before saying "we decided…" or "we tried…"**: cite it, or don't claim it.
64
- - **When something surprises you.** A lesson may already explain it.
65
-
66
- ## Commands
67
-
68
- | Command | What it answers |
69
- | --- | --- |
70
- | `oats okf bases [--fresh]` | aliases, accepted commit, freshness, validity, your owns/reads |
71
- | `oats okf index [--base A] [NODE \| A/NODE]` | one node's `index.md`; no args: all your nodes; `--base A` alone: the base root index |
72
- | `oats okf cat --base A PATH [--from P]` | one Markdown file, in full |
73
- | `oats okf ls --base A [DIR]` | directory entries, each concept's `type` / `title` / `description` |
74
- | `oats okf links --base A PATH` | the file's outgoing links, resolved, `ok` / `MISSING` / `REFUSED` / `external` |
75
- | `oats okf search [--base A \| --all] [--node N] [--regex] [--case-sensitive] TEXT` | matching lines `{base, path, line, snippet}` |
76
-
77
- All take `--json`. `read` (the okf 2.x spelling of `cat`) is removed in 4.0.0
78
- (`E_REMOVED`): use `cat`.
79
-
80
- ## Navigating
81
-
82
- Paths resolve like OKF links, **from the base root, not the filesystem**:
83
-
84
- - `/node/decisions/x.md` is base-root absolute (the usual form in indexes'
85
- absolute links and in citations);
86
- - a relative link (`../lessons/y.md`, `decisions/x.md`) is relative to the file
87
- it appeared in: pass that file as `--from`;
88
- - a bare `node/x.md` without `--from` resolves from the root.
89
-
90
- Worked example (a lesson linked from a decision):
91
-
92
- ```sh
93
- oats okf index expert
94
- oats okf cat --base project /expert/decisions/retry-policy.md
95
- oats okf links --base project /expert/decisions/retry-policy.md
96
- oats okf cat --base project ../lessons/storm.md --from /expert/decisions/retry-policy.md
97
- ```
98
-
99
- `links` shows every target already resolved, so you can `cat` the resolved
100
- path directly. `ls` is for choosing what to read from its descriptions, not
101
- for reading everything.
102
-
103
- ## Searching
104
-
105
- `oats okf search TEXT` searches your nodes' bases (fixed string,
106
- case-insensitive, Markdown only), capped at 50 hits with "and N more". Narrow
107
- with `--node`, a longer phrase or `--base`; widen with `--all`. Search finds
108
- words, not meaning: when it finds nothing, try a synonym, then navigate from
109
- the index. A hit is a pointer: `cat` the concept before relying on it.
110
-
111
- ## Citing
112
-
113
- Cite what you relied on as `alias/node/concept.md@<short-oid>`, using the oid
114
- from the receipt line (a directory base cites `alias@dir:<digest>`). Cite in
115
- STATE.md, notes/, PR descriptions and answers, so a reader knows which
116
- accepted state you saw.
117
-
118
- ## Freshness
119
-
120
- Reads use the cached accepted commit while it is younger than the
121
- `consult-max-age` setting (default 300 s); after that the accepted branch is
122
- refetched first. `--fresh` refetches now (for example right after a PR
123
- merged). If a fetch fails, the last fetched accepted commit is still served,
124
- marked `stale: true` / `STALE:` with the reason: say so when it matters. With
125
- nothing cached and no network, the command fails with `E_BASE_UNAVAILABLE`:
126
- report it, and do not answer from memory or from an old `./knowledge/`.
127
-
128
- ## Gotchas
129
-
130
- - Links resolve from the base root. `/node/x.md` is never a filesystem path,
131
- and filesystem paths, `..` escapes, URLs, hidden paths and symlinks are
132
- refused (`E_PATH`).
133
- - Never bulk-`cat` a whole node or loop `cat` over `ls` output. Index first,
134
- then follow the few relevant links.
135
- - Don't edit knowledge. The write path is notes/ → the knowledge harvester →
136
- a reviewed PR (or a directory publication). Write insights to notes/ (the
137
- okf-instance-knowledge skill), not into a base.
138
- - `oats okf refresh` and `read` are gone (`E_REMOVED`): every read already sees the
139
- accepted state.
140
- - `cat` reads `.md` files only (`E_NOT_MARKDOWN` otherwise); `E_NOT_FOUND`
141
- lists the nearest directory's entries to try instead.
142
-
143
- Read [references/consult.md](references/consult.md) for more search examples,
144
- the error table and freshness edge cases.
@@ -1,86 +0,0 @@
1
- # okf-consultation — reference detail
2
-
3
- The okf-consultation skill's detail. Read this when navigating links, when a search is noisy or empty, when a
4
- receipt says `STALE`, or when a command errors. Run every command from your
5
- instance home (`oats okf …` resolves your registered source there).
6
-
7
- ## Navigation, worked example
8
-
9
- Task: "change how retries back off". Your soul owns `project/expert`.
10
-
11
- ```sh
12
- oats okf index # ## project/expert (owns) … ## project/peer (reads)
13
- # * [Retry policy](decisions/retry-policy.md) - Why retries back off exponentially.
14
- oats okf cat --base project /expert/decisions/retry-policy.md
15
- # … "superseded the fixed delay; see [the incident](../lessons/fixed-delay-storm.md)"
16
- oats okf links --base project /expert/decisions/retry-policy.md
17
- # ok /expert/lessons/fixed-delay-storm.md (../lessons/fixed-delay-storm.md)
18
- # MISSING /expert/decisions/jitter.md
19
- oats okf cat --base project ../lessons/fixed-delay-storm.md \
20
- --from /expert/decisions/retry-policy.md
21
- ```
22
-
23
- - `index` with a node name (`oats okf index expert` or `project/expert`) prints
24
- one index; `--base A` alone prints the base's root `index.md`.
25
- - A link in a concept is relative to **that concept's directory**: pass the
26
- concept as `--from`, or use `links` to see every target already resolved.
27
- - `/node/x.md` is always from the base root; a bare `node/x.md` without
28
- `--from` is also from the root.
29
- - `ls --base A /node/decisions` shows each concept's `type`, `title` and
30
- `description` — use it to pick what to `cat`, not to read everything.
31
- - `MISSING` in `links` is a dangling link (allowed by OKF; not an error).
32
- `REFUSED` is a link that would leave the base or is malformed.
33
-
34
- ## Search
35
-
36
- ```sh
37
- oats okf search "backoff" # your nodes' bases, case-insensitive
38
- oats okf search --node expert "jitter" # one of your nodes
39
- oats okf search --base project --node peer "rate limit"
40
- oats okf search --all "idempotency" # every bound base
41
- oats okf search --regex "retr(y|ies)" # opt-in regex
42
- ```
43
-
44
- - Fixed string, case-insensitive by default (`--case-sensitive` to change);
45
- `--regex` is extended regex in Git bases, JavaScript RegExp in directory ones.
46
- - Only `.md` files inside the base root; results are `{base, path, line,
47
- snippet}`, capped at 50 with "and N more" — narrow with `--node` or a longer
48
- phrase rather than paging.
49
- - Search finds words, not meaning: when it's empty, try a synonym, then
50
- navigate from the index. A hit is a pointer; `cat` the concept before
51
- relying on it.
52
- - Git bases search with `git grep` at the accepted commit (the first search of
53
- a node fetches its blobs in one batch); directory bases walk the files in
54
- place, bounded to 20000 files.
55
-
56
- ## Citing
57
-
58
- Cite what you relied on as `alias/node/concept.md@<short-oid>`, the oid from
59
- the receipt line (`— project@1a2b3c4d5e6f (fetched 2m ago)`). A directory base
60
- cites its digest (`project@dir:9f8e…`). Cite in notes/, PR descriptions and
61
- answers so a reader can see which accepted state you saw.
62
-
63
- ## Freshness
64
-
65
- - Reads use the host cache's accepted commit if it was fetched within
66
- `consult-max-age` seconds (setting, default 300); older, the accepted branch
67
- is fetched first. `--fresh` fetches now. Neither ever selects another
68
- branch or commit: only the accepted one is served.
69
- - Fetch failed (offline, auth, timeout): the last fetched accepted commit is
70
- served with `stale: true` and the reason in the receipt (`STALE:` in text).
71
- Say so if it matters to your answer; retry later with `--fresh`.
72
- - No cached commit and no network → `E_BASE_UNAVAILABLE`: report it, don't
73
- guess from memory or from an old `./knowledge/`.
74
- - Merged a PR a minute ago? `--fresh` sees it once it is on the accepted branch.
75
-
76
- ## Errors
77
-
78
- | Code | Meaning / what to do |
79
- | --- | --- |
80
- | `E_BASE_UNKNOWN` | alias not bound; the message lists the bound aliases (`oats okf bases`) |
81
- | `E_NOT_FOUND` | no such file at the accepted commit; the message lists the nearest directory |
82
- | `E_NOT_MARKDOWN` | `cat` reads `.md` concepts only; use `ls` for a directory |
83
- | `E_PATH` | escapes the base root, filesystem path, URL, hidden path, symlink or submodule |
84
- | `E_RECOVERY` | a directory-base publication is pending; retry after it completes |
85
- | `E_BASE_UNAVAILABLE` | the base can't be read and nothing is cached; report it |
86
- | `E_REMOVED` | `refresh` and `read` no longer exist; use `index` / `cat` |
@@ -1,104 +0,0 @@
1
- ---
2
- name: okf-instance-knowledge
3
- description: >-
4
- Keeping this instance's own knowledge (STATE.md, log.md, notes/) with
5
- judgment: the capture test, what is worth writing down and what is not,
6
- one concept per note with type, claim, why, evidence and generality, when to
7
- write (at the decision, before compaction, before a task boundary), and how
8
- a note cites the soul knowledge it confirms or contradicts. Use at the start
9
- of every task, when a decision is taken or rejected, when something costs
10
- effort to find out, when a human corrects you, before compaction, and
11
- before finishing a task.
12
- ---
13
-
14
- # Instance knowledge
15
-
16
- Your instance knowledge is your working memory: what you are doing, what
17
- happened, and what you learned. It lives in instance home (not ./work):
18
- - **STATE.md**: the current task picture, **rewritten** as it changes. What
19
- the task is, where it stands, what is decided, what is blocked. `# Next`
20
- names ONE next step.
21
- - **log.md**: dated significant events, **append-only**. Never rewrite
22
- history.
23
- - **notes/**: **one concept per insight**, one Markdown file each.
24
-
25
- Your future self reads it after compaction. When harvest is on, the knowledge
26
- harvester reads it with your session transcript and decides what becomes soul
27
- knowledge. Write for both.
28
-
29
- ## The capture test
30
-
31
- > Would my future self after compaction, or the harvester judging this
32
- > session, decide or act better for having it — and is it absent from the
33
- > code, the tracker and the repository docs?
34
-
35
- Both halves must hold. The capture bar is lower than the promotion bar: you
36
- capture what might matter; the harvester promotes what does. Do not
37
- self-censor a real decision because it might not be promoted.
38
-
39
- ## Capture
40
-
41
- - **Decisions taken, and why.** The why is the part that dies with you.
42
- - **Alternatives rejected, and why.** Code shows the outcome, never the road
43
- not taken; without this, a later instance "helpfully" takes it.
44
- - **Discoveries that cost effort**: facts about the world that were written
45
- nowhere.
46
- - **Limitations, and the workaround that worked.**
47
- - **Conclusions of an investigation**, not its transcript.
48
- - **Blockers**, with what they block and what unblocks them.
49
- - **Human direction and corrections**, as you understood them, with when.
50
- - **Surprises**: the world behaved differently from what your soul knowledge
51
- says. That is a *candidate supersession*: flag it as one and cite the
52
- concept it contradicts.
53
- - **Process and environment lessons** the repository cannot express.
54
-
55
- ## Don't capture
56
-
57
- - Descriptions of the code, or maps of the repository: code is the truth
58
- about code, and a stored description drifts and lies.
59
- - Command logs and tool output; retries that taught nothing.
60
- - Secrets and credentials, however they appear.
61
- - Third-party messages verbatim (a lesson *about* one is fine).
62
- - What the tracker or the docs already hold: link to it instead.
63
-
64
- ## The form of a note
65
-
66
- ```markdown
67
- ---
68
- type: Decision # Decision | Rejected | Discovery | Limitation | Conclusion | Lesson | Blocker
69
- title: Retry budget is per request, not per connection
70
- description: One-line claim, the sentence an index would show.
71
- generality: soul # instance (true only for this task) | soul (likely true for the soul) — a hint, not a verdict
72
- observed: 2026-09-26, load test on the staging cluster (turns around the 14:10 run)
73
- ---
74
-
75
- The claim, then **why**: the reasoning, the alternatives, the evidence.
76
- Relates to: oats/expert/decisions/retries.md@5b6a9cab (refines it).
77
- ```
78
-
79
- - A one-line claim in `description`; the *why* in the body.
80
- - Evidence and provenance: what was observed, when, from what.
81
- - **Generality** tells the harvester whether you think it outlives the task.
82
- - A note that confirms, refines or contradicts soul knowledge **cites it**
83
- (`alias/node/concept.md@<short-oid>`, from `oats okf`'s receipt). That is
84
- what lets the harvester situate it.
85
-
86
- ## When
87
-
88
- - **At the decision, as it happens.** A decision reconstructed at the end has
89
- lost its why.
90
- - **Before compaction** and **before a task boundary**: update STATE.md and
91
- log.md, and write the notes you have been meaning to write.
92
- - **Consult first**: before writing a note, check notes/ and `oats okf search`
93
- so you refine or cite rather than duplicate.
94
-
95
- ## The theory, briefly
96
-
97
- - **Decision versus description.** A decision is superseded explicitly, and
98
- the new one names the old; a description goes stale silently. Capture
99
- decisions, not descriptions.
100
- - **Code is truth about code.** Anything a fresh instance could learn from
101
- the repository in ten minutes is not worth your note.
102
- - **Indexical residue dies with the instance.** "Was working on X", "the PR
103
- from this morning" mean nothing to anyone else. Write the durable claim
104
- underneath it, or nothing.
@@ -1,140 +0,0 @@
1
- #!/usr/bin/env node
2
- // oats.okf-harvest: the harvester's two commands. Both are thin: the delivery
3
- // code lives in oats.okf (a capability module is fetched per directory, so it
4
- // cannot import oats.okf's lib), and `complete` runs the source's frozen
5
- // `oats okf complete` from the source deployment, never from this home.
6
- import { spawnSync } from 'node:child_process';
7
- import { readFileSync, lstatSync } from 'node:fs';
8
- import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
9
- import { fileURLToPath } from 'node:url';
10
-
11
- const HELP = `oats okf-harvest complete --source FILE --run ID --judgment ABS_FILE [--json]
12
- oats okf-harvest harvest-status --source FILE --run ID [--json]
13
- complete runs the source's frozen \`oats okf complete\` in its deployment (the
14
- only delivery path). harvest-status reports each PR's state and what to do:
15
- stay, retire or max-age (setting harvester-max-age, default 7d).
16
- `;
17
- const fail = (code, message, extra = {}) => { throw Object.assign(new Error(message), { code, ...extra }); };
18
- const IDENTITY = /^(OATS_(?!HOME_DIR$|PACKAGE_CATALOG$)|PI_AGENT|GIT_)/;
19
-
20
- export function parseFlags(args, allowed) {
21
- const flags = {};
22
- for (let i = 0; i < args.length; i++) {
23
- const a = args[i];
24
- if (!a.startsWith('--')) fail('E_USAGE', `unexpected argument ${a}`);
25
- const k = a.slice(2);
26
- if (k in flags) fail('E_USAGE', `duplicate --${k}`);
27
- if (!allowed.includes(k)) fail('E_USAGE', `unknown flag --${k}`);
28
- if (k === 'json') { flags.json = true; continue; }
29
- if (!args[i + 1] || args[i + 1].startsWith('--')) fail('E_USAGE', `--${k} needs a value`);
30
- flags[k] = args[++i];
31
- }
32
- return flags;
33
- }
34
- const readJson = (file, what) => {
35
- try { return JSON.parse(readFileSync(file, 'utf8')); } catch (e) { fail('E_SOURCE', `${what} is unreadable: ${file} (${e.code || e.message})`); }
36
- };
37
- /** The frozen source descriptor: <stateDir>/sources/<uuid>/source.json. */
38
- export function readSource(file) {
39
- if (typeof file !== 'string' || !isAbsolute(file) || resolve(file) !== file) fail('E_USAGE', '--source must be an absolute descriptor path');
40
- if (basename(file) !== 'source.json' || !/^[0-9a-f-]{36}$/.test(basename(dirname(file))) || basename(dirname(dirname(file))) !== 'sources') fail('E_SOURCE', 'not an OKF source descriptor path (<stateDir>/sources/<id>/source.json)');
41
- if (lstatSync(file, { throwIfNoEntry: false })?.isFile() !== true) fail('E_SOURCE', `source descriptor missing: ${file}`);
42
- const s = readJson(file, 'source descriptor');
43
- if (s?.version !== 1 || s.id !== basename(dirname(file)) || typeof s.context !== 'string' || !isAbsolute(s.context) || typeof s.agent !== 'string') fail('E_SOURCE', 'invalid source descriptor');
44
- return s;
45
- }
46
- export function readRun(source, file, id) {
47
- if (typeof id !== 'string' || !/^[0-9a-f-]{36}$/.test(id)) fail('E_USAGE', '--run must be a run id');
48
- const run = readJson(join(dirname(file), 'runs', id, 'run.json'), 'run');
49
- if (run?.id !== id || run.source !== source.id) fail('E_RUN', 'run identity mismatch');
50
- return run;
51
- }
52
- /** The completion argv, exactly as oats.okf's completionArgv freezes it. */
53
- export function completionArgv(source, file, run, judgment) {
54
- const tail = ['okf', 'complete', '--source', file, '--run', run, '--judgment', judgment];
55
- const e = source.executionBinding;
56
- if (e !== undefined) {
57
- if (e?.schemaVersion !== 1 || typeof e.deployment !== 'string' || !isAbsolute(e.deployment) || !/^sha256-[a-f0-9]{64}$/.test(e.resolution?.id || '')) fail('E_SOURCE', 'invalid captured completion execution binding');
58
- return ['--deployment', e.deployment, '--resolution', e.resolution.id, ...tail, '--json'];
59
- }
60
- return [...tail, '--soul', source.agent, '--json'];
61
- }
62
- // A refusal meaning oats.okf cannot run for the source soul in its deployment.
63
- const INACTIVE = new Set(['E_CAPABILITY_INACTIVE', 'E_CAPABILITY_BLOCKED', 'E_CAPABILITY_MISSING', 'E_PACKAGE_MISSING', 'E_PACKAGE_INTEGRITY', 'E_SOUL_UNKNOWN', 'E_SOUL_DISABLED', 'E_UNKNOWN_COMMAND']);
64
- export function complete(flags, env = process.env) {
65
- for (const k of ['source', 'run', 'judgment']) if (!flags[k]) fail('E_USAGE', `--${k} is required`);
66
- if (!isAbsolute(flags.judgment)) fail('E_USAGE', '--judgment must be an absolute path');
67
- const source = readSource(flags.source);
68
- readRun(source, flags.source, flags.run);
69
- const cli = env.OATS_CLI_BIN;
70
- if (!cli || !isAbsolute(cli)) fail('E_RUNTIME', 'absolute OATS_CLI_BIN required; never resolve oats on PATH');
71
- const clean = Object.fromEntries(Object.entries(env).filter(([k]) => !IDENTITY.test(k)));
72
- const argv = completionArgv(source, flags.source, flags.run, flags.judgment);
73
- const r = spawnSync(cli, argv, { cwd: source.context, env: clean, encoding: 'utf8', timeout: 30 * 60 * 1000, maxBuffer: 16 * 1024 * 1024 });
74
- let answer; try { answer = JSON.parse(r.stdout); } catch { /* below */ }
75
- if (answer?.schemaVersion === 1 && answer.ok === true) return { deployment: source.context, ...answer.result };
76
- const code = answer?.error?.code || 'E_COMPLETE', message = answer?.error?.message || (r.error?.message || r.stderr || `exit ${r.status}`).trim();
77
- if (INACTIVE.has(code)) fail('E_SOURCE_INACTIVE', `oats.okf cannot run for source soul ${source.agent} in ${source.context} (${code}: ${message}). Nothing was published: report this to the okf team and your operator, and stay.`, { cause: code });
78
- fail(code, `${message} (completion ran in ${source.context}; keep your home and report)`);
79
- }
80
- /** "7d" | "48h" | "90m" | seconds → milliseconds. */
81
- export function maxAgeMs(value) {
82
- if (value === undefined || value === null) return 7 * 86400000;
83
- if (Number.isInteger(value) && value > 0) return value * 1000;
84
- const m = /^(\d+)(m|h|d)$/.exec(String(value));
85
- if (!m || Number(m[1]) < 1) fail('E_CONFIG', 'harvester-max-age must be a duration like 7d, 48h or 90m, or a positive number of seconds');
86
- return Number(m[1]) * { m: 60000, h: 3600000, d: 86400000 }[m[2]];
87
- }
88
- function settings(env) {
89
- let s; try { s = JSON.parse(env.OATS_SETTINGS || '{}'); } catch { fail('E_CONFIG', 'OATS_SETTINGS is not JSON'); }
90
- return s && typeof s === 'object' ? s : {};
91
- }
92
- function prState(pr, env) {
93
- const r = spawnSync('gh', ['pr', 'view', pr.url, '--json', 'state,mergedAt,closedAt,url,number'], { encoding: 'utf8', timeout: 60000, env: Object.fromEntries(Object.entries(env).filter(([k]) => !IDENTITY.test(k))) });
94
- if (r.status !== 0) return { url: pr.url, number: pr.number, state: 'UNKNOWN', error: (r.stderr || r.error?.message || `exit ${r.status}`).trim() };
95
- const v = JSON.parse(r.stdout);
96
- return { url: v.url, number: v.number, state: v.state, mergedAt: v.mergedAt || null, closedAt: v.closedAt || null };
97
- }
98
- export function harvestStatus(flags, env = process.env, { now = Date.now(), view = prState } = {}) {
99
- for (const k of ['source', 'run']) if (!flags[k]) fail('E_USAGE', `--${k} is required`);
100
- const source = readSource(flags.source), run = readRun(source, flags.source, flags.run);
101
- const limit = maxAgeMs(settings(env)['harvester-max-age']);
102
- const age = now - Date.parse(run.created);
103
- const receipts = run.receipts && typeof run.receipts === 'object' ? run.receipts : {};
104
- const destinations = Object.entries(receipts).map(([alias, r]) => {
105
- if (r?.pr?.url) return { alias, receipt: r.status, pr: view(r.pr, env) };
106
- return { alias, receipt: r?.status ?? null, pr: null };
107
- });
108
- const judged = !!run.judgment;
109
- let action, reason;
110
- const open = destinations.filter((d) => d.pr && !['MERGED', 'CLOSED'].includes(d.pr.state));
111
- const pending = destinations.filter((d) => !d.pr && !['no-change', 'accepted'].includes(d.receipt));
112
- if (!judged || pending.length) { action = age >= limit ? 'max-age' : 'stay'; reason = !judged ? 'the run is not completed yet' : `destinations not delivered: ${pending.map((d) => d.alias).join(', ')}`; }
113
- else if (open.length) { action = age >= limit ? 'max-age' : 'stay'; reason = `open PR: ${open.map((d) => d.pr.url).join(', ')}`; }
114
- else { action = 'retire'; reason = destinations.some((d) => d.pr) ? 'every PR is merged or closed' : 'no PR was needed (no-change or directory publication)'; }
115
- if (action === 'max-age') reason += `; older than harvester-max-age (${Math.round(limit / 3600000)}h): tell the okf team and retire, never close the PR`;
116
- return { run: run.id, status: run.status, ageSeconds: Math.round(age / 1000), maxAgeSeconds: limit / 1000, destinations, action, reason };
117
- }
118
- function text(event, r) {
119
- if (event === 'harvest-status') return [`run ${r.run} (${r.status}): ${r.action} — ${r.reason}`, ...r.destinations.map((d) => ` ${d.alias}: ${d.pr ? `${d.pr.state} ${d.pr.url}` : d.receipt}`)].join('\n');
120
- return `completed run ${r.run}: ${r.status}${Object.entries(r.receipts || {}).map(([a, x]) => `\n ${a}: ${x.status}${x.pr?.url ? ` ${x.pr.url}` : ''}`).join('')}`;
121
- }
122
- if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
123
- const args = process.argv.slice(2), event = args[0];
124
- if (!event || args.includes('--help') || args.includes('-h')) process.stdout.write(HELP);
125
- else {
126
- const json = args.includes('--json');
127
- try {
128
- let result;
129
- if (event === 'complete') result = complete(parseFlags(args.slice(1), ['source', 'run', 'judgment', 'json']));
130
- else if (event === 'harvest-status') result = harvestStatus(parseFlags(args.slice(1), ['source', 'run', 'json']));
131
- else fail('E_USAGE', `unknown command ${event}; see --help`);
132
- process.stdout.write((json ? JSON.stringify({ schemaVersion: 1, ok: true, result }) : text(event, result)) + '\n');
133
- } catch (e) {
134
- const code = e.code || 'E_OKF_HARVEST';
135
- if (json) process.stdout.write(JSON.stringify({ schemaVersion: 1, ok: false, error: { code, message: e.message } }) + '\n');
136
- else process.stderr.write(`oats okf-harvest ${event}: ${code}: ${e.message}\n`);
137
- process.exitCode = 1;
138
- }
139
- }
140
- }
@@ -1,12 +0,0 @@
1
- ## Knowledge harvester (oats.okf-harvest)
2
-
3
- You are a **judge, not a worker**. Load the **knowledge-harvest** skill before
4
- anything else, and judge by **knowledge-theory**.
5
-
6
- - Read the whole input: the notes AND every transcript window. Cite the turn
7
- ids you relied on in the judgment receipt.
8
- - Your staged roots in ./work are your only write surface, and only the owned
9
- nodes in them. `oats okf-harvest complete` is the only delivery path.
10
- - Stay alive until your PR is merged or closed. On every wake, run
11
- `oats okf-harvest harvest-status` first, answer the maintainer in the okf
12
- team, and retire only when it says `retire` or `max-age`. Never close the PR.
@@ -1,26 +0,0 @@
1
- {
2
- "capability": "oats.okf-harvest",
3
- "command": "okf-harvest",
4
- "version": "4.0.1",
5
- "compatibility": {
6
- "oats": ">=0.29.0"
7
- },
8
- "description": "The OKF knowledge harvester: judges one source instance's captured notes and session transcript by the OKF promotion doctrine, opens the labelled harvest PR with its provenance block, and stays in the okf team until the PR is merged or closed.",
9
- "requires": [
10
- { "command": "gh", "why": "read the harvest PR's state (harvest-status)" }
11
- ],
12
- "settings": {
13
- "harvester-max-age": {
14
- "default": "7d",
15
- "description": "How long a harvester stays alive waiting for its PR (a duration like 7d, 48h or 90m, or seconds). At max-age it tells the okf team and retires; it never closes the PR."
16
- }
17
- },
18
- "skills": [
19
- "skills"
20
- ],
21
- "inject": "injects/harvester.md",
22
- "commands": {
23
- "complete": "bin/okf-harvest.mjs complete",
24
- "harvest-status": "bin/okf-harvest.mjs harvest-status"
25
- }
26
- }