@open-agent-toolkit/cli 0.2.29 → 0.2.31

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 (87) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/cli-utilities/configuration.md +52 -1
  3. package/assets/docs/contributing/code.md +19 -7
  4. package/assets/docs/contributing/explainer-kit-verification.md +9 -1
  5. package/assets/docs/contributing/skills.md +9 -0
  6. package/assets/docs/workflows/projects/artifacts.md +5 -0
  7. package/assets/docs/workflows/projects/index.md +1 -0
  8. package/assets/docs/workflows/projects/lifecycle.md +23 -0
  9. package/assets/docs/workflows/projects/retro.md +261 -0
  10. package/assets/docs/workflows/skills/explainer-kit-providers.md +16 -5
  11. package/assets/docs/workflows/skills/explainer-kit.md +98 -38
  12. package/assets/docs/workflows/skills/index.md +6 -0
  13. package/assets/public-package-versions.json +4 -4
  14. package/assets/skills/explainer-kit/SKILL.md +33 -8
  15. package/assets/skills/explainer-kit/briefs/project-recap.md +25 -7
  16. package/assets/skills/explainer-kit/recipes/project-recap.v2.json +72 -0
  17. package/assets/skills/explainer-kit/references/contracts.md +49 -17
  18. package/assets/skills/explainer-kit/references/destination-contract.md +141 -25
  19. package/assets/skills/explainer-kit/references/extension-contract.md +19 -10
  20. package/assets/skills/explainer-kit/references/visual-authoring.md +24 -0
  21. package/assets/skills/explainer-kit/references/visual-review.md +19 -5
  22. package/assets/skills/explainer-kit/schemas/author-request.v3.schema.json +241 -0
  23. package/assets/skills/explainer-kit/schemas/publish-receipt.v2.schema.json +215 -0
  24. package/assets/skills/explainer-kit/schemas/publish-request.v2.schema.json +34 -0
  25. package/assets/skills/explainer-kit/schemas/run-request.schema.json +4 -1
  26. package/assets/skills/explainer-kit/schemas/terminal-evidence.v1.schema.json +81 -0
  27. package/assets/skills/explainer-kit/schemas/visual-review-evidence.v1.schema.json +66 -0
  28. package/assets/skills/explainer-kit/scripts/lib/catalog.mjs +109 -3
  29. package/assets/skills/explainer-kit/scripts/lib/contracts.mjs +550 -17
  30. package/assets/skills/explainer-kit/scripts/lib/durability.mjs +90 -8
  31. package/assets/skills/explainer-kit/scripts/lib/fs-safe.mjs +5 -0
  32. package/assets/skills/explainer-kit/scripts/lib/internal-references.mjs +538 -0
  33. package/assets/skills/explainer-kit/scripts/lib/package-coverage.mjs +129 -11
  34. package/assets/skills/explainer-kit/scripts/lib/publication-policy.mjs +54 -0
  35. package/assets/skills/explainer-kit/scripts/lib/recipes.mjs +2 -1
  36. package/assets/skills/explainer-kit/scripts/lib/records.mjs +139 -22
  37. package/assets/skills/explainer-kit/scripts/lib/s3-roots.mjs +353 -0
  38. package/assets/skills/explainer-kit/scripts/lib/s3-static.mjs +237 -107
  39. package/assets/skills/explainer-kit/scripts/lib/set-plan.mjs +1 -0
  40. package/assets/skills/explainer-kit/scripts/lib/terminal-evidence.mjs +157 -0
  41. package/assets/skills/explainer-kit/scripts/lib/visual-review.mjs +26 -6
  42. package/assets/skills/explainer-kit/scripts/run.mjs +1006 -144
  43. package/assets/skills/oat-explainer-kit/SKILL.md +16 -3
  44. package/assets/skills/oat-explainer-kit/references/config-contract.md +13 -8
  45. package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +50 -6
  46. package/assets/skills/oat-explainer-kit/references/migration.md +2 -1
  47. package/assets/skills/oat-explainer-kit/references/visual-review-callback.md +11 -0
  48. package/assets/skills/oat-explainer-kit/scripts/bind-project-sources.mjs +37 -15
  49. package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +83 -0
  50. package/assets/skills/oat-explainer-kit/scripts/derive-destination.mjs +91 -0
  51. package/assets/skills/oat-explainer-kit/scripts/finalize-tracked-run.mjs +66 -10
  52. package/assets/skills/oat-explainer-kit/scripts/resolve-config.mjs +60 -21
  53. package/assets/skills/oat-explainer-kit/scripts/resolve-paths.mjs +52 -8
  54. package/assets/skills/oat-explainer-kit/scripts/run.mjs +271 -36
  55. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +38 -38
  56. package/assets/skills/oat-project-complete/SKILL.md +60 -8
  57. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +38 -38
  58. package/assets/skills/oat-project-implement/SKILL.md +1 -1
  59. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +28 -6
  60. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +38 -38
  61. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +38 -38
  62. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +38 -38
  63. package/assets/skills/oat-project-retro/SKILL.md +310 -0
  64. package/assets/skills/oat-project-retro/references/apply-procedure.md +212 -0
  65. package/assets/skills/oat-project-retro/references/evidence-and-lanes.md +91 -0
  66. package/assets/skills/oat-project-retro/references/retro-quality-bar.md +100 -0
  67. package/assets/skills/oat-project-retro-file/SKILL.md +387 -0
  68. package/assets/templates/project-retro.md +236 -0
  69. package/dist/commands/config/index.d.ts.map +1 -1
  70. package/dist/commands/config/index.js +99 -0
  71. package/dist/commands/init/tools/shared/skill-manifest.d.ts +2 -2
  72. package/dist/commands/init/tools/shared/skill-manifest.d.ts.map +1 -1
  73. package/dist/commands/init/tools/shared/skill-manifest.js +3 -0
  74. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  75. package/dist/commands/project/archive/archive-utils.js +57 -7
  76. package/dist/commands/project/archive/explainer-terminal-evidence.d.ts +29 -0
  77. package/dist/commands/project/archive/explainer-terminal-evidence.d.ts.map +1 -0
  78. package/dist/commands/project/archive/explainer-terminal-evidence.js +37 -0
  79. package/dist/config/oat-config.d.ts +14 -1
  80. package/dist/config/oat-config.d.ts.map +1 -1
  81. package/dist/config/oat-config.js +42 -2
  82. package/dist/config/resolve.d.ts.map +1 -1
  83. package/dist/config/resolve.js +9 -0
  84. package/package.json +2 -2
  85. /package/assets/skills/explainer-kit/recipes/{project-recap.json → project-recap.v1.json} +0 -0
  86. /package/assets/skills/explainer-kit/schemas/{publish-receipt.schema.json → publish-receipt.v1.schema.json} +0 -0
  87. /package/assets/skills/explainer-kit/schemas/{publish-request.schema.json → publish-request.v1.schema.json} +0 -0
