Repository navigation
Spec gap: no way to author a composition-only manifest where the model is unknowable #256
Description
Activity
Decision: option 1, a composition-only profile with declared unbound artifacts.
Recording the shape so this is actionable without re-deriving it.
Why this over the narrower fix
model_attestation_type: "unbound"would have been a smaller change, and it only fixes the model. A repository-scoped manifest has the same problem withdecision_traceandmemory_baseline: there is no execution to trace and no memory state, because the model and the session do not exist yet. Fixing one field would leave the other two needing the same workaround.It also matches a rule that already proved necessary elsewhere in this stack. The capture engines had a defect where an unmeasured category rendered as a measured zero, and the fix was to state the absence rather than let a reader infer it.
unbound_artifactsis that rule applied to manifests: an artifact that is deliberately not bound is named, so a verifier can distinguish "this manifest does not cover the model" from "this manifest is malformed".Proposed shape
{ "@type": "AgentManifest", "profile": "composition-only", "unbound_artifacts": ["model_identity", "decision_trace", "memory_baseline"], "artifacts": { "system_prompt": { "...": "..." }, "policy_bundle": { "...": "..." }, "tool_manifest": { "...": "..." } } }Suggested rules:
profiledefaults to the current full-binding behaviour when absent, so every existing manifest stays conformant and nothing needs reissuing.unbound_artifactsis REQUIRED and non-empty whenprofileiscomposition-only, and MUST NOT list an artifact that also appears inartifacts. Declaring and binding the same artifact is a contradiction, not a preference.- Verification returns
NOT_BOUNDfor each declared artifact, which is the value section 5.2 already defines and which nothing can currently produce. - A composition-only manifest is not eligible for Level 0 or above. Levels assert an agent instance; this asserts a contribution to one. Better to say so than to invent a Level -1.
- Conformance tests: a composition-only manifest verifies with
NOT_BOUNDon declared artifacts; one that omits an artifact without declaring it stays non-conformant; one that both declares and binds the same artifact is rejected.
Consumer that needs it
agentrust-io/integrationscopilot measures what a repository contributes to GitHub Copilot:.github/copilot-instructions.md,.github/instructions/**,AGENTS.mdanywhere in the tree, three skill roots, and MCP config. It currently emits nothing and claims nointegrates_with, because every workaround formodel_identitywould be an unverifiable claim. This unblocks it, and the same applies to any CI gate, policy check, or marketplace scanning a published skill.Happy to implement once the shape is agreed.
Where this came from
Building an agent-integrity check for GitHub Copilot in agentrust-io/integrations#68. It measures what a repository contributes to an agent's composition:
.github/copilot-instructions.md,.github/instructions/**,AGENTS.mdanywhere in the tree,.github/skills/*,.claude/skills/*,.agents/skills/*, and MCP config. Those files decide how the coding agent behaves, they arrive by pull request, and they are reviewable.It cannot emit an Agent Manifest, and I think the reason is a genuine gap rather than a limitation of the integration.
The problem
Level 0 requires all artifact bindings (section on levels: "Software-only | All artifact bindings"), and
artifacts.model_identityis artifact 4.A repository cannot know the model. Copilot's model is chosen at session time by the user's plan and settings. The same repository serves every model a user might select, and the composition the repository contributes is identical across all of them.
model_hashis unavailable, and so isprovider/model_id/versionin any truthful form.The obvious workarounds are all dishonest in a way this project usually refuses:
provider: github, model_id: copilotdescribes a product, not a model.model_id: unknownasserts a binding to a thing named "unknown".So the integration currently emits nothing and claims no
integrates_with, which I would rather fix in the spec than paper over in the integration.The part that suggests the spec already half-agrees
The verification result vocabulary (section 5.2) is:
NOT_BOUNDexists for every artifact in that result object. But there is no legal way to author a manifest that produces it, because every level requires all bindings present. A verifier can report a state no conformant manifest can reach.That reads like an internal inconsistency rather than a missing feature.
What I would propose
Three options, roughly in order of how much I like them.
1. A composition-only profile. A manifest that binds a stated subset of artifacts and declares which ones it deliberately does not bind, with verification returning
NOT_BOUNDfor those. Something like:{ "@type": "AgentManifest", "profile": "composition-only", "unbound_artifacts": ["model_identity", "decision_trace", "memory_baseline"], "artifacts": { "system_prompt": {...}, "tool_manifest": {...}, "policy_bundle": {...} } }The declaration is the point: an unbound artifact is stated, not silently absent, so a verifier can tell "this manifest does not cover the model" from "this manifest is malformed". That is the same distinction we ended up needing in the capture engines, where an unmeasured category had to be labelled rather than rendered as zero.
2.
model_attestation_type: "unbound"alongside the existinghash-boundandprovider-asserted, withprovider/model_id/versionnullable in that mode only. Smaller change, and it slots into machinery that already exists. Less general: the same problem applies todecision_traceandmemory_baselinefor a repository-scoped manifest, and this only fixes the model.3. Leave the spec alone and say composition-only manifests are out of scope. Also a fine answer. If so, it is worth stating explicitly, because the natural reading of "Agent Manifest describes what an agent IS" invites exactly the attempt I just made.
Why it might matter beyond this one integration
Anything that inspects a repository rather than a running agent hits this: a CI check, a policy gate on a pull request, a marketplace scanning a published skill. Those are all "here is the composition, the model is chosen later by whoever runs it". If that class is in scope for agent-manifest, it needs a way to say so.
Happy to implement whichever direction you prefer.