@open-agent-toolkit/cli 0.2.19 → 0.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/assets/config/dispatch-matrix-recommendation.json +15 -5
  2. package/assets/docs/cli-utilities/configuration.md +10 -5
  3. package/assets/docs/contributing/index.md +1 -0
  4. package/assets/docs/contributing/verifying-cursor-pins.md +282 -0
  5. package/assets/docs/workflows/projects/artifacts.md +1 -1
  6. package/assets/docs/workflows/projects/dispatch-ceiling.md +50 -4
  7. package/assets/docs/workflows/skills/explainer-kit.md +188 -23
  8. package/assets/docs/workflows/skills/index.md +1 -1
  9. package/assets/public-package-versions.json +4 -4
  10. package/assets/skills/explainer-kit/SKILL.md +87 -25
  11. package/assets/skills/explainer-kit/briefs/deep-dive.md +35 -0
  12. package/assets/skills/explainer-kit/briefs/engineer-tour.md +45 -0
  13. package/assets/skills/explainer-kit/briefs/program-recap.md +41 -0
  14. package/assets/skills/explainer-kit/briefs/project-explainer.md +38 -0
  15. package/assets/skills/explainer-kit/briefs/project-page.md +38 -0
  16. package/assets/skills/explainer-kit/briefs/project-recap.md +47 -0
  17. package/assets/skills/explainer-kit/briefs/supporting-diagram.md +28 -0
  18. package/assets/skills/explainer-kit/briefs/walkthrough-deck.md +35 -0
  19. package/assets/skills/explainer-kit/examples/project-recap/content.md +57 -14
  20. package/assets/skills/explainer-kit/examples/project-recap/fact-base.json +104 -0
  21. package/assets/skills/explainer-kit/examples/project-recap/fact-base.md +26 -4
  22. package/assets/skills/explainer-kit/recipes/engineer-tour.json +27 -10
  23. package/assets/skills/explainer-kit/recipes/program-recap.json +35 -11
  24. package/assets/skills/explainer-kit/recipes/project-explainer.json +27 -10
  25. package/assets/skills/explainer-kit/recipes/project-recap.json +43 -11
  26. package/assets/skills/explainer-kit/references/contracts.md +45 -19
  27. package/assets/skills/explainer-kit/schemas/author-request.v2.schema.json +41 -0
  28. package/assets/skills/explainer-kit/schemas/author-result.v2.schema.json +52 -0
  29. package/assets/skills/explainer-kit/scripts/lib/browser-runtime.mjs +442 -0
  30. package/assets/skills/explainer-kit/scripts/lib/content-approval.mjs +223 -10
  31. package/assets/skills/explainer-kit/scripts/lib/contracts.mjs +28 -43
  32. package/assets/skills/explainer-kit/scripts/lib/diagram.mjs +237 -0
  33. package/assets/skills/explainer-kit/scripts/lib/html-safety.mjs +680 -0
  34. package/assets/skills/explainer-kit/scripts/lib/markdown.mjs +414 -0
  35. package/assets/skills/explainer-kit/scripts/lib/qa.mjs +309 -10
  36. package/assets/skills/explainer-kit/scripts/lib/recipes.mjs +313 -41
  37. package/assets/skills/explainer-kit/scripts/lib/records.mjs +61 -0
  38. package/assets/skills/explainer-kit/scripts/lib/render.mjs +166 -12
  39. package/assets/skills/explainer-kit/scripts/render-qa.mjs +147 -2
  40. package/assets/skills/explainer-kit/scripts/run.mjs +796 -272
  41. package/assets/skills/explainer-kit/templates/deck-shell.html +25 -5
  42. package/assets/skills/explainer-kit/templates/diagram-shell.html +29 -7
  43. package/assets/skills/explainer-kit/templates/engineer-tour.html +133 -9
  44. package/assets/skills/explainer-kit/templates/house-style.html +82 -0
  45. package/assets/skills/oat-explainer-kit/SKILL.md +16 -9
  46. package/assets/skills/oat-explainer-kit/references/author-callback.md +51 -0
  47. package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +10 -8
  48. package/assets/skills/oat-explainer-kit/scripts/resolve-intent.mjs +14 -0
  49. package/assets/skills/oat-explainer-kit/scripts/run.mjs +7 -11
  50. package/assets/skills/oat-project-complete/SKILL.md +18 -2
  51. package/assets/skills/oat-project-implement/SKILL.md +1 -1
  52. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +7 -1
  53. package/assets/skills/oat-wave-execute/SKILL.md +12 -19
  54. package/assets/skills/oat-wave-program/SKILL.md +12 -13
  55. package/assets/skills/subagent-orchestration/SKILL.md +1 -1
  56. package/assets/skills/subagent-orchestration/references/evidence-and-refresh.md +153 -15
  57. package/assets/skills/subagent-orchestration/references/model-selection-principles.md +75 -3
  58. package/assets/skills/subagent-orchestration/references/provider-claude.md +95 -35
  59. package/assets/skills/subagent-orchestration/references/provider-codex.md +36 -10
  60. package/assets/skills/subagent-orchestration/references/provider-cursor.md +91 -15
  61. package/dist/providers/cursor/codec/catalog.d.ts +19 -1
  62. package/dist/providers/cursor/codec/catalog.d.ts.map +1 -1
  63. package/dist/providers/cursor/codec/catalog.js +54 -0
  64. package/package.json +2 -2
  65. package/assets/skills/explainer-kit/schemas/author-request.schema.json +0 -85
  66. package/assets/skills/explainer-kit/schemas/author-result.schema.json +0 -65