@@ -10,15 +10,39 @@ node scripts/publish.mjs \
10
10
  --confirm-publish
11
11
  ```
12
12
 
13
- The request uses `explainer-kit.publish-request/v1`. Credentials come only from
14
- the standard AWS credential chain or the request's optional profile. Never put
15
- access keys, secret keys, session tokens, or SSO tokens in a request.
16
-
17
- ## Corresponding roots
18
-
19
- `s3Uri` and `publicBaseUrl` must identify corresponding roots. Both are
20
- normalized without trailing slashes. For a path `P` relative to `siteRoot`, the
21
- connector writes `<s3Uri>/P` and verifies `<publicBaseUrl>/P`.
13
+ New requests use `explainer-kit.publish-request/v2` and explicitly declare
14
+ `publicAccess` as `public` or `protected`. V1 remains readable as public-mode
15
+ replay. Credentials come only from the standard AWS credential chain or the
16
+ request's optional profile. Never put access keys, secret keys, session tokens,
17
+ or SSO tokens in a request.
18
+
19
+ ## How the two roots compose
20
+
21
+ `s3Uri` and `publicBaseUrl` are each normalized without trailing slashes. For a
22
+ path `P` relative to `siteRoot`, the connector writes `<s3Uri>/P` and verifies
23
+ `<publicBaseUrl>/P`. That composition is the whole of the relationship.
24
+
25
+ **No relational validation is performed between the two roots, by design.** The
26
+ mapping from an S3 key to a public URL is underdetermined by these two strings:
27
+ it lives in CDN configuration the connector cannot read. Both of these are
28
+ legitimate, and they disagree structurally:
29
+
30
+ | Shape | `s3Uri` | `publicBaseUrl` |
31
+ | ----- | ---------------------------- | ----------------------------- |
32
+ | A | `s3://bucket/repositories/x` | `https://host/repositories/x` |
33
+ | B | `s3://bucket/explainers` | `https://host` |
34
+
35
+ B is an ordinary CloudFront **Origin Path** deployment, where a bucket prefix is
36
+ mapped to the distribution root. Requiring the public path to equal the S3 key
37
+ prefix rejects it. Suffix-containment does not rescue the rule either — an empty
38
+ public path is a suffix of everything, so B would pass vacuously while
39
+ path-rewriting deployments (CloudFront Functions, Lambda@Edge, custom origins)
40
+ still produce false rejections.
41
+
42
+ Divergence between the two paths is therefore reported as a **non-blocking
43
+ warning**, never a failure. Correctness of an advertised URL is established by
44
+ verification, not by string shape — which is also why `publicAccess: protected`,
45
+ where no anonymous fetch happens, cannot establish it at all.
22
46
 
