-
Notifications
You must be signed in to change notification settings - Fork 0
Add OpenSpec proposal for non-asset file support in facet archives #428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
eXamadeus
merged 2 commits into
main
from
julian/07-13-add_openspec_proposal_for_non-asset_file_support_in_facet_archives
Jul 23, 2026
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| schema: spec-driven | ||
| created: 2026-07-13 |
169 changes: 169 additions & 0 deletions
169
openspec/changes/support-non-asset-files/adversarial/artifacts/design.md
Large diffs are not rendered by default.
Oops, something went wrong.
42 changes: 42 additions & 0 deletions
42
openspec/changes/support-non-asset-files/adversarial/artifacts/proposal.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| ## Why | ||
|
|
||
| Facet authors cannot currently include documentation, licenses, development notes, or companion skill resources in a built facet because the artifact contract rejects every file that is not a declared skill, agent, command, or manifest. Facets need a safe way to carry these supporting files without falsely treating them as independently installable assets. | ||
|
|
||
| ## What Changes | ||
|
|
||
| - The facet manifest SHALL be able to declare supplementary files, including conventional files such as `README.md`, `LICENSE`, `DEVELOPMENT.md`, and nested files belonging to a skill. | ||
| - A build SHALL include every declared supplementary file in the deterministic facet archive and SHALL integrity-protect it with the same per-file and whole-archive guarantees applied to asset files. Missing, undeclared, duplicate, or unsafe file paths SHALL fail validation rather than creating an ambiguous artifact. | ||
| - Supplementary files SHALL remain distinct from assets: they SHALL NOT acquire an asset type, adapter metadata, an independent install scope, or a lockfile asset tuple. | ||
| - When a skill is installed, declared files contained by that skill's directory SHOULD be materialized with the skill through the adapter. Supplementary files associated with command and agent paths, and files elsewhere in the facet, SHALL remain archive content and SHALL NOT be materialized. | ||
| - `README.md` SHALL be documented as a conventional supplementary file, while the manifest retains one general file-declaration mechanism rather than a second README-specific source of truth. | ||
| - **BREAKING**: Artifacts containing supplementary files extend the archive entry set beyond the current format's asset-only exclusivity rule. The protocol/archive format SHALL use an explicit compatibility boundary so older consumers do not misinterpret these artifacts; existing asset-only facets SHALL remain valid. | ||
| - Documentation covering manifests, builds, archives, integrity, authoring, and installation SHALL be updated to distinguish archived files from installable assets. | ||
|
|
||
| ## Capabilities | ||
|
|
||
| ### New Capabilities | ||
|
|
||
| None. | ||
|
|
||
| ### Modified Capabilities | ||
|
|
||
| - `authoring__facets`: Authors can declare, validate, and build supplementary files in addition to installable assets. | ||
| - `protocol__schemas`: Published facet and build-manifest schemas represent the complete tracked file set without classifying supplementary files as assets. | ||
| - `protocol__content-hashing`: Deterministic archives and per-file hash records cover all declared content, not only asset prompt files. | ||
| - `protocol__integrity`: Archive verification reconciles and verifies every declared supplementary file while preserving path-safety guarantees. | ||
| - `installation`: Installation materializes companion files inside installed skill directories but retains other supplementary files only as verified archive content. | ||
| - `adapter__assets`: The skill installation contract can carry a skill's declared companion-file tree without expanding command or agent installation into directory installation. | ||
|
|
||
| ## Non-goals | ||
|
|
||
| - This change SHALL NOT add a `facet info` command or render README content in the CLI; retaining README content enables that separate future capability. | ||
| - This change SHALL NOT make arbitrary supplementary files directly installable or add new adapter-independent destination paths. | ||
| - This change SHALL NOT give commands or agents companion-directory installation semantics. | ||
| - This change SHALL NOT preserve executable permissions, symlinks, or other filesystem metadata for supplementary files. | ||
| - This change SHALL NOT automatically package untracked source-tree files; archive membership remains explicit and reviewable. | ||
|
|
||
| ## Impact | ||
|
|
||
| The published protocol and reference implementation will change across manifest/build schemas, archive assembly and parsing, content hashing, verification, build validation, installation planning/materialization, and the adapter SDK's skill-install input. Implementations will need compatibility tests for legacy asset-only artifacts and the new archive format, plus security tests for traversal, collisions, undeclared entries, and tampering of non-asset files. | ||
|
|
||
| This proposal was informed by `docs/specification/manifest.mdx`, `docs/specification/build.mdx`, `docs/specification/archive.mdx`, `docs/specification/integrity.mdx`, `docs/guides/create-your-first-facet.mdx`, `docs/guides/install-facets.mdx`, and the root `README.md`. Those pages currently describe facets and integrity in asset-only terms and SHOULD be updated with the new tracked-file and materialization boundaries. | ||
115 changes: 115 additions & 0 deletions
115
...ges/support-non-asset-files/adversarial/artifacts/specs/adapter__assets/spec.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| ## MODIFIED Requirements | ||
|
|
||
| ### Requirement: Adapters provide asset installation | ||
|
|
||
| An adapter SHALL accept a request to install an asset at a given scope. The request SHALL be tagged by asset type, and each type's payload SHALL carry exactly the data that type can hold: | ||
|
|
||
| - a **skill** request carries the skill's primary content plus a map of companion paths (relative to the skill's root) to file bytes; an empty map is the valid representation of a companion-less skill; | ||
| - an **agent** or **command** request carries a single content string and structurally cannot carry companion files. | ||
|
|
||
| The adapter SHALL receive the scope, asset name, per-asset metadata, and the type-tagged payload. The adapter SHALL handle all storage concerns internally — including path resolution, directory creation, metadata assembly, and file format. Companion paths SHALL be confined to the skill's resolved storage root; a companion path that would escape it SHALL be rejected as a structured failure before any write. Metadata and front-matter conventions SHALL apply only to the primary content; companion bytes SHALL be written verbatim. | ||
|
|
||
| A skill installation SHALL be all-or-nothing: the adapter SHALL install the complete bundle — primary file plus every companion — and SHALL remove previously installed companion paths absent from the new bundle, committing the result as one operation. On failure the adapter SHALL leave no partial bundle: either the prior state or the complete new state remains. Installation SHALL be idempotent: installing an asset whose name already exists at that scope SHALL overwrite the existing asset, replacing its companion set with the new bundle. Expected failures SHALL be structured results, not thrown errors. | ||
|
|
||
| #### Scenario: Install a skill asset with companions | ||
|
|
||
| - **WHEN** the system requests an adapter to install a skill whose payload carries primary content and two companion files at a given scope | ||
| - **THEN** the adapter SHALL store the primary file and both companions at the locations appropriate for that scope | ||
| - **AND** the adapter SHALL incorporate the metadata into the stored primary asset according to its tool's conventions | ||
| - **AND** the companion bytes SHALL be stored verbatim without metadata or front-matter processing | ||
|
|
||
| #### Scenario: Install a companion-less skill | ||
|
|
||
| - **WHEN** the system requests an adapter to install a skill whose companion map is empty | ||
| - **THEN** the adapter SHALL store the primary file | ||
| - **AND** the operation SHALL be valid without any companion writes | ||
|
|
||
| #### Scenario: An agent or command request cannot carry companions | ||
|
|
||
| - **WHEN** the system constructs an install request for an agent or command | ||
| - **THEN** the request's payload SHALL carry only the single content string | ||
| - **AND** no companion data SHALL be expressible in that request | ||
|
|
||
| #### Scenario: Install an asset at the user scope | ||
|
|
||
| - **WHEN** the system requests an adapter to install an asset at the user scope | ||
| - **THEN** the adapter SHALL store the asset using the adapter's user-level storage root | ||
|
|
||
| #### Scenario: Reinstalling a skill replaces its companion set | ||
|
|
||
| - **WHEN** the system requests an adapter to install a skill whose name already exists at the given scope | ||
| - **AND** the previously installed skill included a companion the new bundle omits | ||
| - **THEN** the adapter SHALL overwrite the primary file and install the new companions | ||
| - **AND** the adapter SHALL remove the omitted previously-installed companion | ||
| - **AND** the adapter SHALL NOT produce an error for the name collision | ||
|
|
||
| #### Scenario: A failed skill install leaves no partial bundle | ||
|
|
||
| - **WHEN** an adapter fails partway through installing a skill bundle (for example a companion write fails) | ||
| - **THEN** the adapter SHALL report a structured failure | ||
| - **AND** the skill's storage location SHALL NOT contain a mixture of old and new bundle files | ||
|
|
||
| #### Scenario: An escaping companion path is rejected | ||
|
|
||
| - **WHEN** an install request carries a companion path that would resolve outside the skill's storage root (for example via `..` segments) | ||
| - **THEN** the adapter SHALL reject the request with a structured failure identifying the path | ||
| - **AND** the adapter SHALL NOT write any file | ||
|
|
||
| ### Requirement: Adapters provide asset reading | ||
|
|
||
| An adapter SHALL accept a request to read an asset from a given scope. The adapter SHALL receive the scope, asset type, and asset name. The result SHALL be tagged by asset type: a skill read SHALL return the primary content plus the companion files present in the skill's storage, and an agent or command read SHALL return the single content string. Returned primary content SHALL be the canonical logical content — the adapter SHALL project any tool-specific storage encoding back to the content the system installed — so that callers can compare it against canonical recorded hashes. Companion bytes SHALL be returned verbatim. The adapter SHALL also return any adapter-specific metadata stored alongside the asset. | ||
|
eXamadeus marked this conversation as resolved.
|
||
|
|
||
| #### Scenario: Read an existing skill with companions | ||
|
|
||
| - **WHEN** the system requests an adapter to read a skill whose storage contains a primary file and companion files | ||
| - **THEN** the adapter SHALL return the primary content, the companion files, and the stored metadata | ||
|
|
||
| #### Scenario: Read returns canonical logical content | ||
|
|
||
| - **WHEN** an adapter stores primary content in a tool-specific format that differs from the installed canonical content | ||
| - **AND** the system reads that asset back | ||
| - **THEN** the returned primary content SHALL equal the canonical logical content the system installed, absent user modification | ||
| - **AND** a caller comparing it against the canonical recorded hash SHALL observe a match | ||
|
|
||
| #### Scenario: Read a non-existent asset | ||
|
|
||
| - **WHEN** the system requests an adapter to read an asset that does not exist at the given scope | ||
| - **THEN** the adapter SHALL indicate that the asset was not found | ||
|
|
||
| ### Requirement: Adapters provide asset deletion | ||
|
|
||
| An adapter SHALL accept a request to delete an asset from a given scope. The adapter SHALL receive the scope, asset type, and asset name — and, for a skill, the set of owned companion paths to remove. Skill deletion SHALL remove the primary file and every owned companion as one operation, and SHALL NOT delete files in the skill's storage location that are not in the owned set. Deletion SHALL NOT remove an entire directory wholesale when unowned files remain in it. Expected failures SHALL be structured results. | ||
|
eXamadeus marked this conversation as resolved.
|
||
|
|
||
| #### Scenario: Delete a skill and its owned companions | ||
|
|
||
| - **WHEN** the system requests an adapter to delete a skill, providing its owned companion paths | ||
| - **THEN** the adapter SHALL remove the primary file and every owned companion from that scope | ||
|
|
||
| #### Scenario: Deletion preserves unowned files in the skill's location | ||
|
|
||
| - **WHEN** a skill's storage location contains a file that is not the primary file and not in the owned companion set | ||
| - **AND** the system requests deletion of that skill | ||
| - **THEN** the adapter SHALL NOT delete the unowned file | ||
|
|
||
| #### Scenario: Delete a non-existent asset | ||
|
|
||
| - **WHEN** the system requests an adapter to delete an asset that does not exist at the given scope | ||
| - **THEN** the adapter SHALL indicate that the asset was not found | ||
|
|
||
| ## ADDED Requirements | ||
|
|
||
| ### Requirement: Adapters never receive archive-only supplementary files | ||
|
|
||
| Install, read, and delete requests SHALL have no representation for archive-only supplementary files (files that ship in a facet's archive but do not belong to any asset). The only non-asset file data an adapter ever receives is a skill's companion map inside a skill-tagged payload. A facet's root `README.md`, `LICENSE`, or other archive-only files SHALL never appear in any adapter request. | ||
|
|
||
| #### Scenario: Installing a facet with archive-only files sends adapters only assets | ||
|
|
||
| - **WHEN** the system installs a facet that ships a root `README.md` alongside its assets | ||
| - **THEN** every adapter request issued during the install SHALL describe an asset (skill, agent, or command) | ||
| - **AND** no request SHALL reference `README.md` | ||
|
|
||
| #### Scenario: No request shape can carry a supplementary file | ||
|
|
||
| - **WHEN** an install, read, or delete request is constructed | ||
| - **THEN** its type-tagged payload SHALL be one of the asset variants | ||
| - **AND** no variant SHALL exist for archive-only supplementary files | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.