@@ -24,6 +24,7 @@
24
24
  --sans: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
25
25
  --serif: ui-serif, Georgia, serif;
26
26
  --mono: ui-monospace, SFMono-Regular, Consolas, monospace;
27
+ /* AUTHOR EXTENSION REGION: resolved theme tokens */
27
28
  {{THEME_CSS}}
28
29
  }
29
30
  * {
@@ -39,6 +40,9 @@
39
40
  color: var(--ink);
40
41
  font-family: var(--sans);
41
42
  }
43
+ noscript p {
44
+ color: var(--muted);
45
+ }
42
46
  .deck {
43
47
  display: flex;
44
48
  width: 100%;
@@ -197,16 +201,28 @@
197
201
  }
198
202
  </style>
199
203
  </head>
200
- <body>
204
+ <body data-explainer-shell="deck-shell">
201
205
  <noscript>
202
206
  <p>This deck remains available below as a readable vertical document.</p>
203
207
  </noscript>
204
- <main class="deck" aria-label="{{TITLE}}">{{SLIDES}}</main>
205
- <nav class="deck-controls" aria-label="Slide navigation">
208
+ <main class="deck" data-shell-anchor="deck" aria-label="{{TITLE}}">
209
+ <!-- AUTHOR EXTENSION REGION: semantic section.slide frames -->
210
+ {{SLIDES}}
211
+ <!-- END AUTHOR EXTENSION REGION -->
212
+ </main>
213
+ <nav
214
+ class="deck-controls"
215
+ data-shell-anchor="deck-controls"
216
+ aria-label="Slide navigation"
217
+ >
206
218
  <button type="button" data-direction="-1" aria-label="Previous slide">
207
219
 
208
220
  </button>
209
- <span id="deck-counter" aria-live="polite"></span>
221
+ <span
222
+ id="deck-counter"
223
+ data-shell-anchor="deck-counter"
224
+ aria-live="polite"
225
+ ></span>
210
226
  <button type="button" data-direction="1" aria-label="Next slide">
211
227
 
212
228
  </button>
@@ -214,11 +230,15 @@
214
230
  <div
215
231
  class="deck-progress"
216
232
  id="deck-progress"
233
+ data-shell-anchor="deck-progress"
217
234
  role="progressbar"
218
235
  aria-label="Slide progress"
219
236
  aria-valuemin="1"
220
237
  >
221
- <span class="deck-progress__bar"></span>
238
+ <span
239
+ class="deck-progress__bar"
240
+ data-shell-anchor="deck-progress-bar"
241
+ ></span>
222
242
  </div>
223
243
  <script>