23
47
  For example:
24
48
 
@@ -32,7 +56,39 @@ For example:
32
56
  | public URL | `https://cdn.example.com/published/initiatives/demo/index.html` |
33
57
 
34
58
  Use explicit `index.html` URLs. Directory redirects are not portable evidence.
35
- The destination must serve uploaded bytes at the corresponding public path.
59
+ The destination must serve the uploaded bytes at the composed public path. That
60
+ is a requirement on the deployment, not something the connector validates from
61
+ the two root strings; see below.
62
+
63
+ ## The manifest a connector receives is intentionally incomplete
64
+
65
+ The core persists the manifest **before** it invokes the publisher callback, so
66
+ the file at `manifestPath` carries `outcome: "incomplete"` while the `publish`
67
+ stage is still `running`. This is a contractually intended intermediate state,
68
+ not a corrupt or half-written record, and a connector must not reject it on the
69
+ strength of `outcome` alone.
70
+
71
+ Do not decide publishability from the manifest by itself. Read the build record
72
+ named by `manifest.buildRecord.path` (resolved relative to the manifest) and
73
+ require all of:
74
+
75
+ - the manifest carries no `visual-review-required:` warning;
76
+ - the build record's own `outcome` is `incomplete`;
77
+ - its `publish` stage exists and is `running`; and
78
+ - every stage before `publish` is `passed`, `warned`, or `skipped` and carries
79
+ no `visual-review-required:` warning.
80
+
81
+ Only that combination makes an `incomplete` manifest publishable. The one other
82
+ eligible shape is a finalized `built-durable` manifest that is not
83
+ review-flagged. Any other `incomplete` manifest, and every manifest whose run is
84
+ flagged, failed, or superseded, must be refused. The built-in connector performs
85
+ exactly this check before its first network call; third-party connectors are
86
+ required to perform an equivalent one.
87
+
88
+ The published bytes cannot diverge from the finalized manifest: the catalog
89
+ projection omits `outcome` and `warnings`, and both manifest writes share one
90
+ `finalizedAt`. After the callback returns a valid receipt, the core rewrites the
91
+ manifest with its terminal outcome.
36
92
 
37
93
  ## Safety and ordering
38
94
 
@@ -41,16 +97,22 @@ site-relative paths before network access. It then:
41
97
 
42
98
  1. uploads a sentinel whose path contains the run ID and a random 128-bit
43
99
  suffix;
44
- 2. verifies the sentinel with `head-object`;
45
- 3. fetches that exact sentinel through the public root;
100
+ 2. verifies the sentinel with a service-computed SHA-256 checksum or an
101
+ authenticated download hash;
102
+ 3. for public destinations, fetches that exact sentinel anonymously through the
103
+ public root; protected destinations skip this public fetch explicitly;
46
104
  4. deletes only that sentinel;
47
105
  5. uploads or idempotently skips each declared artifact;
48
- 6. verifies object metadata, content type, and SHA-256 of the exact response
49
- bytes from each public artifact URL; and
50
- 7. atomically writes `explainer-kit.publish-receipt/v1`.
106
+ 6. verifies exact object bytes from service-computed SHA-256 evidence or an
107
+ authenticated download hash, then additionally verifies the exact anonymous
108
+ response bytes for public destinations; and
109
+ 7. atomically writes `explainer-kit.publish-receipt/v2` with separate
110
+ authenticated-object and anonymous-public verification facts.
51
111
 
