@codedrifters/configulator 0.0.272 → 0.0.273
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/lib/index.d.mts +34 -1
- package/lib/index.d.ts +34 -1
- package/lib/index.js +294 -1
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +292 -1
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.mjs
CHANGED
|
@@ -8737,6 +8737,295 @@ var extractApiProcedure = {
|
|
|
8737
8737
|
description: "Run @microsoft/api-extractor for a single package and write the .api.md rollup to the scratch folder declared by the package's api-extractor.json. Rollups are regenerate-on-scan per docs-sync epic #448 resolved decision #3 \u2014 never committed to git.",
|
|
8738
8738
|
content: renderExtractApiProcedure()
|
|
8739
8739
|
};
|
|
8740
|
+
function renderCheckLinksProcedure() {
|
|
8741
|
+
return [
|
|
8742
|
+
"#!/usr/bin/env bash",
|
|
8743
|
+
"# check-links.sh \u2014 Link integrity checker for the Starlight docs site.",
|
|
8744
|
+
"#",
|
|
8745
|
+
"# Usage:",
|
|
8746
|
+
"# .claude/procedures/check-links.sh <mode> <docs-root> [<site-dir>]",
|
|
8747
|
+
"#",
|
|
8748
|
+
"# Where:",
|
|
8749
|
+
"# <mode> \u2014 one of `internal`, `external`, or `all`.",
|
|
8750
|
+
"# <docs-root> \u2014 path to the markdown content tree",
|
|
8751
|
+
"# (e.g. `docs/src/content/docs`). Walked recursively",
|
|
8752
|
+
"# for `*.md` / `*.mdx` files.",
|
|
8753
|
+
"# <site-dir> \u2014 (optional, internal/all only) path to the Starlight",
|
|
8754
|
+
"# project root that contains `astro.config.{ts,mjs,js}`.",
|
|
8755
|
+
"# Defaults to two levels up from `<docs-root>` so the",
|
|
8756
|
+
"# standard Starlight layout (`<site>/src/content/docs`)",
|
|
8757
|
+
"# resolves automatically.",
|
|
8758
|
+
"#",
|
|
8759
|
+
"# Wraps two external tools:",
|
|
8760
|
+
"# - `astro check` \u2014 internal links and content-collection refs",
|
|
8761
|
+
"# inside the Starlight site.",
|
|
8762
|
+
"# - `lychee` \u2014 external `https://\u2026` URLs across the docs tree",
|
|
8763
|
+
"# (https://github.com/lycheeverse/lychee).",
|
|
8764
|
+
"#",
|
|
8765
|
+
"# Output (stdout, single JSON array):",
|
|
8766
|
+
"#",
|
|
8767
|
+
"# [",
|
|
8768
|
+
"# {",
|
|
8769
|
+
'# "url": "<href as written in the markdown source>",',
|
|
8770
|
+
'# "docPath": "<path relative to <docs-root>>",',
|
|
8771
|
+
'# "line": <1-indexed line number>,',
|
|
8772
|
+
'# "kind": "internal" | "external",',
|
|
8773
|
+
'# "reason": "<short tool-supplied diagnostic>"',
|
|
8774
|
+
"# },",
|
|
8775
|
+
"# ...",
|
|
8776
|
+
"# ]",
|
|
8777
|
+
"#",
|
|
8778
|
+
"# An empty array (`[]`) is emitted when no broken links are found.",
|
|
8779
|
+
"# Detection is **data**, not failure: this helper exits 0 when a",
|
|
8780
|
+
"# tool ran successfully and reported zero or more broken links.",
|
|
8781
|
+
"# The downstream docs-sync scan phase (#519/#520) is responsible",
|
|
8782
|
+
"# for deciding which findings are advisory and which block.",
|
|
8783
|
+
"#",
|
|
8784
|
+
"# Exit codes:",
|
|
8785
|
+
"# 0 \u2014 every requested tool ran successfully; findings (zero or",
|
|
8786
|
+
"# more) are on stdout as a JSON array.",
|
|
8787
|
+
"# 1 \u2014 usage error (missing args, unreadable docs root).",
|
|
8788
|
+
"# 2 \u2014 a required external tool is not installed or not on PATH",
|
|
8789
|
+
"# (`astro` / `lychee` / `node` / `jq`).",
|
|
8790
|
+
"# 3 \u2014 a tool ran but exited non-zero for a reason other than",
|
|
8791
|
+
"# broken-link detection (config error, IO error, network",
|
|
8792
|
+
"# failure for lychee, etc.). Stderr carries the diagnostic.",
|
|
8793
|
+
"#",
|
|
8794
|
+
"# The script never edits files. Diagnostics flow to stderr; the",
|
|
8795
|
+
"# only thing on stdout is the normalized JSON array.",
|
|
8796
|
+
"",
|
|
8797
|
+
"set -uo pipefail",
|
|
8798
|
+
"",
|
|
8799
|
+
"err() {",
|
|
8800
|
+
' printf "check-links.sh: %s\\n" "$*" >&2',
|
|
8801
|
+
"}",
|
|
8802
|
+
"",
|
|
8803
|
+
'if [ "$#" -lt 2 ]; then',
|
|
8804
|
+
' err "usage: check-links.sh <internal|external|all> <docs-root> [<site-dir>]"',
|
|
8805
|
+
" exit 1",
|
|
8806
|
+
"fi",
|
|
8807
|
+
"",
|
|
8808
|
+
'mode="$1"',
|
|
8809
|
+
'docs_root="$2"',
|
|
8810
|
+
'site_dir="${3:-}"',
|
|
8811
|
+
"",
|
|
8812
|
+
'case "$mode" in',
|
|
8813
|
+
" internal | external | all) ;;",
|
|
8814
|
+
" *)",
|
|
8815
|
+
` err "unknown mode '$mode' \u2014 expected 'internal', 'external', or 'all'"`,
|
|
8816
|
+
" exit 1",
|
|
8817
|
+
" ;;",
|
|
8818
|
+
"esac",
|
|
8819
|
+
"",
|
|
8820
|
+
'if [ ! -d "$docs_root" ]; then',
|
|
8821
|
+
' err "docs root not found: $docs_root"',
|
|
8822
|
+
" exit 1",
|
|
8823
|
+
"fi",
|
|
8824
|
+
"",
|
|
8825
|
+
'if [ -z "$site_dir" ]; then',
|
|
8826
|
+
" # Standard Starlight layout: <site>/src/content/docs. Walk two",
|
|
8827
|
+
" # parents up from the content root to recover the site dir.",
|
|
8828
|
+
' site_dir="$(cd "$docs_root/../../.." && pwd)"',
|
|
8829
|
+
"fi",
|
|
8830
|
+
"",
|
|
8831
|
+
"# `jq` is required to merge the per-tool JSON output streams. Fail",
|
|
8832
|
+
"# fast with the dedicated tool-missing exit code if it is absent.",
|
|
8833
|
+
"if ! command -v jq >/dev/null 2>&1; then",
|
|
8834
|
+
' err "jq is required but not on PATH"',
|
|
8835
|
+
" exit 2",
|
|
8836
|
+
"fi",
|
|
8837
|
+
"",
|
|
8838
|
+
'tmp_dir="$(mktemp -d -t check-links-XXXXXX)"',
|
|
8839
|
+
"# shellcheck disable=SC2064",
|
|
8840
|
+
`trap "rm -rf '$tmp_dir'" EXIT`,
|
|
8841
|
+
"",
|
|
8842
|
+
'internal_json="$tmp_dir/internal.json"',
|
|
8843
|
+
'external_json="$tmp_dir/external.json"',
|
|
8844
|
+
'printf "[]" > "$internal_json"',
|
|
8845
|
+
'printf "[]" > "$external_json"',
|
|
8846
|
+
"",
|
|
8847
|
+
"# ---------------------------------------------------------------",
|
|
8848
|
+
"# Internal-link check",
|
|
8849
|
+
"# ---------------------------------------------------------------",
|
|
8850
|
+
"# `astro check` runs inside the Starlight project root and walks",
|
|
8851
|
+
"# content collections to validate internal references. It exits",
|
|
8852
|
+
"# non-zero when references are broken \u2014 that is a *finding* for",
|
|
8853
|
+
"# this helper, not a tool failure, so we capture stderr and parse",
|
|
8854
|
+
"# it into the normalized record shape rather than propagating the",
|
|
8855
|
+
"# non-zero exit.",
|
|
8856
|
+
'if [ "$mode" = "internal" ] || [ "$mode" = "all" ]; then',
|
|
8857
|
+
" if ! command -v node >/dev/null 2>&1; then",
|
|
8858
|
+
' err "node is required but not on PATH"',
|
|
8859
|
+
" exit 2",
|
|
8860
|
+
" fi",
|
|
8861
|
+
"",
|
|
8862
|
+
' if [ ! -d "$site_dir" ]; then',
|
|
8863
|
+
' err "site dir not found: $site_dir"',
|
|
8864
|
+
" exit 1",
|
|
8865
|
+
" fi",
|
|
8866
|
+
"",
|
|
8867
|
+
" # Locate the astro binary in the site's local node_modules first",
|
|
8868
|
+
" # so the version matches what `pnpm install` resolved for the",
|
|
8869
|
+
" # Starlight site. Fall back to a workspace-aware `pnpm exec`.",
|
|
8870
|
+
' if [ -x "$site_dir/node_modules/.bin/astro" ]; then',
|
|
8871
|
+
' astro_bin=("$site_dir/node_modules/.bin/astro")',
|
|
8872
|
+
" elif command -v pnpm >/dev/null 2>&1; then",
|
|
8873
|
+
' astro_bin=(pnpm --dir "$site_dir" exec astro)',
|
|
8874
|
+
" else",
|
|
8875
|
+
' err "astro binary not found in $site_dir/node_modules/.bin and pnpm is unavailable"',
|
|
8876
|
+
" exit 2",
|
|
8877
|
+
" fi",
|
|
8878
|
+
"",
|
|
8879
|
+
' astro_log="$tmp_dir/astro.log"',
|
|
8880
|
+
" set +e",
|
|
8881
|
+
' ( cd "$site_dir" && "${astro_bin[@]}" check ) > "$astro_log" 2>&1',
|
|
8882
|
+
" astro_status=$?",
|
|
8883
|
+
" set -e",
|
|
8884
|
+
"",
|
|
8885
|
+
" # `astro check` exits 1 on findings and >=2 on tool failure.",
|
|
8886
|
+
" # Translate to the normalized record stream regardless of exit.",
|
|
8887
|
+
' if [ "$astro_status" -ge 2 ]; then',
|
|
8888
|
+
' err "astro check exited with status $astro_status (tool failure)"',
|
|
8889
|
+
' cat "$astro_log" >&2 || true',
|
|
8890
|
+
" exit 3",
|
|
8891
|
+
" fi",
|
|
8892
|
+
"",
|
|
8893
|
+
" # Parse the line-oriented log into JSON records. The `astro",
|
|
8894
|
+
" # check` output for a broken reference looks like:",
|
|
8895
|
+
" #",
|
|
8896
|
+
" # src/content/docs/foo.md:42:8 - error <code>: <reason>",
|
|
8897
|
+
" #",
|
|
8898
|
+
" # The helper extracts `<docPath>`, `<line>`, and `<reason>` and",
|
|
8899
|
+
" # synthesises a `url` field by quoting the offending excerpt",
|
|
8900
|
+
" # when astro reports one (it does not always); when no excerpt",
|
|
8901
|
+
" # is available we fall back to an empty string so the schema",
|
|
8902
|
+
" # stays uniform.",
|
|
8903
|
+
` awk -v docs_root="$docs_root" -v site_dir="$site_dir" '`,
|
|
8904
|
+
" BEGIN {",
|
|
8905
|
+
' printf "[";',
|
|
8906
|
+
" first = 1;",
|
|
8907
|
+
" }",
|
|
8908
|
+
' # Match "<path>:<line>:<col> - <severity> <code>: <message>"',
|
|
8909
|
+
" /^.+:[0-9]+:[0-9]+ - / {",
|
|
8910
|
+
' split($0, head, " - ");',
|
|
8911
|
+
' n = split(head[1], loc, ":");',
|
|
8912
|
+
" file = loc[1];",
|
|
8913
|
+
' for (i = 2; i < n - 1; i++) { file = file ":" loc[i]; }',
|
|
8914
|
+
" line = loc[n - 1];",
|
|
8915
|
+
' message = "";',
|
|
8916
|
+
" for (i = 2; i <= length(head); i++) {",
|
|
8917
|
+
' if (i > 2) message = message " - ";',
|
|
8918
|
+
" message = message head[i];",
|
|
8919
|
+
" }",
|
|
8920
|
+
" # Resolve the file relative to docs_root for stability.",
|
|
8921
|
+
" abs = file;",
|
|
8922
|
+
' if (substr(abs, 1, 1) != "/") {',
|
|
8923
|
+
' abs = site_dir "/" abs;',
|
|
8924
|
+
" }",
|
|
8925
|
+
' sub(docs_root "/", "", abs);',
|
|
8926
|
+
' gsub(/"/, "\\\\\\"", message);',
|
|
8927
|
+
' gsub(/"/, "\\\\\\"", abs);',
|
|
8928
|
+
' if (!first) printf ",";',
|
|
8929
|
+
" first = 0;",
|
|
8930
|
+
' printf "{\\"url\\":\\"\\",\\"docPath\\":\\"%s\\",\\"line\\":%s,\\"kind\\":\\"internal\\",\\"reason\\":\\"%s\\"}", abs, line, message;',
|
|
8931
|
+
" }",
|
|
8932
|
+
" END {",
|
|
8933
|
+
' printf "]";',
|
|
8934
|
+
" }",
|
|
8935
|
+
` ' "$astro_log" > "$internal_json"`,
|
|
8936
|
+
"",
|
|
8937
|
+
" # Validate the JSON we synthesised. Catches awk escaping bugs",
|
|
8938
|
+
" # before we hand the payload to the merge step.",
|
|
8939
|
+
' if ! jq -e . "$internal_json" >/dev/null 2>&1; then',
|
|
8940
|
+
' err "failed to normalize astro check output to JSON"',
|
|
8941
|
+
' cat "$internal_json" >&2 || true',
|
|
8942
|
+
" exit 3",
|
|
8943
|
+
" fi",
|
|
8944
|
+
"fi",
|
|
8945
|
+
"",
|
|
8946
|
+
"# ---------------------------------------------------------------",
|
|
8947
|
+
"# External-link check",
|
|
8948
|
+
"# ---------------------------------------------------------------",
|
|
8949
|
+
"# `lychee` walks the markdown tree and reports unreachable URLs.",
|
|
8950
|
+
"# Its `--format json` output is structured per-link; we project",
|
|
8951
|
+
"# only the failed entries into the normalized record shape.",
|
|
8952
|
+
'if [ "$mode" = "external" ] || [ "$mode" = "all" ]; then',
|
|
8953
|
+
" if ! command -v lychee >/dev/null 2>&1; then",
|
|
8954
|
+
' err "lychee is required but not on PATH (https://github.com/lycheeverse/lychee)"',
|
|
8955
|
+
" exit 2",
|
|
8956
|
+
" fi",
|
|
8957
|
+
"",
|
|
8958
|
+
' lychee_json="$tmp_dir/lychee.json"',
|
|
8959
|
+
" set +e",
|
|
8960
|
+
" # `--no-progress` avoids interactive carriage-returns mangling",
|
|
8961
|
+
" # the JSON. `--format json` emits a single object whose `fail_map`",
|
|
8962
|
+
" # field lists the broken URLs grouped by source file.",
|
|
8963
|
+
" # `--exclude-mail` skips mailto: links (out of scope for this",
|
|
8964
|
+
" # helper).",
|
|
8965
|
+
' lychee --no-progress --format json --exclude-mail "$docs_root" > "$lychee_json" 2>"$tmp_dir/lychee.err"',
|
|
8966
|
+
" lychee_status=$?",
|
|
8967
|
+
" set -e",
|
|
8968
|
+
"",
|
|
8969
|
+
" # lychee exits 0 when every link resolved, 2 when one or more",
|
|
8970
|
+
" # links failed. Anything else is a tool failure (config, IO).",
|
|
8971
|
+
' if [ "$lychee_status" -ne 0 ] && [ "$lychee_status" -ne 2 ]; then',
|
|
8972
|
+
' err "lychee exited with status $lychee_status (tool failure)"',
|
|
8973
|
+
' cat "$tmp_dir/lychee.err" >&2 || true',
|
|
8974
|
+
" exit 3",
|
|
8975
|
+
" fi",
|
|
8976
|
+
"",
|
|
8977
|
+
" # Project lychee's `fail_map` into the normalized record shape.",
|
|
8978
|
+
' # The `fail_map` is `{ "<source-path>": [ { url, status: { details? } }, ... ] }`.',
|
|
8979
|
+
" # lychee does not report a line number for every match, so we",
|
|
8980
|
+
" # default to 0 when it is missing (downstream consumers treat",
|
|
8981
|
+
' # 0 as "unknown line").',
|
|
8982
|
+
` jq --arg root "$docs_root" '`,
|
|
8983
|
+
" def trim_root($p; $r):",
|
|
8984
|
+
' if ($p | startswith($r + "/")) then ($p | ltrimstr($r + "/"))',
|
|
8985
|
+
' elif ($p == $r) then ""',
|
|
8986
|
+
" else $p end;",
|
|
8987
|
+
" [",
|
|
8988
|
+
" ( .fail_map // {} ) as $map",
|
|
8989
|
+
" | $map | to_entries[]",
|
|
8990
|
+
" | .key as $src",
|
|
8991
|
+
" | .value[]",
|
|
8992
|
+
" | {",
|
|
8993
|
+
' url: (.url // ""),',
|
|
8994
|
+
" docPath: trim_root($src; $root),",
|
|
8995
|
+
" line: ((.line // 0) | tonumber? // 0),",
|
|
8996
|
+
' kind: "external",',
|
|
8997
|
+
' reason: ( (.status.details // .status.text // .status.code // "broken") | tostring )',
|
|
8998
|
+
" }",
|
|
8999
|
+
" ]",
|
|
9000
|
+
` ' "$lychee_json" > "$external_json" 2>"$tmp_dir/lychee.parse.err"`,
|
|
9001
|
+
"",
|
|
9002
|
+
' if ! jq -e . "$external_json" >/dev/null 2>&1; then',
|
|
9003
|
+
' err "failed to parse lychee JSON output"',
|
|
9004
|
+
' cat "$tmp_dir/lychee.parse.err" >&2 || true',
|
|
9005
|
+
' cat "$lychee_json" >&2 || true',
|
|
9006
|
+
" exit 3",
|
|
9007
|
+
" fi",
|
|
9008
|
+
"fi",
|
|
9009
|
+
"",
|
|
9010
|
+
"# ---------------------------------------------------------------",
|
|
9011
|
+
"# Merge & emit",
|
|
9012
|
+
"# ---------------------------------------------------------------",
|
|
9013
|
+
"# Sort records deterministically (kind, docPath, line, url) so",
|
|
9014
|
+
"# downstream consumers can compare reports across runs without",
|
|
9015
|
+
"# fighting platform-specific ordering noise.",
|
|
9016
|
+
"jq -s '",
|
|
9017
|
+
" add",
|
|
9018
|
+
" | sort_by(.kind, .docPath, .line, .url)",
|
|
9019
|
+
`' "$internal_json" "$external_json"`,
|
|
9020
|
+
"",
|
|
9021
|
+
"exit 0"
|
|
9022
|
+
].join("\n");
|
|
9023
|
+
}
|
|
9024
|
+
var checkLinksProcedure = {
|
|
9025
|
+
name: "check-links.sh",
|
|
9026
|
+
description: "Link integrity checker that wraps `astro check` (internal links) and `lychee` (external URLs) and normalizes their output into a single JSON-array stream of { url, docPath, line, kind, reason } records. Detection is data: the helper exits 0 when a tool ran successfully regardless of how many broken links it reported. Non-zero exits are reserved for tool-level failures.",
|
|
9027
|
+
content: renderCheckLinksProcedure()
|
|
9028
|
+
};
|
|
8740
9029
|
function buildDocsSyncBundle(paths = DEFAULT_AGENT_PATHS) {
|
|
8741
9030
|
return {
|
|
8742
9031
|
name: "docs-sync",
|
|
@@ -8786,7 +9075,7 @@ function buildDocsSyncBundle(paths = DEFAULT_AGENT_PATHS) {
|
|
|
8786
9075
|
],
|
|
8787
9076
|
skills: [buildDocsSyncPrSkill(), buildDocsSyncAuditSkill()],
|
|
8788
9077
|
subAgents: [buildDocsSyncSubAgent(paths)],
|
|
8789
|
-
procedures: [extractApiProcedure],
|
|
9078
|
+
procedures: [extractApiProcedure, checkLinksProcedure],
|
|
8790
9079
|
labels: [
|
|
8791
9080
|
{
|
|
8792
9081
|
name: "type:docs-sync",
|
|
@@ -31262,6 +31551,7 @@ export {
|
|
|
31262
31551
|
buildStandardsResearchBundle,
|
|
31263
31552
|
buildUnblockDependentsProcedure,
|
|
31264
31553
|
businessModelsBundle,
|
|
31554
|
+
checkLinksProcedure,
|
|
31265
31555
|
classifyIssueScope,
|
|
31266
31556
|
classifyRun,
|
|
31267
31557
|
companyProfileBundle,
|
|
@@ -31285,6 +31575,7 @@ export {
|
|
|
31285
31575
|
regulatoryResearchBundle,
|
|
31286
31576
|
renderAgentTierCaseStatement,
|
|
31287
31577
|
renderAgentTierSection,
|
|
31578
|
+
renderCheckLinksProcedure,
|
|
31288
31579
|
renderCustomDocSectionBlock,
|
|
31289
31580
|
renderCustomDocSections,
|
|
31290
31581
|
renderExtractApiProcedure,
|