224
244
  (() => {
@@ -20,6 +20,7 @@
20
20
  --accent: hsl(215 28% 32%);
21
21
  --sans: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
22
22
  --mono: ui-monospace, SFMono-Regular, Consolas, monospace;
23
+ /* AUTHOR EXTENSION REGION: resolved theme tokens */
23
24
  {{THEME_CSS}}
24
25
  }
25
26
  * {
@@ -125,35 +126,56 @@
125
126
  }
126
127
  </style>
127
128
  </head>
128
- <body>
129
+ <body data-explainer-shell="diagram-shell">
129
130
  <main>
130
131
  <header>
131
- <h1 id="diagram-title">{{TITLE}}</h1>
132
- <p id="diagram-description">{{DESCRIPTION}}</p>
132
+ <h1 id="diagram-title" data-shell-anchor="diagram-title">{{TITLE}}</h1>
133
+ <p id="diagram-description" data-shell-anchor="diagram-description">
134
+ {{DESCRIPTION}}
135
+ </p>
133
136
  </header>
134
- <section class="diagram-shell" aria-labelledby="diagram-title">
137
+ <section
138
+ class="diagram-shell"
139
+ data-shell-anchor="diagram-shell"
140
+ aria-labelledby="diagram-title"
141
+ >
135
142
  <p class="diagram-hint">
136
143
  Use the controls or Ctrl/Command + wheel to zoom; drag to pan.
137
144
  </p>
138
- <div class="zoom-controls" aria-label="Diagram zoom">
145
+ <div
146
+ class="zoom-controls"
147
+ data-shell-anchor="zoom-controls"
148
+ aria-label="Diagram zoom"
149
+ >
139
150
  <button type="button" data-zoom="in" aria-label="Zoom in">+</button>
140
151
  <button type="button" data-zoom="out" aria-label="Zoom out">−</button>
141
152
  <button type="button" data-zoom="reset" aria-label="Reset zoom">
142
153
 
143
154
  </button>
144
155
  </div>
145
- <div class="diagram-viewport">
156
+ <div class="diagram-viewport" data-shell-anchor="diagram-viewport">
146
157
  <svg
147
158
  class="diagram-canvas"
159
+ data-shell-anchor="diagram-canvas"
148
160
  viewBox="0 0 1200 720"
149
161
  role="img"
150
162
  aria-labelledby="diagram-title diagram-description"
151
163
  xmlns="http://www.w3.org/2000/svg"
152
164
  >
165
+ <!-- AUTHOR EXTENSION REGION: accessible inline SVG diagram -->
153
166
  {{DIAGRAM}}
167
+ <!-- END AUTHOR EXTENSION REGION -->
154
168
  </svg>
155
169
  </div>
156
- <div class="legend" aria-label="Diagram legend">{{LEGEND}}</div>
170
+ <div
171
+ class="legend"
172
+ data-shell-anchor="diagram-legend"
173
+ aria-label="Diagram legend"
174
+ >
175
+ <!-- AUTHOR EXTENSION REGION: optional visual legend -->
176
+ {{LEGEND}}
177
+ <!-- END AUTHOR EXTENSION REGION -->
178
+ </div>
157
179
  </section>
158
180
  </main>
159
181
  <script>
@@ -24,6 +24,7 @@
24
24
  --sans: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
25
25
  --serif: ui-serif, Georgia, serif;
26
26
  --mono: ui-monospace, SFMono-Regular, Consolas, monospace;
27
+ /* AUTHOR EXTENSION REGION: resolved theme tokens */
27
28
  {{THEME_CSS}}
28
29
  }
29
30
  * {
@@ -56,8 +57,7 @@
56
57
  padding-block: 2.5rem;
57
58
  }
58
59
  .toc-brand,
