@medicine-wheel/community-review
Version:
Community-based ceremonial review protocol for Medicine Wheel — implements Wilson's validation through Elder review circles, consensus, and relational accountability
55 lines • 2.56 kB
JavaScript
;
/**
* @medicine-wheel/community-review — Storyteller Perspective Gate
*
* A runtime quality boundary: output that lacks the creator's storyteller
* signature is rejected with a useful revision reason, so an agent revises
* rather than ships voiceless output.
*
* Episode 066 (Jerry thread): "if there is no Miette perspective … in the
* output, it's going to get rejected and the agent will have to revise."
* Modeled on the existing `mw_enforce_gate` rejection pattern — accountability
* at the interface layer, not model retraining.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.storytellerGate = storytellerGate;
exports.enforceStorytellerGate = enforceStorytellerGate;
/**
* Evaluate an output against a storyteller signature.
*
* @param output The produced text to evaluate.
* @param signature The creative signature it must carry.
*/
function storytellerGate(output, signature) {
const minMarkers = Math.max(1, signature.minMarkers ?? 1);
const haystack = (output ?? '').toLowerCase();
const matchedMarkers = signature.markers.filter((marker) => {
const needle = marker.trim().toLowerCase();
return needle.length > 0 && haystack.includes(needle);
});
const passed = matchedMarkers.length >= minMarkers;
const missingSignature = matchedMarkers.length === 0;
if (passed) {
return { passed, matchedMarkers, missingSignature };
}
const label = signature.label ?? 'storyteller perspective';
const missing = signature.markers.filter((m) => !matchedMarkers.includes(m));
const need = minMarkers - matchedMarkers.length;
const revisionReason = `Rejected: output does not carry the ${label}. ` +
`Found ${matchedMarkers.length}/${minMarkers} required signature marker(s). ` +
`Revise to include at least ${need} more of: ${missing.join(', ')}. ` +
`An output without the storyteller's voice is not accountable to its author — ` +
`add the narrative resonance before this can pass.`;
return { passed, matchedMarkers, missingSignature, revisionReason };
}
/**
* Convenience: throw when the gate rejects, mirroring `mw_enforce_gate`
* rejection semantics for call sites that prefer fail-fast over inspection.
*/
function enforceStorytellerGate(output, signature) {
const result = storytellerGate(output, signature);
if (!result.passed) {
throw new Error(result.revisionReason ?? 'Storyteller gate rejected the output.');
}
}
//# sourceMappingURL=storyteller.js.map