revise October 2027 long-form interview plan articles
Build and deploy / deploy (push) Successful in 16s

This commit is contained in:
2026-07-31 20:58:33 +03:00
parent 2de029eff2
commit 0ae1c4612c
7 changed files with 290 additions and 1 deletions
+2
View File
@@ -112,6 +112,7 @@ import { revisions as june2027Revisions } from '../scripts/upgrade-2027-06.mjs';
import { revisions as july2027Revisions } from '../scripts/upgrade-2027-07.mjs';
import { revisions as august2027Revisions } from '../scripts/upgrade-2027-08.mjs';
import { revisions as september2027Revisions } from '../scripts/upgrade-2027-09.mjs';
import { revisions as october2027Revisions } from '../scripts/upgrade-2027-10.mjs';
// This layer replaces archived source entries without losing their stable slug and date.
export const editorialRevisions = [
@@ -229,4 +230,5 @@ export const editorialRevisions = [
...july2027Revisions,
...august2027Revisions,
...september2027Revisions,
...october2027Revisions,
];
@@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="375" height="225" viewBox="0 0 375 225" role="img" aria-labelledby="title desc">
<title id="title">Карта контракта утверждения</title>
<desc id="desc">Именованное синтетическое утверждение проходит проверку источника, происхождения, независимости и опровержимости. Скрытый или отсутствующий слой останавливает вывод.</desc>
<rect width="375" height="225" fill="#f7f9fc"/>
<g font-family="Arial, sans-serif" fill="#17233a"><text x="12" y="19" font-size="15" font-weight="700">Контракт утверждения</text><text x="12" y="34" font-size="9" fill="#4b5870">P116: форма проверки, не факт</text>
<rect x="10" y="51" width="82" height="57" rx="7" fill="#e8f0ff" stroke="#3e6bb8"/><text x="18" y="70" font-size="11" font-weight="700">1. Claim</text><text x="18" y="86" font-size="9">named literal</text><text x="18" y="99" font-size="9">не ответ</text>
<rect x="101" y="51" width="82" height="57" rx="7" fill="#eaf8f2" stroke="#23805c"/><text x="109" y="70" font-size="11" font-weight="700">2. Source</text><text x="109" y="86" font-size="9">not-collected</text><text x="109" y="99" font-size="9">hidden → stop</text>
<rect x="192" y="51" width="82" height="57" rx="7" fill="#fff6df" stroke="#aa7312"/><text x="200" y="70" font-size="11" font-weight="700">3. Origin</text><text x="200" y="86" font-size="9">activity + time</text><text x="200" y="99" font-size="9">не из prose</text>
<rect x="283" y="51" width="82" height="57" rx="7" fill="#f5ecfb" stroke="#7b4599"/><text x="291" y="70" font-size="11" font-weight="700">4. Check</text><text x="291" y="86" font-size="9">other path</text><text x="291" y="99" font-size="9">falsifier</text>
<path d="M92 79H101M183 79H192M274 79H283" stroke="#53647d" stroke-width="2" marker-end="url(#a)"/>
<rect x="43" y="138" width="127" height="48" rx="7" fill="#fff0f0" stroke="#ae3f3f"/><text x="54" y="158" font-size="12" font-weight="700" fill="#852c2c">STOP</text><text x="54" y="174" font-size="9">unnamed · hidden · claimed</text>
<rect x="205" y="138" width="127" height="48" rx="7" fill="#eaf8f2" stroke="#23805c"/><text x="216" y="158" font-size="12" font-weight="700" fill="#195d43">HAND-OFF</text><text x="216" y="174" font-size="9">not-attempted</text>
<path d="M233 108V123H106V138" fill="none" stroke="#ae3f3f" stroke-width="2" marker-end="url(#r)"/><path d="M324 108V123H268V138" fill="none" stroke="#23805c" stroke-width="2" marker-end="url(#g)"/>
<text x="12" y="211" font-size="9" fill="#4b5870">not-collected и not-tested сохраняют неизвестность.</text></g>
<defs><marker id="a" markerWidth="6" markerHeight="6" refX="5" refY="2" orient="auto"><path d="M0,0 L0,4 L6,2z" fill="#53647d"/></marker><marker id="r" markerWidth="6" markerHeight="6" refX="5" refY="2" orient="auto"><path d="M0,0 L0,4 L6,2z" fill="#ae3f3f"/></marker><marker id="g" markerWidth="6" markerHeight="6" refX="5" refY="2" orient="auto"><path d="M0,0 L0,4 L6,2z" fill="#23805c"/></marker></defs>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="375" height="225" viewBox="0 0 375 225" role="img" aria-labelledby="title desc">
<title id="title">Петля редакционного hand-off</title>
<desc id="desc">Временная граница, контракт утверждения и состояния evidence образуют hand-off без создания интервью, transcript, speaker, approval или publication.</desc>
<rect width="375" height="225" fill="#f7f9fc"/>
<g font-family="Arial, sans-serif" fill="#17233a"><text x="10" y="19" font-size="15" font-weight="700">Hand-off без fabricated record</text>
<rect x="12" y="52" width="91" height="66" rx="12" fill="#e8f0ff" stroke="#3e6bb8"/><text x="27" y="76" font-size="12" font-weight="700" fill="#1d3f7a">Dates</text><text x="21" y="94" font-size="9">2026-07-31</text><text x="31" y="108" font-size="9">2027-10</text>
<rect x="141" y="52" width="91" height="66" rx="12" fill="#fff6df" stroke="#aa7312"/><text x="151" y="76" font-size="12" font-weight="700" fill="#79520b">Assertion</text><text x="151" y="94" font-size="9">named literal</text><text x="151" y="108" font-size="9">без ответа</text>
<rect x="270" y="52" width="91" height="66" rx="12" fill="#f5ecfb" stroke="#7b4599"/><text x="280" y="76" font-size="12" font-weight="700" fill="#5d2877">Evidence</text><text x="280" y="94" font-size="9">not-collected</text><text x="280" y="108" font-size="9">not-tested</text>
<path d="M103 85H141M232 85H270" stroke="#53647d" stroke-width="2" marker-end="url(#a)"/>
<rect x="112" y="142" width="151" height="43" rx="8" fill="#eaf8f2" stroke="#23805c"/><text x="127" y="161" font-size="12" font-weight="700" fill="#195d43">HAND-OFF</text><text x="127" y="177" font-size="9">synthetic plan / not-attempted</text>
<path d="M316 118V130H188V142" fill="none" stroke="#23805c" stroke-width="2" marker-end="url(#g)"/>
<rect x="32" y="195" width="311" height="19" rx="5" fill="#fff0f0" stroke="#ae3f3f"/><text x="42" y="208" font-size="9" fill="#852c2c">Не создаются: transcript · speaker · approval · publication</text></g>
<defs><marker id="a" markerWidth="6" markerHeight="6" refX="5" refY="2" orient="auto"><path d="M0,0 L0,4 L6,2z" fill="#53647d"/></marker><marker id="g" markerWidth="6" markerHeight="6" refX="5" refY="2" orient="auto"><path d="M0,0 L0,4 L6,2z" fill="#23805c"/></marker></defs>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="375" height="225" viewBox="0 0 375 225" role="img" aria-labelledby="title desc">
<title id="title">Матрица границ evidence и provenance</title>
<desc id="desc">Пять строк отличают утверждение, evidence, происхождение, независимое подтверждение и опровержимость. Скрытый слой не повышает уверенность.</desc>
<rect width="375" height="225" fill="#f8fafc"/>
<g font-family="Arial, sans-serif" fill="#17233a"><text x="10" y="18" font-size="15" font-weight="700">Evidence ≠ связный рассказ</text>
<rect x="10" y="29" width="355" height="24" rx="4" fill="#203b68"/><text x="18" y="45" font-size="10" font-weight="700" fill="#fff">Слой</text><text x="93" y="45" font-size="10" font-weight="700" fill="#fff">Вопрос</text><text x="243" y="45" font-size="10" font-weight="700" fill="#fff">Граница P116</text>
<g stroke="#9ba8bc" stroke-width=".6"><rect x="10" y="53" width="355" height="25" fill="#edf3ff"/><rect x="10" y="78" width="355" height="25" fill="#fff"/><rect x="10" y="103" width="355" height="25" fill="#edf3ff"/><rect x="10" y="128" width="355" height="25" fill="#fff"/><rect x="10" y="153" width="355" height="25" fill="#edf3ff"/><path d="M82 29V178M233 29V178"/></g>
<text x="18" y="69" font-size="9" font-weight="700">Claim</text><text x="93" y="69" font-size="9">Что сказано?</text><text x="243" y="69" font-size="9">not-collected</text>
<text x="18" y="94" font-size="9" font-weight="700">Evidence</text><text x="93" y="94" font-size="9">Чем проверить?</text><text x="243" y="94" font-size="9">нет substitute</text>
<text x="18" y="119" font-size="9" font-weight="700">Origin</text><text x="93" y="119" font-size="9">Откуда?</text><text x="243" y="119" font-size="9">не из prose</text>
<text x="18" y="144" font-size="9" font-weight="700">Other path</text><text x="93" y="144" font-size="9">Независим?</text><text x="243" y="144" font-size="9">повтор не source</text>
<text x="18" y="169" font-size="9" font-weight="700">Falsifier</text><text x="93" y="169" font-size="9">Что сузит?</text><text x="243" y="169" font-size="9">not-tested</text>
<rect x="10" y="192" width="355" height="22" rx="5" fill="#fff0f0" stroke="#ae3f3f"/><text x="19" y="207" font-size="9" font-weight="700" fill="#852c2c">hidden / claimed / fabricated → STOP</text></g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

+160
View File
@@ -0,0 +1,160 @@
const escapeHtml = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&#039;');
const p = (text) => `<p>${text}</p>`;
const h2 = (text) => `<h2>${text}</h2>`;
const code = (text) => `<pre><code>${escapeHtml(text)}</code></pre>`;
const ol = (items) => `<ol>${items.map((item) => `<li>${item}</li>`).join('')}</ol>`;
const figure = (src, alt, caption) => `<figure><img src="${src}" alt="${alt}" loading="lazy" /><figcaption>${caption}</figcaption></figure>`;
const table = (caption, headers, rows) => `<div class="table-scroll"><table><caption>${caption}</caption><thead><tr>${headers.map((cell) => `<th scope="col">${cell}</th>`).join('')}</tr></thead><tbody>${rows.map((row) => `<tr>${row.map((cell) => `<td>${cell}</td>`).join('')}</tr>`).join('')}</tbody></table></div>`;
function cloneFixed(value) { return JSON.parse(JSON.stringify(value)); }
function deepFreeze(value) { if (value && typeof value === 'object' && !Object.isFrozen(value)) { Object.values(value).forEach(deepFreeze); Object.freeze(value); } return value; }
function plainText(html) { return html.replace(/<[^>]+>/g, ' ').replace(/&(?:quot|amp|lt|gt|#039);/g, ' ').replace(/\s+/g, ' ').trim(); }
function bodyText(html) { return plainText(html.replace(/<h2>Проверяемые источники<\/h2>[\s\S]*$/, '')); }
const REFERENCES = deepFreeze({
provDm: { title: 'W3C PROV-DM: The PROV Data Model', url: 'https://www.w3.org/TR/2013/REC-prov-dm-20130430/', version: 'W3C Recommendation, 30 April 2013, dated immutable publication' },
c2pa13: { title: 'C2PA Technical Specification 1.3', url: 'https://spec.c2pa.org/specifications/specifications/1.3/specs/C2PA_Specification.html', version: 'C2PA Technical Specification 1.3, April 2023, version-pinned publication' },
});
function sources(entries) { return `<ul>${entries.map(({ key, use, boundary }) => { const ref = REFERENCES[key]; return `<li><a href="${ref.url}" target="_blank" rel="noopener noreferrer">${escapeHtml(ref.title)}</a> — ${escapeHtml(ref.version)}. Применение: ${escapeHtml(use)} Граница: ${escapeHtml(boundary)}</li>`; }).join('')}</ul>`; }
const FIXED_INTERVIEW_LITERALS = deepFreeze({
'long-form-interview-plan-v1': { id: 'long-form-interview-plan-v1', editorialDate: '2026-07-31', planningIssue: '2027-10', sourceCutoff: '2026-07-31', assertion: { id: 'synthetic-assertion-contract-v1', state: 'named-synthetic-only' }, evidence: { claim: 'not-collected', source: 'not-collected', provenance: 'not-collected', independentConfirmation: 'not-collected', falsifiability: 'not-tested' }, record: { interview: 'not-created', transcript: 'not-created', speaker: 'not-named', quote: 'not-created', code: 'not-created', metric: 'not-collected', approval: 'not-requested', review: 'not-created', publication: 'not-attempted', ownership: 'not-assigned' }, requestedOutput: 'synthetic-plan-hand-off' },
'long-form-interview-undated-v1': { id: 'long-form-interview-undated-v1', editorialDate: '', planningIssue: '2027-10', sourceCutoff: '2026-07-31', assertion: { id: 'synthetic-assertion-contract-v1', state: 'named-synthetic-only' }, evidence: { claim: 'not-collected', source: 'not-collected', provenance: 'not-collected', independentConfirmation: 'not-collected', falsifiability: 'not-tested' }, record: { interview: 'not-created', transcript: 'not-created', speaker: 'not-named', quote: 'not-created', code: 'not-created', metric: 'not-collected', approval: 'not-requested', review: 'not-created', publication: 'not-attempted', ownership: 'not-assigned' }, requestedOutput: 'synthetic-plan-hand-off' },
'long-form-interview-unnamed-claim-v1': { id: 'long-form-interview-unnamed-claim-v1', editorialDate: '2026-07-31', planningIssue: '2027-10', sourceCutoff: '2026-07-31', assertion: { id: '', state: 'implicit' }, evidence: { claim: 'not-collected', source: 'not-collected', provenance: 'not-collected', independentConfirmation: 'not-collected', falsifiability: 'not-tested' }, record: { interview: 'not-created', transcript: 'not-created', speaker: 'not-named', quote: 'not-created', code: 'not-created', metric: 'not-collected', approval: 'not-requested', review: 'not-created', publication: 'not-attempted', ownership: 'not-assigned' }, requestedOutput: 'synthetic-plan-hand-off' },
'long-form-interview-hidden-source-v1': { id: 'long-form-interview-hidden-source-v1', editorialDate: '2026-07-31', planningIssue: '2027-10', sourceCutoff: '2026-07-31', assertion: { id: 'synthetic-assertion-contract-v1', state: 'named-synthetic-only' }, evidence: { claim: 'not-collected', source: 'hidden', provenance: 'not-collected', independentConfirmation: 'not-collected', falsifiability: 'not-tested' }, record: { interview: 'not-created', transcript: 'not-created', speaker: 'not-named', quote: 'not-created', code: 'not-created', metric: 'not-collected', approval: 'not-requested', review: 'not-created', publication: 'not-attempted', ownership: 'not-assigned' }, requestedOutput: 'synthetic-plan-hand-off' },
'long-form-interview-claimed-evidence-v1': { id: 'long-form-interview-claimed-evidence-v1', editorialDate: '2026-07-31', planningIssue: '2027-10', sourceCutoff: '2026-07-31', assertion: { id: 'synthetic-assertion-contract-v1', state: 'named-synthetic-only' }, evidence: { claim: 'claimed', source: 'not-collected', provenance: 'not-collected', independentConfirmation: 'not-collected', falsifiability: 'not-tested' }, record: { interview: 'not-created', transcript: 'not-created', speaker: 'not-named', quote: 'not-created', code: 'not-created', metric: 'not-collected', approval: 'not-requested', review: 'not-created', publication: 'not-attempted', ownership: 'not-assigned' }, requestedOutput: 'synthetic-plan-hand-off' },
'long-form-interview-fabricated-record-v1': { id: 'long-form-interview-fabricated-record-v1', editorialDate: '2026-07-31', planningIssue: '2027-10', sourceCutoff: '2026-07-31', assertion: { id: 'synthetic-assertion-contract-v1', state: 'named-synthetic-only' }, evidence: { claim: 'not-collected', source: 'not-collected', provenance: 'not-collected', independentConfirmation: 'not-collected', falsifiability: 'not-tested' }, record: { interview: 'claimed', transcript: 'claimed', speaker: 'named', quote: 'claimed', code: 'claimed', metric: 'claimed', approval: 'claimed', review: 'claimed', publication: 'claimed', ownership: 'assigned' }, requestedOutput: 'synthetic-plan-hand-off' },
'long-form-interview-disallowed-result-v1': { id: 'long-form-interview-disallowed-result-v1', editorialDate: '2026-07-31', planningIssue: '2027-10', sourceCutoff: '2026-07-31', assertion: { id: 'synthetic-assertion-contract-v1', state: 'named-synthetic-only' }, evidence: { claim: 'not-collected', source: 'not-collected', provenance: 'not-collected', independentConfirmation: 'not-collected', falsifiability: 'not-tested' }, record: { interview: 'not-created', transcript: 'not-created', speaker: 'not-named', quote: 'not-created', code: 'not-created', metric: 'not-collected', approval: 'not-requested', review: 'not-created', publication: 'not-attempted', ownership: 'not-assigned' }, requestedOutput: 'publication-approved' },
});
export function createLongFormInterviewLiteral(id = 'long-form-interview-plan-v1') { const value = FIXED_INTERVIEW_LITERALS[id]; return value ? deepFreeze(cloneFixed(value)) : undefined; }
function stop(status, reason, nextAction) { return deepFreeze({ status, reason, nextAction, productionEffect: 'not-attempted' }); }
export function assessLongFormInterviewPlan(input) {
const known = Object.values(FIXED_INTERVIEW_LITERALS).some((item) => JSON.stringify(item) === JSON.stringify(input));
if (!known) return stop('stop-unknown-fixed-literal', 'input-is-not-a-known-named-fixed-literal', 'select-a-named-fixed-literal');
if (input.editorialDate !== '2026-07-31' || input.planningIssue !== '2027-10' || input.sourceCutoff !== '2026-07-31') return stop('stop-temporal-boundary-required', 'editorial-date-planning-issue-and-source-cutoff-must-be-exact', 'restore-the-fixed-temporal-boundary');
if (input.assertion.id !== 'synthetic-assertion-contract-v1' || input.assertion.state !== 'named-synthetic-only') return stop('stop-unnamed-claim', 'assertion-must-be-a-named-fixed-synthetic-literal', 'restore-the-named-assertion-contract');
if (input.evidence.source !== 'not-collected') return stop('stop-hidden-source', 'source-cannot-be-hidden-or-inferred', 'keep-source-not-collected');
if (input.evidence.claim !== 'not-collected' || input.evidence.provenance !== 'not-collected' || input.evidence.independentConfirmation !== 'not-collected' || input.evidence.falsifiability !== 'not-tested') return stop('stop-claimed-evidence-or-confirmation', 'claim-provenance-confirmation-and-falsifiability-are-not-collected', 'remove-the-claimed-evidence');
if (Object.values(input.record).some((value) => !['not-created', 'not-named', 'not-collected', 'not-requested', 'not-attempted', 'not-assigned'].includes(value))) return stop('stop-fabricated-interview-record', 'interview-transcript-speaker-quote-code-metric-approval-review-publication-and-owner-cannot-be-created', 'restore-uncreated-record-states');
if (input.requestedOutput !== 'synthetic-plan-hand-off') return stop('stop-disallowed-positive-result', 'future-plan-cannot-claim-approval-publication-or-outcome', 'use-synthetic-plan-hand-off');
return deepFreeze({ status: 'synthetic-plan-hand-off', literalId: input.id, planningIssue: input.planningIssue, assertion: deepFreeze(cloneFixed(input.assertion)), evidence: deepFreeze(cloneFixed(input.evidence)), record: deepFreeze(cloneFixed(input.record)), productionEffect: 'not-attempted', nextAction: 'open-a-separate-authorized-scope-only-if-a-real-claim-needs-evidence' });
}
export function inspectAssertionContractLiteral() { const input = createLongFormInterviewLiteral(); const output = assessLongFormInterviewPlan(input); return deepFreeze({ assertion: input.assertion.id, claim: input.evidence.claim, status: output.status, productionEffect: output.productionEffect }); }
export function inspectEvidenceBoundaryLiteral() { const input = createLongFormInterviewLiteral(); return deepFreeze({ provenance: input.evidence.provenance, confirmation: input.evidence.independentConfirmation, falsifiability: input.evidence.falsifiability, status: assessLongFormInterviewPlan(input).status }); }
export function inspectEditorialHandoffLiteral() { const output = assessLongFormInterviewPlan(createLongFormInterviewLiteral()); return deepFreeze({ transcript: output.record.transcript, speaker: output.record.speaker, publication: output.record.publication, status: output.status }); }
export function runLongFormInterviewFixture() {
const expected = [['long-form-interview-plan-v1', 'synthetic-plan-hand-off'], ['long-form-interview-undated-v1', 'stop-temporal-boundary-required'], ['long-form-interview-unnamed-claim-v1', 'stop-unnamed-claim'], ['long-form-interview-hidden-source-v1', 'stop-hidden-source'], ['long-form-interview-claimed-evidence-v1', 'stop-claimed-evidence-or-confirmation'], ['long-form-interview-fabricated-record-v1', 'stop-fabricated-interview-record'], ['long-form-interview-disallowed-result-v1', 'stop-disallowed-positive-result']];
const checks = expected.map(([id, status]) => ({ id, expected: status, actual: assessLongFormInterviewPlan(createLongFormInterviewLiteral(id)).status }));
const sample = createLongFormInterviewLiteral();
return deepFreeze({ passed: checks.filter((item) => item.expected === item.actual).length, total: checks.length, accepted: checks.every((item) => item.expected === item.actual) && Object.isFrozen(sample) && Object.isFrozen(sample.assertion) && Object.isFrozen(sample.evidence) && Object.isFrozen(sample.record), checks: deepFreeze(checks) });
}
function revision(meta, parts, referenceEntries) { const contentHtml = parts.join('') + h2('Проверяемые источники') + sources(referenceEntries); const proseLength = bodyText(contentHtml).length; if (proseLength < 10000 || proseLength > 13000) throw new Error(`${meta.slug}: body length ${proseLength}`); return deepFreeze({ ...meta, contentHtml, proseLength }); }
const refs = [
{ key: 'provDm', use: 'Даёт термины entity, activity, derivation и provenance для отделения утверждения от его происхождения.', boundary: 'Не подтверждает интервью, участника, высказывание, исходный код, метрику, review или будущую публикацию.' },
{ key: 'c2pa13', use: 'Даёт vocabulary assertions, provenance data, validation и distinction between verified association and value judgement.', boundary: 'Не делает synthetic literal свидетельством и не подтверждает правдивость, approval, ownership или outcome будущего материала.' },
];
const practice = revision({ slug: 'editorial-2027-10-practice-long-form-interview', title: 'Длинное техническое интервью: контракт утверждения до вопроса', categories: ['Интервью', 'Разработка'], cover: '/assets/editorial/2027/long-form-interview-2027-claim-evidence-map.svg', excerpt: 'План на октябрь 2027: как до вопроса зафиксировать, что именно можно утверждать, чем это проверяется и что остаётся неизвестным.', readingMinutes: 27 }, [
p('P116 — редакционный сценарий на октябрь 2027, составленный 2026-07-31. Длинная техническая беседа опасна не длиной, а первым неразмеченным утверждением. Вопрос уже может нести вывод о причине, решении или результате, хотя ни источник, ни граница ответа не определены. Цена ошибки проста: будущая редактура получает гладкую историю и начинает считать её evidence, хотя в пакете есть только план вопроса.'),
p('Вторая цена появляется, когда question list называют подготовленным интервью. Здесь нет actual interview, transcript, speaker, quote, code, metric, approval, review, ownership, publication или production effect. Нет и скрытого substitute: незаполненная строка не превращается в наблюдение. Единственный положительный evaluator output — <code>synthetic-plan-hand-off</code> с <code>productionEffect: not-attempted</code>. Всякая другая ветка должна остановиться, а не стать осторожной формулировкой.'),
h2('Начинаем не с вопроса, а с типа утверждения'),
p('Практика для длинного формата начинается с короткой карточки assertion. Она не просит кого-либо отвечать и не описывает предполагаемый ответ. Карточка называет только форму будущего вопроса: identifier, предмет проверки, допустимый класс evidence, provenance state и condition, при котором фраза не должна попасть в текст. В P116 эта карточка называется <code>synthetic-assertion-contract-v1</code>. Имя нарочно не похоже на технологию, продукт или человека.'),
p('Такой порядок кажется медленным, пока не приходится чистить материал после красивого разговора. Если сначала написать вопрос о выборе технологии, в нём легко спрятать, что выбор был, что он имел альтернативы и что у него был известный эффект. Контракт разворачивает эти три допущения в независимые поля. До evidence они получают не удобный default, а <code>not-collected</code>. До отдельного scope даже falsifiability остаётся <code>not-tested</code>: мы не знаем, какой внешний факт сможет опровергнуть будущий ответ.'),
table('Контракт утверждения для P116', ['Поле', 'Допустимый literal', 'Что оно не разрешает'], [['Assertion', '<code>synthetic-assertion-contract-v1</code>', 'Реальный вопрос или известную тему'], ['Claim', '<code>not-collected</code>', 'Вывод о причине, выборе или результате'], ['Source и provenance', '<code>not-collected</code>', 'Ссылку на скрытый документ или память'], ['Independent confirmation', '<code>not-collected</code>', 'Независимую вторую проверку'], ['Falsifiability', '<code>not-tested</code>', 'Критерий, что будущая фраза уже выдержала проверку']]),
p('Здесь важен не словарь, а направление вывода. Claim — это то, что текст хотел бы сказать. Evidence — то, что могло бы поддержать claim. Provenance — откуда evidence произошло и какая activity его породила. Independent confirmation — отдельная проверка, которая не копирует тот же неизвестный источник. Falsifiability — заранее названное условие, при котором claim придётся снять или сузить. Эти слова не взаимозаменяемы: два одинаковых пересказа не становятся независимыми только потому, что лежат в разных абзацах.'),
p('У длинного интервью есть соблазн заменить контракт умной формулировкой. Например, написать вопрос так, чтобы он уже намекал на ответ. Для plan/scenario это неверная оптимизация. Чем конкретнее такой намёк, тем выше шанс, что редактор унаследует его как факт. Поэтому карточка не хранит домен, команду, дату события, канал, автора или цифру. Она хранит только named synthetic literal и отрицательные состояния. Нужная конкретика может появиться позже, но только вместе с новым разрешением и собственным происхождением.'),
figure('/assets/editorial/2027/long-form-interview-2027-claim-evidence-map.svg', 'Схема: контракт утверждения проходит через source, provenance, independent confirmation и falsifiability; при отсутствии любого статуса сохраняется остановка, а не текстовый вывод.', 'Карта показывает форму редакционной проверки P116. Это не карта реального интервью и не список полученных доказательств.'),
h2('Runnable example: literal не становится разговором'),
p('Пример ниже можно выполнить локально. Он импортирует только этот module, создаёт копию named fixed literal и запускает evaluator. Он не касается диска, соединений, переменных процесса, текущего времени, секретов, телеметрии, системных интерфейсов или внешних данных. Он не создаёт interview, не отправляет вопрос, не запрашивает approval и не публикует текст. PASS означает ровно одно: in-memory shape соответствует запрету на выдуманный narrative.'),
code("import { inspectAssertionContractLiteral } from './scripts/upgrade-2027-10.mjs';\n\nconst result = inspectAssertionContractLiteral();\nconsole.log(result);\n// { assertion: 'synthetic-assertion-contract-v1',\n// claim: 'not-collected',\n// status: 'synthetic-plan-hand-off',\n// productionEffect: 'not-attempted' }"),
p('Полезна и отрицательная проверка. Literal с пустым identifier не трактуется как вопрос, который можно уточнить позднее. Literal с <code>source: hidden</code> не получает мягкий warning. Literal с <code>claim: claimed</code> не принимается как черновик. В закрытом evaluator нет режима «почти верно»: неизвестный object тоже возвращает stop-status. Такая жёсткость нужна потому, что длинный формат сильнее обычной заметки создаёт доверие к связному рассказу.'),
h2('Как собрать question contract без подмены факта'),
p('Сначала отделите предмет от предположения. Предметом может быть область будущего разбора: граница решения, порядок проверки, ограничение подхода. Предположение звучит иначе: будто выбор уже был сделан, проблема наблюдалась или последствие измерено. В P116 предположение не переписывают более осторожным словом; его убирают. Вопрос остаётся вопросом только пока не содержит готового факта внутри синтаксиса.'),
p('Затем назовите минимальный evidence class, но не придумывайте экземпляр. Для statement о поведении кода классом мог бы быть versioned artifact и воспроизводимая проверка. Для statement о редакционном решении — явно созданная запись с датой, scope и полем происхождения. Это не означает, что такие артефакты существуют для P116. Наоборот, отсутствие экземпляра фиксируется отдельно. План не имеет права создать source, потому что красивому тексту нужен источник.'),
p('Третий шаг — описать stop condition прежде, чем придумывать follow-up. Если origin не виден, нельзя делать attribution. Если один и тот же origin пересказан дважды, нельзя называть это independent confirmation. Если нет условия опровержения, нельзя повышать уверенность от повторения. Эти правила не делают будущий материал беднее. Они сокращают ложные ветви до того, как редактор начнёт защищать их плотностью текста или именем предполагаемого собеседника.'),
h2('Карточка должна пережить смену формата'),
p('Question contract полезен и тогда, когда будущий формат перестанет быть длинным. Один и тот же assertion может попасть в короткую заметку, список тем, внутренний комментарий или вообще не попасть никуда. Если карточка содержит готовую драматургию, она тянет этот narrative за собой. Если содержит только claim boundary, она остаётся переносимой. Поэтому в ней нельзя хранить предполагаемый порядок реплик, настроение, мотивацию или обещанный финал. Эти детали принадлежат материалу, который пока не существует.'),
p('Проверяйте гранулярность отдельно. Формула «почему выбрали подход» слишком широка: она смешивает факт выбора, альтернативы, критерий и последствия. Формула «какой artefact мог бы различить два описания границы» уже указывает на техническое действие, но не предполагает его ответ. Сужение вопроса не должно незаметно стать сужением ответа. Когда это различие не фиксируют, редактор легко подменяет будущую проверку собственным знанием о типичном проекте.'),
p('Для каждого поля полезно задать запрещённую операцию. Claim нельзя повысить до confidence score. Source нельзя получить из свободного текста. Provenance нельзя заменить URL на общую документацию. Confirmation нельзя засчитать по совпадению слов. Falsifier нельзя назвать после того, как narrative уже выбран. Такой список звучит как защита от очевидного, но именно эти подстановки обычно не видны в больших черновиках: каждое решение выглядит локальным, а итог становится уверенной историей без опоры.'),
p('Контракт также защищает автора от ложной обязанности продолжать. После создания fixed literal не нужно изображать, что следующий вопрос уже сформирован лучше чужого. P116 не сравнивает варианты и не оценивает редакторскую зрелость. Он всего лишь сохраняет право остановиться на вопросе. В наставническом тоне это важная практическая граница: хорошая подготовка иногда состоит в том, чтобы не превращать неполный вход в работу для других людей.'),
h2('Порядок действий'),
ol(['Записать editor date <code>2026-07-31</code>, planDate <code>2027-10</code> и source cutoff <code>2026-07-31</code>; не выводить их из текущего времени.', 'Создать только named assertion literal; не добавлять тему, участника, quote, цифру, код или предполагаемое решение.', 'Для claim, source, provenance и independent confirmation оставить <code>not-collected</code>; для falsifiability — <code>not-tested</code>.', 'Запустить fixture и проверить, что unnamed claim, hidden source и claimed evidence получают stop-status.', 'Проверить, что будущий текст называет план вопроса, а не actual interview или готовый материал.', 'Открывать другой scope лишь когда конкретному утверждению действительно требуется разрешённое evidence.']),
h2('Где контракт намеренно слаб'),
p('Контракт не оценивает качество будущего вопроса, не назначает интервьюера и не выбирает площадку. Он не умеет решить, будет ли у будущего материала ценность для читателя. Это ограничения, а не дефекты: попытка решить их сейчас создала бы ownership, approval или production narrative без полномочий. In-memory fixture также не проверяет документы, записи, людей или внешние системы. Он проверяет только то, что программа отказалась выдавать план за свидетельство.'),
p('Контракт не делает вопрос безопасным сам по себе. Реальная работа может потребовать согласия, проверки доступа, редакционного решения, хранения материалов и отдельного review. Ничего из этого не существует в P116 и ничего из этого нельзя достроить из статуса <code>not-collected</code>. Сильная сторона планового документа — не полнота, а возможность честно показать, какой вход пока отсутствует. Поэтому visual и table здесь тоже описывают форму контроля, а не обстоятельства разговора.'),
h2('Следующий шаг'),
p('Если будущая задача захочет написать один claim, она должна открыть отдельный authorized scope и принести собственные temporal boundary, source policy, provenance record, method независимого подтверждения и условие опровержения. До такого решения P116 заканчивается без интервью, без transcript и без опубликованного результата. Его единственный допустимый итог — <code>synthetic-plan-hand-off</code> с <code>productionEffect: not-attempted</code>.')
], refs);
const mechanism = revision({ slug: 'editorial-2027-10-mechanism-long-form-interview', title: 'Длинное техническое интервью: evidence, provenance и опровержимость', categories: ['Интервью', 'Разработка'], cover: '/assets/editorial/2027/long-form-interview-2027-source-boundary-matrix.svg', excerpt: 'План на октябрь 2027: почему совпадающие фразы не являются независимым подтверждением и как не выдать provenance за доказанный вывод.', readingMinutes: 28 }, [
p('P116 — плановый выпуск на 2027-10 с редакторской датой 2026-07-31 и source cutoff 2026-07-31. Ошибка механизма начинается, когда связная техническая история получает статус доказательства без visible origin. Одна и та же незафиксированная деталь может пройти через заметки, черновик и вопросник, а потом выглядеть как три подтверждения. Цена — редактор усиливает assertion количеством повторов и не замечает, что у всех повторов один неизвестный корень.'),
p('Другая цена — считать отсутствие возражения проверкой. В этом scenario нет actual interview, transcript, speaker, quote, code, metric, approval, review, publication, ownership или production effect. Поэтому нельзя сказать, что кто-то подтвердил или опроверг будущую версию. Positive output evaluator только один: <code>synthetic-plan-hand-off</code> с <code>productionEffect: not-attempted</code>. Любой hidden source, claimed evidence или fabricated record обязан завершиться fail-closed status.'),
h2('Evidence не равно тексту, который удобно цитировать'),
p('Механизм начинается с простого разделения. Evidence — конкретный material, который можно предъявить в разрешённом scope. Provenance — цепочка, объясняющая, откуда material появился, какая activity его породила и где лежит граница использования. Claim — вывод, который пытается опереться на этот material. Falsifiability — способ заранее сказать, что именно сделает вывод непригодным. Пока хотя бы одна часть отсутствует, текст может описывать вопрос, но не должен изображать установленный факт.'),
p('Independent confirmation требует не второго формулировочного варианта, а независимого пути к проверке. Два файла, созданные из одного неизвестного payload, не являются двумя evidence records. Два редактора, пересказавшие одну непомеченную фразу, не создают второго origin. Даже cryptographic binding не превращает содержание в истину: он может показывать связь assertion с asset и целостность формы, но не производит наблюдение, которого не было. Для P116 это важная граница между технической аккуратностью и фабрикацией.'),
table('Матрица механизма evidence', ['Слой', 'Что можно проверить в будущем scope', 'Что нельзя заключить в P116'], [['Claim', 'Точная формулировка и scope', 'Что он верен'], ['Evidence', 'Наличие разрешённого artefact', 'Что artefact уже существует'], ['Provenance', 'Origin, activity и temporal boundary', 'Кто сказал или сделал что-либо'], ['Independent confirmation', 'Отдельность метода и origin', 'Что два похожих текста независимы'], ['Falsifiability', 'Условие снятия или сужения claim', 'Что тест уже прошёл']]),
p('Плановый evaluator не моделирует реальные источники и не пытается угадать, будут ли они доступны. Его literals дают специальную форму для отсутствия: <code>not-collected</code> у claim, source, provenance и confirmation; <code>not-tested</code> у falsifiability. Эти значения не означают низкое качество материала. Они означают, что P116 не запускал activity, которая могла бы создать или проверить material. Механизм полезен именно потому, что не превращает неизвестность в рейтинг уверенности.'),
p('Здесь же видно, почему source boundary важнее количества ссылок. Внешние спецификации ниже поддерживают терминологию происхождения и validation. Они не являются источниками о будущих участниках или фактах беседы. Нельзя взять точное определение provenance и присоединить к нему вымышленную биографию процесса. Нормативный источник задаёт язык для разграничения, но не заменяет origin record конкретного claim. В P116 sources помогают читать поля, а не заполняют поля за будущую работу.'),
figure('/assets/editorial/2027/long-form-interview-2027-source-boundary-matrix.svg', 'Матрица: claim отделён от evidence, provenance, независимого подтверждения и условия опровержения; неизвестный или скрытый слой ведёт к stop-status.', 'Матрица показывает проверку формы P116. Она не фиксирует источник, участника или результат технического интервью.'),
h2('Почему falsifiability надо писать до narrative'),
p('Опровержимость в редакционной работе не означает обещание найти ошибку. Это договорённость не расширять claim, пока не определено, какое наблюдение заставит его снять или ограничить. Без такого условия любая новая деталь читается как поддержка, а несоответствие объясняется исключением. В длинном формате это особенно дорого: читатель получает десять связанных абзацев и естественно предполагает, что они прошли одинаковую проверку. Между тем один абзац мог быть только планом вопроса.'),
p('Для технической темы условие опровержения обычно привязано к виду evidence, а не к красивому контраргументу. Пример: будущий assertion о поведении кода мог бы требовать version-pinned artifact и результат минимальной воспроизводимой проверки. Если artifact относится к другой версии или проверка не различает альтернативы, claim остаётся неподтверждённым. Это не fictional code example P116; это форма границы. Мы не называем проект, функцию, output или число, чтобы не превратить пояснение в fake record.'),
p('Independent confirmation проверяют сразу после provenance. Сначала спрашивают: какие entities и activities связаны с первым evidence? Затем: использует ли второй путь те же entity, activity или скрытый интерпретатор? Только после этого можно говорить о независимости. Если связи неизвестны, корректный статус — не «вероятно независимо», а <code>not-collected</code>. Такая последовательность защищает от common-mode error: несколько аккуратных документов могут повторять один и тот же неподтверждённый слой.'),
h2('Runnable example: evaluator не дорисовывает подтверждение'),
p('Этот пример запускает только pure function над fixed in-memory literal. Он не открывает repository или файловые пути, не делает сетевых вызовов, не смотрит process variables, время, secrets, telemetry, system interfaces либо external data. Он не ищет origin, не вызывает валидатор, не создаёт signature и не публикует result. Вывод показывает состояние boundary, не состояние мира. Его можно исполнить безопасно, потому что data flow замкнут внутри модуля.'),
code("import { inspectEvidenceBoundaryLiteral } from './scripts/upgrade-2027-10.mjs';\n\nconst result = inspectEvidenceBoundaryLiteral();\nconsole.log(result);\n// { provenance: 'not-collected', confirmation: 'not-collected',\n// falsifiability: 'not-tested', status: 'synthetic-plan-hand-off' }"),
p('Отрицательные fixtures делают правило видимым. <code>long-form-interview-hidden-source-v1</code> останавливается до narrative. <code>long-form-interview-claimed-evidence-v1</code> не получает более высокий confidence, потому что в P116 нельзя собрать claim. <code>long-form-interview-fabricated-record-v1</code> останавливается одним статусом для claimed interview, transcript, speaker, quote, code, metric, approval, review, publication и ownership. Это не список вероятных ошибок реального процесса; это закрытая защита от того, чтобы synthetic literal имитировал наблюдение.'),
h2('Проверка механизма по шагам'),
ol(['Сформулировать один claim type без ответа, истории и оценки будущего материала.', 'Записать required evidence class, но оставить конкретный evidence instance отсутствующим.', 'Связать provenance с origin и activity только в новом authorised scope; не подставлять память, ссылку или чужой пересказ.', 'Проверить independence: второй путь не должен наследовать тот же неизвестный origin или метод.', 'Назвать falsifier до вывода; если он не определён, оставить <code>not-tested</code>.', 'Прогнать fixture и убедиться, что hidden source, claimed evidence и fabricated record не деградируют до warning.']),
h2('Ложные сокращения и их стоимость'),
p('Первое ложное сокращение — считать, что provenance равна quality. Provenance помогает понять происхождение и границу trust decision, но сама не делает statement полезным или истинным. Второе — считать, что signature закрывает смысловой спор. Она может защитить association и целостность, не подтверждая интерпретацию. Третье — считать, что два согласных абзаца уже образуют independent confirmation. Без разных origins это только более громкий повтор. Все три сокращения создают привлекательный текст, но лишают будущую проверку точки входа.'),
p('Есть и обратная ошибка: требовать от plan/scenario полный evidence ledger. Это заставляет автора изобретать documents, people и measurements, чтобы таблица не выглядела пустой. В P116 пустые states — правильный результат. Мы не знаем ни формата будущего материала, ни того, будет ли доказательство вообще нужно. Поэтому evaluator не хранит fallback source, confidence score или заранее одобренный route. Such defaults особенно опасны: они делают неполный context похожим на подготовленное решение.'),
h2('Разделяйте проверку формы и проверку содержания'),
p('Сначала проверяется форма записи: literal известен, даты точны, поля не получают скрытых значений. Затем, в другом scope, может проверяться содержание будущего claim. Смешивать эти этапы нельзя. Формальная проверка может доказать, что object не содержит fabricated field, но не может сказать, что техническое объяснение верно. И наоборот, даже сильный материал не отменяет необходимость показать его origin. Два вида проверки дополняют друг друга, но не заменяют один другой.'),
p('Это различие особенно полезно при независимом подтверждении. У второго пути должны быть отдельно названы material, method и relationship с первым путём. Нельзя считать независимостью тот случай, когда второй reviewer читает первый summary, а затем соглашается с ним. Нельзя считать независимостью тот случай, когда одна система экспортирует один и тот же state в два файла. Until the paths are described, P116 сохраняет <code>not-collected</code>, даже если потенциально можно было бы придумать правдоподобную схему.'),
p('Falsifier тоже надо держать маленьким. Он не обязан опровергать весь будущий материал; достаточно определить условие, которое не позволит произнести конкретный claim в заявленной широте. Например, несовпадение temporal boundary может снять право переносить statement между версиями. Отсутствие различающего теста может снять причинный вывод. Неудача не делает источник плохим и не делает автора некомпетентным. Она только возвращает assertion в состояние, где его нельзя использовать как установленную связь.'),
p('Такой механизм не запрещает редакционную интерпретацию. Он требует подписать её уровнем уверенности и не спутать с evidence. В будущем scope можно будет отдельно записать, где заканчивается observed material и начинается пояснение для читателя. P116 намеренно не создаёт даже эту границу для конкретного сюжета: нет сюжета, нет observation, нет authorial conclusion. Есть лишь правило, что empty provenance нельзя компенсировать гладкой логикой.'),
h2('Ограничения и следующий scope'),
p('P116 не является provenance system, fact-checking process, interview protocol или validation service. Он не определяет, какие источники будут допустимы в будущем, и не обещает, что independent confirmation достижимо. Никакой status здесь не говорит о правдивости, качестве, ценности или согласовании будущего текста. Fixture проверяет только closed-world equality с named literals. Внешний claim, даже правдоподобный, должен быть отвергнут до тех пор, пока другой scope не определит его данные и полномочия.'),
p('Следующий шаг — создать отдельный scope, если конкретный editorial claim действительно требует evidence. В нём надо зафиксировать source policy, origin record, access boundary, method независимой проверки, falsifier и правило, что делать при отсутствии данных. P116 не переносит в этот scope готовый вывод. Он оставляет только <code>synthetic-plan-hand-off</code> и <code>productionEffect: not-attempted</code>, чтобы future work не получила invented certainty вместе с планом.')
], refs);
const field = revision({ slug: 'editorial-2027-10-field-long-form-interview', title: 'Длинное техническое интервью: редакционный hand-off без transcript', categories: ['Интервью', 'Разработка'], cover: '/assets/editorial/2027/long-form-interview-2027-editorial-handoff-loop.svg', excerpt: 'План на октябрь 2027: как передать будущий редакционный вопрос, не создав transcript, speaker, approval или историю публикации.', readingMinutes: 27 }, [
p('P116 — future editorial plan/scenario: editor date 2026-07-31, planDate 2027-10, source cutoff 2026-07-31. В field hand-off самая дорогая ошибка выглядит как аккуратная папка: question list, схема, ссылка и краткое резюме. Получатель видит полноту формы и может решить, что interview уже состоялся, материалы собраны, а дальнейшая работа — лишь выпуск. Цена такой подмены — fabricated transcript и approval появляются не в тексте, а в ожиданиях следующего человека.'),
p('В этом пакете нет actual interview, transcript, speaker, quote, code, metric, evidence, review, publication, ownership или production effect. Нельзя прикрыть их neutral labels: <code>not-created</code> не означает потерянный файл, <code>not-named</code> не означает скрытого собеседника, <code>not-requested</code> не означает pending approval. Единственный positive evaluator result — <code>synthetic-plan-hand-off</code> с <code>productionEffect: not-attempted</code>. Всё, что пытается выдать plan за редакционный факт, закрывается fail-closed.'),
h2('Field hand-off передаёт границу, а не narrative'),
p('Хорошая передача в изолированном scope должна быть достаточно полезной, чтобы новый scope мог начать с правильного вопроса, и достаточно пустой, чтобы не унаследовать ложный результат. Поэтому P116 отдаёт четыре вещи: temporal boundary, named assertion contract, evidence states и record states. Он не отдаёт тезис будущей статьи, список вопросов к человеку, summary ответа или путь публикации. Такой набор намеренно похож на технический interface: у него есть доступные поля и явные запреты, но нет скрытого поведения.'),
p('Record states важнее, чем кажутся. <code>interview: not-created</code> запрещает называть план состоявшимся разговором. <code>transcript: not-created</code> запрещает делать вид, что существует расшифровка. <code>speaker: not-named</code> запрещает attribution. <code>quote: not-created</code> и <code>code: not-created</code> не позволяют добавить illustrative fragment без происхождения. <code>metric: not-collected</code> не оставляет цифре роль decoration. Остальные states так же явно не создают approval, review, publication или owner.'),
table('Field hand-off и недопустимая интерпретация', ['Поле hand-off', 'Состояние P116', 'Неверное чтение'], [['Interview', '<code>not-created</code>', 'Разговор назначен или состоялся'], ['Transcript и quote', '<code>not-created</code>', 'Есть запись или дословная фраза'], ['Speaker', '<code>not-named</code>', 'Можно приписать позицию роли или человеку'], ['Approval и review', '<code>not-requested</code> / <code>not-created</code>', 'Материал согласован или проверен'], ['Publication и ownership', '<code>not-attempted</code> / <code>not-assigned</code>', 'Есть канал выпуска или ответственный']]),
p('Эта точность не бюрократическая. Handoff часто переживает автора и исходный контекст. Через неделю status без происхождения легко читается как история: «не нашли transcript», «неизвестен speaker», «approval задержался». P116 говорит другое: соответствующие activities не создавались в этом scope. Следующий scope может начать совсем по-другому, сузить задачу или отказаться от неё. Он не обязан восстанавливать отсутствующий процесс и не несёт мнимую обязанность завершить опубликованный narrative.'),
p('Визуальная схема не должна компенсировать отсутствие реальных материалов реалистичными иконками. Поэтому SVG P116 содержит только gates и состояния, без портретов, сервисов, таймлайна или имитации документа. Русские alt и caption прямо называют её редакционным loop. На узком экране caption имеет тот же вес, что основной текст: если она скажет «интервью», а body скажет «план», читатель запомнит первое. Accessibility здесь поддерживает temporal honesty, а не только формальную разметку.'),
figure('/assets/editorial/2027/long-form-interview-2027-editorial-handoff-loop.svg', 'Петля hand-off: temporal boundary, assertion contract и evidence states ведут либо к отдельному authorised scope, либо к stop; transcript, speaker, approval и publication не создаются.', 'Схема показывает маршрут передачи P116 без fabricated transcript, интервью, владельца или публикации.'),
h2('Runnable example: передача не делает публикацию'),
p('Пример ниже проверяет output evaluator и выводит только fixed record states. Он не открывает папку или repository, не использует I/O, переменные окружения, часы процесса, секреты, телеметрию, системные API либо внешние records. Он не создаёт editor workflow, не назначает owner и не отправляет уведомления. Эти отсутствующие side effects важнее удобной демонстрации: запуск должен быть безопасен в любом локальном shell и не давать ложного впечатления, что package что-то передал реальному получателю.'),
code("import { inspectEditorialHandoffLiteral } from './scripts/upgrade-2027-10.mjs';\n\nconst result = inspectEditorialHandoffLiteral();\nconsole.log(result);\n// { transcript: 'not-created', speaker: 'not-named',\n// publication: 'not-attempted', status: 'synthetic-plan-hand-off' }"),
p('Если record получает <code>claimed</code>, evaluator не пытается выбрать менее смелую версию. Named bad literal собирает сразу interview, transcript, speaker, quote, code, metric, approval, review, publication и ownership в forbidden shape; результат — <code>stop-fabricated-interview-record</code>. Это также защищает от мелкой подмены: роль без имени всё равно была бы fabricated attribution, а условная цифра всё равно была бы fabricated metric. В P116 нельзя превращать illustrative content в quasi-evidence.'),
h2('Что получатель действительно получает'),
p('Получатель получает границу редакционной ответственности. Он знает, что P116 не устанавливает actual event, не даёт право на contact и не создаёт publication task. Он видит exact dates, positive status и список запрещённых переходов. Этого достаточно, чтобы не использовать package как доказательство при решении. Если для следующего решения evidence не требуется, hand-off может остаться конечным артефактом. Если требуется, он сообщает, что нужен новый scope, а не продолжение по умолчанию.'),
p('Получатель не получает owner. Такое отсутствие иногда кажется неудобным: кому тогда адресовать вопрос? Но owner — не decoration документа, а решение с последствиями. Его невозможно спрятать за generic role, потому что даже role создаёт ожидание и маршрут работы. P116 оставляет <code>ownership: not-assigned</code>. Новый authorised scope сам обязан определить полномочия, контакт, consent, storage и exit condition; до этого старый plan не должен толкать работу в конкретную сторону.'),
p('То же относится к approval. Approval не можно симулировать фразой «готово к согласованию», если не определены материал, reviewer и правило решения. В P116 approval имеет <code>not-requested</code>, потому что запрашивать нечего. Review — <code>not-created</code>, потому что нечего проверять. Такая пара предотвращает классическую ошибку hand-off: наличие аккуратной схемы ошибочно принимают за готовность начать publication. Схема показывает только условия, при которых будущая работа должна остановиться.'),
h2('Порядок редакционной передачи'),
ol(['Передать exact temporal boundary: editor date <code>2026-07-31</code>, planDate <code>2027-10</code>, source cutoff <code>2026-07-31</code>.', 'Передать named assertion literal и states evidence; не добавлять summary, предполагаемую тему или список людей.', 'Сохранить interview, transcript, quote, code и review в <code>not-created</code>; не создавать illustrative substitutes.', 'Сохранить speaker как <code>not-named</code>, approval как <code>not-requested</code>, ownership как <code>not-assigned</code> и publication как <code>not-attempted</code>.', 'Прогнать fixture: hidden source, claimed evidence, fabricated record и disallowed positive result должны остановиться.', 'Открыть отдельный scope только при конкретном решении; он может завершиться без интервью и без публикации.']),
h2('Граница источников и редакционной целостности'),
p('W3C PROV-DM полезен здесь как vocabulary: entity, activity, agent и derivation помогают не склеить plan с record. Но он не создаёт entity, activity или agent в P116. C2PA 1.3 полезна другим ограничением: validation association и tamper evidence не дают value judgement о содержании. В editorial hand-off это значит, что даже хорошо оформленный object нельзя объявить правдивым рассказом. Мы используем обе спецификации как язык границы, а не как authority над future interview.'),
p('Список sources находится после body и содержит exact URL, version/date, use и boundary. Это важная форма: source section должна быть проверяемой, но не должна выглядеть как скрытый пакет evidence о неизвестном событии. Ни одна ссылка не подтверждает person, statement, metric, approval или effect. Если новый scope принесёт собственные materials, он обязан отделить их provenance от этих нормативных ссылок. Иначе vocabulary quietly becomes a borrowed source, а hand-off снова начинает рассказывать историю вместо передачи ограничения.'),
h2('Как не испортить передачу полезной конкретикой'),
p('Первый риск — добавить образец transcript, чтобы получателю было понятнее. Даже если в нём нет имени, образец быстро становится шаблоном ожидаемого ответа и выглядит как fragment реального разговора. Второй риск — добавить условный code block. Он создаёт ложное впечатление, что будущая тема уже связана с конкретной системой. Третий риск — вставить приблизительную метрику для масштаба. Такая цифра почти неизбежно будет процитирована без слова «условная». P116 не использует ни один из этих приёмов.'),
p('Полезность hand-off строится иначе: на точных запретах и следующем безопасном входе. Получатель видит, какие states нельзя повышать, какие facts нельзя дописывать и какие вопросы должен решить новый scope. Это меньше похоже на brief, зато не давит на будущую работу готовой постановкой. В изолированном пакете ограничение часто ценнее детали, потому что detail без authorisation создаёт именно тот долг, который hand-off обязан был не переносить.'),
p('Четвёртый риск — назвать generic owner, чтобы пакет не выглядел бесхозным. Но generic owner не нейтрален: он меняет, кто предполагаемо отвечает за privacy, контакт и публикацию. Поэтому <code>not-assigned</code> не следует заменять названием функции или команды. Аналогично нельзя писать, что approval «остаётся за редактором»: это уже ownership decision. Новый scope должен принять его явно или оставить работу незапущенной. P116 не имеет мандата делать это вместо него.'),
p('Пятый риск — посчитать PASS fixture знаком готовности к выпуску. Fixture знает только fixed literals и сознательно не читает внешний мир. Он не может увидеть корректность текста, желание участника, право хранения или качество будущей редакторской работы. PASS доказывает исключительно, что запрещённые shapes не прошли evaluator. Это полезный, но узкий результат. В hand-off его надо писать рядом с <code>productionEffect: not-attempted</code>, иначе техническая проверка снова станет суррогатом реального approval.'),
h2('Ограничения и следующий шаг'),
p('P116 не заменяет consent process, editorial policy, fact check, records retention, interview format или publication workflow. Он не определяет язык будущего материала и не гарантирует, что работа будет кому-либо нужна. Fixture не является review, потому что проверяет synthetic literal, а не текст разговора. Он не создаёт production effect и не измеряет качество. Эти ограничения удерживают scope от расширения в систему редакционного управления, которой пользователь не поручал появиться.'),
p('Следующий шаг возможен, если отдельное решение требует реального claim. Новый scope должен назвать материалы, доступ, provenance, независимое подтверждение, falsifier, privacy boundary, owner и разрешённый выход без выпуска. Пока он не создан, P116 оставляет только <code>synthetic-plan-hand-off</code> с <code>productionEffect: not-attempted</code>. Это не недоделанное интервью; это честно завершённый hand-off, который не фабрикует ни transcript, ни speaker, ни outcome.')
], refs);
export const revisions = deepFreeze([practice, mechanism, field]);
export function verifyRevisionsAgainstFixture() { const fixture = runLongFormInterviewFixture(); const articleChecks = revisions.map((item) => { const text = bodyText(item.contentHtml); return text.length >= 10000 && text.length <= 13000 && /(цен[аы]|стоимост|дорог)/i.test(text.slice(0, 1500)) && /<table>/.test(item.contentHtml) && /<figure>/.test(item.contentHtml) && /<pre><code>/.test(item.contentHtml) && /<ol>/.test(item.contentHtml) && /2027-10/.test(text) && /2026-07-31/.test(text) && /productionEffect: not-attempted/.test(text); }); return deepFreeze({ passed: fixture.passed + articleChecks.filter(Boolean).length, total: fixture.total + articleChecks.length, accepted: fixture.accepted && articleChecks.every(Boolean), fixture, articleChecks, characters: Object.fromEntries(revisions.map((item) => [item.slug, bodyText(item.contentHtml).length])) }); }
if (process.argv.includes('--verify-fixture')) { const result = verifyRevisionsAgainstFixture(); process.stdout.write(JSON.stringify(result, null, 2) + '\n'); if (!result.accepted) process.exitCode = 1; }
if (process.argv.includes('--print-revisions')) process.stdout.write(JSON.stringify(revisions) + '\n');