Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ If the user supplies a writing sample of their own previous prose, analyse it be

A sample outranks Authentext style rules, including the Pattern 13 dash ban: if the sample uses em dashes, keep them at roughly the sample's frequency. Matching the author beats scrubbing the tell. The sample does not outrank Never add, Never lose, or protected spans.

Facts found in the corpus may inform voice. They may be cited back as "you have written this before." They must not be inserted into the current document unless the user asks and the current source already supports the claim. A corpus does not license fabrication or invented biography.

The sample may be pasted text, or an explicit pointer the user names:

- Local file: a path such as `./drafts/column.md`
Expand Down Expand Up @@ -161,7 +163,7 @@ Voice comes from stance and rhythm, never from invented biography. The most comm

Where prose is flat because it lacks concrete detail, the fix is to ask the writer for the detail, or to flag the gap. It is not to supply one. Stance, reaction, uncertainty, and cadence are yours to add. Facts and history are not.

Skip this section entirely for clinical, legal, regulatory, and submitted academic material, where first-person texture is not the register and the added-voice failure mode is expensive.
Skip this section entirely for clinical, legal, regulatory, and submitted academic material, where first-person texture is not the register and the added-voice failure mode is expensive. Skip it even when a first-person corpus is available. Do not import memoir texture, "I", or invented biography into those registers.

### Before (clean but soulless)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"status": "in_progress",
"created_at": "2026-08-11",
"updated_at": "2026-08-12",
"current_phase": "Phase 3: Optional plugin sources",
"current_phase": "Phase 4: Precedence wiring",
"parallel_safe": false,
"depends_on": ["editorial-safety-invariants_20260811"],
"coordinates_with": ["pattern-registry-contracts_20260811"],
Expand Down
14 changes: 8 additions & 6 deletions conductor/tracks/voice-corpus-calibration_20260811/plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@

## Phase 3: Optional plugin sources

- [~] Task: Write failing tests that email and other plugins are off by
default and require a named grant.
- [~] Task: Add a thin adapter interface. Do not ship a mail client.
- [ ] Task: Phase Verification & Checkpoint (Refer to `workflow.md`).
- [x] Task: Write failing tests that email and other plugins are off by
default and require a named grant. (commit: 488a3af)
- [x] Task: Add a thin adapter interface. Do not ship a mail client.
(commit: 488a3af)
- [x] Task: Phase Verification & Checkpoint (Refer to `workflow.md`).
[checkpoint: fa40812]

## Phase 4: Precedence wiring

- [ ] Task: Write failing tests that a calibrated sample outranks the dash
- [~] Task: Write failing tests that a calibrated sample outranks the dash
ban and that corpus facts cannot be inserted into the current draft.
- [ ] Task: Wire precedence in skill prose and in the intake/diagnostic
- [~] Task: Wire precedence in skill prose and in the intake/diagnostic
contracts.
- [ ] Task: Phase Verification & Checkpoint (Refer to `workflow.md`).

Expand Down
4 changes: 3 additions & 1 deletion references/core-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ If the user supplies a writing sample of their own previous prose, analyse it be

A sample outranks Authentext style rules, including the Pattern 13 dash ban: if the sample uses em dashes, keep them at roughly the sample's frequency. Matching the author beats scrubbing the tell. The sample does not outrank Never add, Never lose, or protected spans.

Facts found in the corpus may inform voice. They may be cited back as "you have written this before." They must not be inserted into the current document unless the user asks and the current source already supports the claim. A corpus does not license fabrication or invented biography.

The sample may be pasted text, or an explicit pointer the user names:

- Local file: a path such as `./drafts/column.md`
Expand Down Expand Up @@ -171,7 +173,7 @@ Voice comes from stance and rhythm, never from invented biography. The most comm

Where prose is flat because it lacks concrete detail, the fix is to ask the writer for the detail, or to flag the gap. It is not to supply one. Stance, reaction, uncertainty, and cadence are yours to add. Facts and history are not.

