Recipe: Text Resource Closure and Host Build¶
1. Scenario and Non-Scenario¶
Applicable: you need to normalize a set of text resources into a recomputable closure, and based on it materialize a host-adapter build at a contained location, with the build manifest fully digest-verifiable.
Not applicable: needs to include binary resources in the adapter projection (text closure only); needs Kit CLI apply, generic or remote apply, or automatic deleting uninstall.
2. Architecture Choice and Capability ID¶
Preferred capabilities: foundation.harness.resource-closure (deterministic closure and sha256 digest) and foundation.harness.host-adapter (adapter source closure / build / manifest verification / materialize / read-only peer verification through verifyPeerAdapterDirectories).
3. Preconditions and Trust Boundary¶
- The adapter source is a declared text closure (
contentaccepts only string, utf8). - Trust boundary: materialize uses sibling staging + a single rename, and refuses if the target already exists; probe does not spawn by default and does not walk PATH.
4. Minimal Code¶
import {
computeResourceClosure,
buildAdapterClosure,
verifyAdapterBuildManifest,
materializeAdapterBuild,
} from "skill-family-harness-node";
const closure = computeResourceClosure([
{ path: "skill.json", content: "{}" },
{ path: "readme.md", content: "# demo" },
]);
const built = buildAdapterClosure(closure);
verifyAdapterBuildManifest(built.manifest); // fully digest-verifiable
await materializeAdapterBuild(built, { outDir: "./out" }); // contained write to disk
The code above shows the order of first computing the closure, then verifying the manifest, then atomically materializing.
5. Expected Output and Evidence¶
computeResourceClosure returns a deterministic closure object and a sha256 digest; materializeAdapterBuild writes the artifact at the contained target. Evidence: packages/skill-family-harness-node/test/closure.test.mjs and test/host.test.mjs.
6. Safety / Failure Negative Case¶
// Negative case: binary content unsupported -> verification/build refusal
buildAdapterClosure({ path: "x.bin", content: Buffer.from([0, 1, 2]) });
// throws HarnessError: adapter source content supports string (utf8) only
A manifest-digest mismatch, an already-existing target, or a non-trusted executable file also throw.
7. Copy-Paste Verification Command¶
node --test packages/skill-family-harness-node/test/closure.test.mjs \
packages/skill-family-harness-node/test/host.test.mjs
8. Business Logic the Caller Continues to Own¶
- The host's concrete business semantics.
- Host-difference declarations are injected via Profile + Kit host sub-action.
9. Upgrade and Rollback Notes¶
- Harness owns only build and read-only peer verification. The Kit package API
applyHostPlansupports registered, digest-bound local install/update; executing an uninstall plan does not delete files. Kit CLI apply, generic apply, and remote apply remain stably refused, and the full Qoder driver is unsupported. verifyPeerAdapterDirectoriesproves only that peer directories have matching closures, bytes, andlogicalMappings; it derives no install, release, or domain state.- materialize is an atomic sibling + rename, and on failure does not affect the existing target; upgrade follows the
skill-family-harness-nodeversion.