52
- If public sentinel verification fails, no artifact is uploaded. The connector
53
- attempts sentinel cleanup and emits no successful receipt.
112
+ If required sentinel verification fails or its verification capability is
113
+ unavailable, no artifact is uploaded. The connector attempts sentinel cleanup
114
+ and emits no successful receipt. An undeclared `401` or `403` in public mode is
115
+ a verification failure, never evidence that the destination is protected.
54
116
 
55
117
  Publishing is additive. The implementation uses individual `put-object`,
56
118
  `head-object`, and sentinel-only `delete-object` operations. It never performs
@@ -74,10 +136,13 @@ Every upload sets metadata explicitly:
74
136
  | other | manifest media type or `application/octet-stream` |
75
137
 
76
138
  Artifacts use `Cache-Control: public, max-age=300`. The connector stores the
77
- SHA-256 digest as object metadata for idempotency and verifies content type,
78
- cache control, and digest after upload. Public verification hashes response
79
- bytes without text decoding, so binary artifacts and stale wrong-byte 200
80
- responses are covered.
139
+ SHA-256 digest as object metadata for idempotency and supplies
140
+ `--checksum-sha256` on upload. It requests service checksum evidence with
141
+ `--checksum-mode ENABLED`; caller-authored metadata and ETags are never treated
142
+ as object-byte proof. When service SHA-256 evidence is unavailable, the
143
+ connector hashes bytes from an authenticated download. Public verification
144
+ separately hashes response bytes without text decoding, so binary artifacts and
145
+ stale wrong-byte 200 responses are covered.
81
146
 
82
147
  ## Failures and retries
83
148
 
@@ -86,9 +151,60 @@ not run `aws sso login`, retry with another profile, expose AWS diagnostics, or
86
151
  persist credentials. Refresh credentials separately and rerun after approval.
87
152
 
88
153
  Only transient individual object-operation failures receive bounded retries.
89
- Input, authorization, root-correspondence, metadata, and public-verification
90
- failures are not retried. A failed publish preserves the local package.
154
+ Input, authorization, metadata, and public-verification failures are not
155
+ retried. A failed publish preserves the local package.
91
156
 
92
157
  Public roots must be credential-free HTTPS URLs with no username, password,
93
- query, or fragment. Invalid roots fail before AWS or HTTP operations and are
94
- never persisted in receipts.
158
+ query, or fragment. Three further rejections apply, all before any AWS or HTTP
159
+ operation, and none of them are ever persisted in receipts:
160
+
161
+ - **Control characters.** Any codepoint in `0x00`–`0x1f` or `0x7f`–`0x9f`, and
162
+ any backslash, in either root. These otherwise reach S3 object keys, composed
163
+ public URLs, the catalog, the receipt and `aws` argv; `0x9b` is the 8-bit CSI.
164
+ - **Non-public addresses.** Loopback, link-local (`169.254.0.0/16`, `fe80::/10`,
165
+ including the `169.254.169.254` instance-metadata address), unique-local
166
+ (`fc00::/7`) and RFC 1918 private hosts, in both literal IPv4 and IPv6 forms
167
+ including IPv4-mapped spellings. Public verification issues an outbound GET
168
+ against whatever the root names, so an unconstrained root is a request
169
+ primitive aimed at internal addresses. Set
170
+ `EXPLAINER_KIT_ALLOW_PRIVATE_PUBLIC_ROOT=1` to opt back in for a genuinely
171
+ internal mirror. The policy is address-literal only: a hostname that happens
172
+ to resolve inward is not detected.
173
+ - **Redirects.** Public verification uses `redirect: 'error'`. A canonical
174
+ artifact URL is uploaded to a known key and should never legitimately
175
+ redirect, so any redirecting destination is a hard verification failure rather
176
+ than something to follow. A destination that requires redirects is
177
+ incompatible with this connector and will report as such rather than failing
178
+ opaquely later.
179
+
180
+ ## The generated initiative catalog
181
+
182
+ The connector generates one auxiliary artifact the manifest does not declare: an
183
+ initiative catalog at `site/initiatives/<slug>/catalog.json`, uploaded alongside
184
+ the declared artifacts and recorded in the receipt as
185
+ `source: { kind: 'auxiliary', name: 'catalog' }`.
186
+
187
+ A third-party connector must reproduce it **byte for byte**, because
188
+ `recordDurability` rebuilds it from the manifest and compares hashes; a mismatch
189
+ rejects the publication with `cross-record-mismatch`. Build it with
190
+ `catalogFromManifest(manifest, publicBaseUrl, { publicAccess })` and serialize
191
+ with `serializeInitiativeCatalog`, rather than constructing it by hand.
192
+
193
+ Two properties matter most:
194
+
195
+ - The `{ publicAccess }` option is **required**. Omitting it raises a
196
+ `TypeError` rather than defaulting, because the policy selects a field inside
197
+ the serialized bytes and therefore changes the hash. Pass
198
+ `{ publicAccess: undefined }` for `publish-request/v1`, which has no such
199
+ field and is public by definition.
200
+ - `publicVerification` carries **policy, never outcome**: `"required"` for
201
+ public destinations and `"skipped-by-policy"` for protected ones. The catalog
202
+ is serialized and hashed before the first upload and long before any
203
+ per-artifact verification runs, so it cannot carry a verification result
204
+ without invalidating its own hash. The authoritative outcome lives in the
205
+ publish receipt, which the catalog's `runId` identifies. Never write
206
+ `"verified"` into a catalog.
207
+
208
+ Publishability is gated by `assertManifestPublishable`, which raises
209
+ `E_PUBLISH_OUTCOME` for a manifest that is not eligible; see the intermediate
210
+ `incomplete` state described above.
@@ -20,13 +20,18 @@ Private wrappers may retain presets, vault conventions, Google Docs behavior,
20
20
  and personal destinations around this seam. Those values are wrapper-owned;
