fix(skills): harden TasteForge multimodal contract

This commit is contained in:
Affaan Mustafa
2026-08-19 21:47:31 +00:00
parent 348cd34a2b
commit 71e3622640
4 changed files with 131 additions and 15 deletions
+22 -11
View File
@@ -1,6 +1,6 @@
---
name: tasteforge-video
description: Use when a user wants a taste interview for video work, to distill a visual aesthetic into structured, reusable constraints (a style pack), to validate or audit a style pack, to apply a pack's measured cadence and look to local footage, or to export an editable EDL/FCPXML cut. Also for auditing generated-media provenance and for deciding what is local-deterministic versus provider generation. All ECC-side operations are offline and deterministic; provider (Fal) generation fails closed here.
description: Use for file-driven multimodal image, video, and 3D-asset discovery; taste interviews; distill or apply workflows; style-pack validation; editable EDL/FCPXML export; provenance audits; and offline planning that must fail closed before provider generation.
metadata:
origin: ECC
---
@@ -29,8 +29,12 @@ explains it and does not vendor or duplicate its code.
- The user asks for a **generated-media provenance audit** — where did this
pack, spec, or cut come from; what was measured locally versus generated by
a provider; what was dry-run.
- The user asks to **discover or plan file-driven multimodal image, video, or
3D-asset outputs** from local reference files, including separate manifests,
subject-anchored CV effects, or Resolve effect recipes.
- The user mentions TasteForge, style packs, flashethereal, taste distillation,
cadence/rhythm planning, or a taste interview for video.
cadence/rhythm planning, multimodal discovery, distill/apply workflows, or a
taste interview for video.
## Local Deterministic Operations vs Provider Generation
@@ -70,8 +74,8 @@ dry-run/dry_run semantics — say "dry-run spec" or "deterministic plan", never
canonical local GitHub checkout root (never a hard-coded machine path);
package directory `tasteforge/`.
- CLI: `python3 -m tasteforge <command>``provenance`, `inspect`, `validate`,
`interview`, `distill`, `apply`, `export`. `--live` flags exit with code 2
and refuse.
`interview`, `distill`, `apply`, `export`, `multimodal`. `--live` flags exit
with code 2 and refuse.
- Schemas are the contract: taste profile, pack manifest, grade, cadence,
spec, timeline events, application reports (`provider` is enum-locked to
`"none"`; `dry_run` to `true`).
@@ -125,16 +129,23 @@ genres distinct rather than blending them into one generic aesthetic:
The command measures local references with ffprobe/ffmpeg and emits one style
spec per genre, separate image, video, and 3D-asset manifests, provenance, and
a Resolve effect recipe. The effect schedule must be seeded aperiodic. CV
effects require a real subject anchor with fail-closed track-loss behavior.
Every effect carries placement constraints that preserve faces and readable
type and prevent decorative corner meshes from replacing full-frame 3D work.
effects require a real subject anchor whose exact lost-track policy is
`disable_effect_until_track_recovers`; `continue_without_anchor` and every
other policy fail closed. Every effect carries placement constraints that
preserve faces and readable type and prevent decorative corner meshes from
replacing full-frame 3D work.
The returned receipt is the bundle boundary. It binds every emitted evidence
artifact by relative path, byte size, SHA-256, genre, modality,
`provider_execution: false`, and exact reference/time provenance. Manifests and
requests also require `provider_calls: 0`, `provider_execution: false`,
`submit: false`, and disabled provider-call mode. Whole-file evidence uses an
explicit whole-file time basis and never invents timestamps.
`provider_execution:false`, and exact reference/time provenance. The receipt
itself requires `provider_calls:0`, `provider_execution:false`, and
`dry_run:true`. Every modality manifest and every nested request must contain
all four exact fail-closed fields: `provider_calls:0`,
`provider_execution:false`, `dry_run:true`, and `submit:false`; each request
also requires `provider_call_mode:"disabled"`. A missing field is a rejection,
not a default, and `dry_run:false` must be rejected before output is written.
Whole-file evidence uses an explicit whole-file time basis and never invents
timestamps.
Always run bundle validation after creation. A missing image, video, or 3D-asset
manifest must fail closed. Genericized or duplicate genres, periodic schedules,
+70 -4
View File
@@ -20,6 +20,37 @@ function readJson(relativePath) {
return JSON.parse(read(relativePath));
}
function assertExactDryRunBoundary(payload, label) {
assert.strictEqual(payload.provider_calls, 0, `${label} must require provider_calls:0`);
assert.strictEqual(payload.provider_execution, false, `${label} must require provider_execution:false`);
assert.strictEqual(payload.dry_run, true, `${label} must require dry_run:true`);
assert.strictEqual(payload.submit, false, `${label} must require submit:false`);
}
function validateRejectedContractFixture(fixture) {
if (fixture.kind === "manifest") {
assertExactDryRunBoundary(fixture.payload, "manifest");
for (const request of fixture.payload.requests || []) {
assertExactDryRunBoundary(request, "request");
assert.strictEqual(request.provider_call_mode, "disabled");
}
return;
}
if (fixture.kind === "effect_recipe") {
for (const event of fixture.payload.events || []) {
if (event.requires_subject_anchor) {
assert.strictEqual(
event.subject_anchor?.lost_policy,
"disable_effect_until_track_recovers",
"anchored CV effects must disable_effect_until_track_recovers"
);
}
}
return;
}
assert.fail(`unknown fixture kind: ${fixture.kind}`);
}
const tests = [];
function test(name, fn) { tests.push([name, fn]); }
@@ -37,6 +68,15 @@ test("has valid discoverable frontmatter and trigger phrases", () => {
/export EDL\/FCPXML|export .*EDL.*FCPXML/i,
/audit .*generated-media provenance|provenance audit/i,
]) assert.match(skill, trigger);
const description = skill.match(/^description: ([^\n]+)$/m)?.[1] || "";
for (const discoveryTerm of ["multimodal", "image", "video", "3D", "file-driven", "distill", "apply"]) {
assert.match(description, new RegExp(discoveryTerm, "i"), `frontmatter misses ${discoveryTerm}`);
}
const triggers = skill.match(/## When to Use\n([\s\S]*?)\n## /)?.[1] || "";
for (const discoveryTerm of ["multimodal", "image", "video", "3D", "file-driven", "distill", "apply"]) {
assert.match(triggers, new RegExp(discoveryTerm, "i"), `triggers miss ${discoveryTerm}`);
}
});
test("distinguishes local deterministic operations from provider generation", () => {
@@ -97,11 +137,29 @@ test("defines the fail-closed file-driven multimodal contract", () => {
/genre.*modality/is,
/exact reference\/time provenance/i,
/provider_calls:\s*0/i,
/dry_run:\s*true/i,
/submit:\s*false/i,
/disable_effect_until_track_recovers/i,
]) assert.match(skill, phrase);
assert.match(skill, /missing.*manifest.*fail closed/is);
assert.match(skill, /tamper.*fail closed/is);
});
test("executable fixtures reject dry_run:false and continue_without_anchor", () => {
for (const fixtureName of [
"reject-dry-run-false.json",
"reject-continue-without-anchor.json",
]) {
const fixture = readJson(`tests/fixtures/tasteforge-video/${fixtureName}`);
assert.strictEqual(fixture.expected, "reject");
assert.throws(
() => validateRejectedContractFixture(fixture),
undefined,
`${fixtureName} was not rejected`
);
}
});
test("ships through the opt-in media-generation install module and npm package", () => {
const modules = readJson("manifests/install-modules.json").modules;
const module = modules.find((candidate) => candidate.id === "media-generation");
@@ -166,8 +224,10 @@ test("passes the curated skill validator", () => {
// ECC_TEST_NPM_PACK=1 (release/CI verification); the default suite relies on
// the files-array assertions above.
test("ships inside the real npm tarball (opt-in)", () => {
if (process.env.ECC_TEST_NPM_PACK !== "1") return;
const result = spawnSync("npm", ["pack", "--dry-run"], {
if (process.env.ECC_TEST_NPM_PACK !== "1") {
return { skipped: "set ECC_TEST_NPM_PACK=1 to run real npm pack inclusion" };
}
const result = spawnSync("npm", ["pack", "--dry-run", "--ignore-scripts"], {
cwd: REPO_ROOT,
encoding: "utf8",
});
@@ -180,10 +240,16 @@ test("ships inside the real npm tarball (opt-in)", () => {
});
let failed = 0;
let skipped = 0;
console.log("\n=== Testing TasteForge video skill ===\n");
for (const [name, fn] of tests) {
try {
fn();
const result = fn();
if (result?.skipped) {
skipped += 1;
console.log(` - SKIP ${name}: ${result.skipped}`);
continue;
}
console.log(`${name}`);
} catch (error) {
failed += 1;
@@ -192,4 +258,4 @@ for (const [name, fn] of tests) {
}
}
if (failed) process.exit(1);
console.log(`\n${tests.length - failed}/${tests.length} passed`);
console.log(`\n${tests.length - failed - skipped}/${tests.length} passed, ${skipped} skipped`);
@@ -0,0 +1,19 @@
{
"kind": "effect_recipe",
"expected": "reject",
"payload": {
"events": [
{
"effect": "cv_subject_glitch",
"requires_subject_anchor": true,
"subject_anchor": {
"mode": "object_track",
"target": "primary_subject",
"source_ref_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"evidence_time": 0,
"lost_policy": "continue_without_anchor"
}
}
]
}
}
@@ -0,0 +1,20 @@
{
"kind": "manifest",
"expected": "reject",
"payload": {
"modality": "video",
"provider_calls": 0,
"provider_execution": false,
"dry_run": true,
"submit": false,
"requests": [
{
"provider_calls": 0,
"provider_execution": false,
"dry_run": false,
"submit": false,
"provider_call_mode": "disabled"
}
]
}
}