59
- .eyebrow,
60
- .section-number {
60
+ .eyebrow {
61
61
  color: var(--muted);
62
62
  font: 0.7rem/1.4 var(--mono);
63
63
  letter-spacing: 0.12em;
@@ -116,12 +116,105 @@
116
116
  max-width: 100%;
117
117
  margin: 0;
118
118
  overflow-x: auto;
119
+ border: 0;
120
+ border-radius: 0;
121
+ background: transparent;
119
122
  padding: 1rem;
120
123
  font-family: var(--mono);
121
124
  }
122
125
  .snippet:not(.open) pre {
123
126
  display: none;
124
127
  }
128
+ .diagram-scroll {
129
+ max-width: 100%;
130
+ overflow-x: auto;
131
+ }
132
+ .diagram-scroll > svg {
133
+ display: block;
134
+ }
135
+ /* Narrative renderer block output. The renderer emits these for any
136
+ markdown artifact, so the shell must style them or the structure
137
+ renders as unformatted text. */
138
+ .callout {
139
+ min-width: 0;
140
+ border: 1px solid var(--border);
141
+ border-inline-start: 0.25rem solid var(--accent);
142
+ border-radius: 0.6rem;
143
+ background: var(--panel);
144
+ padding: 1rem;
145
+ overflow-wrap: anywhere;
146
+ }
147
+ .callout--important {
148
+ border-inline-start-color: var(--success, var(--accent));
149
+ }
150
+ .callout--warning {
151
+ border-inline-start-color: var(--warning);
152
+ }
153
+ .callout--caution {
154
+ border-inline-start-color: var(--danger, var(--warning));
155
+ }
156
+ .callout__label {
157
+ color: var(--muted);
158
+ font: 0.72rem/1.4 var(--mono);
159
+ font-weight: 700;
160
+ letter-spacing: 0.08em;
161
+ text-transform: uppercase;
162
+ }
163
+ .timeline {
164
+ display: grid;
165
+ gap: 0.8rem;
166
+ padding-inline-start: 0;
167
+ list-style: none;
168
+ }
169
+ .timeline li {
170
+ display: grid;
171
+ grid-template-columns: minmax(7rem, 0.25fr) 1fr;
172
+ gap: 1rem;
173
+ border-inline-start: 0.2rem solid var(--accent);
174
+ padding-inline-start: 1rem;
175
+ }
176
+ .timeline time {
177
+ color: var(--muted);
178
+ font-family: var(--mono);
179
+ }
180
+ .table-scroll,
181
+ pre {
182
+ max-width: 100%;
183
+ overflow-x: auto;
184
+ }
185
+ table {
186
+ width: 100%;
187
+ border-collapse: collapse;
188
+ }
189
+ th,
190
+ td {
191
+ border-block-end: 1px solid var(--border);
192
+ padding: 0.6rem;
193
+ text-align: start;
194
+ }
195
+ pre {
196
+ border: 1px solid var(--border);
197
+ border-radius: 0.6rem;
198
+ background: var(--panel);
199
+ padding: 1rem;
200
+ font-family: var(--mono);
201
+ }
202
+ code {
203
+ font-family: var(--mono);
204
+ }
205
+ blockquote {
206
+ margin-inline: 0;
207
+ border-inline-start: 0.2rem solid var(--border);
208
+ color: var(--muted);
209
+ padding-inline-start: 1rem;
210
+ }
211
+ figure {
212
+ margin-inline: 0;
213
+ }
214
+ figcaption {
215
+ color: var(--muted);
216
+ font: 0.8rem/1.5 var(--mono);
217
+ }
125
218
  .diagram-rail {
126
219
  position: sticky;
127
220
  top: 0;
@@ -140,6 +233,19 @@
140
233
  width: 100%;
141
234
  height: auto;
142
235
  }
236
+ .diagram-card .node rect {
237
+ fill: var(--panel-muted);
238
+ stroke: var(--accent);
239
+ stroke-width: 1.5;
240
+ }
241
+ .diagram-card .edge {
242
+ fill: none;
243
+ stroke: var(--muted);
244
+ }
245
+ .diagram-card text {
246
+ fill: var(--ink);
247
+ font: 0.85rem var(--sans);
248
+ }
143
249
  .diagram-card .node,
144
250
  .diagram-card .edge {
145
251
  transition: opacity 180ms ease, stroke 180ms ease, fill 180ms ease;
@@ -199,25 +305,43 @@
199
305
  }
200
306
  </style>
201
307
  </head>
202
- <body>
203
- <div class="layout">
204
- <nav class="toc" aria-label="Tour sections">
308
+ <body data-explainer-shell="engineer-tour">
309
+ <div class="layout" data-shell-anchor="tour-layout">
310
+ <nav
311
+ class="toc"
312
+ data-shell-anchor="tour-navigation"
313
+ aria-label="Tour sections"
314
+ >
205
315
  <div class="toc-brand">{{EYEBROW}}</div>
316
+ <!-- AUTHOR EXTENSION REGION: section navigation -->
206
317
  {{NAVIGATION}}
318
+ <!-- END AUTHOR EXTENSION REGION -->
207
319
  </nav>
208
- <main class="tour-body">
320
+ <main class="tour-body" data-shell-anchor="tour-body">
209
321
  <header>
210
322
  <div class="eyebrow">{{EYEBROW}}</div>
211
323
  <h1>{{TITLE}}</h1>
212
324
  <p>{{DESCRIPTION}}</p>
213
325
  </header>
326
+ <!-- AUTHOR EXTENSION REGION: narrative tour sections -->
214
327
  {{CONTENT}}
215
- <footer>{{FOOTER}}</footer>
328
+ <!-- END AUTHOR EXTENSION REGION -->
329
+ <footer>
330
+ <!-- AUTHOR EXTENSION REGION: supporting references and next steps -->
331
+ {{FOOTER}}
332
+ <!-- END AUTHOR EXTENSION REGION -->
333
+ </footer>
216
334
  </main>
217
- <aside class="diagram-rail" aria-label="System diagram">
218
- <div class="diagram-card">
335
+ <aside
336
+ class="diagram-rail"
337
+ data-shell-anchor="diagram-rail"
338
+ aria-label="System diagram"
339
+ >
340
+ <div class="diagram-card" data-shell-anchor="diagram-card">
219
341
  <svg viewBox="0 0 360 540" role="img" aria-label="{{TITLE}}">
342
+ <!-- AUTHOR EXTENSION REGION: synchronized system diagram -->
220
343
  {{DIAGRAM}}
344
+ <!-- END AUTHOR EXTENSION REGION -->
221
345
  </svg>
222
346
  </div>
223
347
  </aside>
@@ -118,11 +118,76 @@
118
118
  .callout {
119
119
  border-inline-start: 0.25rem solid var(--accent);
120
120
  }
121
+ .callout--tip,
122
+ .callout--note {
123
+ border-inline-start-color: var(--accent);
124
+ }
125
+ .callout--important {
126
+ border-inline-start-color: var(--success);
127
+ }
128
+ .callout--warning {
129
+ border-inline-start-color: var(--warning);
130
+ }
131
+ .callout--caution {
132
+ border-inline-start-color: var(--danger);
133
+ }
134
+ .callout__label {
135
+ color: var(--muted);
136
+ font: 0.72rem/1.4 var(--mono);
137
+ font-weight: 700;
138
+ letter-spacing: 0.08em;
139
+ text-transform: uppercase;
140
+ }
141
+ blockquote {
142
+ margin-inline: 0;
143
+ border-inline-start: 0.2rem solid var(--border);
144
+ padding-inline-start: 1rem;
145
+ color: var(--muted);
146
+ }
147
+ .task-list {
148
+ padding-inline-start: 0;
149
+ list-style: none;
150
+ }
151
+ .task-list li {
152
+ display: flex;
153
+ align-items: baseline;
154
+ gap: 0.5rem;
155
+ }
156
+ .task-list li > p {
157
+ margin-block: 0.2rem;
158
+ }
159
+ .timeline {
160
+ display: grid;
161
+ gap: 0.8rem;
162
+ padding-inline-start: 0;
163
+ list-style: none;
164
+ }
165
+ .timeline li {
166
+ display: grid;
167
+ grid-template-columns: minmax(7rem, 0.25fr) 1fr;
168
+ gap: 1rem;
169
+ border-inline-start: 0.2rem solid var(--accent);
170
+ padding-inline-start: 1rem;
171
+ }
172
+ .timeline time {
173
+ color: var(--muted);
174
+ font-family: var(--mono);
175
+ }
121
176
  .table-scroll,
177
+ .diagram-scroll,
122
178
  pre {
123
179
  max-width: 100%;
124
180
  overflow-x: auto;
125
181
  }
182
+ .diagram-scroll > svg {
183
+ display: block;
184
+ }
185
+ pre {
186
+ border: 1px solid var(--border);
187
+ border-radius: var(--radius);
188
+ background: var(--panel-muted);
189
+ padding: 1rem;
190
+ }
126
191
  table {
127
192
  width: 100%;
128
193
  border-collapse: collapse;
@@ -137,6 +202,23 @@
137
202
  pre {
138
203
  font-family: var(--mono);
139
204
  }
205
+ :not(pre) > code {
206
+ border-radius: calc(var(--radius) / 2);
207
+ background: var(--panel-muted);
208
+ padding: 0.1em 0.3em;
209
+ }
210
+ figure {
211
+ margin-inline: 0;
212
+ border: 1px solid var(--border);
213
+ border-radius: var(--radius);
214
+ background: var(--panel);
215
+ padding: 1rem;
216
+ }
217
+ figcaption {
218
+ margin-block-start: 0.5rem;
219
+ color: var(--muted);
220
+ font-size: 0.9rem;
221
+ }
140
222
  footer {
141
223
  border-block-start: 1px solid var(--border);
142
224
  color: var(--muted);
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-explainer-kit
3
- version: 1.0.1
3
+ version: 1.0.2
4
4
  description: Use when building project explainers or recaps from OAT configuration, state, and lifecycle artifacts.
5
5
  disable-model-invocation: false
6
6
  user-invocable: true
@@ -19,6 +19,7 @@ Adapt OAT project context into the versioned request consumed by the canonical
19
19
  - Derive canonical project or repository output roots.
20
20
  - Bind OAT lifecycle artifacts to generic recipe source roles.
21
21
  - Resolve project explainer and recap intent before invoking the core.
22
+ - Require lifecycle callers to construct a brief-aware author seam.
22
23
 
23
24
  ## Dependency Direction
24
25
 
@@ -33,7 +34,7 @@ rollback, and operator-owned real-wrapper gate, use `references/migration.md`.
33
34
 
34
35
  Before reading OAT config or invoking the core, call
35
36
  `scripts/check-core.mjs#checkCoreCompatibility` with this installed skill
36
- directory and minimum core version `1.0.0`. Continue only when it returns
37
+ directory and minimum core version `2.0.0`. Continue only when it returns
37
38
  `ok: true`.
38
39
 
39
40
  - Missing core: stop and show
@@ -54,7 +55,7 @@ Call `scripts/run.mjs#runOatExplainer` with the repository root, project
54
55
  invocation, active project path, recipe, slug, lifecycle mode, and any explicit
55
56
  runtime overrides. The adapter:
56
57
 
57
- 1. checks the user-scoped installed core at minimum version `1.0.0`;
58
+ 1. checks the user-scoped installed core at minimum version `2.0.0`;
58
59
  2. resolves only the public `explainers.*` and `workflow.explainers.*` keys;
59
60
  3. derives the canonical project output root;
60
61
  4. binds approved OAT artifacts to the recipe's single `project` source set;
@@ -68,13 +69,19 @@ Missing optional artifacts are omitted, but at least one approved lifecycle
68
69
  artifact is required. An explicit supplied fact-base path bypasses artifact
69
70
  federation and is passed through as `factBase.mode: supplied`.
70
71
 
72
+ Before invocation, read `references/author-callback.md` and construct exactly
73
+ one provider-neutral author seam in both modes: in-process callers supply
74
+ `author`, while JSON/CLI callers supply `authorModulePath` naming a module with
75
+ an `author` function export. The callback consumes `author-request/v2` with the
76
+ recipe brief and fact base inlined, plus theme and any recipe-selected artistic
77
+ shell. It may propose expansion only through recipe profile IDs. The adapter
78
+ validates and resolves that executable input before passing it to
79
+ `core.runExplainer`; callbacks and module paths never enter the persisted run
80
+ request.
81
+
71
82
  Unattended project runs pass `approved-oat-artifacts` provenance to the core's
72
- content-approval seam and never prompt. Every unattended run also requires
73
- exactly one provider-neutral author seam: in-process callers supply `author`,
74
- while JSON/CLI callers supply `authorModulePath` naming a module with an
75
- `author` function export. The adapter validates and resolves that executable
76
- input before passing it to `core.runExplainer`; callbacks and module paths never
77
- enter the persisted run request.
83
+ content-approval seam and never prompt. Automated completion and
84
+ implementation-tail recaps always use `mode: unattended`.
78
85
 
79
86
  Federated runs still require an explicit provider-neutral critic callback.
80
87
  In-process callers may supply `critic` (or `coreOptions.critic` for
@@ -0,0 +1,51 @@
1
+ # Author callback contract
2
+
3
+ Lifecycle callers own the executable author seam; the explainer core owns
4
+ construction of each author request. In-process callers pass an `author`
5
+ callback to `runOatExplainer`. JSON-only and official CLI callers pass
6
+ `authorModulePath`, which must name a module with an `author` function export.
7
+ Provide exactly one of those inputs in both interactive and unattended modes.
8
+ The callback or module may use any provider, but its request and result remain
9
+ provider-neutral.
10
+
11
+ ## Request handling
12
+
13
+ The callback receives one `explainer-kit.author-request/v2` per artifact. The
14
+ core constructs that request from recipe-owned policy:
15
+
16
+ - `brief` contains the prose loaded from the floor entry or expansion profile's
17
+ `briefRef`; the author must treat the inlined brief as its editorial contract.
18
+ - `factBase` contains the reconciled evidence for the run. Ground claims in that
19
+ fact base and do not replace it with ambient project context.
20
+ - `authoring` selects the output path. Return Markdown for `markdown` and a
21
+ complete HTML document for `html`.
22
+ - `theme` is attached to every request. HTML requests also carry the
23
+ recipe-selected `shell`; use it as the starting canvas while following the
24
+ brief's license to elaborate.
25
+ - A floor request may include `floor.requiredNarrative`, which identifies the
26
+ narrative coverage checked later as non-blocking guidelines.
27
+
28
+ Return one matching `explainer-kit.author-result/v2`: preserve `artifactId`,
29
+ set exactly one of `content.markdown` or `content.html`, and include
30
+ `provenance`. Do not persist provider credentials or callback configuration in
31
+ the result.
32
+
33
+ ## Expansion
34
+
35
+ Only a floor result may propose expansion. Put each proposal in
36
+ `proposedArtifacts` as `{id, profileId, rationale}`. Do not choose an artifact
37
+ type, authoring mode, brief, or shell in the proposal; the referenced recipe
38
+ profile, selected by `profileId`, owns those values.
39
+
40
+ The core validates proposal IDs, profile membership, collisions, and finite
41
+ caps. It rejects malformed proposals, records over-limit proposals as warnings,
42
+ and issues a new author request for every accepted artifact. Handle each
43
+ follow-up request independently and do not recursively propose more artifacts.
44
+
45
+ ## Lifecycle invocation
46
+
47
+ Automated project-completion and implementation-tail recaps always call
48
+ `runOatExplainer` with `mode: unattended`. They construct the author seam before
49
+ invocation and supply it alongside the existing provider-neutral `critic` or
50
+ validated `criticModulePath`. Interactive invocations use the same author
51
+ contract; only the later approval behavior differs.
@@ -71,18 +71,20 @@ On a stale-write conflict, the caller must re-read state, resolve precedence
71
71
  again, and decide whether a write is still required. It must not retry the old
72
72
  record blindly.
73
73
 
74
- ## Unattended author execution
74
+ ## Author execution
75
75
 
76
- Every unattended adapter run must provide exactly one provider-neutral author
77
- seam. In-process callers pass `author`; JSON-only and official CLI callers put
78
- `authorModulePath` in the adapter context, naming a module whose `author` export
79
- is a function. Missing module files, invalid exports, and direct-plus-module
80
- conflicts fail at the adapter boundary.
76
+ Every adapter run in both interactive and unattended modes must provide exactly
77
+ one provider-neutral author seam. In-process callers pass `author`; JSON-only
78
+ and official CLI callers put `authorModulePath` in the adapter context, naming
79
+ a module whose `author` export is a function. Missing module files, invalid
80
+ exports, and direct-plus-module conflicts fail at the adapter boundary. See
81
+ `author-callback.md` for brief, fact-base, shell, theme, result, and expansion
82
+ handling.
81
83
 
82
84
  The resolved callback is passed only as the `author` option to
83
85
  `core.runExplainer`. It is never copied into `ExplainerRunRequestV1`,
84
- `run-request.json`, or another retained data contract. Interactive runs may
85
- omit an author and retain their existing reviewed-source path.
86
+ `run-request.json`, or another retained data contract. Interactive runs use the
87
+ same author contract and differ only at the later approval gate.
86
88
 
87
89
  ## Tracked-run finalization
88
90
 
@@ -130,6 +130,20 @@ export function validateIntentRecord(product, record) {
130
130
  return record;
131
131
  }
132
132
 
133
+ export function explainerModeForIntent(intent) {
134
+ if (
135
+ !intent ||
136
+ typeof intent !== 'object' ||
137
+ intent.product !== 'projectRecap' ||
138
+ intent.decision !== 'generate'
139
+ ) {
140
+ throw new Error(
141
+ 'Only a generated projectRecap intent can select completion-chain explainer mode.',
142
+ );
143
+ }
144
+ return 'unattended';
145
+ }
146
+
133
147
  function resolveAutonomous({
134
148
  product,
135
149
  state,
@@ -12,7 +12,7 @@ import {
12
12
  } from './resolve-config.mjs';
13
13
  import { resolveExplainerOutputRoot } from './resolve-paths.mjs';
14
14
 
15
- const MINIMUM_CORE_VERSION = '1.0.0';
15
+ const MINIMUM_CORE_VERSION = '2.0.0';
16
16
  const ADAPTER_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
17
17
 
18
18
  export async function runOatExplainer({
@@ -114,7 +114,6 @@ export async function runOatExplainer({
114
114
  author,
115
115
  authorModulePath,
116
116
  coreOptions,
117
- mode: request.mode,
118
117
  });
119
118
  const lifecycleCritic = await resolveLifecycleCritic({
120
119
  critic,
@@ -141,6 +140,7 @@ export async function runOatExplainer({
141
140
  request,
142
141
  manifest,
143
142
  result,
143
+ marking: result.marking ?? null,
144
144
  outputRoot,
145
145
  };
146
146
  }
@@ -149,7 +149,6 @@ async function resolveLifecycleAuthor({
149
149
  author,
150
150
  authorModulePath,
151
151
  coreOptions,
152
- mode,
153
152
  }) {
154
153
  if (coreOptions?.author !== undefined) {
155
154
  throw new TypeError(
@@ -166,14 +165,11 @@ async function resolveLifecycleAuthor({
166
165
  }
167
166
 
168
167
  if (author === undefined && authorModulePath === undefined) {
169
- if (mode === 'unattended') {
170
- const error = new Error(
171
- 'Unattended OAT explainer runs require exactly one provider-neutral author callback or author module entry point.',
172
- );
173
- error.code = 'E_AUTHOR_REQUIRED';
174
- throw error;
175
- }
176
- return null;
168
+ const error = new Error(
169
+ 'Unattended and interactive OAT explainer runs require exactly one provider-neutral author callback or author module entry point.',
170
+ );
171
+ error.code = 'E_AUTHOR_REQUIRED';
172
+ throw error;
177
173
  }
178
174
  if (authorModulePath === undefined) {
179
175
  return author;
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-complete
3
- version: 1.5.4
3
+ version: 1.6.0
4
4
  description: Use when all implementation work is finished and the project is ready to close. Marks the OAT project lifecycle as complete.
5
5
  disable-model-invocation: true
6
6
  user-invocable: true
@@ -282,7 +282,23 @@ When `SHOULD_GENERATE_RECAP="true"`, inspect manifests under
282
282
  `{PROJECT_PATH}/explainers/` before generating. A fresh `project-recap` manifest for the current completed implementation is reused without invoking the adapter again. Fresh means the manifest identifies recipe `project-recap`, belongs to this project, has a terminal outcome, and its recorded source hashes match the current approved implementation inputs, including the refreshed summary when present.
283
283
 
284
284
  If no fresh recap exists, invoke `scripts/run.mjs#runOatExplainer` exactly once with recipe `project-recap`, project invocation, the active project, and unattended lifecycle mode so approved OAT artifacts do not trigger a second content prompt. A failed adapter run warns but does not block completion. Use a returned valid terminal `project-recap` manifest as the selected run; do not rerun to improve its outcome.
285
- Supply the provider-neutral critic callback (or validated critic module entry point for JSON/CLI invocation) on every federated adapter run.
285
+ Before that invocation, construct exactly one brief-aware, provider-neutral
286
+ author seam as documented by
287
+ `oat-explainer-kit/references/author-callback.md`. In-process callers pass
288
+ `author`; JSON/CLI callers pass a validated `authorModulePath`. Supply it
289
+ alongside the existing `critic` callback (or validated
290
+ `criticModulePath`), and invoke the recap with `mode: unattended`.
291
+
292
+ The author seam is the recap's quality mechanism, so derive its output from the
293
+ request rather than from ambient context or a stock recap shape. Cover every
294
+ `floor.requiredNarrative` section, ground each claim in the supplied `factBase`,
295
+ and follow the inlined `brief` for structure — evidence tables for the
296
+ implementation and validation sections, at least one high-level architecture
297
+ diagram, and lists where material is enumerable. A recap whose warnings include
298
+ `guideline-narrative-coverage-missing`, `guideline-structured-depth-missing`, or
299
+ `guideline-architecture-diagram-missing` is thin: it still completes, but treat
300
+ those warnings as the signal that the authored content did not use the evidence
301
+ it was given.
286
302
 
287
303
  Set `SELECTED_PROJECT_RECAP_RUN` only to the final selected `project-recap` run. The value must be project-relative in the form `explainers/<run-slug>` so it can be passed safely to the archive CLI. An incomplete, stale, wrong-project, or `project-explainer` manifest is never selected as the final recap.
288
304