21
21
  they are not OAT config keys and must not be discovered by the core.
22
22
 
23
- ## Frozen v1 boundary
23
+ ## Frozen versioned boundary
24
24
 
25
25
  The versioned request, artifact package, manifest, build record, durability
26
- request, publish request, and publish receipt are the public boundary. V1 has
27
- no plugin registry and no mid-pipeline callback API for private destinations.
28
- Provider-neutral callbacks already documented by the core remain explicit run
29
- options; they do not transfer stage ownership to a wrapper.
26
+ request, publish request, and publish receipt are the public boundary. New
27
+ publication work uses the immutable `explainer-kit.publish-request/v2` and
28
+ `explainer-kit.publish-receipt/v2` contracts. The corresponding
29
+ `publish-request/v1` and `publish-receipt/v1` contracts remain readable for
30
+ replay; v2 is a new contract version, not an in-place mutation of v1. The
31
+ extension seam has no plugin registry and no mid-pipeline callback API for
32
+ private destinations. Provider-neutral callbacks already documented by the
33
+ core remain explicit run options; they do not transfer stage ownership to a
34
+ wrapper.
30
35
 
31
36
  V1 readers reject unsupported contract majors and identity mismatches rather
32
37
  than guessing. Wrappers should preserve unknown future versions for diagnosis,
@@ -59,13 +64,17 @@ or private content.
59
64
 
60
65
  After the core command returns, the wrapper performs its post-run publication
61
66
  and linking work. It retains the immutable core manifest as
62
- `private-wrapper-manifest.json`, the complete `PublishReceiptV1` as
67
+ `private-wrapper-manifest.json`, the complete `publish-receipt/v2` as
63
68
  `private-wrapper-publish-receipt.json`, and its sanitized wrapper result as
64
69
  `private-wrapper-result.json`. The wrapper result repeats canonical hashes for
65
70
  the request, manifest, and post-run receipt.
66
71
 
67
72
  The wrapper acceptance stage reads those post-run files separately. It
68
- validates the closed receipt contract, every manifest artifact/hash and
69
- destination, the run-unique sentinel, the manifest hash, and the core run ID
70
- against `private-wrapper-execution.json`. Repeating a matching hash cannot make
71
- a foreign or stale receipt attributable to the packaged run.
73
+ validates the closed receipt contract, complete manifest and catalog evidence,
74
+ every source identity, path, artifact hash, destination, and verification fact,
75
+ the run-unique sentinel, the manifest hash, and the core run ID against
76
+ `private-wrapper-execution.json`. Public and protected v2 receipts must each
77
+ provide exactly one entry for every finalized manifest artifact and exactly one
78
+ generated catalog entry. A `publish-receipt/v1` remains consumable only for
79
+ replay. Repeating a matching hash cannot make a foreign, duplicate, incomplete,
80
+ or stale receipt attributable to the packaged run.
@@ -28,10 +28,30 @@ stands. Use one dominant title, a short framing statement, and the most useful
28
28
  visual or status summary before secondary detail. Keep headings descriptive,
