@open-agent-toolkit/cli 0.2.9 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/docs/cli-utilities/configuration.md +28 -14
- package/assets/docs/reference/cli-reference.md +1 -1
- package/assets/docs/workflows/projects/artifacts.md +16 -4
- package/assets/docs/workflows/skills/explainer-kit.md +70 -27
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/explainer-kit/SKILL.md +9 -3
- package/assets/skills/explainer-kit/references/contracts.md +22 -7
- package/assets/skills/explainer-kit/schemas/author-request.schema.json +85 -0
- package/assets/skills/explainer-kit/schemas/author-result.schema.json +65 -0
- package/assets/skills/explainer-kit/schemas/manifest.schema.json +7 -1
- package/assets/skills/explainer-kit/schemas/run-request.schema.json +8 -0
- package/assets/skills/explainer-kit/schemas/theme.schema.json +8 -0
- package/assets/skills/explainer-kit/scripts/lib/content-approval.mjs +26 -1
- package/assets/skills/explainer-kit/scripts/lib/contracts.mjs +61 -0
- package/assets/skills/explainer-kit/scripts/lib/durability.mjs +2 -14
- package/assets/skills/explainer-kit/scripts/lib/qa.mjs +56 -0
- package/assets/skills/explainer-kit/scripts/lib/theme.mjs +102 -4
- package/assets/skills/explainer-kit/scripts/run.mjs +144 -11
- package/assets/skills/explainer-kit/styles/business-corporate.json +77 -0
- package/assets/skills/explainer-kit/styles/clean-neutral.json +77 -0
- package/assets/skills/explainer-kit/styles/dark-edgy.json +77 -0
- package/assets/skills/explainer-kit/styles/navy-ocean.json +82 -0
- package/assets/skills/explainer-kit/templates/deck-shell.html +57 -2
- package/assets/skills/oat-explainer-kit/SKILL.md +15 -9
- package/assets/skills/oat-explainer-kit/references/config-contract.md +11 -6
- package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +13 -0
- package/assets/skills/oat-explainer-kit/scripts/finalize-tracked-run.mjs +10 -14
- package/assets/skills/oat-explainer-kit/scripts/resolve-config.mjs +53 -9
- package/assets/skills/oat-explainer-kit/scripts/run.mjs +68 -0
- package/dist/app/global-cli-installer.d.ts +16 -0
- package/dist/app/global-cli-installer.d.ts.map +1 -0
- package/dist/app/global-cli-installer.js +111 -0
- package/dist/app/tool-bundle-update-guard.d.ts.map +1 -1
- package/dist/app/tool-bundle-update-guard.js +10 -22
- package/dist/app/update-notifier.d.ts.map +1 -1
- package/dist/app/update-notifier.js +4 -3
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +34 -8
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +14 -5
- package/dist/config/oat-config.d.ts +2 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +11 -0
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +3 -2
- package/dist/providers/codex/codec/config-merge.d.ts.map +1 -1
- package/dist/providers/codex/codec/config-merge.js +39 -1
- package/package.json +2 -2
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "clean-neutral",
|
|
3
|
+
"defaultMode": "light",
|
|
4
|
+
"modes": {
|
|
5
|
+
"light": {
|
|
6
|
+
"surface": {
|
|
7
|
+
"canvas": "#f4f6f9",
|
|
8
|
+
"panel": "#ffffff",
|
|
9
|
+
"elevated": "#eef1f5"
|
|
10
|
+
},
|
|
11
|
+
"ink": { "primary": "#16202e", "muted": "#4a5568", "inverse": "#ffffff" },
|
|
12
|
+
"accent": { "primary": "#2f56c9", "secondary": "#0e7180" },
|
|
13
|
+
"status": {
|
|
14
|
+
"success": "#157a54",
|
|
15
|
+
"warning": "#965108",
|
|
16
|
+
"danger": "#bd3a2c",
|
|
17
|
+
"info": "#2f56c9"
|
|
18
|
+
},
|
|
19
|
+
"diagramSeries": ["#2f56c9", "#965108", "#0e7180", "#6a4fc4"]
|
|
20
|
+
},
|
|
21
|
+
"dark": {
|
|
22
|
+
"surface": {
|
|
23
|
+
"canvas": "#111827",
|
|
24
|
+
"panel": "#1f2937",
|
|
25
|
+
"elevated": "#374151"
|
|
26
|
+
},
|
|
27
|
+
"ink": { "primary": "#f9fafb", "muted": "#d1d5db", "inverse": "#111827" },
|
|
28
|
+
"accent": { "primary": "#93c5fd", "secondary": "#5eead4" },
|
|
29
|
+
"status": {
|
|
30
|
+
"success": "#86efac",
|
|
31
|
+
"warning": "#fde047",
|
|
32
|
+
"danger": "#fca5a5",
|
|
33
|
+
"info": "#93c5fd"
|
|
34
|
+
},
|
|
35
|
+
"diagramSeries": ["#93c5fd", "#fde047", "#5eead4", "#c4b5fd"]
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"typography": {
|
|
39
|
+
"sans": ["system-ui", "-apple-system", "BlinkMacSystemFont", "sans-serif"],
|
|
40
|
+
"serif": ["ui-serif", "Georgia", "serif"],
|
|
41
|
+
"mono": ["ui-monospace", "SFMono-Regular", "Consolas", "monospace"],
|
|
42
|
+
"scale": {
|
|
43
|
+
"caption": "0.875rem",
|
|
44
|
+
"body": "1rem",
|
|
45
|
+
"title": "1.5rem",
|
|
46
|
+
"display": "2.25rem"
|
|
47
|
+
},
|
|
48
|
+
"lineHeight": { "caption": 1.4, "body": 1.6, "title": 1.25, "display": 1.1 }
|
|
49
|
+
},
|
|
50
|
+
"spacing": {
|
|
51
|
+
"unit": 4,
|
|
52
|
+
"scale": { "xs": 4, "sm": 8, "md": 16, "lg": 24, "xl": 40 }
|
|
53
|
+
},
|
|
54
|
+
"geometry": { "radius": { "sm": 4, "md": 8, "lg": 12 }, "borderWidth": 1 },
|
|
55
|
+
"elevation": {
|
|
56
|
+
"shadows": {
|
|
57
|
+
"low": "0 1px 2px rgb(22 32 46 / 0.08)",
|
|
58
|
+
"high": "0 12px 28px rgb(22 32 46 / 0.16)"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"density": "comfortable",
|
|
62
|
+
"motion": {
|
|
63
|
+
"enabled": true,
|
|
64
|
+
"durationMs": { "fast": 120, "normal": 200, "slow": 320 },
|
|
65
|
+
"easing": {
|
|
66
|
+
"standard": "ease",
|
|
67
|
+
"emphasized": "cubic-bezier(0.2, 0, 0, 1)"
|
|
68
|
+
},
|
|
69
|
+
"reducedMotion": "disable-nonessential"
|
|
70
|
+
},
|
|
71
|
+
"diagrams": {
|
|
72
|
+
"lineWidth": 2,
|
|
73
|
+
"nodeGap": 32,
|
|
74
|
+
"arrowStyle": "straight",
|
|
75
|
+
"labelTreatment": "boxed"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dark-edgy",
|
|
3
|
+
"defaultMode": "dark",
|
|
4
|
+
"modes": {
|
|
5
|
+
"light": {
|
|
6
|
+
"surface": {
|
|
7
|
+
"canvas": "#f3f5f7",
|
|
8
|
+
"panel": "#ffffff",
|
|
9
|
+
"elevated": "#e6eaee"
|
|
10
|
+
},
|
|
11
|
+
"ink": { "primary": "#17202b", "muted": "#4f5c6d", "inverse": "#0d1117" },
|
|
12
|
+
"accent": { "primary": "#4eb4b9", "secondary": "#4f91ad" },
|
|
13
|
+
"status": {
|
|
14
|
+
"success": "#9fd68a",
|
|
15
|
+
"warning": "#f0b878",
|
|
16
|
+
"danger": "#ff9aa2",
|
|
17
|
+
"info": "#7ddce0"
|
|
18
|
+
},
|
|
19
|
+
"diagramSeries": ["#397a98", "#8d591d", "#4e872f", "#7654a8"]
|
|
20
|
+
},
|
|
21
|
+
"dark": {
|
|
22
|
+
"surface": {
|
|
23
|
+
"canvas": "#0d1117",
|
|
24
|
+
"panel": "#161b22",
|
|
25
|
+
"elevated": "#1c232c"
|
|
26
|
+
},
|
|
27
|
+
"ink": { "primary": "#d9e0e8", "muted": "#aeb8c7", "inverse": "#0d1117" },
|
|
28
|
+
"accent": { "primary": "#7ddce0", "secondary": "#6fb7d8" },
|
|
29
|
+
"status": {
|
|
30
|
+
"success": "#9fd68a",
|
|
31
|
+
"warning": "#f0b878",
|
|
32
|
+
"danger": "#ff9aa2",
|
|
33
|
+
"info": "#7ddce0"
|
|
34
|
+
},
|
|
35
|
+
"diagramSeries": ["#7ddce0", "#f0b878", "#6fb7d8", "#c4a4f0"]
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"typography": {
|
|
39
|
+
"sans": ["system-ui", "-apple-system", "BlinkMacSystemFont", "sans-serif"],
|
|
40
|
+
"serif": ["ui-serif", "Georgia", "serif"],
|
|
41
|
+
"mono": ["ui-monospace", "SFMono-Regular", "Consolas", "monospace"],
|
|
42
|
+
"scale": {
|
|
43
|
+
"caption": "0.8125rem",
|
|
44
|
+
"body": "0.9375rem",
|
|
45
|
+
"title": "1.375rem",
|
|
46
|
+
"display": "2rem"
|
|
47
|
+
},
|
|
48
|
+
"lineHeight": { "caption": 1.35, "body": 1.5, "title": 1.2, "display": 1.1 }
|
|
49
|
+
},
|
|
50
|
+
"spacing": {
|
|
51
|
+
"unit": 3,
|
|
52
|
+
"scale": { "xs": 3, "sm": 6, "md": 12, "lg": 18, "xl": 30 }
|
|
53
|
+
},
|
|
54
|
+
"geometry": { "radius": { "sm": 2, "md": 4, "lg": 8 }, "borderWidth": 1 },
|
|
55
|
+
"elevation": {
|
|
56
|
+
"shadows": {
|
|
57
|
+
"low": "0 1px 2px rgb(0 0 0 / 0.22)",
|
|
58
|
+
"high": "0 12px 30px rgb(0 0 0 / 0.38)"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"density": "compact",
|
|
62
|
+
"motion": {
|
|
63
|
+
"enabled": true,
|
|
64
|
+
"durationMs": { "fast": 100, "normal": 180, "slow": 280 },
|
|
65
|
+
"easing": {
|
|
66
|
+
"standard": "ease",
|
|
67
|
+
"emphasized": "cubic-bezier(0.2, 0.8, 0.2, 1)"
|
|
68
|
+
},
|
|
69
|
+
"reducedMotion": "disable-nonessential"
|
|
70
|
+
},
|
|
71
|
+
"diagrams": {
|
|
72
|
+
"lineWidth": 2,
|
|
73
|
+
"nodeGap": 24,
|
|
74
|
+
"arrowStyle": "straight",
|
|
75
|
+
"labelTreatment": "boxed"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "navy-ocean",
|
|
3
|
+
"defaultMode": "dark",
|
|
4
|
+
"modes": {
|
|
5
|
+
"light": {
|
|
6
|
+
"surface": {
|
|
7
|
+
"canvas": "#f4f7fb",
|
|
8
|
+
"panel": "#ffffff",
|
|
9
|
+
"elevated": "#e5ebf3"
|
|
10
|
+
},
|
|
11
|
+
"ink": { "primary": "#142033", "muted": "#46566d", "inverse": "#ffffff" },
|
|
12
|
+
"accent": { "primary": "#2867a8", "secondary": "#177583" },
|
|
13
|
+
"status": {
|
|
14
|
+
"success": "#187452",
|
|
15
|
+
"warning": "#92500b",
|
|
16
|
+
"danger": "#b83c32",
|
|
17
|
+
"info": "#2867a8"
|
|
18
|
+
},
|
|
19
|
+
"diagramSeries": ["#2867a8", "#92500b", "#177583", "#694eb5"]
|
|
20
|
+
},
|
|
21
|
+
"dark": {
|
|
22
|
+
"surface": {
|
|
23
|
+
"canvas": "#0e1420",
|
|
24
|
+
"panel": "#161d2b",
|
|
25
|
+
"elevated": "#1e2635"
|
|
26
|
+
},
|
|
27
|
+
"ink": { "primary": "#e7ecf3", "muted": "#aeb9c8", "inverse": "#0e1420" },
|
|
28
|
+
"accent": { "primary": "#77abec", "secondary": "#4cb8c4" },
|
|
29
|
+
"status": {
|
|
30
|
+
"success": "#5cc79a",
|
|
31
|
+
"warning": "#e3a54e",
|
|
32
|
+
"danger": "#e2857a",
|
|
33
|
+
"info": "#77abec"
|
|
34
|
+
},
|
|
35
|
+
"diagramSeries": ["#77abec", "#e3a54e", "#4cb8c4", "#a98fe0"]
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"typography": {
|
|
39
|
+
"sans": ["system-ui", "-apple-system", "BlinkMacSystemFont", "sans-serif"],
|
|
40
|
+
"serif": ["Charter", "Bitstream Charter", "Georgia", "serif"],
|
|
41
|
+
"mono": ["ui-monospace", "SFMono-Regular", "Consolas", "monospace"],
|
|
42
|
+
"scale": {
|
|
43
|
+
"caption": "0.875rem",
|
|
44
|
+
"body": "1.0625rem",
|
|
45
|
+
"title": "1.75rem",
|
|
46
|
+
"display": "2.75rem"
|
|
47
|
+
},
|
|
48
|
+
"lineHeight": {
|
|
49
|
+
"caption": 1.45,
|
|
50
|
+
"body": 1.65,
|
|
51
|
+
"title": 1.18,
|
|
52
|
+
"display": 1.05
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"spacing": {
|
|
56
|
+
"unit": 5,
|
|
57
|
+
"scale": { "xs": 5, "sm": 10, "md": 20, "lg": 30, "xl": 48 }
|
|
58
|
+
},
|
|
59
|
+
"geometry": { "radius": { "sm": 4, "md": 8, "lg": 12 }, "borderWidth": 1 },
|
|
60
|
+
"elevation": {
|
|
61
|
+
"shadows": {
|
|
62
|
+
"low": "0 1px 3px rgb(0 0 0 / 0.18)",
|
|
63
|
+
"high": "0 16px 36px rgb(0 0 0 / 0.28)"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"density": "comfortable",
|
|
67
|
+
"motion": {
|
|
68
|
+
"enabled": true,
|
|
69
|
+
"durationMs": { "fast": 140, "normal": 240, "slow": 380 },
|
|
70
|
+
"easing": {
|
|
71
|
+
"standard": "ease-out",
|
|
72
|
+
"emphasized": "cubic-bezier(0.16, 1, 0.3, 1)"
|
|
73
|
+
},
|
|
74
|
+
"reducedMotion": "disable-nonessential"
|
|
75
|
+
},
|
|
76
|
+
"diagrams": {
|
|
77
|
+
"lineWidth": 2,
|
|
78
|
+
"nodeGap": 36,
|
|
79
|
+
"arrowStyle": "curved",
|
|
80
|
+
"labelTreatment": "boxed"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -118,6 +118,20 @@
|
|
|
118
118
|
outline: 2px solid var(--accent);
|
|
119
119
|
outline-offset: 2px;
|
|
120
120
|
}
|
|
121
|
+
.deck-progress {
|
|
122
|
+
position: fixed;
|
|
123
|
+
z-index: 4;
|
|
124
|
+
inset: auto 0 0;
|
|
125
|
+
height: 0.25rem;
|
|
126
|
+
background: var(--panel);
|
|
127
|
+
}
|
|
128
|
+
.deck-progress__bar {
|
|
129
|
+
display: block;
|
|
130
|
+
width: 0;
|
|
131
|
+
height: 100%;
|
|
132
|
+
background: var(--accent);
|
|
133
|
+
transition: width 180ms ease;
|
|
134
|
+
}
|
|
121
135
|
html:not(.js) .deck {
|
|
122
136
|
display: block;
|
|
123
137
|
height: auto;
|
|
@@ -139,6 +153,17 @@
|
|
|
139
153
|
.deck {
|
|
140
154
|
scroll-behavior: auto;
|
|
141
155
|
}
|
|
156
|
+
.deck-progress__bar {
|
|
157
|
+
transition: none;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
@media (max-height: 42rem) {
|
|
161
|
+
.slide {
|
|
162
|
+
padding-block: 1.5rem 4rem;
|
|
163
|
+
}
|
|
164
|
+
.slide__content {
|
|
165
|
+
overflow-y: auto;
|
|
166
|
+
}
|
|
142
167
|
}
|
|
143
168
|
@media print {
|
|
144
169
|
.deck {
|
|
@@ -166,6 +191,9 @@
|
|
|
166
191
|
.deck-controls {
|
|
167
192
|
display: none;
|
|
168
193
|
}
|
|
194
|
+
.deck-progress {
|
|
195
|
+
display: none;
|
|
196
|
+
}
|
|
169
197
|
}
|
|
170
198
|
</style>
|
|
171
199
|
</head>
|
|
@@ -183,21 +211,43 @@
|
|
|
183
211
|
→
|
|
184
212
|
</button>
|
|
185
213
|
</nav>
|
|
214
|
+
<div
|
|
215
|
+
class="deck-progress"
|
|
216
|
+
id="deck-progress"
|
|
217
|
+
role="progressbar"
|
|
218
|
+
aria-label="Slide progress"
|
|
219
|
+
aria-valuemin="1"
|
|
220
|
+
>
|
|
221
|
+
<span class="deck-progress__bar"></span>
|
|
222
|
+
</div>
|
|
186
223
|
<script>
|
|
187
224
|
(() => {
|
|
188
225
|
const deck = document.querySelector('.deck');
|
|
189
226
|
const slides = [...document.querySelectorAll('.slide')];
|
|
190
227
|
const counter = document.querySelector('#deck-counter');
|
|
228
|
+
const progress = document.querySelector('#deck-progress');
|
|
229
|
+
const progressBar = progress.querySelector('.deck-progress__bar');
|
|
230
|
+
const previous = document.querySelector('[data-direction="-1"]');
|
|
231
|
+
const next = document.querySelector('[data-direction="1"]');
|
|
232
|
+
const reducedMotion = matchMedia(
|
|
233
|
+
'(prefers-reduced-motion: reduce)',
|
|
234
|
+
).matches;
|
|
191
235
|
let current = 0;
|
|
192
236
|
|
|
193
237
|
const update = (index) => {
|
|
194
238
|
current = Math.max(0, Math.min(slides.length - 1, index));
|
|
195
239
|
counter.textContent = `${current + 1} / ${slides.length}`;
|
|
240
|
+
progress.setAttribute('aria-valuemax', String(slides.length));
|
|
241
|
+
progress.setAttribute('aria-valuenow', String(current + 1));
|
|
242
|
+
progressBar.style.width = `${((current + 1) / slides.length) * 100}%`;
|
|
243
|
+
previous.disabled = current === 0;
|
|
244
|
+
next.disabled = current === slides.length - 1;
|
|
245
|
+
history.replaceState(null, '', `#slide-${current + 1}`);
|
|
196
246
|
};
|
|
197
247
|
const go = (index) => {
|
|
198
248
|
update(index);
|
|
199
249
|
slides[current]?.scrollIntoView({
|
|
200
|
-
behavior: 'smooth',
|
|
250
|
+
behavior: reducedMotion ? 'auto' : 'smooth',
|
|
201
251
|
block: 'nearest',
|
|
202
252
|
inline: 'start',
|
|
203
253
|
});
|
|
@@ -226,7 +276,12 @@
|
|
|
226
276
|
{ root: deck, threshold: 0.6 },
|
|
227
277
|
);
|
|
228
278
|
slides.forEach((slide) => observer.observe(slide));
|
|
229
|
-
|
|
279
|
+
const requested = location.hash.match(/^#slide-(\d+)$/);
|
|
280
|
+
go(requested ? Number(requested[1]) - 1 : 0);
|
|
281
|
+
addEventListener('hashchange', () => {
|
|
282
|
+
const match = location.hash.match(/^#slide-(\d+)$/);
|
|
283
|
+
if (match) go(Number(match[1]) - 1);
|
|
284
|
+
});
|
|
230
285
|
})();
|
|
231
286
|
</script>
|
|
232
287
|
</body>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-explainer-kit
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.1
|
|
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
|
|
@@ -69,14 +69,20 @@ artifact is required. An explicit supplied fact-base path bypasses artifact
|
|
|
69
69
|
federation and is passed through as `factBase.mode: supplied`.
|
|
70
70
|
|
|
71
71
|
Unattended project runs pass `approved-oat-artifacts` provenance to the core's
|
|
72
|
-
content-approval seam and never prompt.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
`
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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.
|
|
78
|
+
|
|
79
|
+
Federated runs still require an explicit provider-neutral critic callback.
|
|
80
|
+
In-process callers may supply `critic` (or `coreOptions.critic` for
|
|
81
|
+
compatibility); JSON/CLI callers supply `criticModulePath` naming a module whose
|
|
82
|
+
`critic` export implements the same provider-neutral request/result contract.
|
|
83
|
+
Supply exactly one critic seam. Approval provenance does not bypass fact
|
|
84
|
+
reconciliation. Do not read private presets, vault files, provider
|
|
85
|
+
configuration, or ambient destination configuration.
|
|
80
86
|
|
|
81
87
|
## Progress Indicators (User-Facing)
|
|
82
88
|
|
|
@@ -9,8 +9,9 @@ constructing an `explainer-kit.run-request/v1`.
|
|
|
9
9
|
|
|
10
10
|
| Key | Stored scopes | Built-in default |
|
|
11
11
|
| -------------------------------------- | ------------------- | ---------------- |
|
|
12
|
-
| `explainers.defaults.
|
|
13
|
-
| `explainers.defaults.
|
|
12
|
+
| `explainers.defaults.style` | local, shared, user | `clean-neutral` |
|
|
13
|
+
| `explainers.defaults.palette` | local, shared, user | unset |
|
|
14
|
+
| `explainers.defaults.visualProfile` | local, shared, user | unset |
|
|
14
15
|
| `explainers.defaults.themeBundlePath` | local, shared | unset |
|
|
15
16
|
| `explainers.publish.provider` | shared | unset |
|
|
16
17
|
| `explainers.publish.s3Uri` | shared | unset |
|
|
@@ -20,7 +21,7 @@ constructing an `explainer-kit.run-request/v1`.
|
|
|
20
21
|
| `workflow.explainers.projectExplainer` | local, shared, user | `ask` |
|
|
21
22
|
| `workflow.explainers.projectRecap` | local, shared, user | `ask` |
|
|
22
23
|
|
|
23
|
-
Explicit runtime inputs may override these
|
|
24
|
+
Explicit runtime inputs may override these eleven keys for one invocation. They
|
|
24
25
|
do not write config. Recipe, slug, fact-base path, output root, per-run art
|
|
25
26
|
direction, and private wrapper lanes are invocation inputs rather than config
|
|
26
27
|
keys and are rejected from the runtime config-override map.
|
|
@@ -33,9 +34,13 @@ path follows the same repository confinement; a local absolute path may point
|
|
|
33
34
|
outside the repository. Runtime paths follow the local rule. User config cannot
|
|
34
35
|
set a theme bundle path.
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
The four curated styles are `clean-neutral`, `business-corporate`,
|
|
38
|
+
`navy-ocean`, and `dark-edgy`. A theme bundle path has highest precedence,
|
|
39
|
+
followed by an explicit style. Legacy palette and visual-profile fields remain
|
|
40
|
+
accepted as an advanced compatibility path and produce deprecation warnings.
|
|
41
|
+
When no source explicitly configures any selection, the adapter leaves the
|
|
42
|
+
request theme empty so the core records its visible `clean-neutral` fallback
|
|
43
|
+
warning. The adapter passes a resolved bundle as `theme.suppliedBundlePath`.
|
|
39
44
|
|
|
40
45
|
## Publish block
|
|
41
46
|
|
|
@@ -71,6 +71,19 @@ 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
|
|
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.
|
|
81
|
+
|
|
82
|
+
The resolved callback is passed only as the `author` option to
|
|
83
|
+
`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
|
+
|
|
74
87
|
## Tracked-run finalization
|
|
75
88
|
|
|
76
89
|
`planTrackedRunFinalization(request, context)` is the shared command planner for
|
|
@@ -246,22 +246,18 @@ function commitCommands(paths, subject) {
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
function immutablePackagePaths(manifest) {
|
|
249
|
-
|
|
250
|
-
manifest.
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
)
|
|
259
|
-
.map(({ renderedPath }) => renderedPath),
|
|
260
|
-
];
|
|
261
|
-
if (paths.some((path) => typeof path !== 'string' || path.length === 0)) {
|
|
249
|
+
if (
|
|
250
|
+
!manifest.immutableHashes ||
|
|
251
|
+
typeof manifest.immutableHashes !== 'object' ||
|
|
252
|
+
Array.isArray(manifest.immutableHashes)
|
|
253
|
+
) {
|
|
254
|
+
throw new Error('Manifest does not identify immutable package hashes.');
|
|
255
|
+
}
|
|
256
|
+
const paths = Object.keys(manifest.immutableHashes);
|
|
257
|
+
if (paths.length === 0) {
|
|
262
258
|
throw new Error('Manifest does not identify a complete immutable package.');
|
|
263
259
|
}
|
|
264
|
-
return
|
|
260
|
+
return paths;
|
|
265
261
|
}
|
|
266
262
|
|
|
267
263
|
function resolveRunPath(runRoot, path) {
|
|
@@ -7,6 +7,7 @@ import { resolveSourceAwarePath } from './resolve-paths.mjs';
|
|
|
7
7
|
const execFileAsync = promisify(execFile);
|
|
8
8
|
|
|
9
9
|
export const EXPLAINER_CONFIG_KEYS = Object.freeze([
|
|
10
|
+
'explainers.defaults.style',
|
|
10
11
|
'explainers.defaults.palette',
|
|
11
12
|
'explainers.defaults.visualProfile',
|
|
12
13
|
'explainers.defaults.themeBundlePath',
|
|
@@ -22,6 +23,12 @@ export const EXPLAINER_CONFIG_KEYS = Object.freeze([
|
|
|
22
23
|
const CONFIG_KEY_SET = new Set(EXPLAINER_CONFIG_KEYS);
|
|
23
24
|
const SOURCES = new Set(['local', 'shared', 'user', 'env', 'default']);
|
|
24
25
|
const PREFERENCES = new Set(['always', 'ask', 'never']);
|
|
26
|
+
const STYLES = new Set([
|
|
27
|
+
'clean-neutral',
|
|
28
|
+
'business-corporate',
|
|
29
|
+
'navy-ocean',
|
|
30
|
+
'dark-edgy',
|
|
31
|
+
]);
|
|
25
32
|
|
|
26
33
|
export async function resolveExplainerConfig({
|
|
27
34
|
repoRoot,
|
|
@@ -54,6 +61,22 @@ export async function resolveExplainerConfig({
|
|
|
54
61
|
const bundlePath = nullableString(
|
|
55
62
|
values['explainers.defaults.themeBundlePath'],
|
|
56
63
|
);
|
|
64
|
+
const style = nullableString(values['explainers.defaults.style']);
|
|
65
|
+
if (style && !STYLES.has(style)) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
'explainers.defaults.style must name a curated explainer style.',
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
const palette = nullableString(values['explainers.defaults.palette']);
|
|
71
|
+
const visualProfile = nullableString(
|
|
72
|
+
values['explainers.defaults.visualProfile'],
|
|
73
|
+
);
|
|
74
|
+
const hasLegacySelection = palette !== null || visualProfile !== null;
|
|
75
|
+
if (hasLegacySelection) {
|
|
76
|
+
warnings.push(
|
|
77
|
+
'Palette and visual profile configuration is deprecated; use explainers.defaults.style.',
|
|
78
|
+
);
|
|
79
|
+
}
|
|
57
80
|
if (bundlePath) {
|
|
58
81
|
theme.suppliedBundlePath = await resolveSourceAwarePath({
|
|
59
82
|
repoRoot,
|
|
@@ -61,19 +84,35 @@ export async function resolveExplainerConfig({
|
|
|
61
84
|
source: sources['explainers.defaults.themeBundlePath'],
|
|
62
85
|
field: 'explainers.defaults.themeBundlePath',
|
|
63
86
|
});
|
|
64
|
-
if (
|
|
65
|
-
nullableString(values['explainers.defaults.palette']) ||
|
|
66
|
-
nullableString(values['explainers.defaults.visualProfile'])
|
|
67
|
-
) {
|
|
87
|
+
if (style || palette || visualProfile) {
|
|
68
88
|
warnings.push(
|
|
69
|
-
'explainers.defaults.themeBundlePath overrides configured palette and visual profile.',
|
|
89
|
+
'explainers.defaults.themeBundlePath overrides configured style, palette, and visual profile.',
|
|
70
90
|
);
|
|
71
91
|
}
|
|
72
92
|
} else {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
const explicitStyle =
|
|
94
|
+
style && sources['explainers.defaults.style'] !== 'default'
|
|
95
|
+
? style
|
|
96
|
+
: null;
|
|
97
|
+
if (explicitStyle) {
|
|
98
|
+
theme.style = explicitStyle;
|
|
99
|
+
}
|
|
100
|
+
if (palette) {
|
|
101
|
+
theme.palette = palette;
|
|
102
|
+
}
|
|
103
|
+
if (visualProfile) {
|
|
104
|
+
theme.visualProfile = visualProfile;
|
|
105
|
+
}
|
|
106
|
+
if (explicitStyle && hasLegacySelection) {
|
|
107
|
+
warnings.push(
|
|
108
|
+
'explainers.defaults.style wins over deprecated palette and visual profile configuration.',
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
if (!explicitStyle && !hasLegacySelection) {
|
|
112
|
+
warnings.push(
|
|
113
|
+
'No explicit explainer style is configured; the core will default to clean-neutral.',
|
|
114
|
+
);
|
|
115
|
+
}
|
|
77
116
|
}
|
|
78
117
|
|
|
79
118
|
const publish = resolvePublish(values);
|
|
@@ -215,6 +254,11 @@ function normalizeRuntimeValue(key, value) {
|
|
|
215
254
|
if (key === 'explainers.publish.provider' && normalized !== 's3-static') {
|
|
216
255
|
throw new Error(`${key} runtime override must be s3-static.`);
|
|
217
256
|
}
|
|
257
|
+
if (key === 'explainers.defaults.style' && !STYLES.has(normalized)) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
`${key} runtime override must name a curated explainer style.`,
|
|
260
|
+
);
|
|
261
|
+
}
|
|
218
262
|
if (key.startsWith('workflow.explainers.') && !PREFERENCES.has(normalized)) {
|
|
219
263
|
throw new Error(`${key} runtime override must be always, ask, or never.`);
|
|
220
264
|
}
|
|
@@ -32,6 +32,8 @@ export async function runOatExplainer({
|
|
|
32
32
|
defaultMode,
|
|
33
33
|
renderStrategy,
|
|
34
34
|
retainRawArtDirection = false,
|
|
35
|
+
author,
|
|
36
|
+
authorModulePath,
|
|
35
37
|
critic,
|
|
36
38
|
criticModulePath,
|
|
37
39
|
coreOptions = {},
|
|
@@ -108,6 +110,12 @@ export async function runOatExplainer({
|
|
|
108
110
|
throw error;
|
|
109
111
|
}
|
|
110
112
|
|
|
113
|
+
const lifecycleAuthor = await resolveLifecycleAuthor({
|
|
114
|
+
author,
|
|
115
|
+
authorModulePath,
|
|
116
|
+
coreOptions,
|
|
117
|
+
mode: request.mode,
|
|
118
|
+
});
|
|
111
119
|
const lifecycleCritic = await resolveLifecycleCritic({
|
|
112
120
|
critic,
|
|
113
121
|
criticModulePath,
|
|
@@ -115,6 +123,7 @@ export async function runOatExplainer({
|
|
|
115
123
|
});
|
|
116
124
|
const result = await core.runExplainer(request, {
|
|
117
125
|
...coreOptions,
|
|
126
|
+
...(lifecycleAuthor && { author: lifecycleAuthor }),
|
|
118
127
|
...(lifecycleCritic && { critic: lifecycleCritic }),
|
|
119
128
|
...(bound.sourceLoader && { sourceLoader: bound.sourceLoader }),
|
|
120
129
|
reviewedSource: bound.reviewedSource,
|
|
@@ -136,6 +145,65 @@ export async function runOatExplainer({
|
|
|
136
145
|
};
|
|
137
146
|
}
|
|
138
147
|
|
|
148
|
+
async function resolveLifecycleAuthor({
|
|
149
|
+
author,
|
|
150
|
+
authorModulePath,
|
|
151
|
+
coreOptions,
|
|
152
|
+
mode,
|
|
153
|
+
}) {
|
|
154
|
+
if (coreOptions?.author !== undefined) {
|
|
155
|
+
throw new TypeError(
|
|
156
|
+
'coreOptions.author is not supported at the OAT adapter boundary; supply author directly.',
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
if (author !== undefined && typeof author !== 'function') {
|
|
160
|
+
throw new TypeError('author must be a function when supplied.');
|
|
161
|
+
}
|
|
162
|
+
if (author !== undefined && authorModulePath !== undefined) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
'Supply only one provider-neutral author callback or author module entry point.',
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
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;
|
|
177
|
+
}
|
|
178
|
+
if (authorModulePath === undefined) {
|
|
179
|
+
return author;
|
|
180
|
+
}
|
|
181
|
+
if (
|
|
182
|
+
typeof authorModulePath !== 'string' ||
|
|
183
|
+
authorModulePath.trim().length === 0
|
|
184
|
+
) {
|
|
185
|
+
throw new TypeError('authorModulePath must be a non-empty path.');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let authorModule;
|
|
189
|
+
try {
|
|
190
|
+
authorModule = await import(
|
|
191
|
+
pathToFileURL(resolve(authorModulePath.trim())).href
|
|
192
|
+
);
|
|
193
|
+
} catch (cause) {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`Unable to load provider-neutral author module at ${authorModulePath}.`,
|
|
196
|
+
{ cause },
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
if (typeof authorModule.author !== 'function') {
|
|
200
|
+
throw new TypeError(
|
|
201
|
+
'Provider-neutral author module must export an author function.',
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
return authorModule.author;
|
|
205
|
+
}
|
|
206
|
+
|
|
139
207
|
async function resolveLifecycleCritic({
|
|
140
208
|
critic,
|
|
141
209
|
criticModulePath,
|