Skip this section entirely for clinical, legal, regulatory, and submitted academic material, where first-person texture is not the register and the added-voice failure mode is expensive.
Skip this section entirely for clinical, legal, regulatory, and submitted academic material, where first-person texture is not the register and the added-voice failure mode is expensive. Skip it even when a first-person corpus is available. Do not import memoir texture, "I", or invented biography into those registers.

### Before (clean but soulless)

Expand Down
60 changes: 60 additions & 0 deletions scripts/lib/document-intake-policy.js
Original file line number Diff line number Diff line change
Expand Up @@ -499,3 +499,63 @@ export function selectMaterialQuestion(intake = {}) {
},
};
}

const RESTRICTED_VOICE_CLASSES = new Set(['clinical', 'legal', 'regulatory', 'submitted-academic']);

/**
* Decide whether a calibrated sample may override a style rule, and whether a
* corpus fact may enter the current draft. Never-add, never-lose, and
* protected spans still win.
* @param {{
* sampleUsesEmDash?: boolean,
* styleRule?: string,
* corpusFact?: string,
* currentSourceSupports?: boolean,
* userAsked?: boolean,
* protectedSpan?: boolean,
* neverAddConflict?: boolean,
* neverLoseConflict?: boolean,
* documentClass?: string,
* }} [input]
*/
export function resolveVoicePrecedence({
sampleUsesEmDash = false,
styleRule = 'dash-ban',
corpusFact,
currentSourceSupports = false,
userAsked = false,
protectedSpan = false,
neverAddConflict = false,
neverLoseConflict = false,
documentClass,
} = {}) {
const styleOverride =
styleRule === 'dash-ban' && sampleUsesEmDash === true ? 'keep-sample-dash' : 'apply-style-rule';

let insert = false;
let insertReason = 'corpus-fact-not-requested';
if (protectedSpan === true) {
insertReason = 'protected-span';
} else if (neverAddConflict === true) {
insertReason = 'never-add';
} else if (neverLoseConflict === true) {
insertReason = 'never-lose';
} else if (corpusFact && userAsked === true && currentSourceSupports === true) {
insert = true;
insertReason = 'user-asked-and-source-supports';
} else if (corpusFact && userAsked === true && currentSourceSupports !== true) {
insertReason = 'current-source-lacks-claim';
} else if (corpusFact) {
insertReason = 'corpus-does-not-license-fabrication';
}

return {
style_override: styleOverride,
may_insert_corpus_fact: insert,
insert_reason: insertReason,
skip_personality:
typeof documentClass === 'string' && RESTRICTED_VOICE_CLASSES.has(documentClass),
skip_first_person_texture:
typeof documentClass === 'string' && RESTRICTED_VOICE_CLASSES.has(documentClass),
};
}
4 changes: 3 additions & 1 deletion src/modules/SKILL_CORE_PATTERNS.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ If the user supplies a writing sample of their own previous prose, analyse it be

A sample outranks Authentext style rules, including the Pattern 13 dash ban: if the sample uses em dashes, keep them at roughly the sample's frequency. Matching the author beats scrubbing the tell. The sample does not outrank Never add, Never lose, or protected spans.

Facts found in the corpus may inform voice. They may be cited back as "you have written this before." They must not be inserted into the current document unless the user asks and the current source already supports the claim. A corpus does not license fabrication or invented biography.

The sample may be pasted text, or an explicit pointer the user names:

- Local file: a path such as `./drafts/column.md`
Expand Down Expand Up @@ -165,7 +167,7 @@ Voice comes from stance and rhythm, never from invented biography. The most comm

Where prose is flat because it lacks concrete detail, the fix is to ask the writer for the detail, or to flag the gap. It is not to supply one. Stance, reaction, uncertainty, and cadence are yours to add. Facts and history are not.