29
29
  group related items, and use size, spacing, and contrast consistently.
30
30
 
31
+ Assign intentional typography roles to the title, framing statement, section
32
+ headings, labels, body copy, evidence, and annotations. Use weight, scale,
33
+ measure, and contrast to clarify those roles rather than making every text block
34
+ equally loud. Keep the role system consistent across artifacts without forcing
35
+ every medium into the same composition.
36
+
31
37
  Use the shared terminology, status labels, and numbers exactly. Never create a
32
38
  shorter synonym that changes meaning. Keep source-backed uncertainty visible as
33
39
  `needs confirmation`.
34
40
 
41
+ ## Compose to the evidence
42
+
43
+ Treat composition and density as editorial choices. Group facts that belong
44
+ together, give the main claim enough emphasis, and let supporting evidence
45
+ recede without becoming hard to find. Restructure crowded content instead of
46
+ shrinking it, and remove decorative filler instead of stretching sparse
47
+ material.
48
+
49
+ Seek medium leverage: a visual artifact should make a relationship, comparison,
50
+ sequence, or decision easier to understand than prose alone. Vary the treatment
51
+ to fit the evidence and avoid template repetition across sections, cards, or
52
+ slides. Shared visual language should create cross-artifact cohesion, not a set
53
+ of cloned layouts.
54
+
35
55
  ## Hubs and responsive navigation
36
56
 
37
57
  - Lead with the project outcome and current state, then expose architecture,
@@ -45,6 +65,8 @@ shorter synonym that changes meaning. Keep source-backed uncertainty visible as
45
65
 
46
66
  ## Diagrams and system visuals
47
67
 
68
+ - Preserve diagram semantics: topology, direction, ownership, state, and edge
69
+ meaning must survive the visual treatment.
48
70
  - Encode relationships with position and connectors, not color alone.
49
71
  - Label nodes with concrete nouns and edges with actions or data movement.
50
72
  - Make direction explicit and include a legend only when the encoding needs it.
@@ -58,6 +80,8 @@ shorter synonym that changes meaning. Keep source-backed uncertainty visible as
58
80
  attribute escaping, including `data-edge-label=""` for an unlabeled edge.
59
81
  - Give the canvas an accessible name and description. Keep labels readable at
60
82
  the required viewport widths and provide bounded pan or zoom for large maps.
83
+ - Fit the frame to the content so the meaningful topology is prominent rather
84
+ than stranded in unused canvas.
61
85
  - Use the same component names and status vocabulary as the hub and deck.
62
86
 
63
87
  ## Decks
@@ -12,17 +12,30 @@ Inspect the complete set before assigning artifact findings. Verify:
12
12
 
13
13
  - **First viewport:** each artifact establishes purpose, project state, and the
14
14
  primary reader question without scrolling.
15
+ - **Typography:** titles, framing text, headings, labels, body copy, and
16
+ annotations have distinct, readable roles that remain consistent across the
17
+ set.
15
18
  - **Hierarchy:** the most important outcome or relationship is dominant, with
16
19
  secondary detail grouped and ordered consistently.
17
- - **Representation choice:** the selected medium makes the evidence easier to
18
- understand than plain prose would.
20
+ - **Composition:** grouping, alignment, spacing, and emphasis create a clear
21
+ reading path suited to the artifact's evidence.
22
+ - **Density:** crowded material is restructured instead of miniaturized, while
23
+ sparse material is not padded with decorative filler.
24
+ - **Medium leverage:** the selected medium makes a relationship, comparison,
25
+ sequence, or decision easier to understand than plain prose would.
19
26
  - **Legibility:** text, labels, status cues, tables, and connectors remain
20
27
  readable at every required viewport.
21
28
  - **Medium fit:** the hub orients and links, the system visual preserves
22
29
  relationships, the deck paces a narrative, and optional artifacts add a
23
30
  distinct source-backed perspective.
24
- - **Cohesion:** terminology, status labels, numbers, color meaning, and visual
25
- language match the shared ledger and one another.
31
+ - **Template repetition:** sections, cards, and slides vary when the evidence
32
+ calls for a different treatment instead of repeating one shell mechanically.
33
+ - **Diagram semantics:** topology, direction, labels, edge meaning, and
34
+ fit-to-content framing communicate the planned relationships without false
35
+ linearization or decorative ambiguity.
36
+ - **Cross-artifact cohesion:** terminology, status labels, numbers, color
37
+ meaning, typographic roles, and visual language match the shared ledger and
38
+ one another.
26
39
  - **Coverage and redundancy:** planned sources and reader questions are covered
