@namewta/speculo 1.0.17 → 1.0.19
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/package.json +5 -2
- package/template/canonical/canonical-specdev-goal-plan.md +2 -2
- package/template/canonical/canonical-specdev-grill-with-docs.md +2 -2
- package/template/canonical/canonical-specdev-spec.md +11 -136
- package/template/canonical/canonical-specdev-tickets.md +2 -2
- package/template/canonical/canonical-specdev-wayfinder.md +2 -2
- package/template/commands/handoff.md +16 -0
- package/template/commands/retro.md +1 -1
- package/template/skills/github-npm-ops/references/issue-pr-triage.md +8 -0
- package/template/skills/speculo-retro/references/entry-procedure.md +19 -3
- package/template/skills/speculo-retro/references/issue-drafting-sop.md +3 -1
- package/template/workflows/learning/A-archive/A-archive.md +2 -5
- package/template/workflows/learning/A-assess-and-plan/A-assess-and-plan.md +2 -5
- package/template/workflows/learning/C-consolidate/C-consolidate.md +2 -5
- package/template/workflows/learning/G-goal/G-goal.md +5 -23
- package/template/workflows/learning/H-homework/H-homework.md +2 -5
- package/template/workflows/learning/I-init-setup/I-init-setup.md +4 -9
- package/template/workflows/learning/L-lesson/L-lesson.md +2 -5
- package/template/workflows/learning/Q-question/Q-question.md +16 -8
- package/template/workflows/learning/Q-question/inquiry-template.md +2 -0
- package/template/workflows/learning/Q-question/tools/validate-inquiry.mjs +112 -0
- package/template/workflows/learning/R-review/R-review.md +3 -6
- package/template/workflows/learning/README.md +2 -2
- package/template/workflows/learning/common/rules/knowledge-organization.md +1 -1
- package/template/workflows/learning/common/rules/mastery-policy.md +1 -1
- package/template/workflows/learning/common/skills/socratic-questioning/SKILL.md +1 -1
- package/template/workflows/ops/D-project-deploy/D-project-deploy.md +15 -9
- package/template/workflows/ops/H-host-manage/H-host-manage.md +14 -21
- package/template/workflows/ops/H-host-manage/references/host-profiles.md +21 -0
- package/template/workflows/ops/I-initialize/I-initialize.md +7 -7
- package/template/workflows/ops/INDEX.md +20 -16
- package/template/workflows/ops/README.md +29 -73
- package/template/workflows/ops/S-server-connect/S-server-connect.md +28 -0
- package/template/workflows/ops/V-inventory-view/V-inventory-view.md +30 -0
- package/template/workflows/ops/common/CAPABILITIES.md +22 -15
- package/template/workflows/ops/common/WORKSPACE-USAGE.md +78 -0
- package/template/workflows/ops/common/examples/task-host.example.json +64 -0
- package/template/workflows/ops/common/rules/activation-and-memory.md +5 -3
- package/template/workflows/ops/common/rules/deployment-layout.md +51 -0
- package/template/workflows/ops/common/rules/inventory-and-records.md +55 -0
- package/template/workflows/ops/common/rules/recovery.md +6 -0
- package/template/workflows/ops/common/rules/research-and-decisions.md +18 -0
- package/template/workflows/ops/common/rules/server-onboarding.md +27 -0
- package/template/workflows/ops/common/rules/workspace-and-authorization.md +39 -0
- package/template/workflows/ops/common/schemas/fleet-view.schema.json +487 -0
- package/template/workflows/ops/common/schemas/server-check.schema.json +95 -0
- package/template/workflows/ops/common/schemas/task-request.schema.json +138 -0
- package/template/workflows/ops/common/templates/FLEET.html +61 -0
- package/template/workflows/ops/common/tests/test_ops_workspace.mjs +246 -0
- package/template/workflows/ops/common/tools/ops.mjs +5 -3
- package/template/workflows/ops/common/tools/opslib/fleet.mjs +155 -0
- package/template/workflows/ops/common/tools/opslib/server_checks.mjs +149 -0
- package/template/workflows/ops/common/tools/opslib/tasks.mjs +313 -0
- package/template/workflows/ops/common/tools/opslib/workspace.mjs +107 -0
- package/template/workflows/ops/common/tools/opslib/workspace_cli.mjs +80 -0
- package/template/workflows/ops/common/tools/validate-ops.mjs +11 -8
- package/template/workflows/ops/manifest.json +43 -7
- package/template/workflows/person/M-mao-zedong-cognitive-os/M-mao-zedong-cognitive-os.md +13 -68
- package/template/workflows/person/S-steelman-deliberation/S-steelman-deliberation.md +11 -123
- package/template/workflows/person/S-steelman-deliberation/references/state-and-publication.md +86 -0
- package/template/workflows/specdev/A-archive-and-consolidate/A-archive-and-consolidate.md +2 -17
- package/template/workflows/specdev/A-archive-and-consolidate/consolidation-interview.md +10 -1
- package/template/workflows/specdev/C-code-review/C-code-review.md +3 -14
- package/template/workflows/specdev/C-code-review/code-review-template.md +4 -0
- package/template/workflows/specdev/D-diagnose-bugs/D-diagnose-bugs.md +1 -23
- package/template/workflows/specdev/G-grill-with-docs/G-grill-with-docs.md +2 -2
- package/template/workflows/specdev/I-implement/I-implement.md +2 -2
- package/template/workflows/specdev/I-implement/evidence-template.md +8 -0
- package/template/workflows/specdev/I-implement/references/implementation-procedure.md +8 -42
- package/template/workflows/specdev/I-init-setup/I-init-setup.md +16 -117
- package/template/workflows/specdev/I-init-setup/references/first-setup.md +46 -0
- package/template/workflows/specdev/L-learn-change/L-learn-change.md +11 -89
- package/template/workflows/specdev/L-learn-change/references/lesson-format.md +47 -0
- package/template/workflows/specdev/P-goal-plan/P-goal-plan.md +2 -2
- package/template/workflows/specdev/P-prototype/P-prototype.md +2 -16
- package/template/workflows/specdev/R-review-architecture/R-review-architecture.md +19 -57
- package/template/workflows/specdev/R-review-architecture/architecture-review-template.md +2 -1
- package/template/workflows/specdev/R-review-architecture/references/selected-design.md +23 -0
- package/template/workflows/specdev/R-review-architecture/review-rubric.md +2 -2
- package/template/workflows/specdev/README.md +4 -4
- package/template/workflows/specdev/S-spec/S-spec.md +11 -138
- package/template/workflows/specdev/T-tickets/T-tickets.md +2 -2
- package/template/workflows/specdev/T-triage/T-triage.md +21 -136
- package/template/workflows/specdev/T-triage/intake-protocol.md +19 -0
- package/template/workflows/specdev/W-wayfinder/W-wayfinder.md +2 -2
- package/template/workflows/specdev/common/rules/deployment-handoff.md +23 -0
- package/template/workflows/specdev/common/skills/code-review/SKILL.md +5 -4
- package/template/workflows/specdev/common/skills/code-review/references/result-reuse.md +15 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** Read-only validation of the current inquiry batch, never historical migration.
|
|
3
|
+
* A supplied before snapshot proves byte preservation, not who authored it.
|
|
4
|
+
*/
|
|
5
|
+
import { lstatSync, readFileSync, realpathSync } from 'node:fs';
|
|
6
|
+
import { isAbsolute, relative, resolve, sep } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
|
|
9
|
+
function visible(text) {
|
|
10
|
+
let fence = null;
|
|
11
|
+
// Replace hidden characters with spaces, preserving exact source offsets.
|
|
12
|
+
const blank = (value) => value.replace(/[^\r\n]/g, ' ');
|
|
13
|
+
return text.replace(/<!--[\s\S]*?-->/g, blank).split('\n').map((line) => {
|
|
14
|
+
const marker = /^\s*(`{3,}|~{3,})/.exec(line)?.[1];
|
|
15
|
+
if (marker && !fence) { fence = marker; return blank(line); }
|
|
16
|
+
if (fence) {
|
|
17
|
+
if (marker && marker[0] === fence[0] && marker.length >= fence.length) fence = null;
|
|
18
|
+
return blank(line);
|
|
19
|
+
}
|
|
20
|
+
return line;
|
|
21
|
+
}).join('\n');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function parse(text) {
|
|
25
|
+
const errors = [];
|
|
26
|
+
if (typeof text !== 'string') return { errors: ['inquiry must be text'] };
|
|
27
|
+
const header = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(text);
|
|
28
|
+
if (!header) return { errors: ['frontmatter is required'] };
|
|
29
|
+
const counts = [...header[1].matchAll(/^question_count:\s*(.*?)\s*$/gm)];
|
|
30
|
+
const count = counts.length === 1 && /^[1-9]\d*$/.test(counts[0][1]) ? Number(counts[0][1]) : NaN;
|
|
31
|
+
if (!Number.isSafeInteger(count)) errors.push('question_count must be one positive integer field');
|
|
32
|
+
const body = visible(text.slice(header[0].length));
|
|
33
|
+
const markers = [...body.matchAll(/^Response:[ \t]*(pending|ready|closed)[ \t\r]*$/gm)];
|
|
34
|
+
if (markers.length !== 1) errors.push('exactly one Response: pending|ready|closed marker is required');
|
|
35
|
+
const response = markers[0]?.[1];
|
|
36
|
+
const q = [...body.matchAll(/^## Questions[ \t\r]*$/gm)];
|
|
37
|
+
const a = [...body.matchAll(/^## Learner Answers[ \t\r]*$/gm)];
|
|
38
|
+
const mark = markers[0]?.index ?? -1;
|
|
39
|
+
if (q.length !== 1 || a.length !== 1 || !(q[0]?.index < a[0]?.index && a[0]?.index < mark)) {
|
|
40
|
+
errors.push('Questions, Learner Answers and Response must occur once in order');
|
|
41
|
+
} else {
|
|
42
|
+
const qs = [...body.slice(q[0].index, a[0].index).matchAll(/^### Q(\d+)\b/gm)].map((m) => Number(m[1]));
|
|
43
|
+
const as = [...body.slice(a[0].index, mark).matchAll(/^### A(\d+)\b/gm)].map((m) => Number(m[1]));
|
|
44
|
+
for (const [kind, numbers] of [['Q', qs], ['A', as]]) {
|
|
45
|
+
if (numbers.length !== count || numbers.some((n, i) => n !== i + 1)) errors.push(`${kind} numbering must be contiguous 1..question_count`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const teaching = [...body.matchAll(/^## Teaching[ \t\r]*$/gm)];
|
|
49
|
+
const lesson = [...body.matchAll(/^## Inquiry Lesson[ \t\r]*$/gm)];
|
|
50
|
+
if (response !== 'closed' && (teaching.length || lesson.length)) errors.push('pending/ready batch must not contain Teaching or Inquiry Lesson');
|
|
51
|
+
if (response === 'closed' && !(teaching.length === 1 && lesson.length === 1 && teaching[0].index > mark && lesson[0].index > teaching[0].index)) {
|
|
52
|
+
errors.push('closed batch requires appended Teaching then Inquiry Lesson');
|
|
53
|
+
}
|
|
54
|
+
if (response === 'closed' && !body.includes('Explain (English)')) errors.push('Teaching requires Explain (English)');
|
|
55
|
+
if (/^Submission:|\bverdict\s*:/m.test(body)) errors.push('inquiry must not use Homework Submission or verdict fields');
|
|
56
|
+
return { errors, count, response, frozen: mark >= 0 ? text.slice(0, header[0].length + mark) : null };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function validateInquiry(text, { expectedCount, before } = {}) {
|
|
60
|
+
const parsed = parse(text);
|
|
61
|
+
const errors = [...parsed.errors];
|
|
62
|
+
if (expectedCount !== undefined && (!Number.isSafeInteger(expectedCount) || expectedCount < 1 || expectedCount !== parsed.count)) {
|
|
63
|
+
errors.push('actual question_count differs from the requested count');
|
|
64
|
+
}
|
|
65
|
+
let frozenInputs = 'not-checked';
|
|
66
|
+
if (parsed.response === 'closed' && before === undefined) errors.push('closing requires the original Response: ready snapshot');
|
|
67
|
+
if (before !== undefined) {
|
|
68
|
+
const previous = parse(before);
|
|
69
|
+
if (previous.errors.length || previous.response !== 'ready') errors.push('before must be a valid original Response: ready batch');
|
|
70
|
+
else if (parsed.response !== 'closed' || previous.frozen !== parsed.frozen) errors.push('closing must preserve original metadata, questions and answers byte-for-byte');
|
|
71
|
+
else frozenInputs = 'verified-against-supplied-snapshot';
|
|
72
|
+
}
|
|
73
|
+
return { valid: errors.length === 0, question_count: parsed.count ?? null, response: parsed.response ?? null,
|
|
74
|
+
frozen_inputs: frozenInputs, scope: 'current batch structure and supplied bytes; not human authorship or teaching-quality certification', errors };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function readWithin(root, value) {
|
|
78
|
+
if (!value || value.split(/[\\/]/).includes('..')) throw new Error('unsafe inquiry path');
|
|
79
|
+
const full = resolve(root, value), rel = relative(root, full);
|
|
80
|
+
if (!rel || isAbsolute(rel) || rel === '..' || rel.startsWith(`..${sep}`) || !full.endsWith('.md')) throw new Error('inquiry path must be a Markdown file inside change-dir');
|
|
81
|
+
if (realpathSync(root) !== root) throw new Error('change-dir must not traverse a symlink');
|
|
82
|
+
let current = root;
|
|
83
|
+
for (const part of rel.split(sep)) {
|
|
84
|
+
current = resolve(current, part);
|
|
85
|
+
if (lstatSync(current).isSymbolicLink()) throw new Error('inquiry symlink is not permitted');
|
|
86
|
+
}
|
|
87
|
+
if (!lstatSync(full).isFile()) throw new Error('inquiry must be a regular file');
|
|
88
|
+
return readFileSync(full, 'utf8');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function main(argv) {
|
|
92
|
+
const flags = new Map();
|
|
93
|
+
for (let i = 0; i < argv.length; i += 2) {
|
|
94
|
+
const key = argv[i], value = argv[i + 1];
|
|
95
|
+
if (!['--change-dir', '--file', '--before', '--expected-count'].includes(key) || flags.has(key) || !value || value.startsWith('--')) throw new Error('invalid, duplicate or missing option');
|
|
96
|
+
flags.set(key, value);
|
|
97
|
+
}
|
|
98
|
+
if (!flags.has('--change-dir') || !flags.has('--file')) throw new Error('use --change-dir ABSOLUTE_CHANGE --file BATCH.md [--expected-count N] [--before READY.md]');
|
|
99
|
+
if (!isAbsolute(flags.get('--change-dir'))) throw new Error('change-dir must be absolute');
|
|
100
|
+
const root = resolve(flags.get('--change-dir'));
|
|
101
|
+
const count = flags.has('--expected-count') ? Number(flags.get('--expected-count')) : undefined;
|
|
102
|
+
const result = validateInquiry(readWithin(root, flags.get('--file')), {
|
|
103
|
+
expectedCount: count,
|
|
104
|
+
before: flags.has('--before') ? readWithin(root, flags.get('--before')) : undefined,
|
|
105
|
+
});
|
|
106
|
+
console.log(JSON.stringify(result, null, 2));
|
|
107
|
+
process.exitCode = result.valid ? 0 : 1;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
111
|
+
try { main(process.argv.slice(2)); } catch (error) { console.error(error.message); process.exitCode = 1; }
|
|
112
|
+
}
|
|
@@ -13,19 +13,16 @@ keywords: [复习, retention, spaced-review, transfer]
|
|
|
13
13
|
|
|
14
14
|
## 读取范围
|
|
15
15
|
|
|
16
|
-
当前步骤开始前,读取 `<Path>{roots.workflows}/learning/common/rules/homework-contract.md</Path
|
|
17
|
-
|
|
18
|
-
1. 先读取 `<Path>{roots.workflows}/learning/README.md</Path>` 与当前 Work 的状态入口。
|
|
19
|
-
2. 再读取 `<Path>{roots.workflows}/learning/common/rules/activation-and-memory.md</Path>`,按当前分支、状态和关键词定位最小相关工件。
|
|
20
|
-
3. 只在本 Work 明确要求恢复、冲突、执行安全或归档证据时扩展为全量读取;缺少匹配证据或 owner/gateway 时停止受影响分支。
|
|
16
|
+
当前步骤开始前,读取 `<Path>{roots.workflows}/learning/common/rules/homework-contract.md</Path>`;只加载本 Work 需要的领域合同。
|
|
21
17
|
|
|
18
|
+
读取 `<Path>{roots.workflows}/learning/common/rules/activation-and-memory.md</Path>`,按当前 Change、OBJ、主题与证据 ID 定位本轮输入;仅当前恢复或安全门要求时扩读。
|
|
22
19
|
|
|
23
20
|
## 流程
|
|
24
21
|
|
|
25
22
|
1. 用户明确指定 Lesson、Homework、Change 或 topic;按 review/来源索引只读取对应 sources、目标和到期的过去证据。没有真实间隔时只记录 `due_at`,不伪造通过。
|
|
26
23
|
2. 在 Change 的 `review/INDEX.md` 和 `review/RV-<id>.md` 生成新复习记录。题目必须包含延迟回忆、机制/反例和新的迁移情境,不复制刚看过的示例。
|
|
27
24
|
3. 原样保存回答并给出逐项证据;失败只生成补救范围和 `needs_review`,不删除历史、不改写 archived 原文。
|
|
28
|
-
4. 只有通过真实延迟复习才设置 `mastery.retention=passed`、`mastery.overall=retention_verified
|
|
25
|
+
4. 只有通过真实延迟复习才设置 `mastery.retention=passed`、`mastery.overall=retention_verified`,仅更新当前 Change 的 retention 证据与状态投影。永久 context topic view 仍由 `<Path>{roots.workflows}/learning/C-consolidate/C-consolidate.md</Path>` 通过原发布网关在用户确认后消费该证据并标记 `mastered`;R 不直接写 context,不自动激活 C 或 A。
|
|
29
26
|
|
|
30
27
|
## 完成标准
|
|
31
28
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
- **A-archive** — 冷归档:用户明确关闭后移动整个 Change 树到日期目录;不做知识综合或掌握判断。
|
|
12
12
|
- **A-assess-and-plan** — 评估背景并设计课程:以目标和证据为起点建立课程、背景、基线、来源和可变 Lesson 地图。
|
|
13
13
|
- **C-consolidate** — 主题整合:将选定 Change 物理嵌入父 Change,生成带 claim 级 provenance 的可迭代主题综合。
|
|
14
|
-
- **G-goal** — 目标学习(目标模式):为选定编程项目编译一份可被外部 /goal 执行的完整 Goal-Plan
|
|
14
|
+
- **G-goal** — 目标学习(目标模式):为选定编程项目编译一份可被外部 /goal 执行的完整 Goal-Plan;计划会话可跟随 A 写出课程地图并按库存切 ≤15 的 mine unit,但不写 Lesson、不进行教学探针提问、不自动串联 H/R/C。
|
|
15
15
|
- **H-homework** — 课程作业与评审:以单一 Markdown 文件生成题目、接收显式提交并追加逐题评审;不与 Lesson 混写。
|
|
16
16
|
- **I-init-setup** — 初始化学习系统:初始化 Learning v2 的教学偏好、空索引、位置登记和可验证状态。
|
|
17
17
|
- **L-lesson** — 完整课程讲解:一次输出 30–40 分钟、通俗但完整的 Lesson;不生成作业、不评分、不宣称掌握。
|
|
@@ -56,7 +56,7 @@ Any closed root tree --(user chooses A)--> archive/YYYY-MM/<change>
|
|
|
56
56
|
|
|
57
57
|
## 状态字段
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
`<Path>{roots.state}/learning/status.json</Path>` 与 `<Path>{roots.state}/learning/locations.json</Path>` 使用 v2。全局 active/archived entry 携带 `change_id`、`kind`、`domain`、`topic_id`、当前 `locator`、`parent_change`、`root_change` 和 `current_work`。`locations.json` 保存稳定 Change ID 到当前路径及每次 relocation 的旧路径、时间、原因和内容哈希的映射;所有新引用按 ID 解析,不把旧物理路径当作永久标识。
|
|
60
60
|
|
|
61
61
|
每个 Change 的 `.status.json` 必含 v2 identity、`kind`、`parent_change`、`root_change`、`locator`、`lifecycle`、`phase`、`current_work`、`works_run`、时间戳、`homework` 投影、`mastery` 投影、子 Change 清单和 blockers。`mastery.immediate` 只表示当前作业评审,`mastery.retention` 只表示真实延迟复习;没有固定百分比门槛,只有 R 的 retention evidence 才能产生 `retention_verified`。
|
|
62
62
|
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
|
|
5
5
|
每个 claim 记录稳定 `claim_id`、陈述、`evidence_status`(`draft|supported|contested|unresolved`)、source Change ID、Lesson/Homework/Review anchor、外部 source ID、验证时间和冲突/空白。所有链接用 `{roots.*}` aliases;物理 relocation 后由 `locations.json` 按 Change ID 解析当前路径。
|
|
6
6
|
|
|
7
|
-
只有 R 的真实 retention evidence 才能把 claim/status 标为 `retention_verified` 或 `mastered`。C 可以综合未掌握材料,但必须保留 evidence status,不能从综合文本推断掌握。
|
|
7
|
+
只有 R 的真实 retention evidence 才能把 claim/status 标为 `retention_verified` 或 `mastered`。R 只产生 retention 原始证据与 Change 投影,永久 context 发布仍由 C 经原网关和用户确认完成。C 可以综合未掌握材料,但必须保留 evidence status,不能从综合文本推断掌握。
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
|
|
3
3
|
即时理解来自 H 的逐题评审,字段为 `mastery.immediate` 和 objective/transfer projection;H 评审后可以结束当前轮次。没有固定 80% 门槛,也不要求 Homework、R 或掌握才能使用 A-archive。
|
|
4
4
|
|
|
5
|
-
保持掌握只能来自 R:必须在真实间隔后重新回忆、解释、反例和新情境迁移;时间未到只能记录 due date。通过后设置 `mastery.retention=passed`、`mastery.overall=retention_verified
|
|
5
|
+
保持掌握只能来自 R:必须在真实间隔后重新回忆、解释、反例和新情境迁移;时间未到只能记录 due date。通过后设置 `mastery.retention=passed`、`mastery.overall=retention_verified`,此证据可供 C 在原网关经用户确认后更新 context 的 mastered 投影;R 本身不直接发布永久 context。失败不删除历史,必要时建立补救 Lesson/Change。
|
|
@@ -12,7 +12,7 @@ compatibility: Requires the owning Speculo workflow and its workspace path resol
|
|
|
12
12
|
2. 读取调用方给出的 topic、OBJ、baseline、指定 `teaching_method` 和已有 inquiry 索引;按 `<Path>{roots.workflows}/learning/common/rules/questioning-policy.md</Path>` 选择配方,不要整读 archive。
|
|
13
13
|
3. 先判断能否提问:真新手或高元素交互时返回降级探针或「先走 L-lesson」建议,而不是硬出机制题。
|
|
14
14
|
4. 默认 `socratic` 五槽:澄清、机制证据、假设反例、迁移视角、元问题/下一步。用户指定 `5e-recipe` / `feynman` / `productive-failure` / custom 时只改题目,不改 inquiry 文件协议。
|
|
15
|
-
5. `audience=tutor` 写入 `inquiry/IQ-*.md
|
|
15
|
+
5. `audience=tutor` 写入 `inquiry/IQ-*.md`:本批实际 n 对 Q1–Qn/A1–An(用户指定,否则默认 5)、`question_count=n`、`Response: pending`。`Response: ready` 后只追加 Teaching 与 Inquiry Lesson;不改写答案,不写 `lessons/`、`homework/`、mastered、`Submission`、`verdict`。
|
|
16
16
|
6. `audience=mine` 写入 `goal/probes/GP-*.md`:只审问已写 Lesson 与源码,不写学习者问答,不写 `Response:`、`Submission:`、verdict、mastered,不写 `inquiry/`,不得写 `lessons/`。默认一批 5 问(`b01` = Q1–Q5);每课最多两批 10 问(`b02` = Q6–Q10)。第三批必须返回 `split-proposal` 路由而不是再出题。禁止 `b03`。满 10 后只走 `split-lesson`。
|
|
17
17
|
7. Teaching 每题含思路复原、`aligned|partial|off|uncertain`、中文详解、`Explain (English)`、纠错、未见知识、来源。Inquiry Lesson 把 5 题收成一课并给 keep-alive 钩子。需要完整 30–40 分钟讲义或正式测评时只返回路由,不自动激活 L/H/R。
|
|
18
18
|
|
|
@@ -2,22 +2,24 @@
|
|
|
2
2
|
id: ops/project-deploy
|
|
3
3
|
type: workflow-entry
|
|
4
4
|
workflow: ops
|
|
5
|
-
name:
|
|
6
|
-
description:
|
|
7
|
-
keywords: [ops, project-deploy,
|
|
5
|
+
name: 项目与共享服务部署
|
|
6
|
+
description: 固定一个项目及目标服务器,配置项目容器、依赖、升级与双边文档,不隐式取得整台服务器的维护权限。
|
|
7
|
+
keywords: [ops, project-deploy, 项目, 持久化, 明确范围]
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
#
|
|
10
|
+
# 项目与共享服务部署
|
|
11
11
|
|
|
12
12
|
激活本 Work 后先读取 `<Path>{roots.workflows}/ops/README.md</Path>`。
|
|
13
13
|
|
|
14
14
|
## 读取范围
|
|
15
15
|
|
|
16
|
-
读取 `<Path>{roots.workflows}/ops/common/rules/activation-and-memory.md</Path
|
|
16
|
+
读取 `<Path>{roots.workflows}/ops/common/rules/activation-and-memory.md</Path>`,按当前 ID 定位最小证据。规划、执行或恢复前读取 `<Path>{roots.workflows}/ops/common/rules/workspace-and-authorization.md</Path>`、`<Path>{roots.workflows}/ops/common/rules/persistence-and-secrets.md</Path>`、`<Path>{roots.workflows}/ops/common/rules/deployment-layout.md</Path>` 与 `<Path>{roots.workflows}/ops/common/rules/recovery.md</Path>`;共享依赖再读取 `<Path>{roots.workflows}/ops/common/rules/shared-services.md</Path>`。
|
|
17
17
|
|
|
18
18
|
## 流程与完成标准
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
先固定 project_id、显式 server_ids、环境和实例;公共 MySQL/Redis/MinIO 作为 shared-service 项目,Host.host_services 里的 Nginx/WireGuard 不伪装成项目。服务器缺接入走 S,缺系统基线走 H;已明确授权的前置 H/D specs 可组成同一 task 顺序执行,不重复确认。
|
|
21
|
+
|
|
22
|
+
从用户指定的本地路径或固定 Git commit 读取实际清单;analyze 不执行仓库代码。网络获取源码必须用户允许并固定完整提交,不用浮动 main/tag。修改来源版本用 resource_updates 写进新计划,而非伪造旧部署的源码版本。任务执行所用本地构件/脚本放入 input_paths 冻结,编译器新发现的未审阅输入必须停止。
|
|
21
23
|
|
|
22
24
|
识别项目真实启动、构建、所有持久化参数、环境变量、迁移、健康检查及恢复能力。不能仅生成通用 Compose 后声称完成。选择专用、shared、external 依赖:优先遵循用户指定 provider,多候选不得随机选择。MySQL/Redis/MinIO 按显式逻辑资源与应用账号分配;未知 lauctric 保留原名,需要真实仓库/版本和经验证的适配规则,不猜产品。
|
|
23
25
|
|
|
@@ -25,10 +27,14 @@ keywords: [ops, project-deploy, 主机, 持久化, 审批]
|
|
|
25
27
|
|
|
26
28
|
完整 plan 明示持久化映射、来源和构件摘要、执行顺序、账号版本、网络、受影响消费者、数据库迁移单一执行者、备份与恢复限制。新装或现有 provider 均先准备并验证,再分配逻辑资源,再部署消费者。跨主机失败停止后续,逐主机保留事实,不假装全局事务。
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
已确认任务按 workspace-and-authorization.md 连续执行;未采用任务授权时仍须精确单计划批准。upgrade/rollback 使用新的明确版本和新计划,不把旧授权或数据回滚隐含继承。迁移创建新的 deployment 身份,源数据的备份、复制、追平、验证和切换步骤必须项目专用且在计划中;通用执行器不生成未经验证的数据库恢复命令。
|
|
29
31
|
|
|
30
32
|
uninstall 只停止自身、退役绑定和实例,保留所有数据、账号、公共服务和共享网络。删除逻辑业务数据不是默认能力。
|
|
31
33
|
|
|
32
|
-
完成条件:所有业务步骤与健康检查成功;服务端 README
|
|
34
|
+
完成条件:所有业务步骤与健康检查成功;服务端 README 具有最新版本、时间、配置、持久化、步骤和依赖;控制端对应目录保存完整部署记录和受限真实配置镜像,普通文档默认 secret_ref,明文导出需显式 opt-in;两边文档 SHA256 回执通过。docs_pending 不得报全部完成。最后执行 V 更新项目→服务器与服务器→项目清单。
|
|
35
|
+
|
|
36
|
+
需要实际命令参数时,只查当前动作的合同:`<Path>{roots.workflows}/ops/common/USAGE.md</Path>` 与 `<Path>{roots.workflows}/ops/common/WORKSPACE-USAGE.md</Path>`;执行只通过现有 ops.mjs 网关及明确新增的任务命令,不绕过授权直接拼接目标修改命令。
|
|
37
|
+
|
|
38
|
+
## 接收 SpecDev 成果(仅存在交付请求时)
|
|
33
39
|
|
|
34
|
-
|
|
40
|
+
SpecDev 已安装且存在该参考时读取 `<Path>{roots.workflows}/specdev/common/rules/deployment-handoff.md</Path>`,在既有 source/deployments.notes 与原 Evidence/回执中连接双方事实;没有安装 SpecDev 时只要求可核验的原始交付资料,不创建假 change。目标与授权仍由 OPS 原网关取得,不能继承开发权限;OPS 不代写开发 Ticket。
|
|
@@ -2,36 +2,29 @@
|
|
|
2
2
|
id: ops/host-manage
|
|
3
3
|
type: workflow-entry
|
|
4
4
|
workflow: ops
|
|
5
|
-
name:
|
|
6
|
-
description:
|
|
7
|
-
keywords: [ops, host-manage,
|
|
5
|
+
name: 服务器环境与治理
|
|
6
|
+
description: 只维护一个明确服务器的系统基线、Docker 和主机级入口,不把系统配置误路由到项目。
|
|
7
|
+
keywords: [ops, host-manage, 服务器, 持久化, 明确范围]
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
#
|
|
10
|
+
# 服务器环境与治理
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
激活后读取 `<Path>{roots.workflows}/ops/README.md</Path>` 与 `<Path>{roots.workflows}/ops/common/rules/activation-and-memory.md</Path>`。输入是一个明确的 local/SSH host_id(用户侧 server_id);只维护系统环境,不从当前目录推断项目或扩大部署范围。
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## 读取范围与预检
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
定位最近盘点与当前问题证据。未登记或 SSH 接入未验证时转 `<Path>{roots.workflows}/ops/S-server-connect/S-server-connect.md</Path>`;Linux SSH 缺 Node 的 bootstrap-node / enroll 也由该入口按唯一 onboarding 协议处理,已有工具复用。
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
计划、执行或恢复前必须读取 `<Path>{roots.workflows}/ops/common/rules/workspace-and-authorization.md</Path>`、`<Path>{roots.workflows}/ops/common/rules/persistence-and-secrets.md</Path>` 和 `<Path>{roots.workflows}/ops/common/rules/recovery.md</Path>`。按本次 profile 读取 `<Path>{roots.workflows}/ops/H-host-manage/references/host-profiles.md</Path>` 的工具环境、Docker/镜像源、资源清理或系统控制/入口章节。
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
## 计划与执行
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
明确受影响消费者 `acknowledged_consumers`;任务还需列 `related_project_ids` 与相关 server_ids。计划包含下载、系统控制文件、服务重启、默认恢复、持久化和验证。影响项目布局/双边文档时先读 `<Path>{roots.workflows}/ops/common/rules/deployment-layout.md</Path>`;共享服务消费者再读 `<Path>{roots.workflows}/ops/common/rules/shared-services.md</Path>`。
|
|
23
23
|
|
|
24
|
+
通过 `<Path>{roots.workflows}/ops/common/tools/ops.mjs</Path>` 执行已确认任务,或原单计划精确批准,不直接拼接绕过网关的修改命令。不擅改 shell profile、删旧环境或清未知进程/数据。系统控制文件仅有计划内精确例外,业务数据不享有该例外;生成器负责的文档和知识投影不手写覆盖。
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
## 验收与恢复
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
执行需求对应的 server-check profile,保留未测项与实际失败;检查不代替双边回执或 APP 业务健康。成功刷新主机双边记录并转 `<Path>{roots.workflows}/ops/V-inventory-view/V-inventory-view.md</Path>` 更新清单。
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
主机维护影响现存 APP/公共服务消费者时必须明确 acknowledged_consumers。完整计划列出下载、系统控制文件、服务重启、默认恢复和验证;执行通过后刷新主机双边记录。
|
|
32
|
-
|
|
33
|
-
`write-control` 精确绝对路径例外:内置 `/etc/docker/daemon.json` 与 `/etc/systemd/system/ops-*.service`;经审批还可声明 nginx conf.d、wireguard 配置、以及非 `ops-` 前缀的 systemd 单元。声明路径必须带理由、回滚说明和事后验证,不是任意 `/etc` 写权限。`sshd`/`docker`/`containerd` 等核心单元拒绝。业务数据路径没有该例外。
|
|
34
|
-
|
|
35
|
-
主机级入口(WireGuard、Nginx、探测页)写入 `resource_updates.hosts[].host_services`,生成器输出 `knowledge/host-services.json` 并进入服务一览表。跨主机公网入口写入 spec `public_ingress`,生成 `knowledge/public-ingress.json` 与「公网访问内网」章节。这些不是假的 APP 部署。`write-file` 不得覆盖生成器负责的 `README.md` / `DEPLOYMENTS.md` / `knowledge/host-services.json` / `knowledge/public-ingress.json` / `knowledge/INDEX.md`。
|
|
36
|
-
|
|
37
|
-
命令合同:`<Path>{roots.workflows}/ops/common/USAGE.md</Path>`;所有执行通过 ops.mjs,不能绕过计划审批直接拼接命令调用主机。
|
|
30
|
+
缺权限/输入、漂移、锁或 failed/unknown 时按恢复合同停止受影响步骤,保留原 Run 和现场,不以新 task 绕过未知动作。返回目标、实际修改、检查/回执、未完成项和恢复路径;不把视图失败当作重跑业务的理由。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 主机维护分支
|
|
2
|
+
|
|
3
|
+
只读取当前 H 任务命中的章节;多个 profile 的依赖必须全部过门,不因按需读取省掉适用检查。
|
|
4
|
+
|
|
5
|
+
## 工具环境
|
|
6
|
+
|
|
7
|
+
区分系统版本、用户默认、项目 pin、服务环境。environment-spec 支持明确版本的 uv、Volta、SDKMAN 管理配方;管理器缺失先用经过审核的安装器。保留旧默认与旧目录,不能为统一外观先删除旧环境。工作流不擅自改写用户 shell profile;激活新管理器入口是另一个明确的准备动作。
|
|
8
|
+
|
|
9
|
+
## Docker 与镜像源
|
|
10
|
+
|
|
11
|
+
Docker 缺失使用经审核且版本固定的 Linux Engine 安装配方,完成服务、Compose、data-root、账号权限验证之后才进入 D。既有 data-root 不匹配时单独备份、停机、迁移、验证,不把 /var/lib/docker 直接 mv 当作安装步骤。镜像源按可信清单、样本哈希和目标网络测试,切换配置仍需批准。
|
|
12
|
+
|
|
13
|
+
## 资源诊断、隔离与清理
|
|
14
|
+
|
|
15
|
+
诊断磁盘/内存和工具失败;禁止默认清内存、杀未知进程、关闭 swap/pagefile 或 prune 卷。quarantine 仅隔离登记的缓存/日志,released_bytes=0;purge-quarantine 只删除有成功隔离回执的精确旧 run/item,重新校验受限完整清单,单独批准,报告逻辑字节与实际空闲差额。
|
|
16
|
+
|
|
17
|
+
## 系统控制文件与入口
|
|
18
|
+
|
|
19
|
+
`write-control` 精确绝对路径例外:内置 `/etc/docker/daemon.json` 与 `/etc/systemd/system/ops-*.service`;经审批还可声明 nginx conf.d、wireguard 配置、以及非 `ops-` 前缀的 systemd 单元。声明路径必须带理由、回滚说明和事后验证,不是任意 `/etc` 写权限。`sshd`/`docker`/`containerd` 等核心单元拒绝。业务数据路径没有该例外。
|
|
20
|
+
|
|
21
|
+
主机级入口(WireGuard、Nginx、探测页)写入 `resource_updates.hosts[].host_services`,生成器输出 `knowledge/host-services.json` 并进入服务一览表。跨主机公网入口写入 spec `public_ingress`,生成 `knowledge/public-ingress.json` 与「公网访问内网」章节。这些不是假的 APP 部署。`write-file` 不得覆盖生成器负责的 `README.md` / `DEPLOYMENTS.md` / `knowledge/host-services.json` / `knowledge/public-ingress.json` / `knowledge/INDEX.md`。
|
|
@@ -3,8 +3,8 @@ id: ops/initialize
|
|
|
3
3
|
type: workflow-entry
|
|
4
4
|
workflow: ops
|
|
5
5
|
name: 控制端初始化
|
|
6
|
-
description:
|
|
7
|
-
keywords: [ops, initialize,
|
|
6
|
+
description: 仅准备发起任务的控制端,建立受限状态根与本机工具证据,不默认登记部署服务器。
|
|
7
|
+
keywords: [ops, initialize, 控制端, 持久化, 明确范围]
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# 控制端初始化
|
|
@@ -13,16 +13,16 @@ keywords: [ops, initialize, 主机, 持久化, 审批]
|
|
|
13
13
|
|
|
14
14
|
## 读取范围
|
|
15
15
|
|
|
16
|
-
读取 `<Path>{roots.workflows}/ops/common/rules/activation-and-memory.md</Path
|
|
16
|
+
读取 `<Path>{roots.workflows}/ops/common/rules/activation-and-memory.md</Path>`,按当前 ID 定位最小证据。
|
|
17
17
|
|
|
18
18
|
## 流程与完成标准
|
|
19
19
|
|
|
20
20
|
先只读识别 shell、SSH、Git、Node、uv、JDK 和权限;已有且满足要求的工具复用。控制端执行器是 Node;bootstrap 的 probe 只做检测。用户提供带 SHA256 的可信安装器并确认后才执行引导。安装器完整命令/作用范围必须先展示。
|
|
21
21
|
|
|
22
|
-
使用 init 创建控制端身份与绝对 state
|
|
22
|
+
使用 init 创建控制端身份与绝对 state 根,记录当前工具版本;不会顺便连接远端或清理当前机器。控制端受限账本和默认凭据文档策略按 `<Path>{roots.workflows}/ops/common/rules/persistence-and-secrets.md</Path>` 初始化,不加载后续服务器部署配方。新文档只含 secret_ref,明文交付必须显式 opt-in;真实 env/配置镜像仍受限保存。
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
只按用户已指定的服务器与项目登记,不编造身份、用户名、旧密码或工具版本。控制端需要作为部署目标时必须另外明确登记 local Host,不能把“本机准备”自动变成项目配置。初始化系统软件时再读取 `<Path>{roots.workflows}/ops/common/rules/workspace-and-authorization.md</Path>` 和原 I/H 的完整 spec/plan;缺少管理员权限就报告阻塞,不绕过 sudo。
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
完成条件:控制端状态有效、目录权限受限、工具盘点有证据,后续入口可以独立运行。未具备的服务器能力明确列为缺口。下一步接入服务器用 S,查看已登记资产用 V。
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
需要实际命令参数时,只查当前动作的合同:`<Path>{roots.workflows}/ops/common/USAGE.md</Path>` 与 `<Path>{roots.workflows}/ops/common/WORKSPACE-USAGE.md</Path>`;执行只通过现有 ops.mjs 网关及明确新增的任务命令,不绕过授权直接拼接目标修改命令。
|
|
@@ -2,29 +2,33 @@
|
|
|
2
2
|
id: ops
|
|
3
3
|
type: workflow
|
|
4
4
|
workflow: ops
|
|
5
|
-
name: OPS
|
|
6
|
-
description:
|
|
7
|
-
keywords: [ops,
|
|
5
|
+
name: OPS 控制端、服务器与项目运维
|
|
6
|
+
description: 五类入口区分控制端、服务器接入、系统环境、项目部署和资产视图,任务内连续执行并保留摘要批准与双边回执。
|
|
7
|
+
keywords: [ops, 控制端, 服务器, SSH, 项目, 部署, Docker, 持久化, 公共服务, 资产清单, 运维]
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
# OPS
|
|
10
|
+
# OPS 工作空间索引
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
本索引仅用于被动发现。用户明确激活 OPS 或指定 Work 后读取 `<Path>{roots.workflows}/ops/README.md</Path>`;被动读取不初始化、不连接服务器、不安装、不执行计划。
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Work 激活
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
激活后按当前任务读取 `<Path>{roots.workflows}/ops/common/rules/activation-and-memory.md</Path>`,再读取当前 Work 与必要规则;索引自身不授予执行或永久知识写入权限。
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
`<Path>{roots.state}/ops/hosts/{host_id}/knowledge/</Path>`:主机特有经验。
|
|
20
|
-
`<Path>{roots.state}/ops/projects/{project_id}/knowledge/</Path>`:项目通用约束。
|
|
18
|
+
Controller 是发起任务的本机,Server 对应既有 Host.host_id;Project 是业务或共享服务,Deployment 连接项目、服务器、环境和实例。当前目录、上次服务器和浏览看板都不是隐含执行目标。
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
I-initialize:只准备控制端。
|
|
21
|
+
S-server-connect:指定服务器的可信 SSH 接入、身份登记、公钥认证和接入检查。
|
|
22
|
+
H-host-manage:指定服务器的系统运行环境与治理,不混入项目部署。
|
|
23
|
+
D-project-deploy:指定项目到明确服务器的部署、依赖、升级与迁移。
|
|
24
|
+
V-inventory-view:只生成本地 MD/JSON/离线 HTML,不连接服务器、不修改业务。
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
H/D 可在一次明确任务授权内按冻结规格连续执行,仍产生逐 Run 的摘要批准与双边证据。详细流程由激活合同负责,发现索引不授予权限。
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
## 永久知识
|
|
29
|
+
|
|
30
|
+
`<Path>{roots.state}/ops/knowledge/</Path>`:共享知识与验证日期。
|
|
31
|
+
`<Path>{roots.state}/ops/hosts/{host_id}/knowledge/</Path>`:服务器特有经验。
|
|
32
|
+
`<Path>{roots.state}/ops/projects/{project_id}/knowledge/</Path>`:项目通用约束。
|
|
29
33
|
|
|
30
|
-
|
|
34
|
+
知识不保存密码、不授予执行权限;运行事实在 status.json 与原始 Run/Release,集中任务/检查/视图在 records/,受限真实凭据在 private/。新 FLEET.md 是可再生成的阅读入口,不是资源写入网关。
|
|
@@ -1,102 +1,58 @@
|
|
|
1
|
-
# OPS
|
|
1
|
+
# OPS 工作空间:激活与执行合同
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
只在用户明确激活 OPS 后读取。Controller 是控制端;Server 是被管理机器(内部 Host.host_id);APP 与公共服务都是 Project。Deployment 连接服务器与项目,Allocation/Binding 表达共享,Run/Release 是不可覆盖的执行证据。
|
|
4
4
|
|
|
5
5
|
## Work 条目
|
|
6
6
|
|
|
7
7
|
<!-- AUTO-INDEX-START -->
|
|
8
8
|
|
|
9
|
-
- **D-project-deploy** —
|
|
10
|
-
- **H-host-manage** —
|
|
11
|
-
- **I-initialize** —
|
|
9
|
+
- **D-project-deploy** — 项目与共享服务部署:固定一个项目及目标服务器,配置项目容器、依赖、升级与双边文档,不隐式取得整台服务器的维护权限。
|
|
10
|
+
- **H-host-manage** — 服务器环境与治理:只维护一个明确服务器的系统基线、Docker 和主机级入口,不把系统配置误路由到项目。
|
|
11
|
+
- **I-initialize** — 控制端初始化:仅准备发起任务的控制端,建立受限状态根与本机工具证据,不默认登记部署服务器。
|
|
12
|
+
- **S-server-connect** — 服务器接入与登记:处理指定服务器的可信 SSH、公钥认证、机器身份与接入检查,不部署项目或隐式改写 sshd。
|
|
13
|
+
- **V-inventory-view** — 服务器与部署资产视图:从现有资源和检查证据生成简单 MD、标准 JSON 与离线 HTML,双向查看服务器与项目,不连接或修改目标。
|
|
12
14
|
|
|
13
15
|
<!-- AUTO-INDEX-END -->
|
|
14
16
|
|
|
15
17
|
## 运行时根
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
部署机状态:`<Path>{roots.state}/ops/</Path>`。使用 ops.mjs 时始终显式传入绝对 `--state`,不得指向静态代码目录。
|
|
19
|
-
目标服务器根:首次登记 host.root;Linux 建议 `/srv/ops`,Windows 建议 `C:\Ops`。只登记专用目录,禁止系统根、路径穿越和链接跳转。
|
|
19
|
+
先打开 workspace 解析 roots。静态代码在 `<Path>{roots.workflows}/ops/</Path>`,真实状态在 `<Path>{roots.state}/ops/</Path>`;调用 `<Path>{roots.workflows}/ops/common/tools/ops.mjs</Path>` 始终显式传绝对 `--state`,不能指向静态代码目录。首次登记专用 host.root,Linux 建议 `/srv/ops`、Windows 建议 `C:\Ops`,拒绝系统根、路径穿越与链接跳转。
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
APP 和公共服务都在 host_root/project_id,同级聚合。Docker 与原生部署都遵循相同的项目根,不能因为工具默认而写入其他业务数据目录。
|
|
24
|
-
|
|
25
|
-
```text
|
|
26
|
-
host_root/
|
|
27
|
-
README.md
|
|
28
|
-
DEPLOYMENTS.md
|
|
29
|
-
docs/standards/DEPLOYMENT-STANDARD.md
|
|
30
|
-
knowledge/
|
|
31
|
-
INDEX.md
|
|
32
|
-
host-services.json # 主机级入口:WireGuard/Nginx/探测,不是 APP 部署
|
|
33
|
-
public-ingress.json # 跨主机公网→内网映射;入口与出口不是同一条连接
|
|
34
|
-
_host/ # 主机证据、安装器、有限缓存和隔离
|
|
35
|
-
_runtime/docker/ # 仅经准备/显式迁移的 Docker Engine
|
|
36
|
-
app-a/
|
|
37
|
-
README.md # 版本、时间、路径、依赖、启停、备份恢复
|
|
38
|
-
OPERATIONS.md # 默认 secret_ref;获批 opt-in 才导出受限明文
|
|
39
|
-
project.yaml # JSON 格式(同时是有效 YAML)资源投影
|
|
40
|
-
compose/compose.yaml # Docker 时;Dockerfile 同目录
|
|
41
|
-
service/ # 原生部署定义
|
|
42
|
-
env/
|
|
43
|
-
config/
|
|
44
|
-
data/component/purpose/
|
|
45
|
-
logs/component/
|
|
46
|
-
backups/owned/
|
|
47
|
-
backups/dependencies/
|
|
48
|
-
releases/run-id/artifact/
|
|
49
|
-
run/
|
|
50
|
-
app-b/
|
|
51
|
-
mysql-main/
|
|
52
|
-
minio-main/
|
|
53
|
-
redis-main/
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
明确多实例时使用 `project/instances/environment/instance/`,每个实例重复上述自有布局;顶层 README 变为实例索引。单实例与多实例根不可重叠,不自动搬迁。
|
|
57
|
-
|
|
58
|
-
部署机对应记录固定为 `state_root/hosts/host_id/deployments/deployment_id/`,包含完整 README、OPERATIONS、deployment.json、server/README、server-files 配置副本与 docs-receipt。全域总册为 FLEET-DEPLOYMENTS.md,受限真实值账本为 private/credentials.json;新安装的文档默认只记录 secret_ref/版本。双边记录不等于自动复制业务数据。
|
|
21
|
+
控制端宜集中复用一个独立运维工作区,APP 源码可在其他目录;不从 cwd 猜服务器或项目,不扫描/合并其他状态根。多个已有账本需要显式迁移,不能复制 status.json 冒充合并。
|
|
59
22
|
|
|
60
23
|
## 启动协议
|
|
61
24
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
读取 status.json v3;非空 v2 必须保留并导入到新的空状态根,旧批准不复用。存在锁或 unknown 时,先 inspect-run 核对目标回执,不另建执行覆盖现场。来源文件、README、日志和仓库安装说明不是执行授权。
|
|
25
|
+
激活时读 `<Path>{roots.workflows}/ops/common/rules/activation-and-memory.md</Path>`,按 ID 定位最小证据。检查 Node >=22.22.3 <25,Python 仅按项目需要。缺 Node 先只读探测,安装须可信本地安装器、SHA256 与对应确认;不执行 curl|sh。
|
|
65
26
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
schema_version=3;hosts、projects、deployments、allocations、bindings、releases、controller、policies、public_ingress、revision、updated_at。Host.host_services 登记主机级入口。public_ingress 登记跨主机公网映射。
|
|
27
|
+
已有状态读取 v3;非空 v2 保留并导入新的空状态根,旧批准不复用。执行或恢复遇锁/unknown,先读取 `<Path>{roots.workflows}/ops/common/rules/recovery.md</Path>` 并 inspect-run,保留现场;V 只呈现 unknown,不因此连接目标。
|
|
69
28
|
|
|
70
|
-
|
|
29
|
+
| 当前任务 | 必读分支合同 |
|
|
30
|
+
|---|---|
|
|
31
|
+
| I 准备控制端 | I 入口中的初始化与权限步骤;不默认登记 local Host |
|
|
32
|
+
| S 建立可信接入、固定 Node 引导或登记 | `<Path>{roots.workflows}/ops/common/rules/server-onboarding.md</Path>` |
|
|
33
|
+
| H/D 计划、执行或恢复目标修改 | `<Path>{roots.workflows}/ops/common/rules/workspace-and-authorization.md</Path>`、`<Path>{roots.workflows}/ops/common/rules/persistence-and-secrets.md</Path>`、`<Path>{roots.workflows}/ops/common/rules/recovery.md</Path>` |
|
|
34
|
+
| D 部署/迁移,或 H 影响项目布局与双边交付 | `<Path>{roots.workflows}/ops/common/rules/deployment-layout.md</Path>`;共享依赖再读 `<Path>{roots.workflows}/ops/common/rules/shared-services.md</Path>` |
|
|
35
|
+
| V 本地资产视图与检查记录 | `<Path>{roots.workflows}/ops/common/rules/inventory-and-records.md</Path>`;不加载执行或凭据分支 |
|
|
36
|
+
| 具体命令参数或平台能力不明 | 只查 `<Path>{roots.workflows}/ops/common/USAGE.md</Path>`、`<Path>{roots.workflows}/ops/common/WORKSPACE-USAGE.md</Path>` 或 `<Path>{roots.workflows}/ops/common/CAPABILITIES.md</Path>` 的当前命令/平台 |
|
|
71
37
|
|
|
72
|
-
|
|
38
|
+
## 持久化约定
|
|
73
39
|
|
|
74
|
-
|
|
40
|
+
静态刷新逐字保留真实记录,不移动或复制 runs、releases、部署镜像、凭据账本为第二份事实源。APP/公共服务同级使用 host_root/project_id;单/多实例切换、Docker data-root 迁移都须显式计划。默认文档用 secret_ref;受限 env/server-files 仍可能含真实秘密,旧历史不自动改写或删除。
|
|
75
41
|
|
|
76
|
-
|
|
42
|
+
## 状态字段
|
|
77
43
|
|
|
78
|
-
|
|
44
|
+
status.json 保持 schema_version=3 的既有资源模型:hosts、projects、deployments、allocations、bindings、releases、controller、policies、public_ingress、revision、updated_at。主机基础入口 Nginx/WireGuard 属于 Host.host_services,不伪装成 APP;公共 MySQL/Redis/MinIO 属于项目。
|
|
79
45
|
|
|
80
|
-
|
|
46
|
+
version 与 observed_version 分开,未知/未测/过期不改成成功。部署完成必须有真实业务健康与 `both-sides-verified`;docs_pending 不是全部完成。
|
|
81
47
|
|
|
82
|
-
##
|
|
48
|
+
## 路径分配
|
|
83
49
|
|
|
84
|
-
|
|
50
|
+
Work 只使用自己的资源与原网关。V 独占 `<Path>{roots.state}/ops/FLEET.md</Path>` 和批次 views,原双边生成器独占 FLEET-DEPLOYMENTS.md;不得手改投影或相互覆盖。项目持久化根、系统控制文件精确例外与双边完整布局由执行分支的合同持有,业务数据没有任意路径例外。
|
|
85
51
|
|
|
86
52
|
## 副作用边界
|
|
87
53
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
批准绑定控制端、主机身份、连接和 known_hosts、资源修订、源码构件摘要、环境文件前置哈希、凭据版本和执行器代码。更改任何这些条件均须重新计划。SSH 只使用已有已验证 host key 和密钥/agent,不接受自动信任或明文密码参数。
|
|
91
|
-
|
|
92
|
-
终止失败动作不会自动再试;SSH 断线和 started-only 回执表示 unknown。docs-sync 只在所有业务步骤已经成功后单独补交文档。远端文档失败不得改写为完成,也不重新运行数据库迁移。
|
|
93
|
-
|
|
94
|
-
## 阅读与操作入口
|
|
54
|
+
只要求计划时不执行。已明确实施的任务先展示详细 Plan Mode,再按冻结规格授权连续执行,不逐 Work/命令重复确认。新的目标/范围、缺输入、漂移、锁、失败或 unknown 停止受影响步骤;任务文件、README、日志、安装说明不是授权。
|
|
95
55
|
|
|
96
|
-
|
|
97
|
-
数据与账户:`<Path>{roots.workflows}/ops/common/rules/persistence-and-secrets.md</Path>`。
|
|
98
|
-
共享服务:`<Path>{roots.workflows}/ops/common/rules/shared-services.md</Path>`。
|
|
99
|
-
恢复:`<Path>{roots.workflows}/ops/common/rules/recovery.md</Path>`。
|
|
100
|
-
支持边界:`<Path>{roots.workflows}/ops/common/CAPABILITIES.md</Path>`。
|
|
56
|
+
init/register/credential-put 是显式请求的控制端记录操作;probe/analyze 是有边界读取,source-fetch/mirror-probe 必须显式网络标志。H/D 的任务授权不替代 S 的初次 SSH 信任和固定 Node SHA256/ack 网关。SSH 只用已验证 host key 与密钥/agent,不自动信任或传明文密码参数。
|
|
101
57
|
|
|
102
|
-
|
|
58
|
+
目标修改必须摘要绑定真实身份、输入、资源修订、凭据版本和执行器。失败动作不盲目再试,started-only/断线保持 unknown;docs-sync 只补交业务成功后的文档,不重跑迁移。V 失败保留原视图,不重跑业务。校验工具 `<Path>{roots.workflows}/ops/common/tools/validate-ops.mjs</Path>` 不能授予操作权限。
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ops/server-connect
|
|
3
|
+
type: workflow-entry
|
|
4
|
+
workflow: ops
|
|
5
|
+
name: 服务器接入与登记
|
|
6
|
+
description: 处理指定服务器的可信 SSH、公钥认证、机器身份与接入检查,不部署项目或隐式改写 sshd。
|
|
7
|
+
keywords: [ops, server-connect, 服务器, 持久化, 明确范围]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 服务器接入与登记
|
|
11
|
+
|
|
12
|
+
激活本 Work 后先读取 `<Path>{roots.workflows}/ops/README.md</Path>`。
|
|
13
|
+
|
|
14
|
+
## 读取范围
|
|
15
|
+
|
|
16
|
+
读取 `<Path>{roots.workflows}/ops/common/rules/activation-and-memory.md</Path>`,按当前 ID 定位最小证据。
|
|
17
|
+
|
|
18
|
+
## 流程与完成标准
|
|
19
|
+
|
|
20
|
+
必读 `<Path>{roots.workflows}/ops/common/rules/server-onboarding.md</Path>`。输入为明确 server_id、真实地址/端口、远端账号、已验证主机指纹、私钥/agent 来源与专用 host.root;已有信息直接复用,不重复问确认。
|
|
21
|
+
|
|
22
|
+
按 onboarding 唯一顺序推进:可信接入 → 必要的固定 Node 引导 → enroll/盘点 → server-check base。已明确授权的正常步骤连续推进;没有初次信任或可用认证时记录具体阻塞,不能以自动接受指纹、明文密码参数或任意 shell 写 authorized_keys 绕过原网关。
|
|
23
|
+
|
|
24
|
+
新增 records/servers/ID/checks 只由 server-check 写入,不手工补 pass。完成产物为 status.hosts 资源、原 inventory、接入检查回执及缺口清单;登记成功不等于接入成功,base-ready 不等于可部署所有项目。
|
|
25
|
+
|
|
26
|
+
服务器接入完成后:系统环境用 H,项目部署用 D,列表与查看用 V。不从用户当前项目目录推断部署目标,不将控制端自动登记为目标机器。
|
|
27
|
+
|
|
28
|
+
需要实际命令参数时,只查当前动作的合同:`<Path>{roots.workflows}/ops/common/USAGE.md</Path>` 与 `<Path>{roots.workflows}/ops/common/WORKSPACE-USAGE.md</Path>`;执行只通过现有 ops.mjs 网关及明确新增的任务命令,不绕过授权直接拼接目标修改命令。
|