You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(engine-bootstrap): route doc-site URLs to kind: web-doc (#4)
PR #3 introduced web-doc as the fourth source kind across the artifact
contract, REFRESH/DISCOVER probes, verify.sh enum, recipes, and the
Step 3.6 cache-seed flow — but never updated bootstrap's Step 1 intake
classifier. URL inputs continued to fall through to `kind: external-doc`,
producing structurally invalid entries (external-doc is path-addressed
local markdown, not URL-addressed) and making Step 3.6 unreachable.
Re-route the intake table, repo/doc disambiguator, bare-org guardrail,
Step 2 slug table, and Step 3 stamping to produce kind: web-doc with
default crawl_mode: "sitemap". Document that bootstrap never produces
external-doc.
Harden verify.sh with per-kind url/path required-field checks so a
malformed entry is rejected at validation time (defense-in-depth for
the silent corruption hand-edits could still produce). Add fixtures
pinning the rejected shapes and the expected post-fix bootstrap output.
Copy file name to clipboardExpand all lines: plugin/skill-engine/docs/02-artifact-contract.md
+4-2Lines changed: 4 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -84,7 +84,7 @@ The `<area-domain>-` prefix in `references/<area-domain>-*.md` is a routing sign
84
84
85
85
The bijection invariant (see "The bijection invariant" below) is unaffected by prefix choice - that contract holds regardless of how `<area-domain>-*` is filled in. The guidance here is about routing UX, not contract compliance.
86
86
87
-
### External-doc sources on source-paths.json
87
+
### `kind: "external-doc"`
88
88
89
89
A `research/source-paths.json` entry can carry an optional `kind` discriminator that names the harvest treatment the engine applies to a source root. When `kind` is absent — the existing-corpus state for every contextualizer that has shipped before this addition — the entry receives the **git-managed source-root** treatment documented in [`03-engine.md`](03-engine.md): per-source SHA via `git rev-parse HEAD`, then sparse-clone or shallow-clone crawl when the SHA has changed. Back-compat is total — every existing source-paths.json entry continues to behave exactly as it did before the discriminator was introduced; `kind` is purely additive. Entries that explicitly set `kind: "external-doc"` receive the external-doc treatment described below.
90
90
@@ -96,7 +96,9 @@ A `research/source-paths.json` entry can carry an optional `kind` discriminator
96
96
}
97
97
```
98
98
99
-
**What `kind: "external-doc"` means.** The `path` field points at pre-curated markdown content that lives outside any code repository — for example, a generic accessibility reference, a SharePoint-style compliance snapshot, an authored markdown sourced outside the navigated code repos. The engine treats this content as a first-class source for [DISCOVER](08-discover-pipeline.md) without applying the git-managed SHA-then-clone flow. Harvest semantics:
99
+
**What `kind: "external-doc"` means.** The `path` field points at pre-curated markdown content that lives outside any code repository — for example, a generic accessibility reference, a SharePoint-style compliance snapshot, an authored markdown sourced outside the navigated code repos. The engine treats this content as a first-class source for [DISCOVER](08-discover-pipeline.md) without applying the git-managed SHA-then-clone flow. external-doc is **not a bootstrap-intake kind** — it carries a contextualizer-internal `path`, not a URL. Entries of this kind arrive in `research/source-paths.json` via DISCOVER, hand-edit, or a future workflow; the engine-bootstrap scaffolder produces `kind: "web-doc"` for doc-site URLs (see [`kind: "web-doc"`](#kind-web-doc)).
100
+
101
+
Harvest semantics:
100
102
101
103
***Directory `path`.** The `path` resolves to a directory containing one-or-more `.md` files, scanned **recursively** so nested subdirectories are included (the exact walk recipe — `find -L`, the `-type f -o -type l` filter, and symlink handling — is canonicalized in the Symlink containment paragraph below and the `external-doc-frontmatter` named check in the contextualizer-side `verify.sh` the plugin stamps at bootstrap). Recursion is deliberate — external-doc directories typically mirror upstream wiki or SharePoint hierarchies the maintainer has not flattened; a shallow scan would silently skip the bulk of the content.
102
104
***Single-file `path`.** A contextualizer that ships exactly one external-doc `.md` file (the canonical example: one accessibility best-practices markdown injected at a known path) supports `kind: "external-doc"` with `path` resolving directly to the `.md` file rather than wrapping it in a directory. The verify check handles both shapes uniformly.
Copy file name to clipboardExpand all lines: plugin/skill-engine/engine-bootstrap-templates/verify.sh
+38-4Lines changed: 38 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -213,10 +213,44 @@ else
213
213
*) fail "sources[$idx] ($id): status '$status' not in {intake, proposed, confirmed, rejected}"; entries_ok=0 ;;
214
214
esac
215
215
fi
216
-
if [ -z"$url" ] && [ -z"$path" ];then
217
-
fail "sources[$idx] ($id): neither url nor path is set — at least one is required"
218
-
entries_ok=0
219
-
fi
216
+
case"$kind"in
217
+
git-managed)
218
+
if [ -z"$url" ];then
219
+
fail "sources[$idx] ($id): url is required when kind is git-managed"
220
+
entries_ok=0
221
+
fi
222
+
;;
223
+
web-doc)
224
+
if [ -z"$url" ];then
225
+
fail "sources[$idx] ($id): url is required when kind is web-doc"
226
+
entries_ok=0
227
+
fi
228
+
if [ -n"$path" ];then
229
+
fail "sources[$idx] ($id): path '$path' set on kind 'web-doc' — web-doc sources are URL-addressed, not path-addressed"
230
+
entries_ok=0
231
+
fi
232
+
;;
233
+
external-doc)
234
+
if [ -z"$path" ];then
235
+
fail "sources[$idx] ($id): path is required when kind is external-doc"
236
+
entries_ok=0
237
+
fi
238
+
if [ -n"$url" ];then
239
+
fail "sources[$idx] ($id): url '$url' set on kind 'external-doc' — external-doc sources are path-addressed (pre-curated local markdown), not URL-addressed"
240
+
entries_ok=0
241
+
fi
242
+
;;
243
+
local-path)
244
+
if [ -z"$path" ];then
245
+
fail "sources[$idx] ($id): path is required when kind is local-path"
246
+
entries_ok=0
247
+
fi
248
+
if [ -n"$url" ];then
249
+
fail "sources[$idx] ($id): url '$url' set on kind 'local-path' — local-path sources are filesystem-addressed, not URL-addressed"
250
+
entries_ok=0
251
+
fi
252
+
;;
253
+
esac
220
254
if [ -n"$branch" ];then
221
255
if [ "$kind"!="git-managed" ];then
222
256
fail "sources[$idx] ($id): branch '$branch' set on kind '$kind' — branch is git-managed only"
|`git@github.com:<org>/<repo>.git`|`<org>-<repo>` (same rule, drop `.git`) |
148
-
|`https://<host>/<path...>` (external-doc) | last meaningful path segment, lowercased; if it's a file, drop the extension |
149
+
|`https://<host>/<path...>` (web-doc) | last meaningful path segment, lowercased; if it's a file, drop the extension. If the URL has no path segments (host-root like `https://docs.example.com/`), fall back to the host with non-alphanumerics → hyphen (e.g., `docs-example-com`).|
149
150
| Local absolute or relative path | basename of the resolved absolute path, lowercased |
150
151
151
152
On collision (two sources slug to the same id), append `-2`, `-3`, ... to the
@@ -263,31 +264,60 @@ locates the root itself from the project working directory.
263
264
### Stamping `research/source-paths.json`
264
265
265
266
Replace the empty `"sources": []` from the template with one entry per
266
-
intaken source, in the order supplied. Each entry:
267
+
intaken source, in the order supplied. The per-entry shape depends on
268
+
`kind`:
269
+
270
+
**`kind: "git-managed"`** — set `url`; add `"branch": "<name>"` only if
If the user supplied a non-default branch in Step 2.4 for this source,
286
-
add a `"branch": "<name>"` key alongside `url`. Omit the key entirely
287
-
when the user accepted the default — downstream code defaults to HEAD
288
-
when the field is absent. Never record an explicit `"branch": "main"`
289
-
or `"branch": "master"` from Step 2.4; the absent-field convention is
290
-
load-bearing for the future-proofing reason documented in Step 2.4.
317
+
Bootstrap does **not** produce `kind: "external-doc"` entries: that kind
318
+
is for pre-curated local `.md` content addressed by a contextualizer-
319
+
internal `path`, not for a URL the user pastes at intake. External-doc
320
+
entries land in `source-paths.json` via DISCOVER or hand-edit.
291
321
292
322
`schema_version: 1` from the template stays as-is. The schema is additive;
293
323
existing v1 files continue to parse cleanly.
@@ -641,3 +671,7 @@ the cache explicitly via `/skill-engine:clean-cache`.
641
671
intake would force a multi-source intake to abort halfway; failing on
642
672
DISCOVER lets the user paste the whole list and address broken entries
643
673
in batch.
674
+
- It does not produce `kind: "external-doc"` entries. external-doc
675
+
sources are pre-curated local markdown addressed by a contextualizer-
676
+
internal `path` (see [`02-artifact-contract.md`](https://github.com/nick-railsback/skill-engine/blob/main/plugin/skill-engine/docs/02-artifact-contract.md#kind-external-doc)); they arrive in `source-paths.json`
0 commit comments