@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,151 +0,0 @@
1
- ---
2
- name: okf-authoring
3
- description: >-
4
- Open Knowledge Format (OKF) authoring craft for knowledge-operations souls:
5
- how to write, edit, move and validate concepts in an OKF bundle (markdown
6
- concepts with YAML frontmatter, per Google Cloud's OKF v0.1 spec), keep
7
- index.md and log.md honest, supersede instead of silently rewriting, and run
8
- the bundled validator. Use when staging or amending concepts in a knowledge
9
- base, fixing index/log entries, reviewing a knowledge PR's Markdown, or when
10
- asked to validate a bundle. Promotion judgment (what belongs in a base) is
11
- the knowledge-theory skill.
12
- ---
13
-
14
- # OKF craft — author, maintain, consume
15
-
16
- An OKF **bundle** is a directory tree of markdown files. Each non-reserved `.md`
17
- file is **one concept**; links between files form the knowledge graph. No
18
- database, no SDK — plain git-versionable text. Spec: OKF v0.1 (Google Cloud).
19
- An external base is one bundle and link namespace. Owned nodes are
20
- nonoverlapping subdirectories, not separate root-link namespaces. Instance
21
- `notes/` files are task-local concepts; no knowledge lives in the soul.
22
-
23
- ## The format in one screen
24
-
25
- - **Concept = one file.** Concept ID = path minus `.md`. Small and specific
26
- beats long and general — split rather than grow.
27
- - **Frontmatter** (`---` delimited): only **`type`** is required (short,
28
- freeform — the spec ships no vocabulary. Fleet core: `Lesson`, `Decision`,
29
- `Playbook`, `Reference`; souls also grow role-specific types like
30
- `Area Guide` or `Roadmap` — see the knowledge-theory skill for routing).
31
- Recommended,
32
- in order: `title`, `description` (ONE sentence — it's what index listings
33
- and skimming agents see), `resource` (URI, only if a real asset backs the
34
- concept), `tags` (YAML list), `timestamp` (ISO date of last meaningful change).
35
- - **Links** are ordinary markdown, keep the `.md`, prefer bundle-root-absolute:
36
- `[clearing playbook](/node/playbooks/clearing-fields.md)`. Links are untyped
37
- directed edges; the surrounding prose carries the relationship's meaning.
38
- - **Reserved files** at any level: `index.md` (navigation) and `log.md`
39
- (history). They carry **no `type`**; only the bundle-root `index.md` may
40
- have frontmatter, and only `okf_version: "0.1"`.
41
- - **Conventional headings** when applicable: `# Schema`, `# Examples`,
42
- `# Citations` (numbered external sources backing claims).
43
-
44
- ## Honesty rules (non-negotiable)
45
-
46
- - **Never invent** a `resource`, `timestamp`, or `description` — leave a field
47
- out rather than guess it.
48
- - Every claim you write down should be something you verified or observed;
49
- cite sources under `# Citations` when the claim came from outside.
50
- - Never create a link to a concept you didn't create or verify exists —
51
- except deliberate not-yet-written knowledge, which is allowed by spec but
52
- should be rare and intentional.
53
- - **Supersede, don't silently rewrite.** When a concept's meaning changes,
54
- update it AND log the change; when it's wrong, correct it and say so in
55
- log.md (`**Fix**: …`). History must stay reconstructible.
56
-
57
- ## Maintaining a bundle
58
-
59
- **Adding a concept:**
60
- 1. Write the file in the right section dir with valid frontmatter.
61
- 2. Link it to/from related concepts (edit those files' bodies).
62
- 3. Add a line to the section's `index.md`: `* [Title](file.md) - description`.
63
- 4. Append to the bundle's `log.md` (see conventions below).
64
-
65
- **Renaming/moving a concept:** update **every inbound link** — search the
66
- whole bundle for the old path (`grep -rn "old-name.md" <bundle>`) — EXCEPT
67
- links inside historical `log.md` entries: never rewrite log history; dangling
68
- links there are expected.
69
-
70
- **Removing:** delete the file, remove its index.md line, fix inbound links,
71
- log a `**Removal**` or `**Deprecation**` entry saying why.
72
-
73
- **log.md conventions** (newest first, `## YYYY-MM-DD` headings):
74
- `* **Creation|Update|Removal|Fix|Deprecation|Harvest|Triage**: prose with
75
- [links](/path.md).` One line per event; the bold word makes logs greppable.
76
-
77
- **index.md discipline:** every concept reachable from an index; descriptions
78
- in listings match the concept's frontmatter `description`. Indexes are
79
- navigation, not content — keep them to listings.
80
-
81
- ## Consuming a bundle (answering from knowledge)
82
-
83
- 1. **Index-first, always.** Start at the root `index.md`; follow only links
84
- relevant to the question. Never bulk-read a bundle — progressive
85
- disclosure is the point of the format.
86
- 2. Frontmatter (`type`, `tags`, `description`) is the quick filter layer;
87
- open bodies only for concepts that survive the filter.
88
- 3. `log.md` answers "what changed recently" — check it when freshness matters.
89
- 4. Cite concepts by path when reporting answers.
90
- 5. Tolerate imperfect concepts: unknown types and stale links are
91
- never a reason to reject or ignore a bundle — that permissiveness is spec.
92
-
93
- ## Validating
94
-
95
- Run the bundled validator (node, no deps) after non-trivial maintenance:
96
-
97
- ```bash
98
- node <skill-dir>/scripts/okf-validate.mjs <bundle-dir> # conformance
99
- node <skill-dir>/scripts/okf-validate.mjs <bundle-dir> --strict # + producer lints
100
- ```
101
-
102
- - **Conformance errors** (must fix): unparseable/missing frontmatter, missing
103
- or empty `type`, reserved files carrying a `type`.
104
- - **Producer lints** (`--strict`, should fix in bundles you produce): broken
105
- intra-bundle links (log.md exempt), links missing `.md`, concepts
106
- unreachable from any index.md, missing `title`/`description`.
107
-
108
- Lints in a bundle you're *consuming* are noise — read on regardless.
109
-
110
- ## Portable source and store declarations
111
-
112
- When the portable binding interface is active (planned OATS >=0.24.0; not yet a
113
- published provider baseline), treat the source declaration as policy and the
114
- captured ProviderBinding as execution authority:
115
-
116
- - In `oats.okf.locations@1`, `fixed` is source-owned, `default` is rebindable,
117
- and `inherit` requires an external binding such as `write.default`.
118
- - Qualify every read and owned node by its declared store. A read grants no
119
- write authority. Never infer the sole readable store as a destination.
120
- - Workspace store envelopes put concrete provider choices under
121
- `payload.bindings`. Workspace, adoption, and operator values remain separate
122
- inputs to the shared resolver; OKF does not select their precedence.
123
- - Durable placement is explicit selected settings: physical absolute
124
- `bindings-file` and `state-dir`, plus selected `harvest-runtime`, optional
125
- `harvest-model` and optional `git-timeout` (seconds for remote Git
126
- operations, default 600). Never derive state from an instance home.
127
- - Provider codecs run only after exact retained executable approval. Their
128
- populated binding is not proof of readiness, enrollment, credentials, privacy
129
- or publication authority. Respect typed non-ready results.
130
- - Captured source descriptors freeze binding/runtime/source identity. Later
131
- reads and workers use those bytes after source/config deletion. Never replace
132
- them with today's soul, workspace, settings or bindings file.
133
- - `responsibleHuman: null` means messaging was explicitly disabled. Missing is
134
- unknown, not disabled.
135
- - New captured source schedules are definition v2 with `capture`, explicit
136
- deployment/resolution selectors and saved `--json`; they do not use `--soul`.
137
- - Captured `setup`, `init`, `migrate`, and `unlock` are deliberate refusals.
138
- Provisioning/migration remains a separate explicit operator path.
139
-
140
- The broker-owned `binding-normalize`, `binding-bind`, and `binding-check`
141
- manifest commands are not manual recipes. Do not invoke them from a working
142
- agent or copy transient `OATS_BINDING_FILE`/`OATS_SOURCE_RECEIPT_FILE` paths.
143
- Those private mode-0600 files exist only for one synchronous captured invocation.
144
-
145
- ## External bases and native tools
146
-
147
- A harvester stages writes with native file tools only under the roots listed
148
- in work/staging.json. A maintainer amends a PR branch in its own checkout.
149
- Either way, validate the WHOLE base, not an isolated node: absolute Markdown
150
- links can cross node boundaries. The harvester's completion command validates
151
- again and refuses any errors or producer warnings.
@@ -1,123 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * okf-validate.mjs — OKF v0.1 bundle validator (no dependencies).
4
- *
5
- * Usage: node okf-validate.mjs <bundle-dir> [--strict] [--json]
6
- *
7
- * Conformance (errors): frontmatter parses; non-empty `type` on concepts;
8
- * reserved files (index.md, log.md) carry no `type`.
9
- * Producer lints (--strict, warnings): broken intra-bundle links (log.md exempt),
10
- * links missing .md, concepts unreachable from any index.md, missing title/description.
11
- * Exit: 0 conformant, 1 errors (or warnings with --strict), 2 usage.
12
- */
13
- import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
14
- import { join, relative, resolve, dirname, posix } from "node:path";
15
-
16
- const args = process.argv.slice(2);
17
- const strict = args.includes("--strict");
18
- const asJson = args.includes("--json");
19
- const dir = args.find((a) => !a.startsWith("--"));
20
- if (!dir || !existsSync(dir)) { console.error("usage: okf-validate.mjs <bundle-dir> [--strict] [--json]"); process.exit(2); }
21
- const root = resolve(dir);
22
-
23
- const files = [];
24
- (function walk(d) {
25
- for (const e of readdirSync(d, { withFileTypes: true })) {
26
- if (e.name.startsWith(".")) continue;
27
- const p = join(d, e.name);
28
- if (e.isDirectory()) walk(p);
29
- else if (e.name.endsWith(".md")) files.push(p);
30
- }
31
- })(root);
32
-
33
- const errors = [], warnings = [];
34
- const rel = (p) => relative(root, p).split("\\").join("/");
35
- const isReserved = (p) => ["index.md", "log.md"].includes(posix.basename(rel(p)));
36
-
37
- function parseFrontmatter(text) {
38
- if (!text.startsWith("---")) return { present: false };
39
- const m = text.match(/^---\r?\n([\s\S]*?)\r?\n---(\r?\n|$)/);
40
- if (!m) return { present: true, parsed: false };
41
- const meta = {};
42
- for (const line of m[1].split("\n")) {
43
- if (/^\s*#/.test(line) || !line.trim()) continue;
44
- const kv = line.match(/^([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/);
45
- if (kv) meta[kv[1]] = kv[2].replace(/\s+#.*$/, "").replace(/^["']|["']$/g, "").trim();
46
- else if (!/^\s+/.test(line)) return { present: true, parsed: false };
47
- }
48
- return { present: true, parsed: true, meta, body: text.slice(m[0].length) };
49
- }
50
-
51
- const concepts = new Map(); // rel path -> { meta, body }
52
- for (const f of files) {
53
- const r = rel(f);
54
- const text = readFileSync(f, "utf8");
55
- const fm = parseFrontmatter(text);
56
- if (isReserved(f)) {
57
- if (fm.present && fm.parsed && fm.meta.type) errors.push(`${r}: reserved file must not carry a 'type'`);
58
- if (fm.present && fm.parsed && posix.basename(r) === "index.md" && r !== "index.md") {
59
- const keys = Object.keys(fm.meta);
60
- if (keys.some((k) => k !== "okf_version")) warnings.push(`${r}: only the bundle-root index.md may carry frontmatter`);
61
- }
62
- concepts.set(r, { reserved: true, body: fm.parsed ? fm.body : text });
63
- continue;
64
- }
65
- if (!fm.present) { errors.push(`${r}: missing YAML frontmatter`); continue; }
66
- if (!fm.parsed) { errors.push(`${r}: unparseable YAML frontmatter`); continue; }
67
- if (!fm.meta.type) errors.push(`${r}: missing or empty required field 'type'`);
68
- if (strict) {
69
- if (!fm.meta.title) warnings.push(`${r}: missing recommended field 'title'`);
70
- if (!fm.meta.description) warnings.push(`${r}: missing recommended field 'description'`);
71
- }
72
- concepts.set(r, { meta: fm.meta, body: fm.body });
73
- }
74
-
75
- if (strict) {
76
- // Link checks (log.md bodies exempt) + reachability from index files.
77
- const reachable = new Set();
78
- const linkRe = /\[[^\]]*\]\(([^)\s]+)\)/g;
79
- const resolveLink = (fromRel, target) => {
80
- if (/^[a-z]+:\/\//i.test(target) || target.startsWith("mailto:")) return null; // external
81
- const clean = target.split("#")[0];
82
- if (!clean) return null;
83
- const abs = clean.startsWith("/")
84
- ? posix.normalize(clean.slice(1))
85
- : posix.normalize(posix.join(posix.dirname(fromRel), clean));
86
- return abs;
87
- };
88
- for (const [r, c] of concepts) {
89
- const body = c.body ?? "";
90
- const fromLog = posix.basename(r) === "log.md";
91
- for (const m of body.matchAll(linkRe)) {
92
- const t = resolveLink(r, m[1]);
93
- if (t === null) continue;
94
- const isDir = t.endsWith("/") || concepts.has(posix.join(t, "index.md")) || existsSync(join(root, t)) && statSync(join(root, t)).isDirectory?.();
95
- if (posix.basename(r) === "index.md" || !fromLog) {
96
- if (!t.endsWith(".md") && !isDir) { if (!fromLog) warnings.push(`${r}: link missing .md extension: ${m[1]}`); continue; }
97
- }
98
- if (fromLog) continue; // history exempt from broken-link lint
99
- if (t.endsWith(".md") && !concepts.has(t)) warnings.push(`${r}: broken link: ${m[1]}`);
100
- if (posix.basename(r) === "index.md" && t.endsWith(".md") && concepts.has(t)) reachable.add(t);
101
- if (posix.basename(r) === "index.md" && isDir) reachable.add(posix.join(t.replace(/\/$/, ""), "index.md"));
102
- }
103
- }
104
- // Reachability: walk index closure (an index that lists a subdir makes that subdir's index reachable).
105
- for (const [r, c] of concepts) {
106
- if (c.reserved || reachable.has(r)) continue;
107
- // root-level concepts listed in root index handled above; report the rest
108
- const anyIndex = [...concepts.keys()].some((k) => posix.basename(k) === "index.md");
109
- if (anyIndex) warnings.push(`${r}: unreachable from any index.md`);
110
- }
111
- }
112
-
113
- const conceptCount = [...concepts.values()].filter((c) => !c.reserved).length;
114
- if (asJson) {
115
- console.log(JSON.stringify({ bundle: root, concepts: conceptCount, errors, warnings, conformant: errors.length === 0 }, null, 2));
116
- } else {
117
- console.log(`OKF validate — ${root}`);
118
- console.log(` ${conceptCount} concept(s), ${errors.length} error(s), ${warnings.length} warning(s)`);
119
- for (const e of errors) console.log(` ERROR ${e}`);
120
- for (const w of warnings) console.log(` warn ${w}`);
121
- console.log(errors.length === 0 ? (strict && warnings.length ? "PASS (with lints)" : "PASS — conformant") : "FAIL — nonconformant");
122
- }
123
- process.exit(errors.length > 0 ? 1 : strict && warnings.length > 0 && process.env.OKF_STRICT_EXIT ? 1 : 0);
@@ -1,146 +0,0 @@
1
- ---
2
- name: okf-trigger-setup
3
- description: >-
4
- Set up and verify the OKF harvest-review trigger, which spawns a knowledge
5
- maintainer for each harvest PR: declare it as a workspace automation
6
- (`oats-triggers/okf-harvest-review.yaml` in a member repo, `from:
7
- oats.okf:harvest-review`, with `runsOn` naming the one host and `owner` the
8
- GitHub account that can merge on the knowledge-base repo), or locally with
9
- `oats trigger add` for a machine-private setup. Covers the okf team, the
10
- self-approval limit and `oats trigger test`. Use when setting up knowledge
11
- operations, when harvest PRs are not being reviewed, when moving the
12
- reviewer to another host, or when asked whether a host may run the
13
- maintainer.
14
- ---
15
-
16
- # Setting up the harvest-review trigger
17
-
18
- The trigger makes a harvest PR get reviewed: when a PR labelled `okf-harvest`
19
- opens on the knowledge-base (KB) repository, the host tick spawns a new
20
- `oats.okf/knowledge-maintainer` in the `okf` team to review it. It runs on one
21
- machine, acting as one GitHub account, and that account must be able to
22
- **merge** on the KB repository.
23
-
24
- ## 1. Choose the host and the account
25
-
26
- - **The account (`owner`)** must be able to merge on the KB repository (push,
27
- maintain or admin). Check from the host:
28
- `gh api repos/<owner>/<repo> --jq .permissions`.
29
- - **The host (`runsOn`)** is the one machine that runs the trigger, named by
30
- its `oats-local.yaml` `host: { name: <slug> }`, and logged in with `gh` as
31
- that account.
32
- - **The harvest switch is independent**: a review host need not harvest (its
33
- `harvest` setting can stay `off`), and a harvesting host need not review.
34
-
35
- ## 2. The self-approval limit
36
-
37
- GitHub forbids approving your own account's PR. If the harvester's host and
38
- the reviewer's account are the same GitHub account, then either:
39
- - the KB repository's `main` must not require approving reviews (merge
40
- permission is enough; the maintainer records its verdict as a PR comment,
41
- not an approval), or
42
- - the trigger's `owner` is a separate reviewer account or machine user.
43
-
44
- Say which one applies when you report the setup.
45
-
46
- ## 3. The okf team
47
-
48
- The package souls carry `team: okf`. The workspace must declare it, with its
49
- messaging mapping. Messaging is aweb (`oats.aweb`, the workspace default);
50
- it needs oats.aweb 1.15.0 or later, which honours the `join=okf` the
51
- harvester spawn and the trigger's `teams: [okf]` pass:
52
-
53
- ```yaml
54
- # oats-workspace.yaml
55
- teams:
56
- okf: { description: Knowledge operations }
57
- defaults:
58
- messaging: { oats.aweb: { from: package } }
59
- messaging:
60
- byTeam:
61
- okf: { team: aweb:<your-org>.okf }
62
- ```
63
-
64
- Another messaging provider works the same way if it honours `join`.
65
-
66
- Without it, the souls list with `E_TEAM_UNKNOWN`, and the harvester and the
67
- maintainer cannot message each other.
68
-
69
- ## 4. Declare it in the workspace (the default)
70
-
71
- A team relies on the review, so declare it in Git, in a member repository (the
72
- workspace's host repo), in its `oats-triggers/` folder:
73
-
74
- ```yaml
75
- # <member>/oats-triggers/okf-harvest-review.yaml
76
- kind: oats-trigger
77
- schemaVersion: 1
78
- description: Review every OKF harvest PR on the knowledge base
79
- from: oats.okf:harvest-review
80
- set: { repo: github.com/<owner>/<kb-repo> } # optional: base, harness, model
81
- runsOn: <host.name of the one machine>
82
- owner: github.com/<the merge-capable account>
83
- ```
84
-
85
- - `kind: oats-trigger` and `schemaVersion: 1` make the file self-describing; a
86
- wrong kind is `E_AUTOMATION_SCHEMA`.
87
- - The id is `id:` if present, else the filename stem (`okf-harvest-review`).
88
- Two files with the same id in one member are `E_AUTOMATION_DUPLICATE`.
89
- - A file named `*.oats-trigger.yaml` anywhere in the member works too (never
90
- under `oats-package/`, `.git/` or `node_modules/`); `oats-triggers/` is the
91
- canonical place.
92
-
93
- Or let the CLI write it: `oats trigger add --from oats.okf:harvest-review
94
- --set repo=github.com/<owner>/<kb-repo> --workspace <member>` (it prints the
95
- file when that repository is not the current checkout). Commit and merge it
96
- like any other change.
97
-
98
- A host runs it only when **both** its `host.name` equals `runsOn` **and** its
99
- `gh` account equals `owner`. Everywhere else it is listed with the reason:
100
- `assigned-elsewhere`, `owner-mismatch` or `host-unnamed`. That keeps exactly
101
- one machine on it, and the operator's consent explicit. A host can opt out
102
- without a commit: `automations.disabled: [<member>/okf-harvest-review]` in its
103
- `oats-local.yaml`. Changes reach the host within about ten minutes (after
104
- `oats sync`, or the tick's refresh).
105
-
106
- ## 5. Or add it locally (machine-private)
107
-
108
- For a personal or experimental setup, add it to this deployment only. It runs
109
- on this host with this host's `gh`, with no `runsOn` or `owner`:
110
-
111
- ```sh
112
- oats trigger add --from oats.okf:harvest-review --set repo=github.com/<owner>/<kb-repo>
113
- # optional: --set base=main --set harness=claude --set model=opus --id okf-harvest-review
114
- ```
115
-
116
- Never run the same review from two places: one workspace declaration, or one
117
- local trigger on one host.
118
-
119
- ## 6. Test it on the host that runs it
120
-
121
- ```sh
122
- oats trigger test <member>/okf-harvest-review # or: oats trigger test okf-harvest-review (local)
123
- oats schedule host install # the host timer, if the test says it is missing
124
- oats trigger status
125
- ```
126
-
127
- - `oats trigger test` checks gh auth and where its credential comes from, the
128
- repository and your merge permissions, the soul, its messaging capability,
129
- the okf team, the host/owner match, and what would fire now. It spawns
130
- nothing. It must pass before you report the setup done; fix what it names.
131
- - **Credentials reach the tick through the host timer, not your shell.** A
132
- `GH_TOKEN` exported in your shell does not reach it; `gh auth login` with the
133
- keyring or config file does.
134
- - Pause with `oats trigger disable <id>`; `remove` leaves running maintainers
135
- alone.
136
-
137
- ## 7. Labels
138
-
139
- Harvest PRs carry `okf-harvest` (the harvester's completion creates the label
140
- if the repository lacks it). The maintainer adds `okf-needs-human` when a PR
141
- would supersede a human-accepted decision. To pre-create both:
142
-
143
- ```sh
144
- gh label create okf-harvest --repo <owner>/<repo> --force --color 0E8A16 --description "OKF harvest PR (oats.okf)"
145
- gh label create okf-needs-human --repo <owner>/<repo> --force --color D93F0B --description "OKF: needs a human decision"
146
- ```
@@ -1,69 +0,0 @@
1
- ## Review discipline: oats.review
2
-
3
- **After every substantive commit, launch the reviewer** — and, when a knowledge
4
- layer is active, run its promotion step alongside (whatever command that layer
5
- documents; omit the line entirely if you have no knowledge layer):
6
-
7
- ```bash
8
- <your knowledge layer's promotion command> # omit when no knowledge layer is active
9
- oats spawn reviewer --work attached --work-dir "$PWD/work" \
10
- --purpose "<short-sha>" \
11
- --task "Review commit <sha> on branch <branch>. Report to <your-instance> per your operating loop."
12
- ```
13
-
14
- - `reviewer` is the oats.dev package's soul (`oats.dev/reviewer`).
15
- `--purpose "<short-sha>"` gives it a unique, commit-relevant instance name
16
- (`oats-dev-reviewer-<short-sha>`); attached mode shares your work tree
17
- and automatically makes the reviewer your child (attached agents are always
18
- children of the work-tree owner — no relation flags needed or allowed).
19
- - The reviewer reviews **that commit's diff only** and reports its verdict
20
- (`APPROVE` / `APPROVE WITH NITS` / `NEEDS CHANGES`) back to you the way your
21
- deployment delivers messages: over your messaging layer when one is active,
22
- and otherwise in its own session transcript, which is where you read it.
23
- When a messaging layer IS active, do not wait actively — finish your turn and
24
- go idle; the layer wakes you when the verdict arrives. `NEEDS CHANGES` means
25
- fix, commit, and re-review before the work is ready.
26
- - Do not review your own commits in its place — the point is eyes that are
27
- not yours.
28
- - Skip only for trivial mechanical commits (typo, lockfile refresh) — when
29
- in doubt, review.
30
-
31
- ## Delivery discipline (all OATS developers)
32
-
33
- - You work in a dedicated worktree on your own branch. **Main only moves
34
- through PRs** — never push to main.
35
- - **Single-developer features**: branch from main (`agents/<instance>` or as
36
- tasked), open the PR yourself (`gh pr create`) when review-clean, then
37
- **spawn a fresh maintainer instance for it** — one per PR, always, even if
38
- another oats-expert instance is live:
39
-
40
- ```bash
41
- oats spawn oats-expert --purpose "pr<n>" --relation parent --relative-to "$OATS_INSTANCE" \
42
- --task "Maintainer review of PR #<n>: run your pr-review gates. You own this PR to its terminal outcome — on RETURN stay alive and idle for my fix notice, re-review, repeat; on merge/close record the delivery in your stewardship knowledge and retire yourself. Report verdicts to <your-instance>."
43
- ```
44
-
45
- Go idle for the verdict. **The maintainer instance stays alive across
46
- RETURN rounds** — when you push fixes, notify the SAME maintainer, continuing
47
- the existing exchange rather than starting a new one; do not spawn another for
48
- this PR. You never merge to main
49
- yourself.
50
-
51
- **Reviewers are the opposite: one per commit, then gone.** The post-commit
52
- reviewer reviews its one diff, reports its verdict, and retires — it no
53
- longer exists when you fix its findings. To re-review a fix, spawn a NEW
54
- reviewer on the fix commit (`--purpose <new-short-sha>`); never message a
55
- retired reviewer or expect it to follow up.
56
- - **Multi-developer features**: the coordinator owns the feature branch
57
- (`feature/<name>`) and the PR. Branch `<you>/<name>` **from the feature
58
- branch**, push your branch, and tell the coordinator when it is ready —
59
- the coordinator merges, validates, and reviews the integrated state. Never
60
- merge into the feature branch yourself.
61
- - **If you need another developer's unmerged code, ask the coordinator** —
62
- never fetch or merge a peer's branch yourself. The coordinator
63
- lands the dependency on the feature branch and tells you to merge the
64
- feature branch into yours.
65
- - Quality bar before handing off or opening a PR: the repo's full test/check
66
- gate green; docs updated with behavior changes.
67
- - While waiting on the reviewer, the coordinator, or a peer: **do not sleep,
68
- poll, or busy-wait** — go idle. An active messaging layer wakes you when the
69
- answer arrives; with none, read the reviewer's own session when it finishes.
@@ -1,10 +0,0 @@
1
- {
2
- "capability": "oats.review",
3
- "private": true,
4
- "version": "1.3.0",
5
- "compatibility": { "oats": ">=0.28.0" },
6
- "description": "Post-commit review discipline: a fresh reviewer (this package's soul `reviewer`) reviews each new commit's diff, reports its verdict to its spawner over the deployment's messaging layer (or in its transcript when there is none), and retires — plus the shared developer delivery discipline and the reviewer's code-review and security-review skills.",
7
- "requires": [],
8
- "skills": ["skills/code-review", "skills/security-review"],
9
- "inject": "injects/review.md"
10
- }
@@ -1,44 +0,0 @@
1
- ---
2
- name: code-review
3
- description: General code review discipline for reviewing a diff or commit range — correctness, design, readability, tests, and API surface, with severity-ranked, actionable findings. Use when asked to review code changes, a commit, a diff, or a PR for quality.
4
- ---
5
-
6
- # Code review
7
-
8
- Review the CHANGE, not the codebase. The standard (from Google's engineering
9
- practices): approve when the change **improves overall code health**, even if
10
- imperfect — demand blockers, suggest the rest.
11
-
12
- ## Pass order (read the diff twice)
13
-
14
- **Pass 1 — does it work?**
15
- - Correctness: logic errors, off-by-one, inverted conditions, wrong operator.
16
- - Edge cases: empty/null/undefined inputs, zero/negative counts, unicode,
17
- concurrent access, timeouts, partial failure mid-operation.
18
- - Error handling: swallowed exceptions, missing cleanup on the error path,
19
- errors that lie about the cause. Every catch must justify itself.
20
- - State: mutation of shared state, stale caches, ordering assumptions.
21
- - Resource lifecycle: files/handles/processes/listeners opened but not closed.
22
-
23
- **Pass 2 — should it be this way?**
24
- - Design: is this the simplest change that solves the problem? Flag
25
- speculative generality and dead configurability.
26
- - Consistency: does it follow the codebase's existing patterns, naming, and
27
- error conventions? (Local consistency beats personal preference.)
28
- - Readability: could a maintainer six months from now follow it without the
29
- PR description? Names carry meaning; comments explain WHY, not what.
30
- - API surface: new exports/flags/config keys are forever — are they earned?
31
- - Tests: does the change carry tests that would FAIL if the logic regressed?
32
- Tests that mirror the implementation instead of the behavior are findings.
33
- - Performance: only flag measurable problems (N+1, unbounded growth,
34
- sync-blocking hot paths) — not micro-optimizations.
35
-
36
- ## Reporting
37
-
38
- - Verdict: `APPROVE` / `APPROVE WITH NITS` / `NEEDS CHANGES`.
39
- - Each finding: `severity — file:line — what + why + concrete fix`.
40
- Severities: **blocker** (wrong/unsafe/regression), **important** (should
41
- fix before merge), **nit** (better, not required — prefix "Nit:").
42
- - Ask questions where intent is unclear instead of asserting a fault.
43
- - Do not pad: no restating the diff, no praise quotas, no style opinions a
44
- formatter could hold. If it's clean, say APPROVE and one line why.
@@ -1,59 +0,0 @@
1
- ---
2
- name: security-review
3
- description: Security-focused review of a diff or commit range — injection, secrets, trust boundaries, authz, unsafe deserialization, supply chain, and path/command safety, ranked by exploitability. Use when asked to security-review changes or as the second pass of a full review.
4
- ---
5
-
6
- # Security review
7
-
8
- Review the change as an attacker would read it: every new input is hostile,
9
- every boundary crossing is an opportunity. Grounded in the OWASP code-review
10
- model — findings ranked by exploitability, not by pattern-match count.
11
-
12
- ## Checklist by trust boundary
13
-
14
- **Inputs (anything the process didn't create itself)**
15
- - Command injection: user/config/network data reaching `exec`/`spawn`/shell
16
- strings. Quoting is not escaping; prefer argv arrays. Flag every
17
- interpolated shell string that carries external data.
18
- - Path traversal: joins with external segments (`../`), symlink following,
19
- zip-slip in extraction. Require canonicalize-then-prefix-check.
20
- - Injection into interpreters: SQL/NoSQL/LDAP/regex/eval/Function/template
21
- engines fed external strings.
22
- - Deserialization: YAML/JSON/pickle-style loads of untrusted bytes with
23
- type resolution or object construction.
24
- - SSRF: URLs from outside fetched by the server; check scheme/host pinning.
25
-
26
- **Secrets & data**
27
- - Hardcoded credentials, tokens, private keys — including in tests, fixtures,
28
- and example configs. Entropy-looking strings deserve a question.
29
- - Secrets in logs, error messages, process args (visible in `ps`), URLs.
30
- - New persistence of sensitive data: is it needed, is it protected, is it
31
- cleaned up on retire/delete paths?
32
-
33
- **AuthN/AuthZ**
34
- - New endpoints/commands/IPC surfaces: who can reach them, and what do they
35
- authorize against? "Bound to localhost" is a real but WEAK boundary — note
36
- what a local malicious process could do.
37
- - Privilege boundaries: does the change let low-trust config/data cause
38
- high-trust execution (hooks, plugins, migrations, CI)?
39
- - TOCTOU: check-then-use on files/permissions/state.
40
-
41
- **Supply chain & execution**
42
- - New dependencies: are they necessary, pinned, and from expected owners?
43
- - Downloaded/cloned artifacts: integrity-checked before execution?
44
- - Anything that writes then executes (temp scripts, curl|sh patterns).
45
-
46
- **Web-facing (when applicable)**
47
- - XSS: external strings reaching innerHTML/attributes without escaping.
48
- - CSRF on state-changing endpoints; CORS wildcards; missing content-type
49
- discipline on APIs.
50
-
51
- ## Reporting
52
-
53
- - Verdict shares the scale: `APPROVE` / `APPROVE WITH NITS` / `NEEDS CHANGES`
54
- — any credible injection/secret/authz finding is a **blocker**.
55
- - Each finding: `severity — file:line — attack scenario in one sentence +
56
- concrete fix`. If you cannot articulate the attack, downgrade to a
57
- question rather than inventing a threat.
58
- - Distinguish "exploitable now" from "hardening" — both are reportable,
59
- only the first blocks.