Skip to content

Implement manifest schema 8, first-party module roots, and install marker v4 - #40

Merged
ivanopcode merged 1 commit into
mainfrom
feat/schema-8-module-roots
Aug 24, 2026
Merged

Implement manifest schema 8, first-party module roots, and install marker v4#40
ivanopcode merged 1 commit into
mainfrom
feat/schema-8-module-roots

Conversation

@ivanopcode

Copy link
Copy Markdown
Owner

Adopts the schema-8 additions of Curator Protocol core sections 4.1.1, 4.2.3, and 10, against curator-spec candidate/schema-8-rc.9 at 6001dc33281b94a4ec7442ab15278550dd0f51d9.

Manifest schema 8

agent-skill.json and csk-skill.json accept schema_version: 8 with two optional fields:

  • modules on a local go-v1 build command: the first-party Go modules of the same package that the build root replaces. Absent or empty keeps the schema-6 and schema-7 meaning of a single-module build root.
  • the co-required execution_policy + interpreter pair on a script command. Both value spaces are closed (script-worker-v1; python3-v1 and node-v1), and a manifest declaring one without the other is invalid.

Schemas 1 through 7 reject all three fields at the top level and on every command. Schemas 2 through 7 reject them as unknown fields; schema 1 rejects them through its reserved-field check, because schema 1 keeps its deployed extension behavior.

Module roots

New src/csk/builds/module_roots.py owns the three steps of the manager profile's fixed order so they stay separable:

  1. Before the fixed go list, the declaration is validated against the frozen snapshot alone: portable relative path other than ., unique, real link-free directory, go.mod directly inside, and pairwise disjoint from every other declared module, every declared build root, and every runtime root under exact and platform-path comparison.
  2. After go list returns and before go build, the effective replace set is read only from <build root>/vendor/modules.txt. Selection annotations reconcile against their unversioned-left directives, which is what rejects a versioned left side without parsing go.mod. Only directory form is admitted, and the correspondence with the declaration is checked in both directions.
  3. The scan surface then runs with the declared directories included and the audited-vendor allowance withheld from replaced modules.

_validate_module no longer rejects every Module.Replace; it admits one exactly on the bijected set. Module.Replace.Dir and .GoMod are never read as evidence a path exists. No build input, cache key, receipt identity, or artifact-relative path changes.

Diagnostics: build_module_root_declaration_invalid, build_module_root_containment_invalid, build_module_root_directive_form_unsupported, build_module_root_directive_undeclared, build_module_root_declaration_unused.

Fail-closed script execution policy

csk implements no script execution policy. A command selecting script-worker-v1 is refused with script_execution_policy_unsupported at csk check and at install, before any mutation, and installer.install_runtime_commands refuses it however it is reached. It is never downgraded to a declared-only shim, because that shim would run package code the manifest says is contained.

Install marker v4

InstallMarkerV3 and the new InstallMarkerV4 share one body: same object shape, same build-entry semantics, same top-level build_source and build_roots rules. v4 binds skill_schema_version 8 exactly, v3 still binds 7 exactly. A schema-8 mutation writes v4, schema 7 writes v3, schemas 1 through 6 write v2, and markers 1 through 4 are read.

Verification

  • python -m mypy exit 0.
  • python -m pytest -q -n 8 exit 0: 1630 passed, 244 skipped.
  • Same suite with CURATOR_CONFORMANCE_ROOT pointed at the curator-spec ref this repo's CI pins (0c81c1f) exit 0: 2735 passed, 84 skipped.
  • A local probe ran all 132 candidate agent-skill-v8 / csk-skill-v8 schema cases through skillspec.load_skill_spec: 0 mismatches. It caught the one real defect found after the first pass, an explicit null being read as absence for modules, execution_policy, and interpreter.

New test modules: tests/test_module_roots.py, tests/test_skillspec_schema8.py, tests/test_install_marker_v4.py, tests/test_install_schema8.py. test_csk_skill_future_schema_fails moved from schema_version: 8 to 9, because 8 is now supported.

Known gap, not introduced here

The candidate install-marker-v4 schema cases disagree with csk on 4 of 27. The identical 4 of 27 fail for install-marker-v3 against both the candidate root and the pinned rc.6 root, so they are pre-existing schema-7 external-repository substitution gaps that marker v4 inherits along with marker v3's body: a branch substitution ref is rejected, a local-path substitution against a network-git effective identity is accepted, and a substitution revision whose hex width contradicts object_format is accepted. tests/test_protocol_conformance.py drives schema cases only for the names in IN_SCOPE_SCHEMA_NAMES, which contains no install-marker-v3 entry, so CI does not surface them. Fixing them means changing schema-7 substitution validation, a different manifest band whose correct expectations live in the rc.9 candidate suite. Recorded in LOGBOOK.md.

Out of scope

The rc.9 candidate conformance consumer and the CI candidate-lane ref generalization are separate tasks. This branch does not touch .github/workflows/ci.yml.

@ivanopcode
ivanopcode force-pushed the feat/schema-8-module-roots branch from 7fec2da to a14a3a2 Compare August 24, 2026 15:15
Adopt the schema-8 additions of Curator Protocol core sections 4.1.1, 4.2.3,
and 10 against curator-spec candidate/schema-8-rc.9.

Manifest schema 8 admits two optional fields. A local go-v1 build command may
declare `modules`, the first-party Go modules of the same package that its
build root replaces. A script command may select the enforced execution policy
with the co-required `execution_policy` and `interpreter` pair, whose value
spaces are closed. Schemas 1 through 7 reject all three fields at the top level
and on every command; schema 1 rejects them through its reserved-field check
because it keeps its deployed extension behavior.

Module roots follow the manager profile's fixed order. The declaration is
validated against the frozen snapshot alone before the fixed `go list`:
portable relative path other than ".", unique, real link-free directory,
`go.mod` directly inside, pairwise disjoint from every other declared module,
every build root, and every runtime root under exact and platform-path
comparison. After `go list` returns and before `go build`, the effective
replace set is read only from `<build root>/vendor/modules.txt`, selection
annotations are reconciled against their unversioned-left directives, every
versioned side and every module-to-module redirect is rejected, and the
one-to-one correspondence with the declaration is checked in both directions.
A package resolving through a replacement is then admitted exactly on the
bijected set, the scan surface extends over the declared directories and their
vendor copies, and the audited-vendor allowance is withheld from a module
carrying a replacement. No build input, cache key, receipt, or artifact path
changes.

csk implements no script execution policy, so a command selecting
`script-worker-v1` is refused with `script_execution_policy_unsupported` at
`csk check` and at install, and the single shim publication point refuses it
however it is reached. Downgrading such a command to a declared-only shim would
run package code the manifest says is contained.

Install marker v4 carries marker-v3 meaning over a schema-8 manifest: same
object shape, same build-entry semantics, same top-level build_source and
build_roots rules. A schema-8 mutation writes v4, schema 7 still writes v3,
schemas 1 through 6 still write v2, and markers 1 through 4 are read.
@ivanopcode
ivanopcode force-pushed the feat/schema-8-module-roots branch from a14a3a2 to 1c6b68e Compare August 24, 2026 15:31
@ivanopcode
ivanopcode merged commit 66068a1 into main Aug 24, 2026
16 checks passed
@ivanopcode
ivanopcode deleted the feat/schema-8-module-roots branch August 24, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant