personal-bot 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/README.zh-CN.md +9 -7
- package/docs/agent-collaboration.md +8 -4
- package/docs/file-storage.md +1 -1
- package/docs/release.md +2 -2
- package/docs/technical-design.md +1 -1
- package/docs/validation.md +3 -1
- package/npm-shrinkwrap.json +2253 -0
- package/package.json +2 -1
- package/resources/agents/coordinator.md +6 -8
- package/resources/agents/general-purpose.md +3 -3
- package/resources/prompts/tool-guidelines.md +2 -2
- package/resources/prompts/workspace.md +8 -6
- package/resources/references/compute.md +5 -5
- package/resources/references/task-conductor.md +4 -4
- package/resources/skills/project-maintenance/SKILL.md +9 -15
- package/resources/skills/provider-connections/SKILL.md +2 -2
- package/resources/templates/workspace-agents.md +3 -3
- package/src/extension/agent-events.ts +52 -13
- package/src/extension/subagent-entry.ts +3 -8
- package/src/integrations/pi/agent-context.ts +1 -1
- package/src/integrations/pi/agent-input.ts +19 -0
- package/src/integrations/pi/team-context.ts +1 -2
- package/src/services/agents/agent-service.ts +4 -0
- package/src/tools/agents/contract.ts +8 -6
- package/src/tools/agents/tool.ts +6 -4
- package/src/tools/teams/contract.ts +33 -15
- package/src/tools/teams/tool.ts +10 -5
- package/resources/skills/analysis-validation/SKILL.md +0 -48
- package/resources/skills/research-evidence/SKILL.md +0 -33
- package/resources/skills/research-evidence/references/hypothesis-checks.md +0 -33
|
@@ -4,17 +4,29 @@ import type { TSchema } from "typebox";
|
|
|
4
4
|
const id = Type.String({ minLength: 1, maxLength: 128 });
|
|
5
5
|
const text = Type.String({ minLength: 1, maxLength: 24000 });
|
|
6
6
|
const name = Type.String({ minLength: 1, maxLength: 64, pattern: "^[^\\r\\n\\x00-\\x1f]+$" });
|
|
7
|
-
const mode = Type.Union([Type.Literal("roundRobin"), Type.Literal("parallel")]);
|
|
8
|
-
const members = Type.Array(Type.Object({ agentId: id, role: Type.String({ minLength: 1, maxLength: 4000 }) }, { additionalProperties: false }), {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
7
|
+
const mode = Type.Union([Type.Literal("roundRobin"), Type.Literal("parallel")], { description: "run 必填:roundRobin 按成员顺序轮流发言;parallel 在并发上限内发言,全员本轮完成后才进入下一轮。" });
|
|
8
|
+
const members = Type.Array(Type.Object({ agentId: id, role: Type.String({ minLength: 1, maxLength: 4000 }) }, { additionalProperties: false }), {
|
|
9
|
+
minItems: 1, maxItems: 50, description: "仅 create,必填:固定成员及职责。成员须属于当前父会话分支、版本兼容且未加入其他未关闭团队。create 不启动模型,也不等待成员就绪。",
|
|
10
|
+
});
|
|
11
|
+
const run = {
|
|
12
|
+
instruction: Type.String({ ...text, description: "仅 run,必填:本次新批次的明确任务与交付要求;不恢复或重放旧批次。" }), mode,
|
|
13
|
+
rounds: Type.Optional(Type.Integer({ minimum: 1, maximum: 10, description: "仅 run:每位成员的轮数,默认 2。" })),
|
|
14
|
+
maxConcurrent: Type.Optional(Type.Integer({ minimum: 1, maximum: 50, description: "仅 run:roundRobin 默认且只允许 1;parallel 默认 min(2, 成员数)。不得超过成员数;已排队但未完成的请求也占用并发名额。" })),
|
|
15
|
+
timeoutSeconds: Type.Optional(Type.Integer({ minimum: 1, maximum: 86400, description: "仅 run:整批期限,默认 900 秒,包含所有轮次和等待。到期停止新安排和领取,子入口尽力中止未被人工接管的在途工作;pause 则允许在途工作收尾。" })),
|
|
16
|
+
};
|
|
17
|
+
const page = {
|
|
18
|
+
afterSeq: Type.Optional(Type.Integer({ minimum: 0, description: "仅 read:读取序号大于此值的消息,默认 0,不得超过 lastSeq。返回 nextAfterSeq 用于继续消息列表;单条续读使用 seq/offset,省略 afterSeq。先补完被截断的正文,再继续列表。" })),
|
|
19
|
+
seq: Type.Optional(Type.Integer({ minimum: 1, description: "仅 read:指定一条消息,配合该消息的 nextOffset 续读。未指定时从 afterSeq 后顺序读取。" })),
|
|
20
|
+
offset: Type.Optional(Type.Integer({ minimum: 0, description: "仅 read:指定 seq 的正文 UTF-16 字符偏移,默认 0;非零时必须同时提供 seq。" })),
|
|
21
|
+
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 16000, description: "仅 read:本页所有消息正文合计的 UTF-16 字符上限,默认 16000,不是消息条数或 token 数;不含元数据和 Markdown 格式开销。" })),
|
|
22
|
+
};
|
|
13
23
|
const object = <T extends Record<string, TSchema>>(fields: T) => Type.Object(fields, { additionalProperties: false });
|
|
14
24
|
export const teamParametersSchema = object({
|
|
15
|
-
action: Type.Union(["create", "list", "status", "read", "run", "pause", "close"].map(v => Type.Literal(v))
|
|
25
|
+
action: Type.Union(["create", "list", "status", "read", "run", "pause", "close"].map(v => Type.Literal(v)), {
|
|
26
|
+
description: "create 只接受并必填 name/brief/members;list 只接受 action;status/pause/close 只接受并必填 teamId;read 必填 teamId,可选 afterSeq/seq/offset/limit;run 必填 teamId/instruction/mode,可选 rounds/maxConcurrent/timeoutSeconds。禁止携带其他 action 的字段。run 要求所有成员存活、idle、当前代次团队接入就绪、无待处理私人输入,且团队未关闭、无运行批次或在途工作。pause 仅停止新安排和未领取请求;close 要求先暂停并等待在途工作结束,不停止成员进程。",
|
|
27
|
+
}),
|
|
16
28
|
teamId: Type.Optional(id), name: Type.Optional(name), brief: Type.Optional(text), members: Type.Optional(members),
|
|
17
|
-
instruction: Type.Optional(
|
|
29
|
+
instruction: Type.Optional(run.instruction), mode: Type.Optional(mode), rounds: run.rounds, maxConcurrent: run.maxConcurrent, timeoutSeconds: run.timeoutSeconds, ...page,
|
|
18
30
|
});
|
|
19
31
|
export const teamActionSchema = Type.Union([
|
|
20
32
|
object({ action: Type.Literal("create"), name, brief: text, members }),
|
|
@@ -24,24 +36,30 @@ export const teamActionSchema = Type.Union([
|
|
|
24
36
|
object({ action: Type.Literal("read"), teamId: id, ...page }),
|
|
25
37
|
]);
|
|
26
38
|
export const teamMessageParametersSchema = object({
|
|
27
|
-
action: Type.Union([Type.Literal("read"), Type.Literal("post")]
|
|
28
|
-
|
|
39
|
+
action: Type.Union([Type.Literal("read"), Type.Literal("post")], {
|
|
40
|
+
description: "read 必填 teamId,只可选 afterSeq/seq/offset/limit,禁止 text/replyTo;post 必填 teamId/text,只可选 replyTo,禁止所有分页字段。",
|
|
41
|
+
}), teamId: id, text: Type.Optional(Type.String({ ...text, description: "仅 post,必填:向全体成员公开的原文,不扩大任务授权。" })),
|
|
42
|
+
replyTo: Type.Optional(Type.Integer({ minimum: 1, description: "仅 post:回复已有消息的 seq。" })), ...page,
|
|
29
43
|
});
|
|
30
44
|
export const teamMessageActionSchema = Type.Union([
|
|
31
45
|
object({ action: Type.Literal("read"), teamId: id, ...page }),
|
|
32
46
|
object({ action: Type.Literal("post"), teamId: id, text, replyTo: Type.Optional(Type.Integer({ minimum: 1 })) }),
|
|
33
47
|
]);
|
|
34
|
-
const nullableInteger = Type.Union([Type.Integer(), Type.Null()]);
|
|
35
48
|
const message = object({ seq: Type.Integer(), operationId: Type.String(),
|
|
36
49
|
author: object({ kind: Type.Union([Type.Literal("user"), Type.Literal("coordinator"), Type.Literal("member")]), agentId: Type.Optional(id), name: Type.String() }),
|
|
37
50
|
text: Type.String(), replyTo: Type.Optional(Type.Integer()), runId: Type.Optional(id),
|
|
38
51
|
source: Type.Optional(object({ requestId: id, cycleId: id })),
|
|
39
|
-
offset: Type.Integer(), totalLength: Type.Integer(
|
|
40
|
-
|
|
52
|
+
offset: Type.Integer(), totalLength: Type.Integer({ description: "完整正文的 UTF-16 字符数。" }),
|
|
53
|
+
nextOffset: Type.Union([Type.Integer(), Type.Null()], { description: "非 null 表示本条正文尚未读完;使用相同 teamId、seq 和此 offset 续读。" }) });
|
|
54
|
+
export const teamPageSchema = object({ teamId: id, messages: Type.Array(message), lastSeq: Type.Integer(),
|
|
55
|
+
nextAfterSeq: Type.Union([Type.Integer(), Type.Null()], { description: "后续消息列表的 afterSeq;null 只表示列表已到末尾,仍须检查每条消息的 nextOffset。指定 seq 时始终为 null。" }) });
|
|
41
56
|
const ownedView = object({ teamId: id, name: Type.String(), brief: Type.String(), closed: Type.Boolean(), owned: Type.Literal(true),
|
|
42
57
|
members: Type.Array(object({ agentId: id, role: Type.String(), name: Type.String(), state: Type.String() })),
|
|
43
|
-
lastSeq: Type.Integer(), activeCount: Type.Integer(),
|
|
44
|
-
unresolved: Type.Array(object({ requestId: id, agentId: id, runId: id, round: Type.Integer(), active: Type.Boolean(),
|
|
58
|
+
lastSeq: Type.Integer(), activeCount: Type.Integer({ description: "所有批次中已领取、进程仍存活且尚无完成记录的请求数;paused 仍可能大于 0。" }),
|
|
59
|
+
unresolved: Type.Array(object({ requestId: id, agentId: id, runId: id, round: Type.Integer(), active: Type.Boolean(),
|
|
60
|
+
state: Type.String({ description: "queued=运行批次中尚未领取;accepted=已领取且仍在途;uncertain=已领取但进程/代次不再匹配、无完成记录;cancelled=批次已停止且未领取,或周期取消;unpublished=已完成但尚未公开有效原文;mixed/interactive=含人工或私人工作,不自动公开;failed/interrupted=失败或中断。不能将 unresolved 当作成功或自动重试许可。" }), cycleId: Type.Optional(id) }), {
|
|
61
|
+
description: "所有批次中尚未确认完成且公开的请求,包含排队、在途、失败、结果不明和不宜公开的工作;不是仅列出运行中的请求。先核对原请求和业务结果,避免重复执行。",
|
|
62
|
+
}),
|
|
45
63
|
run: Type.Optional(object({ runId: id, instruction: Type.String(), mode, state: Type.Union([Type.Literal("running"), Type.Literal("paused"), Type.Literal("finished")]),
|
|
46
64
|
rounds: Type.Integer(), maxConcurrent: Type.Integer(), deadlineAt: Type.Number(), scheduled: Type.Integer(), published: Type.Integer(), reason: Type.Optional(Type.String()) })) });
|
|
47
65
|
const view = Type.Union([ownedView, object({ teamId: id, name: Type.String(), closed: Type.Boolean(), owned: Type.Literal(false) })]);
|
package/src/tools/teams/tool.ts
CHANGED
|
@@ -11,13 +11,15 @@ import { markdownResult, result } from "../result.js";
|
|
|
11
11
|
import { teamParametersSchema, teamActionSchema, teamResultSchema, teamMessageParametersSchema, teamMessageActionSchema, teamMessageResultSchema } from "./contract.js";
|
|
12
12
|
|
|
13
13
|
export function teamTool(service: TeamService, agents: AgentService, access: Pick<CallAccess, "check">) {
|
|
14
|
-
const
|
|
14
|
+
const validators = new Map(teamActionSchema.anyOf.map(action => [action.properties.action.const, schema(action)]));
|
|
15
15
|
return defineTool({ name: "pbot_team", label: "团队",
|
|
16
|
-
description: "主会话管理固定成员团队。create 不启动模型;run
|
|
16
|
+
description: "主会话管理固定成员团队。create 不启动模型;run 开展有限 roundRobin 轮流讨论或 parallel 并行轮次,默认 2 轮、整批 15 分钟,成员直接取得公共原文。团队运行时占用成员;pause 停止新安排和领取,允许在途工作收尾,之后可私人 send;需要中止成员用 pbot_agent stop。到期时子入口尽力中止未被人工接管的团队工作。close 保留成员进程和历史;换成员须关闭旧团队再创建。继续须明确 run 新批次,不重放旧请求。完成仍需业务验收。",
|
|
17
17
|
parameters: teamParametersSchema, outputSchema: teamResultSchema,
|
|
18
18
|
async execute(_id, args, signal, _update, ctx) {
|
|
19
19
|
access.check(); signal?.throwIfAborted();
|
|
20
|
-
|
|
20
|
+
const valid = validators.get(args.action);
|
|
21
|
+
requireThat(valid, "未知的团队 action:" + args.action);
|
|
22
|
+
requireThat(valid(args), "团队 " + args.action + " 参数无效:" + JSON.stringify(valid.errors));
|
|
21
23
|
const input = args as Static<typeof teamParametersSchema>, owner = agentOwner(ctx), views = agents.list(owner);
|
|
22
24
|
service.recover(owner);
|
|
23
25
|
let id = input.teamId!;
|
|
@@ -40,12 +42,15 @@ export function teamTool(service: TeamService, agents: AgentService, access: Pic
|
|
|
40
42
|
});
|
|
41
43
|
}
|
|
42
44
|
export function teamMessageTool(service: TeamService, access: Pick<CallAccess, "check">, actor: (ctx: ExtensionContext) => TeamActor) {
|
|
43
|
-
const
|
|
45
|
+
const validators = new Map(teamMessageActionSchema.anyOf.map(action => [action.properties.action.const, schema(action)]));
|
|
44
46
|
return defineTool({ name: "pbot_team_message", label: "团队消息",
|
|
45
47
|
description: "直接读取/发布团队公共原文。post 不唤醒模型、不增加轮次,所有成员可见,不提供私信或递归委派。成员只能在自己的团队工作中 post。read 用 afterSeq 分页;长消息用 seq/offset/limit 继续,nextOffset 非空表示该条正文不完整。保存成功不是模型已读或业务完成。",
|
|
46
48
|
parameters: teamMessageParametersSchema, outputSchema: teamMessageResultSchema,
|
|
47
49
|
async execute(id, args, signal, _update, ctx) {
|
|
48
|
-
access.check(); signal?.throwIfAborted();
|
|
50
|
+
access.check(); signal?.throwIfAborted();
|
|
51
|
+
const valid = validators.get(args.action);
|
|
52
|
+
requireThat(valid, "未知的团队消息 action:" + args.action);
|
|
53
|
+
requireThat(valid(args), "团队消息 " + args.action + " 参数无效:" + JSON.stringify(valid.errors));
|
|
49
54
|
const input = args as Static<typeof teamMessageParametersSchema>, sender = actor(ctx);
|
|
50
55
|
if (input.action === "read") {
|
|
51
56
|
const page = service.read(input.teamId, sender, input);
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: analysis-validation
|
|
3
|
-
description: 核验数据分析、计算结果和统计结论是否足以支持本次用途。用于交付前检查、数值差异排查、跨来源比较和分析复核,重点检查完整性、口径与推断依据。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 分析核验
|
|
7
|
-
|
|
8
|
-
围绕本次要支持的结论,优先核验足以改变判断的数据和计算。检查范围随结论风险和已发现的问题确定。
|
|
9
|
-
|
|
10
|
-
## 确定核验依据
|
|
11
|
-
|
|
12
|
-
读取已有结论及其实际数据、公式、源码和参数,确认对象范围、样本单位、比较基准和关键假设。缺少原始数据或计算入口时,区分能验证的部分与只能检查说明的部分。
|
|
13
|
-
|
|
14
|
-
## 数据完整性与含义
|
|
15
|
-
|
|
16
|
-
- 核对筛选、分页、截断及对象和期间覆盖。总量以已确认的覆盖范围为限;空结果能否支持“不存在”的判断,取决于查询覆盖。
|
|
17
|
-
- 区分已确认零值、缺失、未查询、不可用和查询失败,按字段定义解释空值与零。
|
|
18
|
-
- 汇总与明细不符时,先对齐期间、范围与定义。只有范围一致且明细完整时,明细重算才可验证汇总;冲突无法解释时保留两者与影响。
|
|
19
|
-
- 按样本单位检查缺失、重复和关联前后的数量,区分同一对象的不同观测与重复计数。
|
|
20
|
-
|
|
21
|
-
根据来源定义、时间语义和指标性质判断字段值是否异常,修正需有依据。
|
|
22
|
-
|
|
23
|
-
## 口径与计算
|
|
24
|
-
|
|
25
|
-
按任务选择能暴露错误的检查:
|
|
26
|
-
|
|
27
|
-
| 对象 | 检查方法 |
|
|
28
|
-
| --- | --- |
|
|
29
|
-
| 比例与平均数 | 核对分子分母对应的对象与期间;分母为零时说明不可计算;分组平均按适当权重合并 |
|
|
30
|
-
| 分项与总数 | 确认可加性,核对合计与差异;重叠分类、不同币种和非加性指标不能直接求和 |
|
|
31
|
-
| 时间比较 | 对齐期间长度、完整程度与时区;区分数据发生时间和当时实际可获得时间 |
|
|
32
|
-
| 单位与市场口径 | 核对币种、数量单位、复权和费用假设;转换需有依据,不隐含换算或市场规则 |
|
|
33
|
-
| 关键计算 | 独立复算影响结论的值,或抽查原始记录与边界;只重跑同一段源码不能排除同一逻辑错误 |
|
|
34
|
-
| 图表 | 核对图表与底层数据、标注、尺度及比较范围,避免显示方式改变读者判断 |
|
|
35
|
-
|
|
36
|
-
输入或口径变化时,说明对可比性和结论的影响。复算依据保留实际命令、参数、必要输入与结果引用。
|
|
37
|
-
|
|
38
|
-
## 推断与适用限制
|
|
39
|
-
|
|
40
|
-
结论涉及样本推广、原因解释或预测时,检查样本选择与排除条件、样本量、幸存者偏差、替代解释和不确定性。多次比较、试验或参数筛选需结合完整选择过程评估结果。
|
|
41
|
-
|
|
42
|
-
时间序列或预测研究需要核对信息在当时是否可知、训练与评估是否泄漏。样本外检验、成本和成交约束按研究用途确定;条件未验证时限制结论范围,不把库默认值当成实际市场条件。
|
|
43
|
-
|
|
44
|
-
若主要问题是来源冲突或证据不足,使用 [research-evidence 技能](../research-evidence/SKILL.md) 处理相应判断。
|
|
45
|
-
|
|
46
|
-
## 交付核验结论
|
|
47
|
-
|
|
48
|
-
说明实际核验范围、发现的问题及其对结论的影响,判断结果足以支持本次用途、带限制可用,还是需要修正。指出关键缺口、适用条件与尚未核验的部分;修正后复查受影响结论。
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: research-evidence
|
|
3
|
-
description: 判断多来源证据能支持哪些研究结论。用于证据综合、来源冲突、方案比较和关键假设验证。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 研究证据与判断
|
|
7
|
-
|
|
8
|
-
围绕本次问题形成可追溯的结论,说明证据支持到哪里、哪些条件会改变判断。
|
|
9
|
-
|
|
10
|
-
## 选择证据
|
|
11
|
-
|
|
12
|
-
明确要支持的主张、对象和时间范围,从已有证据中识别会影响判断的缺口,再补充检索。
|
|
13
|
-
|
|
14
|
-
按主张选择来源:当前状态需要足够新的直接观测;历史事实需要对应时期的记录;规则需要适用版本;原因解释需要能区分替代解释的证据;方案比较需要一致的条件与评价依据。
|
|
15
|
-
|
|
16
|
-
需要选择探索性研究方向、安排关键实验,或判断受阻研究是否应继续时,读[关键假设验证](references/hypothesis-checks.md)。
|
|
17
|
-
|
|
18
|
-
## 核对证据与结论
|
|
19
|
-
|
|
20
|
-
- 追溯关键主张的原始来源,读取支持该主张的上下文。转述、摘要和引用链中的多个页面不算多份独立证据;新增独立观测与重复转述分开判断。
|
|
21
|
-
- 对关键证据保留定位信息、适用版本或时间、对象范围。区分事件发生时间、数据所属期间与取得时间;只记录影响本次使用的项。
|
|
22
|
-
- 将观测与推断分开,说明从证据到结论所依赖的假设。
|
|
23
|
-
- 检查可能推翻关键结论的证据与替代解释。找不到反证不等于已证实,尤其是在覆盖不足或查询失败时。
|
|
24
|
-
- 来源冲突时,核对是否为不同版本、时期、样本或定义。能解释的差异分别说明;无法解释的冲突保留在结论中,不静默选一方或按来源数量表决。
|
|
25
|
-
- 检索无结果时,核对名称、别名、筛选范围和来源是否可访问。只有查询覆盖足以支持时,才能作出不存在或未发生的判断。
|
|
26
|
-
|
|
27
|
-
## 综合与交付
|
|
28
|
-
|
|
29
|
-
按问题组织结论,关键结论附近给出来源或产物引用。说明支持及反对依据、重要假设、未决冲突和适用限制,用证据充分性解释置信程度。
|
|
30
|
-
|
|
31
|
-
以本次交付用途判断证据是否足够。关键缺口阻止结论时,说明缺什么、影响哪部分及如何核实;条件化结论明确其待验证前提。
|
|
32
|
-
|
|
33
|
-
涉及数值、数据比较或统计推断时,按需使用 [analysis-validation 技能](../analysis-validation/SKILL.md)。
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# 关键假设验证
|
|
2
|
-
|
|
3
|
-
用于探索性研究的选题、实验安排和受阻后的方向判断,尽早取得能改变决策的证据。
|
|
4
|
-
|
|
5
|
-
## 找出决定方向的假设
|
|
6
|
-
|
|
7
|
-
从目标和已有证据识别:哪些条件必须成立,结论才有意义;哪项不成立会改变方案;哪些检验依赖其他条件先成立。
|
|
8
|
-
|
|
9
|
-
区分研究假设与方法前提。例如,策略是否具有样本外效果是研究假设;数据是否覆盖所需时期、能否按实际可知时间构造输入,是方法前提。
|
|
10
|
-
|
|
11
|
-
对影响决策的假设,梳理现有支持与反对证据、尚不确定的条件、失败后果、可用检验及其成本。
|
|
12
|
-
|
|
13
|
-
## 选择最有用的下一次检验
|
|
14
|
-
|
|
15
|
-
优先选择不同结果会改变后续决策、能较早取得证据且成本适当的检验。必要时先核实数据与方法前提,再投入更大规模的实验。
|
|
16
|
-
|
|
17
|
-
最小检验可以使用已有数据、较小样本或较简单的方法,但要说明它能够排除什么、仍不能证明什么。
|
|
18
|
-
|
|
19
|
-
执行前明确与本次判断有关的内容:
|
|
20
|
-
|
|
21
|
-
- 要区分的假设或替代解释,以及可观测结果。
|
|
22
|
-
- 所需数据与资源、方法、比较基准和主要限制。
|
|
23
|
-
- 哪些结果支持继续,哪些要求修改或停止,哪些仍无法区分假设。
|
|
24
|
-
|
|
25
|
-
判据来自目标、领域依据或用户约束。看到结果后修改判据时,记录修改原因,并区分探索所得的解释与按原判据得到的结果。
|
|
26
|
-
|
|
27
|
-
## 根据结果调整
|
|
28
|
-
|
|
29
|
-
先判断检验是否有效执行。数据缺失、程序失败或方法不适用不等于研究假设被否定;代理指标改善也不自动证明最终目标达成。
|
|
30
|
-
|
|
31
|
-
有效结果削弱关键假设时,比较继续排查、修改方法、缩小问题或停止该方向的价值。结果仍不确定时,根据下一项证据区分解释的能力决定是否继续。
|
|
32
|
-
|
|
33
|
-
保留支撑方向判断的假设、判据、实际观测和产物引用。复用结果时保留检验条件与适用范围。
|