Repository navigation
Landscape sweep: skills discovery modality keyed by lifecycle task, ledger support and pinned-CLI source reviews (unit A1) - #541
Conversation
|
Cross-family review (GPT-6 through the OmniRoute gateway, read-only). Note: the review diff was taken against the unit base e45328d after the branch had been rebuilt on 11227bf, so its "high" scope finding (346/327 files outside the allowlist, manifests/stack.json) is an artifact of the stale review base, not a change in this PR ( |
build_inputs.py took previous_sweep and the default baseline manifest from the ledger's last completed sweep of either modality, so a skills sweep after a repository sweep emptied the next repository run's history and became its baseline (GPT-6 review of #541, build_inputs.py:124). The ledger names a sweep's modality by its layers' catalogs (sweep_modality: repository for foundation and us-equities layers, skills for skills layers, none for a mixed or empty sweep), and each run now reads only the last completed sweep of its own modality. A modality with no completed sweep gets an empty history and no baseline, and the summary line names the sweep it read. Test: ModalityHistoryTests (repositories, skills, repositories: the third run reads the first; the skills run reads none). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…older hash and Codex's YAML reading Three findings of the GPT-6 review of #541 (source_reviews.py:331, :451, :498): - agents/openai.yaml: with PyYAML installed, yaml.compose_all (the libyaml CSafeLoader when present) builds the node tree and serde_yaml 0.9.34's rules from openai/codex rust-v0.157.1 decide: a plain true/false spelling only, anchors and aliases followed, a second document or a repeated field refused (Codex then ignores the file). Not safe_load: its YAML 1.1 constructor reads yes/no as booleans and drops the scalar style. Without PyYAML only the plain block-mapping subset is read; a flow mapping, an anchor or alias, a tag, a second document, a block scalar or any unrecognized line gives codex_implicit null with the reason, never a guessed true. The review records codex_implicit, unverified_reason and the reader. - Discovery validates each candidate SKILL.md before the CLI's location order applies, as vercel-labs/skills v1.7.0 parseSkillMd does (a name and a description, both non-empty strings, typed as the CLI's yaml package reads YAML 1.2 core scalars), and a copy whose name field names another skill is not a copy (filterSkills). An invalid earlier copy is skipped and recorded in observed.skipped_skill_md, a valid later copy wins, the recursive fallback runs only when no location holds a valid skill, and a skill whose every copy is invalid is refused. - A skill survivor is reviewed at its adjudicated pin and at no other commit: no pin, an unreadable pin or one that reads as another commit (pin_lookup failed), a null skill_md_sha256, or a later refusal (pin_lookup ok) gives no review and a stopped entry in the printed list. The review records the skill folder's git tree id (skill_folder_tree_sha, the CLI lock's skillFolderHash, src/blob.ts getSkillFolderHashFromTree), verified to cover the SKILL.md and agents/openai.yaml bytes read. make_result.py stops a layer with a stopped entry, and completes a skills layer only when each review's reviewed_commit is the adjudicated pin in the returns, over the judged skill_md_sha256, with the folder hash recorded. Tests: the YAML table under both readers (the PyYAML class runs when PyYAML is installed), git-oracle blob and tree ids, the three copy-validation cases, the unreadable pin, a moved pin, no pin and a null hash, the folder hash changing with agents/openai.yaml alone, a listing that does not cover the bytes read, and make_result.py's pin, hash, folder-hash and stopped-layer refusals. The existing review tests now give every survivor its pin and hash. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The README and the decision record said the ledger schema still left out the skills catalog and needed a future edit, but this branch adds it at catalogs/saturation/ledger.schema.json (GPT-6 review of #541, README.md:498). Both now describe the delivered schema and drop the obsolete prerequisite, and they describe what the repairs deliver: reviews at the adjudicated pin only, stopped layers, candidate validation, the skill folder's tree hash, Codex's reading of agents/openai.yaml with or without PyYAML, and each modality's own history. The decision record's sources add the pinned files the repairs rely on (vercel-labs/skills v1.7.0 parseSkillMd, filterSkills, getSkillFolderHashFromTree and package.json; eemeli/yaml v2.9.0's default schema; serde_yaml 0.9.34's bool, map and document rules), notes that the two resolver measurements predate candidate validation, and records the stricter review of a survivor with a null hash as a residual. Test: SkillsDocsTests. Co-Authored-By: Claude Opus 5.5 <[email protected]>
b531d95 to
fda9229
Compare
|
Repair round 2 (GPT-6 cross-family review), head
Failing first: every new test fails against the unchanged b531d95 source (assertion outputs retained in the coordinator's scratch evidence). Deviations from the review's wording, each recorded in the decision record: Checks on this head (scratch TMPDIR/HOME/XDG): 🤖 Generated with Claude Code |
|
Cross-family review (GPT-6 through the OmniRoute gateway, read-only, max effort) of the r2 delta 🤖 Generated with Claude Code |
…it the sweep wrapper, ultra disclosed and bounded, upstream reconnect kept, built-in provider restored The Claude Opus review of 9aff134 returned repair. A native gpt-6.1-sol builder at ultra applied the coordinator's decisions: - B1: the non-ultra total budget returns to 4000 s. An unqueued job plus probe, backstop, version check and grace takes 4140 s, inside the sweep wrapper's 8 x 540 = 4320 s wait (sweep.js:92). Ad-hoc lanes stage more. - M1: ultra is recorded honestly. For gpt-6.1-sol and gpt-6-astra, Codex resolves ultra to the model's multi_agent_reasoning_effort "xhigh" on every root request, plus proactive delegation (models-manager/models.json:22,196; protocol/src/openai_models/reasoning_effort.rs:12-35; core/src/client.rs:863-872). inputs.json and result now carry request_effort next to the staged effort. The live catalog cache agrees. - M2: a root multi-agent wait may block up to 3600 s with sub-agent items dropped from exec (core/src/config/mod.rs:257; exec/src/lib.rs:1624-1629). Ultra lanes therefore default to idle 4200 s and total 14400 s, and a staged ultra idle of 3600 s or less is refused. - M3: usage on ultra or delegated jobs is labelled primary_thread_only (exec/src/lib.rs:1636-1638), never complete. - M4 and L2: the unbounded-reconnect override and the named native provider are removed. The upstream default rides out outages, and the watchdog, which ignores error notices, stops a loop longer than the idle budget. The native lane is back on the built-in provider, as at the base. - L1: failure.json on every non-zero terminal path. - L3: invalid restaging records inputs_changed. - L4: wait uses the same completion rule as result. - L5: quota probe before every attempt. - L6: no retry or backoff without 300 s left. - L7: a turn that completed before the deadline gets kill_grace_s to exit and write its output; the test fake now follows upstream order. - L9: dated amendment to docs/decisions/2026-09-29-codex-lane-default-effort.md. It records the user's 2026-09-30 standard, the resolved-effort fact, the idle rule and the blind-lane exception. Tests: 166 OK (3 skipped). Live native checks on codex-cli 0.159.2 with this head: - max probe: done 0, request_effort max, usage reported; - ultra probe: done 0, request_effort xhigh, usage primary_thread_only; - SIGTERM control: failed 126 incomplete; - argv carries no reconnect override and no named provider. Callers outside this PR (sweep.js, convert.py, build_args.py, all touched by the open #541) are listed as residuals. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
Round-3 repair (GPT-6 cross-family review, two mediums). Head Medium 1, SKILL.md frontmatter typing ( Medium 2, openai.yaml escapes ( Also changed (same class: a copy passed over without the CLI's verdict; flagged for explicit review): a SKILL.md gh cannot read at the pin stops the survivor instead of being skipped (the CLI reads it from its clone; reverses r2's behaviour); names are compared as Failing-first (new tests on the fda9229 source): the list/mapping-description copy was reviewed instead of the valid later copy ( Checks at 1ffeaab: the 4-module unittest set 417 OK (8 skipped: 3 PyYAML-only, 2 jsonschema, 3 environment); Local oracle check (2026-09-30, no receipt): both readers match [email protected] plus parseSkillMd (run under node; the package whose integrity the CLI's lockfile pins) on all 2,455 SKILL.md files of the catalog's GitHub sources at their pins, and contradict it on none of 102 edge cases; Residuals: the PyYAML reader follows libyaml's YAML 1.1 grammar (a frontmatter PyYAML accepts but yaml refuses would be judged by PyYAML; none found); the subset reader does not validate nested indentation for keys other than name/description; license and disable-model-invocation are still read line by line; this host's default python3 has no PyYAML, so the subset reader is the path that runs here. Residuals from #549 (codex_job.py hardening) to carry after it merges: convert.py's request_effort/failure fields and primary_thread_only usage, build_args effort/web_search/budget flags, sweep.js's wait window. SOTA sources: vercel-labs/skills v1.7.0 🤖 Generated with Claude Code |
build_inputs.py took previous_sweep and the default baseline manifest from the ledger's last completed sweep of either modality, so a skills sweep after a repository sweep emptied the next repository run's history and became its baseline (GPT-6 review of #541, build_inputs.py:124). The ledger names a sweep's modality by its layers' catalogs (sweep_modality: repository for foundation and us-equities layers, skills for skills layers, none for a mixed or empty sweep), and each run now reads only the last completed sweep of its own modality. A modality with no completed sweep gets an empty history and no baseline, and the summary line names the sweep it read. Test: ModalityHistoryTests (repositories, skills, repositories: the third run reads the first; the skills run reads none). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…older hash and Codex's YAML reading Three findings of the GPT-6 review of #541 (source_reviews.py:331, :451, :498): - agents/openai.yaml: with PyYAML installed, yaml.compose_all (the libyaml CSafeLoader when present) builds the node tree and serde_yaml 0.9.34's rules from openai/codex rust-v0.157.1 decide: a plain true/false spelling only, anchors and aliases followed, a second document or a repeated field refused (Codex then ignores the file). Not safe_load: its YAML 1.1 constructor reads yes/no as booleans and drops the scalar style. Without PyYAML only the plain block-mapping subset is read; a flow mapping, an anchor or alias, a tag, a second document, a block scalar or any unrecognized line gives codex_implicit null with the reason, never a guessed true. The review records codex_implicit, unverified_reason and the reader. - Discovery validates each candidate SKILL.md before the CLI's location order applies, as vercel-labs/skills v1.7.0 parseSkillMd does (a name and a description, both non-empty strings, typed as the CLI's yaml package reads YAML 1.2 core scalars), and a copy whose name field names another skill is not a copy (filterSkills). An invalid earlier copy is skipped and recorded in observed.skipped_skill_md, a valid later copy wins, the recursive fallback runs only when no location holds a valid skill, and a skill whose every copy is invalid is refused. - A skill survivor is reviewed at its adjudicated pin and at no other commit: no pin, an unreadable pin or one that reads as another commit (pin_lookup failed), a null skill_md_sha256, or a later refusal (pin_lookup ok) gives no review and a stopped entry in the printed list. The review records the skill folder's git tree id (skill_folder_tree_sha, the CLI lock's skillFolderHash, src/blob.ts getSkillFolderHashFromTree), verified to cover the SKILL.md and agents/openai.yaml bytes read. make_result.py stops a layer with a stopped entry, and completes a skills layer only when each review's reviewed_commit is the adjudicated pin in the returns, over the judged skill_md_sha256, with the folder hash recorded. Tests: the YAML table under both readers (the PyYAML class runs when PyYAML is installed), git-oracle blob and tree ids, the three copy-validation cases, the unreadable pin, a moved pin, no pin and a null hash, the folder hash changing with agents/openai.yaml alone, a listing that does not cover the bytes read, and make_result.py's pin, hash, folder-hash and stopped-layer refusals. The existing review tests now give every survivor its pin and hash. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The README and the decision record said the ledger schema still left out the skills catalog and needed a future edit, but this branch adds it at catalogs/saturation/ledger.schema.json (GPT-6 review of #541, README.md:498). Both now describe the delivered schema and drop the obsolete prerequisite, and they describe what the repairs deliver: reviews at the adjudicated pin only, stopped layers, candidate validation, the skill folder's tree hash, Codex's reading of agents/openai.yaml with or without PyYAML, and each modality's own history. The decision record's sources add the pinned files the repairs rely on (vercel-labs/skills v1.7.0 parseSkillMd, filterSkills, getSkillFolderHashFromTree and package.json; eemeli/yaml v2.9.0's default schema; serde_yaml 0.9.34's bool, map and document rules), notes that the two resolver measurements predate candidate validation, and records the stricter review of a survivor with a null hash as a residual. Test: SkillsDocsTests. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…x_implicit unverified GPT-6 round-3 review of #541 (medium 2): without PyYAML, `note: "C:\skills"` beside `policy.allow_implicit_invocation: false` gave a definite codex_implicit false, while serde_yaml 0.9.34 scans with unsafe-libyaml 0.2.11 (src/scanner.rs lines 2195-2361), refuses the whole file ("found unknown escape character") and Codex then leaves implicit invocation on. The subset reader now checks, anywhere in the file, that each quoted scalar closes on its line and that each double-quoted one uses only YAML 1.2's escapes (\x, \u and \U with their 2, 4 and 8 hex digits; no surrogate and nothing beyond U+10FFFF, as libyaml), and otherwise reports codex_implicit null with the reason. With PyYAML the libyaml composer already refuses these files; the pure-Python SafeLoader took a surrogate escape and raised ValueError beyond U+10FFFF, and both now stay unverified as well. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…aml package does GPT-6 round-3 review of #541 (medium 1): a block-sequence description (`description:` then ` - Find bugs.`) was classified as a string, so an invalid find-bugs/SKILL.md still won over a valid skills/find-bugs/SKILL.md. The pinned CLI (vercel-labs/skills v1.7.0 src/skills.ts parseSkillMd, lines 80-133) parses the frontmatter with the yaml package 2.9.0 and skips a copy whose name or description is not a non-empty string. skill_md_check now types the frontmatter as that package does (YAML 1.2, core schema): with PyYAML, yaml.compose_all builds the tree and each scalar is typed by the core schema by its style, not by PyYAML's YAML 1.1 resolver; without it a subset reader covers one-line plain, quoted and flow values, multi-line plain scalars, literal and folded block scalars (strings, as the package reads them) and nested lists and mappings. A list, mapping or flow collection in name or description is an object, so that copy is skipped and a valid later copy wins. Neither reader guesses: a tag, an anchor or alias (subset reader), a key given twice, an escape YAML does not define, a file PyYAML cannot parse or syntax outside the subset leaves the copy unverified (SkillMdUnverified), and when its verdict decides which copy the CLI takes, the survivor is stopped (pin_lookup ok) instead of reviewed at a guessed copy; the fallback check waits for a verified SKILL.md before it trusts the recursive search. In the same class, a SKILL.md gh cannot read is unverified rather than skipped (the CLI reads it from its clone), and a copy's name is compared as the CLI records it (sanitizeMetadata, src/sanitize.ts lines 61-65; an empty one matches its folder, lines 331-333). Checked against yaml 2.9.0 run under node with parseSkillMd's checks: both readers agree on all 2,455 SKILL.md files of the catalog's GitHub sources at their pins, and give no contrary verdict on 102 edge cases; `npx [email protected] add <fixture> --list` skips the list and mapping copies with the same message. Co-Authored-By: Claude Opus 5.5 <[email protected]>
fda9229 to
1ffeaab
Compare
|
Independent Opus evidence review of the round-3 delta (the cross-family gateway review was at its pool cap): 🤖 Generated with Claude Code |
build_inputs.py took previous_sweep and the default baseline manifest from the ledger's last completed sweep of either modality, so a skills sweep after a repository sweep emptied the next repository run's history and became its baseline (GPT-6 review of #541, build_inputs.py:124). The ledger names a sweep's modality by its layers' catalogs (sweep_modality: repository for foundation and us-equities layers, skills for skills layers, none for a mixed or empty sweep), and each run now reads only the last completed sweep of its own modality. A modality with no completed sweep gets an empty history and no baseline, and the summary line names the sweep it read. Test: ModalityHistoryTests (repositories, skills, repositories: the third run reads the first; the skills run reads none). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…older hash and Codex's YAML reading Three findings of the GPT-6 review of #541 (source_reviews.py:331, :451, :498): - agents/openai.yaml: with PyYAML installed, yaml.compose_all (the libyaml CSafeLoader when present) builds the node tree and serde_yaml 0.9.34's rules from openai/codex rust-v0.157.1 decide: a plain true/false spelling only, anchors and aliases followed, a second document or a repeated field refused (Codex then ignores the file). Not safe_load: its YAML 1.1 constructor reads yes/no as booleans and drops the scalar style. Without PyYAML only the plain block-mapping subset is read; a flow mapping, an anchor or alias, a tag, a second document, a block scalar or any unrecognized line gives codex_implicit null with the reason, never a guessed true. The review records codex_implicit, unverified_reason and the reader. - Discovery validates each candidate SKILL.md before the CLI's location order applies, as vercel-labs/skills v1.7.0 parseSkillMd does (a name and a description, both non-empty strings, typed as the CLI's yaml package reads YAML 1.2 core scalars), and a copy whose name field names another skill is not a copy (filterSkills). An invalid earlier copy is skipped and recorded in observed.skipped_skill_md, a valid later copy wins, the recursive fallback runs only when no location holds a valid skill, and a skill whose every copy is invalid is refused. - A skill survivor is reviewed at its adjudicated pin and at no other commit: no pin, an unreadable pin or one that reads as another commit (pin_lookup failed), a null skill_md_sha256, or a later refusal (pin_lookup ok) gives no review and a stopped entry in the printed list. The review records the skill folder's git tree id (skill_folder_tree_sha, the CLI lock's skillFolderHash, src/blob.ts getSkillFolderHashFromTree), verified to cover the SKILL.md and agents/openai.yaml bytes read. make_result.py stops a layer with a stopped entry, and completes a skills layer only when each review's reviewed_commit is the adjudicated pin in the returns, over the judged skill_md_sha256, with the folder hash recorded. Tests: the YAML table under both readers (the PyYAML class runs when PyYAML is installed), git-oracle blob and tree ids, the three copy-validation cases, the unreadable pin, a moved pin, no pin and a null hash, the folder hash changing with agents/openai.yaml alone, a listing that does not cover the bytes read, and make_result.py's pin, hash, folder-hash and stopped-layer refusals. The existing review tests now give every survivor its pin and hash. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The README and the decision record said the ledger schema still left out the skills catalog and needed a future edit, but this branch adds it at catalogs/saturation/ledger.schema.json (GPT-6 review of #541, README.md:498). Both now describe the delivered schema and drop the obsolete prerequisite, and they describe what the repairs deliver: reviews at the adjudicated pin only, stopped layers, candidate validation, the skill folder's tree hash, Codex's reading of agents/openai.yaml with or without PyYAML, and each modality's own history. The decision record's sources add the pinned files the repairs rely on (vercel-labs/skills v1.7.0 parseSkillMd, filterSkills, getSkillFolderHashFromTree and package.json; eemeli/yaml v2.9.0's default schema; serde_yaml 0.9.34's bool, map and document rules), notes that the two resolver measurements predate candidate validation, and records the stricter review of a survivor with a null hash as a residual. Test: SkillsDocsTests. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…x_implicit unverified GPT-6 round-3 review of #541 (medium 2): without PyYAML, `note: "C:\skills"` beside `policy.allow_implicit_invocation: false` gave a definite codex_implicit false, while serde_yaml 0.9.34 scans with unsafe-libyaml 0.2.11 (src/scanner.rs lines 2195-2361), refuses the whole file ("found unknown escape character") and Codex then leaves implicit invocation on. The subset reader now checks, anywhere in the file, that each quoted scalar closes on its line and that each double-quoted one uses only YAML 1.2's escapes (\x, \u and \U with their 2, 4 and 8 hex digits; no surrogate and nothing beyond U+10FFFF, as libyaml), and otherwise reports codex_implicit null with the reason. With PyYAML the libyaml composer already refuses these files; the pure-Python SafeLoader took a surrogate escape and raised ValueError beyond U+10FFFF, and both now stay unverified as well. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…aml package does GPT-6 round-3 review of #541 (medium 1): a block-sequence description (`description:` then ` - Find bugs.`) was classified as a string, so an invalid find-bugs/SKILL.md still won over a valid skills/find-bugs/SKILL.md. The pinned CLI (vercel-labs/skills v1.7.0 src/skills.ts parseSkillMd, lines 80-133) parses the frontmatter with the yaml package 2.9.0 and skips a copy whose name or description is not a non-empty string. skill_md_check now types the frontmatter as that package does (YAML 1.2, core schema): with PyYAML, yaml.compose_all builds the tree and each scalar is typed by the core schema by its style, not by PyYAML's YAML 1.1 resolver; without it a subset reader covers one-line plain, quoted and flow values, multi-line plain scalars, literal and folded block scalars (strings, as the package reads them) and nested lists and mappings. A list, mapping or flow collection in name or description is an object, so that copy is skipped and a valid later copy wins. Neither reader guesses: a tag, an anchor or alias (subset reader), a key given twice, an escape YAML does not define, a file PyYAML cannot parse or syntax outside the subset leaves the copy unverified (SkillMdUnverified), and when its verdict decides which copy the CLI takes, the survivor is stopped (pin_lookup ok) instead of reviewed at a guessed copy; the fallback check waits for a verified SKILL.md before it trusts the recursive search. In the same class, a SKILL.md gh cannot read is unverified rather than skipped (the CLI reads it from its clone), and a copy's name is compared as the CLI records it (sanitizeMetadata, src/sanitize.ts lines 61-65; an empty one matches its folder, lines 331-333). Checked against yaml 2.9.0 run under node with parseSkillMd's checks: both readers agree on all 2,455 SKILL.md files of the catalog's GitHub sources at their pins, and give no contrary verdict on 102 edge cases; `npx [email protected] add <fixture> --list` skips the list and mapping copies with the same message. Co-Authored-By: Claude Opus 5.5 <[email protected]>
1ffeaab to
9e1bd44
Compare
|
Round-4 repair (the independent Opus review of round 3, verdict needs_changes). Head The reader is now the CLI's own code (
Other changes in the same commit:
Docs (
The "neither reader guesses" claim is removed. Receipt (
For a decision: the yaml release. The coordinator should choose which yaml release to pin.
Failing-first. The final tests were run against the round-3 source (1ffeaab):
Findings 2 and 4: each review input was reviewed instead of losing to the valid later copy. For example, the PyYAML reader took Finding 3:
Finding 5: form feed, vertical tab, \x01 and \x1c gave Finding 7: the symlink case stopped with only Finding 1: the docs test found "Neither reader guesses". Finding 6: the non-root name cases already passed on round-3 code. Two reader mutants show they discriminate:
Checks at 44b1f74d:
Residuals:
SOTA sources:
🤖 Generated with Claude Code Coordinator addendum (c5). Final head |
The dry build on the real catalog showed known_skill_refs at 292 refs (7.9 KB of every skills layer input, and of every GPT-6 prompt that embeds it), many invented: an excluded manifest entry that names several repositories was cross-multiplied into owner/repo@name pairs the manifest never claims (microsoft/playwright-cli@webapp-testing). known_skills keeps the installed skills by repository and the excluded skills by the manifest's own source text (4.4 KB). The two skills templates that named the field follow, so the skills-run prompts_sha256 pin moves to 5d9ae85a...48db; the repository pin is unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The skills modality's layers had no ledger path: --report listed only
research-state.json rows, so build_args.py --due-report selected no
skills layer ("no layer selected"), and --append refused
skills/skills-debug as "not a layer in research-state.json".
saturation_ledger.py now reads catalogs/landscape/skills-lifecycle.json
as catalog "skills" layers (skills-<task>) beside the research-state
rows. skills_requirement_sha256 hashes a task's lifecycle_task,
requirement and overturn_when; build_inputs.py --skills-scope will call
it, so the frozen scope and the ledger share one definition. --report
lists every task after the research-state layers (research status "-"),
--append completes a skills RESULT.json, and --check accepts catalog
skills. A SOTA-convergence manifest has no skills section, so a skills
survivor binds to its retained votes and its source review instead of a
manifest row; repository layers keep their manifest binding. A changed
task requirement is a current requirement_changed trigger citing the
skills catalog. --scope is unchanged.
Tests: a skills sweep appends and checks, the report lists skills layers
as due (and the --report --json rows build_args.py reads), unknown
skills layers and mis-bound survivors are refused, and the committed
checkout's report lists all 13 tasks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review findings 1, 3, 5 and 7. - known_skills: the committed adoption/skills/manifest.json states each excluded entry's skills as one comma-separated string, and the loop iterated its characters (363 of 363 excluded values were single characters in the dry build). excluded_names splits on commas and keeps each name or phrase whole; a list is taken item by item. The input fixtures now use the committed string shape, with one list-shaped entry, and a new test builds inputs from the committed catalog and manifest: no known_skills value has length 1, and obra/superpowers lists systematic-debugging. - Whole texts: an installed skill's gap was cut at 300 characters with no marker (variant-analysis, writing-for-agents, security-audit lost text mid-word). The skills modality now passes the gap, the task's open gaps and its overturn_when whole; repository layers keep their caps. - --skills-scope computes each requirement hash with saturation_ledger.skills_requirement_sha256, the ledger's own definition. - Stale source: gh api 'repos/openai/skills/commits?sha=main&since= 2026-07-02T00:00:00Z&per_page=1' returns no commit; the last main commit, 49f948fa, is dated 2026-06-24, 98 days before the check, so the common block's 90-day maintenance rule marks it stale. The catalog records that as a maintenance record on openai-skills (status, check date, API fact), keeps the source for its four installed skills, and adds "Stale source: replacement via this sweep" to skills-ci-pr and skills-security. The other 21 GitHub sources were checked the same way and are maintained (catalog notes). check_skills_catalog validates the optional record. - The two model-invocable requirements say "no true-valued disable-model-invocation (true/yes/on/1)". Co-Authored-By: Claude Opus 5.5 <[email protected]>
…-for doc edits Review finding 4 and 7, GPT-6 review finding (c). - Claude Code accepts true, yes, on and 1 (and false, no, off, 0) in any letter case for boolean frontmatter since v2.1.218 (code.claude.com/docs/en/skills, Frontmatter reference). discover_skills and modality_skills now say "a true-valued disable-model-invocation (true/yes/on/1) in any letter case" instead of the literal "disable-model-invocation: true". - Codex rust-v0.157.1 reads agents/openai.yaml with serde_yaml 0.9.34, whose bool is only a plain true/True/TRUE or false/False/FALSE, and ignores the whole file when it cannot deserialize it (codex-rs/ext/skills/src/loader/metadata.rs, "Fail open"). Both templates ask for a plain false and say that a quoted or other value leaves implicit invocation on. - discover_skills labels the skills of a source whose catalog entry carries a stale maintenance record not_adopted, citing the record, unless a maintained fork or replacement is found (the common block's rule: "no commit on its default branch in the last 90 days"); modality_skills tells the refuters such a source is stale under it. - Writing CLAUDE.md or AGENTS.md conflicts with the canonical instructions only on the skill's own initiative: editing them when asked is skills-agent-docs' requirement, which the unconditional rule contradicted. Failing first: the skills-run prompts_sha256 pin moved from 5d9ae85a...48db to 2c2efbae...63d3 and the template-phrase test failed on the old literal; the repository-run pin (9c34fa72...f14b) passed unchanged, since only skills templates changed. Co-Authored-By: Claude Opus 5.5 <[email protected]>
… adjudicated pin Review finding 2, review finding 4 (Claude booleans), GPT-6 review findings (a) and (b). - Discovery order: skill_review refused any skill whose folder name occurs twice in the tree, which at the catalog pins refused 254 of affaan-m/ECC's 296 names (translations under docs/<lang>/skills, agent copies under .kiro/skills and .agents/skills), 2 of microsoft/skills' and 1 of openai/skills'. cli_skill_dir now follows vercel-labs/skills v1.7.0 discoverSkills (src/skills.ts at 7407f389, lines 180-329; README "Skill Discovery", lines 412-483): a valid root SKILL.md is the only skill; then the root's child folders, skills/ with .curated, .experimental and .system, and the 30 AGENT_PROJECT_SKILL_DIRS, each three levels deep with a shallower SKILL.md shadowing the folders below it; then the folders .claude-plugin manifests declare (plugin-manifest.ts getPluginSkillPaths); and only when none holds a skill, every folder five levels deep. The first location holding the name decides; only two same-named folders there are refused, as are a truncated tree and folders outside these locations (docs/ needs --full-depth). Where the README's folder list differs from the code (31 extra, 7 missing), the code decides. Checked on 2026-09-30: the resolver matches `npx [email protected] add <repo> --list` exactly on six sources (ECC 294, microsoft/skills 13, trailofbits/skills 83, openai/skills 43, mattpocock/skills 37, vercel-labs/agent-browser 1), and all 28 installed skills resolve to their manifest path at their manifest ref. - Adjudicated pin: convert.py writes a skills survivor's pin and skill_md_sha256 into survivors.json, and the review reads the SKILL.md at that pin, falling back to the default branch only when gh cannot read the pin, and saying so in claim and observed.pin_fallback. A SKILL.md whose sha256 differs from the adjudicated one is refused; one skill judged at two pins gets one review per pin. - agents/openai.yaml: openai_yaml_policy reads the documented policy mapping in block and flow form as Codex rust-v0.157.1 does (serde_yaml 0.9.34: only a plain true/false is a bool; a quoted or other value, a repeated key or a tab-indented line makes Codex ignore the file, which leaves implicit invocation on), and records the value as written. PyYAML is not installed on the review host, so no loader is added. - Frontmatter: a trailing comment no longer breaks a name, and disable-model-invocation reads Claude Code's boolean set (true, yes, on, 1 in any letter case). Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review finding 6. make_result.py --decision-record printed "No proposal survived." for a layer whose proposals were refuted and for a layer that lost workers alike. It now lists RESULT.json lost_workers in the context (mapping <role>:<layer>[:followup] and the critic to layers with sweep_common.deviation_rounds, and naming labels that map to no layer), and per layer says whether it has survivors, lost workers (incomplete, not a refutation; its reopen entries keep it from counting as clean), only refuted proposals, or no proposal at all. Co-Authored-By: Claude Opus 5.5 <[email protected]>
README (Skills modality): whole excluded names and texts; the stale-source record; the invocation flags as Claude Code and Codex read them; the unasked-write rule for CLAUDE.md and AGENTS.md; source reviews at the adjudicated pin in the pinned skills CLI's discovery order; and the "reported and skipped" cases stated with make_result.py's gate (a skipped survivor blocks RESULT.json until resolved or the run is recorded as stopped). The ledger bullet replaces "Not yet in the ledger" and names the one remaining gap: ledger.schema.json's catalog enum, which is outside this unit. Decision record: live-page citations use section anchors and the fetched snapshot's sha256 instead of line numbers (two same-day fetches of code.claude.com's skills.md differed); the skills CLI and Codex/serde_yaml facts with their tag commits; the rejected self-written review rule; the stale source; the ledger binding; and named residuals (schema enum, resolver limits, not run). Co-Authored-By: Claude Opus 5.5 <[email protected]>
GPT-6 review finding (d) in the suite: build_args.select_layers over a
skills work directory's rows with the committed checkout's
saturation_ledger.py report selects exactly its due skills layers, and a
report without skills rows (the ledger before a5e830ab) still raises
"no layer selected". Failing first against the previous head's code: no
skills row was due ("[] is not true").
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The skills modality records its layers as catalog "skills"; the ledger's row schema listed only foundation and us-equities. The README names the third value. Co-Authored-By: Claude Opus 5.5 <[email protected]>
build_inputs.py took previous_sweep and the default baseline manifest from the ledger's last completed sweep of either modality, so a skills sweep after a repository sweep emptied the next repository run's history and became its baseline (GPT-6 review of #541, build_inputs.py:124). The ledger names a sweep's modality by its layers' catalogs (sweep_modality: repository for foundation and us-equities layers, skills for skills layers, none for a mixed or empty sweep), and each run now reads only the last completed sweep of its own modality. A modality with no completed sweep gets an empty history and no baseline, and the summary line names the sweep it read. Test: ModalityHistoryTests (repositories, skills, repositories: the third run reads the first; the skills run reads none). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…older hash and Codex's YAML reading Three findings of the GPT-6 review of #541 (source_reviews.py:331, :451, :498): - agents/openai.yaml: with PyYAML installed, yaml.compose_all (the libyaml CSafeLoader when present) builds the node tree and serde_yaml 0.9.34's rules from openai/codex rust-v0.157.1 decide: a plain true/false spelling only, anchors and aliases followed, a second document or a repeated field refused (Codex then ignores the file). Not safe_load: its YAML 1.1 constructor reads yes/no as booleans and drops the scalar style. Without PyYAML only the plain block-mapping subset is read; a flow mapping, an anchor or alias, a tag, a second document, a block scalar or any unrecognized line gives codex_implicit null with the reason, never a guessed true. The review records codex_implicit, unverified_reason and the reader. - Discovery validates each candidate SKILL.md before the CLI's location order applies, as vercel-labs/skills v1.7.0 parseSkillMd does (a name and a description, both non-empty strings, typed as the CLI's yaml package reads YAML 1.2 core scalars), and a copy whose name field names another skill is not a copy (filterSkills). An invalid earlier copy is skipped and recorded in observed.skipped_skill_md, a valid later copy wins, the recursive fallback runs only when no location holds a valid skill, and a skill whose every copy is invalid is refused. - A skill survivor is reviewed at its adjudicated pin and at no other commit: no pin, an unreadable pin or one that reads as another commit (pin_lookup failed), a null skill_md_sha256, or a later refusal (pin_lookup ok) gives no review and a stopped entry in the printed list. The review records the skill folder's git tree id (skill_folder_tree_sha, the CLI lock's skillFolderHash, src/blob.ts getSkillFolderHashFromTree), verified to cover the SKILL.md and agents/openai.yaml bytes read. make_result.py stops a layer with a stopped entry, and completes a skills layer only when each review's reviewed_commit is the adjudicated pin in the returns, over the judged skill_md_sha256, with the folder hash recorded. Tests: the YAML table under both readers (the PyYAML class runs when PyYAML is installed), git-oracle blob and tree ids, the three copy-validation cases, the unreadable pin, a moved pin, no pin and a null hash, the folder hash changing with agents/openai.yaml alone, a listing that does not cover the bytes read, and make_result.py's pin, hash, folder-hash and stopped-layer refusals. The existing review tests now give every survivor its pin and hash. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The README and the decision record said the ledger schema still left out the skills catalog and needed a future edit, but this branch adds it at catalogs/saturation/ledger.schema.json (GPT-6 review of #541, README.md:498). Both now describe the delivered schema and drop the obsolete prerequisite, and they describe what the repairs deliver: reviews at the adjudicated pin only, stopped layers, candidate validation, the skill folder's tree hash, Codex's reading of agents/openai.yaml with or without PyYAML, and each modality's own history. The decision record's sources add the pinned files the repairs rely on (vercel-labs/skills v1.7.0 parseSkillMd, filterSkills, getSkillFolderHashFromTree and package.json; eemeli/yaml v2.9.0's default schema; serde_yaml 0.9.34's bool, map and document rules), notes that the two resolver measurements predate candidate validation, and records the stricter review of a survivor with a null hash as a residual. Test: SkillsDocsTests. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…x_implicit unverified GPT-6 round-3 review of #541 (medium 2): without PyYAML, `note: "C:\skills"` beside `policy.allow_implicit_invocation: false` gave a definite codex_implicit false, while serde_yaml 0.9.34 scans with unsafe-libyaml 0.2.11 (src/scanner.rs lines 2195-2361), refuses the whole file ("found unknown escape character") and Codex then leaves implicit invocation on. The subset reader now checks, anywhere in the file, that each quoted scalar closes on its line and that each double-quoted one uses only YAML 1.2's escapes (\x, \u and \U with their 2, 4 and 8 hex digits; no surrogate and nothing beyond U+10FFFF, as libyaml), and otherwise reports codex_implicit null with the reason. With PyYAML the libyaml composer already refuses these files; the pure-Python SafeLoader took a surrogate escape and raised ValueError beyond U+10FFFF, and both now stay unverified as well. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…aml package does GPT-6 round-3 review of #541 (medium 1): a block-sequence description (`description:` then ` - Find bugs.`) was classified as a string, so an invalid find-bugs/SKILL.md still won over a valid skills/find-bugs/SKILL.md. The pinned CLI (vercel-labs/skills v1.7.0 src/skills.ts parseSkillMd, lines 80-133) parses the frontmatter with the yaml package 2.9.0 and skips a copy whose name or description is not a non-empty string. skill_md_check now types the frontmatter as that package does (YAML 1.2, core schema): with PyYAML, yaml.compose_all builds the tree and each scalar is typed by the core schema by its style, not by PyYAML's YAML 1.1 resolver; without it a subset reader covers one-line plain, quoted and flow values, multi-line plain scalars, literal and folded block scalars (strings, as the package reads them) and nested lists and mappings. A list, mapping or flow collection in name or description is an object, so that copy is skipped and a valid later copy wins. Neither reader guesses: a tag, an anchor or alias (subset reader), a key given twice, an escape YAML does not define, a file PyYAML cannot parse or syntax outside the subset leaves the copy unverified (SkillMdUnverified), and when its verdict decides which copy the CLI takes, the survivor is stopped (pin_lookup ok) instead of reviewed at a guessed copy; the fallback check waits for a verified SKILL.md before it trusts the recursive search. In the same class, a SKILL.md gh cannot read is unverified rather than skipped (the CLI reads it from its clone), and a copy's name is compared as the CLI records it (sanitizeMetadata, src/sanitize.ts lines 61-65; an empty one matches its folder, lines 331-333). Checked against yaml 2.9.0 run under node with parseSkillMd's checks: both readers agree on all 2,455 SKILL.md files of the catalog's GitHub sources at their pins, and give no contrary verdict on 102 edge cases; `npx [email protected] add <fixture> --list` skips the list and mapping copies with the same message. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…nd openai.yaml escapes The sweep README and the decision record describe the frontmatter readers (PyYAML's composer typed by the YAML 1.2 core schema, else the subset reader), the unverified outcome that stops a survivor instead of deciding the CLI's pick by a guess, the name as sanitizeMetadata records it, and the openai.yaml escape check. The decision record replaces the obsolete residual (the frontmatter read line by line) with the readers' limits, records the 2026-09-30 check against yaml 2.9.0, and cites eemeli/yaml v2.9.0, vercel-labs/skills v1.7.0 src/sanitize.ts and unsafe-libyaml 0.2.11. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…s each SKILL.md copy The hand-written SKILL.md frontmatter readers (the PyYAML composer reader and the subset reader) are gone: an independent review of round 3 found both still giving a verdict on frontmatter the CLI's yaml package reads otherwise. skill_md.mjs runs vercel-labs/skills v1.7.0's parseSkillMd, parseFrontmatter, sanitizeMetadata and getSkillDisplayName (src/skills.ts L80-133 and L331-333, src/frontmatter.ts, src/sanitize.ts L18-65 at 7407f389, ported line by line) with the yaml package skills-yaml.pin.json pins (2.9.0 and its npm integrity, the CLI lockfile's), after checking every pinned file's sha256 and the install's lockfile integrity, following the tree-sitter-bash pin pattern (shell-parser.pin.json). It installs nothing; without node or a verified install every copy is unverified and the survivor stops. A line break other than LF or CRLF in a frontmatter gives no verdict (libyaml, which Codex's serde_yaml uses, breaks lines there and the yaml package does not). Every SKILL.md copy read is tied to the regular-file blob the git tree lists (a symlink, missing content or other bytes are unverified), plugin manifests likewise, and the license and disable-model-invocation come from the same parse. agents/openai.yaml keeps its readers, behind a pre-check: bytes that are not UTF-8, characters outside libyaml's printable set (unsafe-libyaml 0.2.11 src/reader.rs L381-395) and line breaks other than LF and CRLF give codex_implicit null with the reason. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…hat it leaves unverified The README's Skills modality section and the decision record said neither frontmatter reader guesses, which an independent review of round 3 refuted (finding 1). They now describe skill_md.mjs and skills-yaml.pin.json (the CLI's parseSkillMd ported line by line, run with the pinned yaml 2.9.0 after its files and lockfile integrity are checked, nothing installed at run time) and name what stays unverified: no node or install, a line break other than LF or CRLF in a frontmatter, a copy that is not the listed regular-file blob, symlinked folders, Claude Code's own parser, the openai.yaml checks, and CI, which does not provision the pin yet. They record that npm resolves the CLI's yaml ^2.8.3 at install time (2.9.1 on 2026-09-30, also this host's install) and that 2.9.0 and 2.9.1 gave the same results, with the receipt. Co-Authored-By: Claude Opus 5.5 <[email protected]>
… own parseSkillMd and skills add --list evidence/artifacts/skills-md-reader-20260930: skill_md.mjs against two oracles on all 2,455 SKILL.md files of the skills catalog's 22 GitHub sources at their pins and on 139 edge cases (the round-3 review's inputs, line breaks, the name rules, the yaml 2.9.1 changes): parseSkillMd and its helpers sliced byte for byte from the published [email protected] dist/cli.mjs, run with the yaml its install resolved (2.9.1) and with the pinned 2.9.0 (local integration check), and the installed CLI's skills add <fixture> --list (independent observation). Corpus: take/take 2,452, skip/skip 3, 0 contradictions, 0 field differences; the CLI lists the same 1,693 names and warns on the same 3 copies. Edge: 0 contradictions; the 9 cases with a line break other than LF or CRLF get no verdict by design. yaml 2.9.0 and 2.9.1 gave identical results there and on 200,000 random multi-line scalars. Four negative controls (two reader mutants, a flipped verdict, a tampered install) fail as they must. run.sh reproduces it; log.txt and counts.json keep every step's exit status and the digests of the raw outputs kept outside the repository. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…CI installs the yaml pin Opus round-4 review of #541, D1: discoverSkills walks each search location with readdir, which follows a symlink at or above it (published dist/cli.mjs L1339-1370), and skips a symlinked skill folder inside one (entry.isDirectory() is false, src/skills.ts L284-298 and L141-149), while the git tree lists a symlink as one blob and nothing below it. The review named a later copy the CLI throws away (seenNames, L1352). location_doubt now marks a location at or below a symlink, and a folder whose SKILL.md is a symlink with skill folders below it; plugin_manifests marks the plugin folders unknown when .claude-plugin is a symlink or a manifest has no verified bytes. Reaching such a location before the pick is decided stops the survivor (LocationUnverified); one after it cannot change the pick. Failing-first on 9e1bd44: all five symlink layouts were reviewed at the wrong copy (exit 0). .github/workflows/validate.yml installs skills-yaml.pin.json before the suite with the tree-sitter step's pattern (a declared widening of A1's paths to this one workflow file), and tests/test_landscape_sweep_skills.py holds it there as tests/test_shell_parser_ci.py holds the tree-sitter pin: a runtime tripwire, structure checks, a ratchet over whole-suite jobs (validate-macos and freshness are recorded gaps) and mutation controls. Also the round-4 test gaps: --skills-yaml, the environment over the HOME default, and the load_error refusal. A comment at the gh read records the .gitattributes checkout transforms as a residual. Co-Authored-By: Claude Opus 5.5 <[email protected]>
… de-duplication and the clone scoped Opus round-4 review of #541. README and decision record: the CLI walks a search location through a symlink at or above it and skips a symlinked skill folder inside one (the round-4 sentence had it backwards), and such a location reached before the pick is decided stops the survivor. The record's name rule now states the actual consequence of de-duplication (add keeps the first skill of a name, dist/cli.mjs L1352; only the update paths at L7382 and L7588 keep duplicates, so the review can name a copy the CLI throws away), scopes "a GitHub source is cloned before discovery" to a source named with a ref (L4101-4102, L5190-5212), lists .gitattributes checkout transforms (LFS, eol, working-tree-encoding) as a residual, and records the CI provisioning of the yaml pin with its two recorded gaps. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…d the CI provisioning of the yaml pin evidence/artifacts/skills-md-reader-20260930, rerun at the round-5 code (33 steps, 2026-09-30 23:45:46Z to 23:46:42Z; code under test by sha256: skill_md.mjs and skills-yaml.pin.json unchanged, source_reviews.py new). The reader results are unchanged (corpus take/take 2,452, skip/skip 3; edge 0 contradictions, 9 line-break refusals; skills add --list agreement; yaml 2.9.0 = 2.9.1). New: symlink_impact.py (8 of 22 sources hold symlinks, 3 a symlinked search location, none a symlinked SKILL.md; all 678 picks unchanged by the rule) and ci_step.py (the pin's 75 hashes are the bytes of the registry tarball whose sha512 is the pinned integrity; validate.yml's step, run with npm 10.9.8, exits 0 and exports the directory; the reader under Node.js 22.23.2 verifies that install). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ick that could depend on it Two cases the round-5 symlink tests missed: .claude-plugin/marketplace.json as a symlink (readFile follows it; the review reads no verified bytes) stops a survivor whose pick would come from the plugin folders or the recursive search, and leaves the review of a pick decided at skills/. Round 4 stopped every review of a repository with a symlinked manifest, with the reason "the git tree lists a symlink at .claude-plugin/...". Decision record: the two includeDuplicateNames: true call sites (dist/cli.mjs L7382, L7588) are named as the update paths, and the symlink residual names the layout it over-stops (.agents/skills -> ../skills searched before a later pick). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ink_impact.py symlink_impact.py now marks the plugin folders unknown for a manifest that is not a regular file, as source_reviews.plugin_manifests does. Rerun at 6643ba60 (33 steps, 2026-09-30 23:56:37Z to 23:57:35Z): no source has a plugin manifest behind a symlink, and every other result is unchanged (679 names, 678 picks equal with and without the rule; the reader and CI provisioning results as before). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…or named, the retired skill dropped Unit F3 (#553), below this PR in the stack, pins skill-creator (anthropics/skills@8a1541c4, trial, codex_enabled false), retires resolving-merge-conflicts and widens the Claude listings and Codex enablement. Built against main's manifest, A1 failed 35 tests on the stack. - build_args.py: TEMPLATE_SKILLS gains skill-creator, which the skills templates already name for its paired with-skill/without-skill benchmark; templates.json common's Skills paragraph names it for Claude Code only (Codex ships a different skill of that name), read and never run. Both prompts_sha256 pins move (repository 9c34fa72...f14b -> b61956f3...726d, skills 2c2efbae...63d3 -> a76ee858...b460). - catalogs/landscape/skills-lifecycle.json: skill-creator serves skills-skill-lifecycle; resolving-merge-conflicts leaves skills-ci-pr, retired by unit F3 (#553), whose open gap now says no installed skill resolves rebase conflicts; the open gaps that stated pre-F3 codex_enabled and listing values are removed or restated, and skills-agent-docs' requirement points skill authoring at skill-creator. - tests: a catalog test holds each flag an open gap states to the manifest (12 stale statements fail it on the previous catalog); the whole-gap input test bounds security-audit's gap by the 600-character cut, since F3 shortened it to 930 characters. - README and decision record: the repository run's prompts_sha256 moved once; the 28-skill path check is scoped to the manifest before F3. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…d rerun run.sh's step() wrote the oracle-versions command's final newline into log.txt as a trailing space, which git diff --check reported on line 26; the line is this receipt's own log format, not retained tool output, so the logger now strips trailing blanks and the receipt was run again (2026-10-01 00:56:03Z to 00:57:01Z, 33 steps, the same exit statuses). Against the 2026-09-30 run, log.txt differs only in its times and that trailing space, and counts.json only in the run times, the checkout commit and the hashes of raw outputs kept outside the repository (the scratch path, node process ids and npm timings inside them). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…(hot-file protocol) Co-Authored-By: Claude Opus 5.5 <[email protected]>
6daf0e8 to
3e9af33
Compare
|
Cross-family review of the round-6 delta (the two stacked-state repair commits above |
Scope
catalogs/landscape/skills-lifecycle.json), with a strictdiscover-skills.jsonschema (skill identity at a pin,model_invocable,codex_implicit,replaces), skills-specific discover and critic templates that reuse the facts and fit refuters, source reviews performed at the adjudicated pin in the pinned skills CLI's own discovery order, a decision-record writer, andscripts/saturation_ledger.pyreporting and recordingskills-*layers so--due-reportselects them. Repository layers and their prompts are unchanged.11227bfd(origin/main at rebase)lane:foundationtools/sota-convergence/landscape-sweep/{README.md,build_args.py,build_inputs.py,convert.py,make_prompt.py,make_result.py,source_reviews.py,sweep.js,templates.json,schemas/discover-skills.json},catalogs/landscape/skills-lifecycle.json(new),catalogs/README.md,catalogs/saturation/ledger.schema.json(+"skills"catalog) andcatalogs/saturation/README.md,scripts/saturation_ledger.py,docs/decisions/2026-09-30-skills-sweep-modality.md(new),tests/test_landscape_sweep_harness.py,tests/test_landscape_sweep_skills.py(new),tests/test_saturation_ledger.py;manifests/evidence.json(re-registration only, last commit).true; the installed skill's gap text was silently truncated; nestedagents/openai.yamlpolicy blocks parsed wrong; the templates rejected any skill that writes AGENTS.md/CLAUDE.md, contradicting theskills-agent-docstask; the ledger did not select skills layers. openai/skills is recorded as a stale source (nomaincommit since 2026-06-24) and its skills are labellednot_adoptedunless a maintained replacement is found.SOTA sources
7407f389):src/skills.tsdiscoverSkills(L180-329),AGENT_PROJECT_SKILL_DIRS(L12-43),src/plugin-manifest.ts,src/add.ts,src/blob.ts(L306-342); README "Skill Discovery" (L412-483) and "Plugin Manifest Discovery" (L485-505). The resolver was checked against the realnpx [email protected] add <repo> --liston six sources (ECC 294, microsoft/skills 13, trailofbits 83, openai/skills 43, mattpocock 37, agent-browser 1; exact match).36650394):codex-rs/ext/skills/src/loader/metadata.rs(L27-56, 130-139),codex-rs/skills/src/model.rs; serde_yaml 0.9.34 (2009506d)src/de.rsparse_boolL932-938,parse_nullL925-930,deserialize_optionL1517-1558.8d22bd7e…c811d(2026-09-30); developers.openai.com/codex/skills, Optional metadata (sha256d1579156…6a20); agentskills.io/specification, Frontmatter (sha2564c649bdf…9e11).templates.jsoncommon block, OpenSSF Scorecard Maintained);gh api commits?since=checks of the 22 GitHub sources on 2026-09-30.docs/decisions/2026-09-25-skills-trial-and-usage.md,adoption/skills/manifest.json,scripts/saturation_ledger.py.Evidence-class table
python3 scripts/validate.pypassed; the three registry tests OK;tests.test_sota_convergenceOKTMPDIR=/dev/shm/ntci-tmp python3 -m unittest tests.test_landscape_sweep_harness tests.test_saturation_ledger tests.test_sota_convergence tests.test_landscape_sweep_skills: 386 tests OK (5 environment skips)--liston six sourcesgh apitrees at the pins;npx [email protected] add <repo> --listbuild_inputs.py --skills-scope;build_inputs.py --work-dir <W> --modality skills(13 skills layers);build_args.py --smoke skills-researchexit 0; known_skills values whole (167 values, 0 single characters)python3 scripts/saturation_ledger.py --check: ok, chain intactNo model calls and no sweep run. The GPT-6 lane has not yet exercised the schema's
patternandminimumfields in strict mode; the first live skills sweep (unit D1) is the check.Local commands run
Decision record
docs/decisions/2026-09-30-skills-sweep-modality.md(alternatives: a separate skills sweep script vs a modality in the packaged sweep; overturn: a measured run showing the modality cannot express a skills verdict; citations by section anchor plus snapshot sha256).Host evidence
No files under
evidence/hosts/changed.Checklist
.github/workflows/validate.ymlgains the yaml-pin provisioning step (derived fromskills-yaml.pin.json, exported throughGITHUB_ENV; zizmor 1.30.1 no findings, actionlint 1.17.0 exit 0; held in place bytests/test_landscape_sweep_skills.py).🤖 Generated with Claude Code