feat: 任务书 11,指标名加候选前缀、消融重做接着改、判重说明补关键设定
- 假设专用指标短名不能含"."(最长 64),冻结时由 materials 的 freezeProtocol 改为全名"候选编号.短名";可引用清单用全名,已占用清单只剩任务指标和两个保留键。 - 消融格核验不通过重做时,工作目录是上一次交的这一格代码的副本,能读的版本加上它,完整代码照旧列出;消融实现提示词同步改。 - jev 判重材料说明补 keySettings 一句。 - 结构.md 第八部分 vocab、materials、jev,WORK_LOG 同步更新。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -16,7 +16,7 @@ export type DedupFactor = Pick<Factor, "name" | "method" | "keySettings">;
|
||||
/** 一份冻结协议的条款(docs/方法.md 4.3 ⑥"冻结协议包括"),字段与统一提交相同。 */
|
||||
export type FrozenProtocol = Pick<Submission<"unification">, "factors" | "safeguards" | "metrics" | "body" | "clauses">;
|
||||
|
||||
/** 协议要求候选代码采集的一条指标(新登记的和引用的都在内,由调用方查全)。 */
|
||||
/** 协议要求候选代码采集的一条指标(新登记的和引用的都在内,由调用方查全),编号是冻结协议里的全名"候选编号.短名"。 */
|
||||
export type ProtocolMetric = Pick<HypothesisMetric, "id" | "howMeasured" | "missing">;
|
||||
|
||||
/** 查代码改动时对照的那部分协议:协议正文和要采集的指标。没有要采集的指标时是空数组。 */
|
||||
|
||||
@@ -31,6 +31,7 @@ const TASKS: Readonly<Record<Site, string>> = {
|
||||
dedup:
|
||||
"Two research proposals from the same round of a study that improves a program by changing its code. " +
|
||||
"Each proposal lists its change as `factors`: one or more separate edits, each with a short `name` and a `method` saying what to change and how. " +
|
||||
"Each factor also has `keySettings`: the setting values that decide its effect, such as a step size or a time window (\"无\" when there are none). " +
|
||||
"Together the factors of one proposal are the whole change that one implementation would carry out. " +
|
||||
"The proposals were written by different researchers, in Chinese or English.",
|
||||
freeze:
|
||||
|
||||
@@ -33,7 +33,7 @@ function metricSection(d: Draft, p: FrozenProtocol): void {
|
||||
d.section("要实现的指标定义", [
|
||||
all.length === 0 ? "(这份协议没有要实现的假设专用指标)" : json(all),
|
||||
"",
|
||||
"每个指标都由候选代码在正式运行时算出、写进结果文件;测不到的写 null,不写 0。",
|
||||
"每个指标都由候选代码在正式运行时算出、写进结果文件,键照抄这里的 id(全名\"候选编号.短名\");测不到的写 null,不写 0。",
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -145,17 +145,17 @@ export function verification(d: Draft): ChecklistOf<"verification"> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 消融两种任务共用(方法.md 4.3 ⑯):任务与本轮、完整代码与本批基线、这一格(关哪个因子、换成什么)。
|
||||
* 消融两种任务共用(方法.md 4.3 ⑯):任务与本轮、完整代码与本批基线(cellCode 不为 null 时加上这一格已交的代码)、这一格(关哪个因子、换成什么)。
|
||||
* 交回本任务要处理的东西的公共部分:因子清单、完整代码的位置表、冻结协议。
|
||||
*/
|
||||
function ablation(d: Draft, role: string, codeNote: string[]): { cell: string; key: string; factors: string[]; lines: string[] } {
|
||||
function ablation(d: Draft, role: string, cellCode: string | null, codeNote: string[]): { cell: string; key: string; factors: string[]; lines: string[] } {
|
||||
const cell = d.req.object!;
|
||||
const { candidate, key } = splitCell(cell);
|
||||
const { p, items } = frozen(d, candidate);
|
||||
taskSection(d, role, `消融格 ${cell}(候选 ${candidate} 关掉 ${key})`);
|
||||
d.read(candidate, "完整代码");
|
||||
d.read(p.baseline, "本批基线(因子没写关掉时换成什么,就回到它在这件事上的做法)");
|
||||
if (d.req.kind === "ablationVerification") d.read(cell, "要核验的这一格的代码");
|
||||
if (cellCode !== null) d.read(cell, cellCode);
|
||||
d.section("完整代码(消融的起点)", [...codeLines(d), ...codeNote]);
|
||||
const f = p.factors[items.factors.indexOf(key)]!;
|
||||
d.section("这一格", [
|
||||
@@ -167,12 +167,13 @@ function ablation(d: Draft, role: string, codeNote: string[]): { cell: string; k
|
||||
}
|
||||
|
||||
/**
|
||||
* ⑯ 消融实现:从完整代码出发只关指定的因子。核验不通过重做时(这一格已有公开的消融核验)另放退回意见:
|
||||
* 最近一次核验里关错了的因子和核验员写的依据,写法同修复的退回意见。
|
||||
* ⑯ 消融实现:从完整代码出发只关指定的因子。核验不通过重做时(这一格已有公开的消融核验),和修复一样从上一次交的这一格代码
|
||||
* 接着改(用户 2026-10-03 定),另放退回意见:最近一次核验里关错了的因子和核验员写的依据,写法同修复的退回意见。
|
||||
*/
|
||||
export function ablationImplementation(d: Draft): ChecklistOf<"ablationImplementation"> {
|
||||
const a = ablation(d, "实验员", ["你的工作目录是完整代码的副本,改动都落在工作目录里。"]);
|
||||
const verified = d.board.published("ablationVerification").filter((s) => s.target === a.cell).at(-1);
|
||||
const verified = d.board.published("ablationVerification").filter((s) => s.target === d.req.object).at(-1);
|
||||
const start = verified === undefined ? "完整代码的副本" : "上一次交的这一格代码的副本,从它接着改;完整代码列在这里作对照";
|
||||
const a = ablation(d, "实验员", verified === undefined ? null : "你上一次交的这一格代码", [`你的工作目录是${start},改动都落在工作目录里。`]);
|
||||
const opinion: string[] = [];
|
||||
if (verified !== undefined) {
|
||||
const off = new Set([a.key, ...lastAblation(d, a.cell).alsoOff]);
|
||||
@@ -189,7 +190,7 @@ const lastAblation = (d: Draft, cell: string) => d.board.published("ablationImpl
|
||||
|
||||
/** ⑯ 消融核验:只查是不是只关了指定的因子(加实验员报的一起关的因子)。不算没有归属的改动。 */
|
||||
export function ablationVerification(d: Draft): ChecklistOf<"ablationVerification"> {
|
||||
const a = ablation(d, "核验员", []);
|
||||
const a = ablation(d, "核验员", "要核验的这一格的代码", []);
|
||||
const also = lastAblation(d, a.cell).alsoOff;
|
||||
d.section("这一格实际要关的因子", [
|
||||
[a.key, ...also].join("、") + (also.length === 0 ? "(只关指定的因子)" : "(指定的因子加实验员报的一起关的因子)"),
|
||||
|
||||
@@ -151,14 +151,14 @@ export function beliefSection(d: Draft): void {
|
||||
d.section("信念本", [beliefBookOf(d.board, d.req.study, d.round)]);
|
||||
}
|
||||
|
||||
/** 已登记指标清单(方法.md 第五部分"指标"):程序采集的,加冻结协议里登记过的假设专用指标。 */
|
||||
/** 已登记指标清单(方法.md 第五部分"指标"):程序采集的,加冻结协议里登记过的假设专用指标(全名)。 */
|
||||
export function metricsSection(d: Draft): void {
|
||||
const registered = registeredMetrics(d.board);
|
||||
d.section("已登记指标清单", [
|
||||
"程序每次都会采集(不用登记):",
|
||||
...d.req.study.metrics.map((m) => `- ${m.id}(${m.layer === "final" ? "最终指标" : "常规辅助"},${directionText(m.direction)},单位 ${m.unit}):${m.meaning}`),
|
||||
"",
|
||||
"研究者在冻结协议里登记过的假设专用指标(要测的量这里已经有,就写进 reused,不要重新定义;引用时沿用原登记的\"测不到时怎么办\"):",
|
||||
"研究者在冻结协议里登记过的假设专用指标,编号是全名\"候选编号.短名\"(要测的量这里已经有,就把全名写进 reused,不要重新定义;引用时沿用原登记的\"测不到时怎么办\"):",
|
||||
...(registered.length === 0
|
||||
? ["(还没有)"]
|
||||
: registered.map((m) => `- ${m.id}(候选 ${m.candidate} 登记,${directionText(m.direction)},单位 ${m.unit},测不到时${m.missing === "recordMissing" ? "只记缺失" : "整次作废"}):${m.meaning};怎么测:${m.howMeasured}`)),
|
||||
|
||||
@@ -18,6 +18,7 @@ export {
|
||||
explanationId,
|
||||
factorId,
|
||||
factorKey,
|
||||
freezeProtocol,
|
||||
ORIGINAL_BASELINE,
|
||||
proposalId,
|
||||
splitCell,
|
||||
|
||||
@@ -40,14 +40,16 @@ function frame(d: Draft, own: Own, middle: () => void): void {
|
||||
if (d.round >= 1) metricsSection(d);
|
||||
}
|
||||
|
||||
/** 提案、回应、统一共用的因子规则(方法.md 第五部分"延续""指标"、4.3 ②)。答案路径、保障动手次数的两个键也算占用(用户 2026-10-03 定)。 */
|
||||
/**
|
||||
* 提案、回应、统一共用的因子规则(方法.md 第五部分"延续""指标"、4.3 ②)。能引用的是已登记指标的全名;已占用的只有任务的指标和
|
||||
* 两个保留键(用户 2026-10-03 定),已登记的全名带"."、新登记的短名不带,不会重名。
|
||||
*/
|
||||
function factorRules(d: Draft) {
|
||||
const registered = registeredMetrics(d.board).map((m) => m.id);
|
||||
return {
|
||||
factorLimit: d.req.study.factorLimit,
|
||||
continuable: d.board.protocols().flatMap((p) => p.protocol.factors.map((_, i) => factorId(p.candidate, factorKey(i)))),
|
||||
reusableMetrics: registered,
|
||||
takenMetricIds: [...d.req.study.metrics.map((m) => m.id), ANSWER_PATH_KEY, SAFEGUARD_TRIGGERS_KEY, ...registered],
|
||||
reusableMetrics: registeredMetrics(d.board).map((m) => m.id),
|
||||
takenMetricIds: [...d.req.study.metrics.map((m) => m.id), ANSWER_PATH_KEY, SAFEGUARD_TRIGGERS_KEY],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+16
-2
@@ -54,11 +54,25 @@ export const callId = (stageId: string, actor: string, kind: string, object: str
|
||||
// 冻结协议(账本记录 protocol.protocol,方法.md 4.3 ⑥)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** 冻结协议的主体:submissions 的 protocolBody 交回的五项,与它的 ProtocolBody 同形(materials 不引用 submissions)。 */
|
||||
type ProtocolBody = Pick<Submission<"unification">, "factors" | "safeguards" | "metrics" | "body" | "clauses">;
|
||||
|
||||
/**
|
||||
* 一个候选的冻结协议(方法.md 4.3 ⑥"冻结协议包括"),拼法在 submissions;答复留在回应或统一的提交里(用户 2026-10-03 定)。
|
||||
* 一个候选的冻结协议(方法.md 4.3 ⑥"冻结协议包括"),由 freezeProtocol 写成;答复留在回应或统一的提交里(用户 2026-10-03 定)。
|
||||
* baseline 是出发的基线对象编号,round 是冻结的轮次,proposals 是合并进来的全部原提案。留池候选沿用这一份(4.3 ①)。
|
||||
* metrics 里的编号都是全名"候选编号.短名"。
|
||||
*/
|
||||
export type FrozenProtocol = Pick<Submission<"unification">, "factors" | "safeguards" | "metrics" | "body" | "clauses"> & { round: number; baseline: string; proposals: string[] };
|
||||
export type FrozenProtocol = ProtocolBody & { round: number; baseline: string; proposals: string[] };
|
||||
|
||||
/**
|
||||
* flow 写冻结协议时调用:主体加上轮次、基线、合并了哪些原提案,新登记的假设专用指标改用全名"候选编号.短名"
|
||||
* (用户 2026-10-03 定)。同一轮的研究者互相看不到提案,会起同一个短名、定义却不同;候选编号判重合并之后才有,
|
||||
* 所以只能在冻结时加。引用的指标本来就写全名,照抄。
|
||||
*/
|
||||
export function freezeProtocol(body: ProtocolBody, candidate: string, round: number, baseline: string, proposals: string[]): FrozenProtocol {
|
||||
const defined = body.metrics.defined.map((m) => ({ ...m, id: `${candidate}.${m.id}` }));
|
||||
return { ...body, metrics: { defined, reused: body.metrics.reused }, round, baseline, proposals };
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 冻结代码的位置表(账本记录 code.locations)
|
||||
|
||||
@@ -10,8 +10,12 @@ import type { SubmissionKind } from "./roster.ts";
|
||||
type FactorRules = {
|
||||
factorLimit: number;
|
||||
continuable: string[];
|
||||
/** 冻结协议里登记过的假设专用指标的全名("候选编号.短名")。 */
|
||||
reusableMetrics: string[];
|
||||
/** 最终指标、常规辅助指标和冻结协议里登记过的假设专用指标,新登记的不能和它们重名。 */
|
||||
/**
|
||||
* 新登记的短名不能用的编号:最终指标、常规辅助指标和答案路径的两个保留键。
|
||||
* 已登记的假设专用指标不在这里:它们的全名都带".",短名不带,不会重名。
|
||||
*/
|
||||
takenMetricIds: string[];
|
||||
};
|
||||
|
||||
|
||||
+10
-3
@@ -52,12 +52,19 @@ const METRIC_FIELDS = {
|
||||
}),
|
||||
};
|
||||
|
||||
/** 研究者在协议里登记的一条假设专用指标。编号由研究者起,候选代码按这个编号写出取值。 */
|
||||
/**
|
||||
* 研究者在提案、回应、统一里登记的一条假设专用指标,id 是研究者起的短名。
|
||||
* 冻结时 materials 的 freezeProtocol 把它改成全名"候选编号.短名"(用户 2026-10-03 定):同一轮的研究者互相看不到提案,
|
||||
* 会起同一个短名、定义却不同。短名不含"."、全名都含,两者不会撞。冻结协议、tasks 收的指标沿用这个类型,id 是全名。
|
||||
* 短名最长 64 个字符,加上候选编号后的全名仍在 Id 的 128 个字符以内。
|
||||
*/
|
||||
export const HypothesisMetric = Type.Object(
|
||||
{
|
||||
id: Type.String({
|
||||
...Id,
|
||||
description: "指标短名,只用字母、数字和 ._-,候选代码按它写出取值",
|
||||
pattern: "^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$",
|
||||
description:
|
||||
"指标短名:只用字母、数字和 _-,不能含\".\",最长 64 个字符。冻结时程序在前面加上候选编号,成为全名\"候选编号.短名\"" +
|
||||
"(例如 r2-c1.restart-gain);冻结之后引用它、候选代码在结果文件里写它的取值,都用全名",
|
||||
}),
|
||||
...METRIC_FIELDS,
|
||||
},
|
||||
|
||||
@@ -176,10 +176,10 @@ const SAFEGUARDS = Type.Array(SafeguardName, {
|
||||
const METRICS = Type.Object(
|
||||
{
|
||||
defined: Type.Array(HypothesisMetric, {
|
||||
description: "新登记的假设专用指标;没有就交空数组",
|
||||
description: "新登记的假设专用指标,编号只写短名;没有就交空数组",
|
||||
}),
|
||||
reused: Type.Array(Id, {
|
||||
description: "引用别人登记过的假设专用指标,照材料里已登记指标清单的编号写;没有就交空数组",
|
||||
description: "引用已登记的假设专用指标,照材料里已登记指标清单的全名(\"候选编号.短名\")写;没有就交空数组",
|
||||
}),
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user