27
40
  once at the right depth; optional artifacts do not repeat the hub or deck
28
41
  without a justified purpose.
@@ -49,7 +62,8 @@ Use severity proportionally:
49
62
  Return exactly one provider-neutral disposition:
50
63
 
51
64
  - `pass` when the full set clears the rubric with no required correction.
52
- - `correct` when bounded artifact-scoped changes can clear the rubric.
65
+ - `correct` when bounded artifact-scoped changes can clear the rubric; every
66
+ finding must name a concrete, actionable correction.
53
67
  - `fail` when evidence is missing, the plan or ledger is internally invalid, or
54
68
  correction would require unsupported facts or a different artifact set.
55
69
 
@@ -0,0 +1,241 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "explainer-kit.author-request/v3",
4
+ "title": "AuthorRequestV3",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schemaVersion",
9
+ "artifactId",
10
+ "artifactType",
11
+ "authoring",
12
+ "brief",
13
+ "visualAuthoringGuidance",
14
+ "factBase",
15
+ "theme",
16
+ "setContext",
17
+ "plannedArtifact",
18
+ "artifactLinks"
19
+ ],
20
+ "properties": {
21
+ "schemaVersion": { "const": "explainer-kit.author-request/v3" },
22
+ "artifactId": { "type": "string", "minLength": 1 },
23
+ "artifactType": {
24
+ "enum": ["hub", "diagram", "explainer", "deck", "catalog"]
25
+ },
26
+ "authoring": { "enum": ["markdown", "html"] },
27
+ "brief": { "type": "string", "minLength": 1 },
28
+ "visualAuthoringGuidance": { "type": "string", "minLength": 1 },
29
+ "factBase": { "$ref": "explainer-kit.fact-base/v1" },
30
+ "shell": { "type": "string", "minLength": 1 },
31
+ "theme": { "$ref": "explainer-kit.theme/v1" },
32
+ "setContext": { "$ref": "explainer-kit.set-plan/v1" },
33
+ "plannedArtifact": { "$ref": "#/$defs/plannedArtifact" },
34
+ "artifactLinks": {
35
+ "type": "array",
36
+ "items": { "$ref": "#/$defs/artifactLink" },
37
+ "minItems": 1,
38
+ "uniqueItems": true
39
+ },
40
+ "graphSemantics": {
41
+ "type": "array",
42
+ "items": { "$ref": "#/$defs/graphSemantics" },
43
+ "minItems": 1
44
+ },
45
+ "floor": {
46
+ "type": "object",
47
+ "additionalProperties": false,
48
+ "required": ["requiredNarrative"],
49
+ "properties": {
50
+ "requiredNarrative": {
51
+ "type": "array",
52
+ "items": { "type": "string", "minLength": 1 },
53
+ "minItems": 1,
54
+ "uniqueItems": true
55
+ }
56
+ }
57
+ }
58
+ },
59
+ "$defs": {
60
+ "artifactLink": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "required": ["artifactId", "artifactType", "sitePath", "href"],
64
+ "properties": {
65
+ "artifactId": {
66
+ "type": "string",
67
+ "pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*$"
68
+ },
69
+ "artifactType": {
70
+ "enum": ["hub", "diagram", "explainer", "deck", "catalog"]
71
+ },
72
+ "sitePath": {
73
+ "type": "string",
74
+ "pattern": "^site/[a-z0-9._-]+(?:/[a-z0-9._-]+)*/index\\.html$"
75
+ },
76
+ "href": {
77
+ "type": "string",
78
+ "pattern": "^(?:index\\.html|(?:\\.\\./)*[a-z0-9._-]+(?:/[a-z0-9._-]+)*/index\\.html)$"
79
+ }
80
+ }
81
+ },
82
+ "graphSemantics": {
83
+ "type": "object",
84
+ "additionalProperties": false,
85
+ "required": ["direction", "nodes", "edges", "topology"],
86
+ "properties": {
87
+ "direction": { "enum": ["TD", "LR"] },
88
+ "nodes": {
89
+ "type": "array",
90
+ "items": {
91
+ "type": "object",
92
+ "additionalProperties": false,
93
+ "required": ["id", "label", "shape", "explicit"],
94
+ "properties": {
95
+ "id": { "type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_-]*$" },
96
+ "label": { "type": "string", "minLength": 1 },
97
+ "shape": { "enum": ["rectangle", "rounded", "diamond"] },
98
+ "explicit": { "type": "boolean" }
99
+ }
100
+ },
101
+ "minItems": 1,
102
+ "uniqueItems": true
103
+ },
104
+ "edges": {
105
+ "type": "array",
106
+ "items": {
107
+ "type": "object",
108
+ "additionalProperties": false,
109
+ "required": ["from", "to", "kind", "label"],
110
+ "properties": {
111
+ "from": {
112
+ "type": "string",
113
+ "pattern": "^[A-Za-z][A-Za-z0-9_-]*$"
114
+ },
115
+ "to": { "type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_-]*$" },
116
+ "kind": { "enum": ["arrow", "line"] },
117
+ "label": { "type": "string" }
118
+ }
119
+ },
120
+ "minItems": 1
121
+ },
122
+ "topology": {
123
+ "type": "object",
124
+ "additionalProperties": false,
125
+ "required": [
126
+ "kind",
127
+ "features",
128
+ "branchNodes",
129
+ "fanInNodes",
130
+ "cycle",
131
+ "order"
132
+ ],
133
+ "properties": {
134
+ "kind": { "const": "non-linear" },
135
+ "features": {
136
+ "type": "array",
137
+ "items": {
138
+ "enum": [
139
+ "branch",
140
+ "fan-in",
141
+ "cycle",
142
+ "disconnected",
143
+ "non-linear"
144
+ ]
145
+ },
146
+ "minItems": 1,
147
+ "uniqueItems": true
148
+ },
149
+ "branchNodes": {
150
+ "type": "array",
151
+ "items": {
152
+ "type": "string",
153
+ "pattern": "^[A-Za-z][A-Za-z0-9_-]*$"
154
+ },
155
+ "uniqueItems": true
156
+ },
157
+ "fanInNodes": {
158
+ "type": "array",
159
+ "items": {
160
+ "type": "string",
161
+ "pattern": "^[A-Za-z][A-Za-z0-9_-]*$"
162
+ },
163
+ "uniqueItems": true
164
+ },
165
+ "cycle": { "type": "boolean" },
166
+ "order": {
167
+ "type": "array",
168
+ "items": {
169
+ "type": "string",
170
+ "pattern": "^[A-Za-z][A-Za-z0-9_-]*$"
171
+ },
172
+ "maxItems": 0
173
+ }
174
+ }
175
+ }
176
+ }
177
+ },
178
+ "plannedArtifact": {
179
+ "type": "object",
180
+ "additionalProperties": false,
181
+ "required": [
182
+ "artifactId",
183
+ "artifactType",
184
+ "profileId",
185
+ "required",
186
+ "sourceIds",
187
+ "draft",
188
+ "visualIntent"
189
+ ],
190
+ "properties": {
191
+ "artifactId": {
192
+ "type": "string",
193
+ "pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*$"
194
+ },
195
+ "artifactType": {
196
+ "enum": ["hub", "diagram", "explainer", "deck", "catalog"]
197
+ },
198
+ "profileId": {
199
+ "type": "string",
200
+ "pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*$"
201
+ },
202
+ "required": { "type": "boolean" },
203
+ "sourceIds": {
204
+ "type": "array",
205
+ "items": {
206
+ "type": "string",
207
+ "pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*$"
208
+ },
209
+ "minItems": 1,
210
+ "uniqueItems": true
211
+ },
212
+ "draft": { "type": "string", "minLength": 1 },
213
+ "visualIntent": { "type": "string", "minLength": 1 },
214
+ "justification": {
215
+ "type": "object",
216
+ "additionalProperties": false,
217
+ "required": ["kind", "sourceIds", "rationale"],
218
+ "properties": {
219
+ "kind": {
220
+ "enum": [
221
+ "status-change",
222
+ "rollout-complexity",
223
+ "source-backed-detail"
224
+ ]
225
+ },
226
+ "sourceIds": {
227
+ "type": "array",
228
+ "items": {
229
+ "type": "string",
230
+ "pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*$"
231
+ },
232
+ "minItems": 1,
233
+ "uniqueItems": true
234
+ },
235
+ "rationale": { "type": "string", "minLength": 1 }
236
+ }
237
+ }
238
+ }
239
+ }
240
+ }
241
+ }