Skip to content
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,42 @@ main. The payload is offline and unqualified. It does not call GitHub or a CLI,
use a credential, rerun or cancel work, dispatch a workflow, change a repository,
grant authority or qualification, or activate a profile.

## Inactive local Git candidate materializer

`adapters/local-git-materializer/v1/` implements the existing portable-core v2
`core.forge.materialize-candidate.v2` capability without a Git forge. It reads one
exact, sanitized bare source repository and one contract-bound patch. It imports
reachable objects into a caller-disposable bare repository, applies the patch to a
scratch-only index, and returns a canonical receipt and validated stage result.
Reachable source history is limited to 65,536 objects and 256 MiB of uncompressed
object data; the streamed pack is capped at the same byte limit.
The complete source filesystem inventory is capped at 65,536 entries and 8 MiB,
and repository config is snapshotted at 1 MiB before parsing.
Each tree scan is limited to 65,536 entries, 1,024 tree objects, 64 path
components, and a 16 MiB encoded listing. Each commit or tree is size-checked
before a non-recursive tree step, and each step validates UTF-8 before its bounded
built-in path walk.
Before mutating the index, patch paths must already fit the contract and their
cumulative source blob sizes plus patch bytes must fit a 256 MiB candidate budget.

The fixed `materialize` command accepts only caller-named physical source,
candidate, and scratch boundaries, with every path independently absolute. It
rejects worktrees, alternates, shallow or
partial repositories, replace or graft state, active hooks and filters, remote
configuration, unsafe paths, binary or copy/rename patches, empty subtrees,
symlinks, and submodules. It never
inherits host Git templates, checks out a worktree, or runs a transport command.
An empty producer patch returns the explicit `no-change` result. Tests cover both
SHA-1 and SHA-256 object formats with disposable local fixtures.

This PR lands only the inactive package payload. A later assembly PR may add a
manifest whose package reference points to this payload's durable commit on main.
GitHub and later GitLab change-request normalizers remain separate observation
inputs; they do not claim this materialization capability. The package is not
qualified, selected, installed, or activated. It reads no credential, contacts no
provider or real target during construction, and cannot push, publish, merge, or
grant authority.

## Inactive Claude Code producer normalizer payload

`adapters/claude-code-producer/v1/normalize.jq` validates one untrusted producer
Expand Down
31 changes: 31 additions & 0 deletions RESTORE.md
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,37 @@ default-set wiring. The pure jq payload is offline and unqualified. It does not
call GitHub, use a credential, rerun, cancel, or dispatch work, change a
repository, grant authority or qualification, or activate a profile.

Restore the three paths in the manifest's inactive local Git materializer block,
then run:

```sh
bash scripts/test/local-git-materializer-adapter.test.sh
```

This builds disposable SHA-1 and SHA-256 source repositories, validates a complete
portable-core v2 profile and stage request, and proves that a contract-bound patch
becomes a deterministic bare child commit and path-free receipt. The negative
matrix rejects moved identities, unsafe directories and paths, hooks, filters,
remotes, worktrees, alternates, shallow or partial repositories, replace state,
binary patches, symlinks, submodules, host Git templates, and reachable source
history above the fixed 65,536-object or 256 MiB import budget. Copy/rename patch
metadata and source trees containing empty subtrees also fail closed. It proves empty-patch
`no-change` and rejects tree scans above 65,536 entries, 64 path components, or a
16 MiB encoded listing. It also checks that the source stays unchanged and scratch
is removed. Input and config snapshots are stream-capped before parsing. The
complete source filesystem scan is capped at 65,536 entries and 8 MiB. Tree scans
are capped at 1,024 tree objects, with each object size-checked before non-recursive
expansion. A shared-large-blob
fixture proves the 256 MiB pre-apply candidate
budget blocks path fan-out before Git writes changed blobs.

This payload has no adapter manifest. A later assembly PR may bind the directory
tree through the payload's durable main commit. It is an inactive, local-only
materializer, not a GitHub or GitLab operation. Restoring it does not qualify an
adapter, select or activate a profile, read a credential, contact a provider or
real target during construction, or permit push, publish, merge, or another
external write.

Restore the two paths in the manifest's inactive Claude Code producer normalizer
payload block, then run:

Expand Down
Loading