Skip this section entirely for clinical, legal, regulatory, and submitted academic material, where first-person texture is not the register and the added-voice failure mode is expensive.
Skip this section entirely for clinical, legal, regulatory, and submitted academic material, where first-person texture is not the register and the added-voice failure mode is expensive. Skip it even when a first-person corpus is available. Do not import memoir texture, "I", or invented biography into those registers.

### Before (clean but soulless)

Expand Down
57 changes: 57 additions & 0 deletions test/document-intake-policy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
parseCorpusPointer,
resolveDeliveryMode,
resolvePluginSource,
resolveVoicePrecedence,
selectMaterialQuestion,
} from '../scripts/lib/document-intake-policy.js';

Expand Down Expand Up @@ -392,3 +393,59 @@ test('asks for a plugin grant when a plugin is named without one', () => {
assert.equal(decision.question.field, 'plugin_grant');
assert.match(decision.question.text, /plugin/i);
});

test('a calibrated sample outranks the dash ban but not never-add or protected spans', () => {
const dash = resolveVoicePrecedence({ sampleUsesEmDash: true, styleRule: 'dash-ban' });
assert.equal(dash.style_override, 'keep-sample-dash');

const blocked = resolveVoicePrecedence({
sampleUsesEmDash: true,
styleRule: 'dash-ban',
corpusFact: 'I worked at Example Hospital in 2019.',
protectedSpan: true,
});
assert.equal(blocked.style_override, 'keep-sample-dash');
assert.equal(blocked.may_insert_corpus_fact, false);
assert.equal(blocked.insert_reason, 'protected-span');

const neverAdd = resolveVoicePrecedence({
corpusFact: 'I worked at Example Hospital in 2019.',
neverAddConflict: true,
});
assert.equal(neverAdd.may_insert_corpus_fact, false);
assert.equal(neverAdd.insert_reason, 'never-add');
});

test('corpus facts cannot be inserted into the current draft unless asked and supported', () => {
const silent = resolveVoicePrecedence({
corpusFact: 'The 2019 cohort used a stepped-wedge design.',
});
assert.equal(silent.may_insert_corpus_fact, false);
assert.equal(silent.insert_reason, 'corpus-does-not-license-fabrication');

const askedOnly = resolveVoicePrecedence({
corpusFact: 'The 2019 cohort used a stepped-wedge design.',
userAsked: true,
currentSourceSupports: false,
});
assert.equal(askedOnly.may_insert_corpus_fact, false);
assert.equal(askedOnly.insert_reason, 'current-source-lacks-claim');

const allowed = resolveVoicePrecedence({
corpusFact: 'The 2019 cohort used a stepped-wedge design.',
userAsked: true,
currentSourceSupports: true,
});
assert.equal(allowed.may_insert_corpus_fact, true);
assert.equal(allowed.insert_reason, 'user-asked-and-source-supports');
});

test('skips personality and first-person texture for restricted document classes', () => {
for (const documentClass of ['clinical', 'legal', 'regulatory', 'submitted-academic']) {
const decision = resolveVoicePrecedence({ documentClass });
assert.equal(decision.skip_personality, true, documentClass);
assert.equal(decision.skip_first_person_texture, true, documentClass);
}
const ordinary = resolveVoicePrecedence({ documentClass: 'workplace' });
assert.equal(ordinary.skip_personality, false);
});
18 changes: 18 additions & 0 deletions test/voice-corpus-calibration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,21 @@ test('voice calibration keeps host plugins off until named and granted', () => {
assert.match(source, /Default is off/);
}
});

test('skill prose says corpus facts do not license fabrication', () => {
for (const source of [canonicalSource, generated, coreReference]) {
assert.match(source, /does not license fabrication/);
assert.match(source, /you have written this before/);
assert.match(source, /current source already supports/);
}
});

test('personality skip covers clinical legal regulatory and submitted academic even with a corpus', () => {
for (const source of [canonicalSource, generated, coreReference]) {
assert.match(
source,
/Skip this section entirely for clinical, legal, regulatory, and submitted academic/
);
assert.match(source, /even when a first-person corpus is available/);
}
});
Loading