psyclaw 0.24.0 → 0.25.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 +46 -53
- package/{dist/apps → apps}/panel/index.html +28 -50
- package/package.json +10 -20
- package/scripts/__pycache__/build_dist.cpython-314.pyc +0 -0
- package/scripts/__pycache__/build_whitepaper_docx.cpython-314.pyc +0 -0
- package/scripts/build_preprint_docx.py +729 -0
- package/scripts/build_preprint_figures.py +238 -0
- package/scripts/build_three_line_table_fixture.py +56 -0
- package/scripts/build_whitepaper_docx.py +768 -0
- package/scripts/check-branding.mjs +159 -0
- package/scripts/copy-panel.mjs +11 -0
- package/scripts/rebrand-pi.mjs +292 -0
- package/scripts/verify_docx.py +41 -0
- package/skills/core/citation-audit/SKILL.md +9 -9
- package/skills/core/evidence-capture/SKILL.md +9 -9
- package/skills/core/manifest.json +15 -15
- package/skills/core/research-brief/SKILL.md +8 -8
- package/skills/core/research-intake/SKILL.md +9 -9
- package/dist/src/adapters/pi/extension.d.ts +0 -19
- package/dist/src/adapters/pi/extension.js +0 -735
- package/dist/src/adapters/pi/extension.js.map +0 -1
- package/dist/src/adapters/pi/model.d.ts +0 -72
- package/dist/src/adapters/pi/model.js +0 -152
- package/dist/src/adapters/pi/model.js.map +0 -1
- package/dist/src/adapters/pi/resources.d.ts +0 -23
- package/dist/src/adapters/pi/resources.js +0 -54
- package/dist/src/adapters/pi/resources.js.map +0 -1
- package/dist/src/adapters/pi/rpc.d.ts +0 -56
- package/dist/src/adapters/pi/rpc.js +0 -248
- package/dist/src/adapters/pi/rpc.js.map +0 -1
- package/dist/src/adapters/pi/session.d.ts +0 -30
- package/dist/src/adapters/pi/session.js +0 -64
- package/dist/src/adapters/pi/session.js.map +0 -1
- package/dist/src/agents/catalog.d.ts +0 -30
- package/dist/src/agents/catalog.js +0 -118
- package/dist/src/agents/catalog.js.map +0 -1
- package/dist/src/agents/discover.d.ts +0 -28
- package/dist/src/agents/discover.js +0 -127
- package/dist/src/agents/discover.js.map +0 -1
- package/dist/src/agents/import.d.ts +0 -67
- package/dist/src/agents/import.js +0 -801
- package/dist/src/agents/import.js.map +0 -1
- package/dist/src/analysis/hooks.d.ts +0 -81
- package/dist/src/analysis/hooks.js +0 -139
- package/dist/src/analysis/hooks.js.map +0 -1
- package/dist/src/analysis/pre-registration.d.ts +0 -18
- package/dist/src/analysis/pre-registration.js +0 -86
- package/dist/src/analysis/pre-registration.js.map +0 -1
- package/dist/src/branding.d.ts +0 -43
- package/dist/src/branding.js +0 -127
- package/dist/src/branding.js.map +0 -1
- package/dist/src/chat.d.ts +0 -16
- package/dist/src/chat.js +0 -67
- package/dist/src/chat.js.map +0 -1
- package/dist/src/cli.d.ts +0 -2
- package/dist/src/cli.js +0 -316
- package/dist/src/cli.js.map +0 -1
- package/dist/src/core/citations.d.ts +0 -44
- package/dist/src/core/citations.js +0 -48
- package/dist/src/core/citations.js.map +0 -1
- package/dist/src/core/contracts.d.ts +0 -119
- package/dist/src/core/contracts.js +0 -2
- package/dist/src/core/contracts.js.map +0 -1
- package/dist/src/core/docx.d.ts +0 -11
- package/dist/src/core/docx.js +0 -46
- package/dist/src/core/docx.js.map +0 -1
- package/dist/src/core/doi.d.ts +0 -41
- package/dist/src/core/doi.js +0 -82
- package/dist/src/core/doi.js.map +0 -1
- package/dist/src/core/evidence-policy.d.ts +0 -24
- package/dist/src/core/evidence-policy.js +0 -308
- package/dist/src/core/evidence-policy.js.map +0 -1
- package/dist/src/core/filekind.d.ts +0 -15
- package/dist/src/core/filekind.js +0 -82
- package/dist/src/core/filekind.js.map +0 -1
- package/dist/src/core/hash.d.ts +0 -2
- package/dist/src/core/hash.js +0 -17
- package/dist/src/core/hash.js.map +0 -1
- package/dist/src/core/pricing.d.ts +0 -38
- package/dist/src/core/pricing.js +0 -110
- package/dist/src/core/pricing.js.map +0 -1
- package/dist/src/core/redact.d.ts +0 -12
- package/dist/src/core/redact.js +0 -48
- package/dist/src/core/redact.js.map +0 -1
- package/dist/src/core/references.d.ts +0 -55
- package/dist/src/core/references.js +0 -102
- package/dist/src/core/references.js.map +0 -1
- package/dist/src/core/schemas.d.ts +0 -162
- package/dist/src/core/schemas.js +0 -160
- package/dist/src/core/schemas.js.map +0 -1
- package/dist/src/extension.d.ts +0 -1
- package/dist/src/extension.js +0 -2
- package/dist/src/extension.js.map +0 -1
- package/dist/src/index.d.ts +0 -72
- package/dist/src/index.js +0 -73
- package/dist/src/index.js.map +0 -1
- package/dist/src/install/installer.d.ts +0 -147
- package/dist/src/install/installer.js +0 -743
- package/dist/src/install/installer.js.map +0 -1
- package/dist/src/integrations/contracts.d.ts +0 -35
- package/dist/src/integrations/contracts.js +0 -27
- package/dist/src/integrations/contracts.js.map +0 -1
- package/dist/src/integrations/mcp.d.ts +0 -155
- package/dist/src/integrations/mcp.js +0 -826
- package/dist/src/integrations/mcp.js.map +0 -1
- package/dist/src/knowledge-map/contracts.d.ts +0 -20
- package/dist/src/knowledge-map/contracts.js +0 -2
- package/dist/src/knowledge-map/contracts.js.map +0 -1
- package/dist/src/knowledge-map/index.d.ts +0 -4
- package/dist/src/knowledge-map/index.js +0 -39
- package/dist/src/knowledge-map/index.js.map +0 -1
- package/dist/src/literature/contracts.d.ts +0 -106
- package/dist/src/literature/contracts.js +0 -2
- package/dist/src/literature/contracts.js.map +0 -1
- package/dist/src/literature/fulltext.d.ts +0 -7
- package/dist/src/literature/fulltext.js +0 -24
- package/dist/src/literature/fulltext.js.map +0 -1
- package/dist/src/literature/knowledge-map.d.ts +0 -2
- package/dist/src/literature/knowledge-map.js +0 -20
- package/dist/src/literature/knowledge-map.js.map +0 -1
- package/dist/src/literature/ledger.d.ts +0 -3
- package/dist/src/literature/ledger.js +0 -17
- package/dist/src/literature/ledger.js.map +0 -1
- package/dist/src/literature/metadata.d.ts +0 -6
- package/dist/src/literature/metadata.js +0 -32
- package/dist/src/literature/metadata.js.map +0 -1
- package/dist/src/memory/store.d.ts +0 -22
- package/dist/src/memory/store.js +0 -73
- package/dist/src/memory/store.js.map +0 -1
- package/dist/src/orchestration/contracts.d.ts +0 -61
- package/dist/src/orchestration/contracts.js +0 -2
- package/dist/src/orchestration/contracts.js.map +0 -1
- package/dist/src/orchestration/pi-executor.d.ts +0 -28
- package/dist/src/orchestration/pi-executor.js +0 -169
- package/dist/src/orchestration/pi-executor.js.map +0 -1
- package/dist/src/orchestration/runner.d.ts +0 -196
- package/dist/src/orchestration/runner.js +0 -991
- package/dist/src/orchestration/runner.js.map +0 -1
- package/dist/src/orchestration/scheduler.d.ts +0 -8
- package/dist/src/orchestration/scheduler.js +0 -335
- package/dist/src/orchestration/scheduler.js.map +0 -1
- package/dist/src/panel/events.d.ts +0 -20
- package/dist/src/panel/events.js +0 -93
- package/dist/src/panel/events.js.map +0 -1
- package/dist/src/panel/extension.d.ts +0 -8
- package/dist/src/panel/extension.js +0 -114
- package/dist/src/panel/extension.js.map +0 -1
- package/dist/src/panel/literature-map.d.ts +0 -26
- package/dist/src/panel/literature-map.js +0 -34
- package/dist/src/panel/literature-map.js.map +0 -1
- package/dist/src/panel/projection.d.ts +0 -51
- package/dist/src/panel/projection.js +0 -288
- package/dist/src/panel/projection.js.map +0 -1
- package/dist/src/panel/server.d.ts +0 -46
- package/dist/src/panel/server.js +0 -1610
- package/dist/src/panel/server.js.map +0 -1
- package/dist/src/panel/usage.d.ts +0 -53
- package/dist/src/panel/usage.js +0 -150
- package/dist/src/panel/usage.js.map +0 -1
- package/dist/src/project/bootstrap.d.ts +0 -10
- package/dist/src/project/bootstrap.js +0 -83
- package/dist/src/project/bootstrap.js.map +0 -1
- package/dist/src/project/hitl.d.ts +0 -12
- package/dist/src/project/hitl.js +0 -43
- package/dist/src/project/hitl.js.map +0 -1
- package/dist/src/project/jsonl.d.ts +0 -16
- package/dist/src/project/jsonl.js +0 -93
- package/dist/src/project/jsonl.js.map +0 -1
- package/dist/src/project/manuscript.d.ts +0 -21
- package/dist/src/project/manuscript.js +0 -74
- package/dist/src/project/manuscript.js.map +0 -1
- package/dist/src/project/paths.d.ts +0 -38
- package/dist/src/project/paths.js +0 -166
- package/dist/src/project/paths.js.map +0 -1
- package/dist/src/project/versions.d.ts +0 -10
- package/dist/src/project/versions.js +0 -14
- package/dist/src/project/versions.js.map +0 -1
- package/dist/src/psyclaw-theme.d.ts +0 -88
- package/dist/src/psyclaw-theme.js +0 -89
- package/dist/src/psyclaw-theme.js.map +0 -1
- package/dist/src/research/brief.d.ts +0 -11
- package/dist/src/research/brief.js +0 -81
- package/dist/src/research/brief.js.map +0 -1
- package/dist/src/research/ledger.d.ts +0 -12
- package/dist/src/research/ledger.js +0 -43
- package/dist/src/research/ledger.js.map +0 -1
- package/dist/src/run.d.ts +0 -20
- package/dist/src/run.js +0 -34
- package/dist/src/run.js.map +0 -1
- package/dist/src/setup.d.ts +0 -54
- package/dist/src/setup.js +0 -221
- package/dist/src/setup.js.map +0 -1
- package/dist/src/skills/contracts.d.ts +0 -105
- package/dist/src/skills/contracts.js +0 -3
- package/dist/src/skills/contracts.js.map +0 -1
- package/dist/src/skills/preflight.d.ts +0 -10
- package/dist/src/skills/preflight.js +0 -39
- package/dist/src/skills/preflight.js.map +0 -1
- package/dist/src/skills/registry.d.ts +0 -28
- package/dist/src/skills/registry.js +0 -556
- package/dist/src/skills/registry.js.map +0 -1
- package/dist/src/style/artifact.d.ts +0 -6
- package/dist/src/style/artifact.js +0 -61
- package/dist/src/style/artifact.js.map +0 -1
- package/dist/src/style/cli-ui.d.ts +0 -41
- package/dist/src/style/cli-ui.js +0 -119
- package/dist/src/style/cli-ui.js.map +0 -1
- package/dist/src/style/contracts.d.ts +0 -34
- package/dist/src/style/contracts.js +0 -2
- package/dist/src/style/contracts.js.map +0 -1
- package/dist/src/style/registry.d.ts +0 -16
- package/dist/src/style/registry.js +0 -50
- package/dist/src/style/registry.js.map +0 -1
- package/dist/src/trust/manifest.d.ts +0 -42
- package/dist/src/trust/manifest.js +0 -53
- package/dist/src/trust/manifest.js.map +0 -1
- package/dist/src/trust/sbom.d.ts +0 -54
- package/dist/src/trust/sbom.js +0 -77
- package/dist/src/trust/sbom.js.map +0 -1
- package/dist/src/tui/app.d.ts +0 -3
- package/dist/src/tui/app.js +0 -103
- package/dist/src/tui/app.js.map +0 -1
- package/dist/src/tui/model.d.ts +0 -13
- package/dist/src/tui/model.js +0 -25
- package/dist/src/tui/model.js.map +0 -1
- package/dist/src/updates/check.d.ts +0 -43
- package/dist/src/updates/check.js +0 -68
- package/dist/src/updates/check.js.map +0 -1
- package/dist/src/updates/manifest.d.ts +0 -19
- package/dist/src/updates/manifest.js +0 -58
- package/dist/src/updates/manifest.js.map +0 -1
- package/dist/src/updates/registry.d.ts +0 -21
- package/dist/src/updates/registry.js +0 -82
- package/dist/src/updates/registry.js.map +0 -1
- package/dist/src/updates/skills.d.ts +0 -15
- package/dist/src/updates/skills.js +0 -39
- package/dist/src/updates/skills.js.map +0 -1
- package/dist/src/updates/status.d.ts +0 -7
- package/dist/src/updates/status.js +0 -37
- package/dist/src/updates/status.js.map +0 -1
- package/dist/src/updates/update.d.ts +0 -43
- package/dist/src/updates/update.js +0 -126
- package/dist/src/updates/update.js.map +0 -1
- package/dist/src/wizard.d.ts +0 -7
- package/dist/src/wizard.js +0 -90
- package/dist/src/wizard.js.map +0 -1
- package/dist/src/workflows/analysis-delegation.d.ts +0 -3
- package/dist/src/workflows/analysis-delegation.js +0 -96
- package/dist/src/workflows/analysis-delegation.js.map +0 -1
- package/dist/src/workflows/expert-review-runner.d.ts +0 -29
- package/dist/src/workflows/expert-review-runner.js +0 -35
- package/dist/src/workflows/expert-review-runner.js.map +0 -1
- package/dist/src/workflows/expert-review.d.ts +0 -140
- package/dist/src/workflows/expert-review.js +0 -111
- package/dist/src/workflows/expert-review.js.map +0 -1
- package/dist/src/workflows/institutional-fulltext.d.ts +0 -16
- package/dist/src/workflows/institutional-fulltext.js +0 -110
- package/dist/src/workflows/institutional-fulltext.js.map +0 -1
- package/dist/src/workflows/literature-review.d.ts +0 -3
- package/dist/src/workflows/literature-review.js +0 -76
- package/dist/src/workflows/literature-review.js.map +0 -1
- package/dist/src/workflows/meta-analysis.d.ts +0 -38
- package/dist/src/workflows/meta-analysis.js +0 -185
- package/dist/src/workflows/meta-analysis.js.map +0 -1
- package/dist/src/workflows/publish.d.ts +0 -51
- package/dist/src/workflows/publish.js +0 -153
- package/dist/src/workflows/publish.js.map +0 -1
- package/dist/src/workflows/spec.d.ts +0 -51
- package/dist/src/workflows/spec.js +0 -157
- package/dist/src/workflows/spec.js.map +0 -1
- package/dist/src/workflows/style-contract.d.ts +0 -24
- package/dist/src/workflows/style-contract.js +0 -23
- package/dist/src/workflows/style-contract.js.map +0 -1
- package/dist/src/workflows/writing-review.d.ts +0 -15
- package/dist/src/workflows/writing-review.js +0 -82
- package/dist/src/workflows/writing-review.js.map +0 -1
- package/package.json.psyclaw +0 -21
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { sha256Text } from "../core/hash.js";
|
|
4
|
-
import { appendJsonlIfMissing, atomicWriteFile } from "../project/jsonl.js";
|
|
5
|
-
import { projectPaths } from "../project/paths.js";
|
|
6
|
-
import { readProject } from "../research/ledger.js";
|
|
7
|
-
import { createStageRunner } from "../run.js";
|
|
8
|
-
import { finalizeWorkflow } from "./spec.js";
|
|
9
|
-
export const metaAnalysisSpec = {
|
|
10
|
-
id: "meta-analysis",
|
|
11
|
-
version: "1.0.0",
|
|
12
|
-
description: "Systematic meta-analysis: literature intake, effect-size dataset contract, R metafor audit, brief.",
|
|
13
|
-
paradigms: ["meta-analysis"],
|
|
14
|
-
steps: [
|
|
15
|
-
{ id: "intake", role: "researcher", effect: "read", description: "search OpenAlex for studies" },
|
|
16
|
-
{ id: "capture", role: "analyst", effect: "read", description: "bind the effect-size dataset contract" },
|
|
17
|
-
{ id: "audit", role: "analyst", effect: "write", description: "delegate metafor audit (I², Egger funnel)" },
|
|
18
|
-
{ id: "brief", role: "writer", effect: "write", description: "write the report and ledger entry" },
|
|
19
|
-
],
|
|
20
|
-
requiredArtifacts: ["meta-analysis.json", "meta-analysis.md"],
|
|
21
|
-
};
|
|
22
|
-
/** Search OpenAlex for studies matching the target (real network; injectable for tests). */
|
|
23
|
-
export async function searchOpenAlex(target, nStudies, fetchFn = fetch) {
|
|
24
|
-
const perPage = Math.min(50, Math.max(1, nStudies));
|
|
25
|
-
const url = `https://api.openalex.org/works?search=${encodeURIComponent(target)}&per-page=${perPage}&mailto=psyclaw@example.org`;
|
|
26
|
-
const response = await fetchFn(url, { signal: AbortSignal.timeout(15_000) });
|
|
27
|
-
if (!response.ok)
|
|
28
|
-
throw new Error(`OpenAlex 检索失败 (${response.status})`);
|
|
29
|
-
const body = await response.json();
|
|
30
|
-
return (body.results ?? []).slice(0, nStudies).map((item, index) => ({
|
|
31
|
-
id: `study_${index + 1}`,
|
|
32
|
-
title: item.title ?? "untitled",
|
|
33
|
-
authors: (item.authorships ?? []).map((entry) => entry.author?.display_name ?? "?").slice(0, 10),
|
|
34
|
-
...(item.publication_year === undefined ? {} : { year: item.publication_year }),
|
|
35
|
-
...(item.host_venue?.display_name ? { venue: item.host_venue.display_name } : {}),
|
|
36
|
-
...(item.doi ? { doi: item.doi } : {}),
|
|
37
|
-
...(item.cited_by_count === undefined ? {} : { citations: item.cited_by_count }),
|
|
38
|
-
}));
|
|
39
|
-
}
|
|
40
|
-
/** Parse a CSV with at least `study_id,effect_size,standard_error`. */
|
|
41
|
-
export function parseEffectCsv(text) {
|
|
42
|
-
const rows = [];
|
|
43
|
-
const lines = text.split(/\r?\n/).filter((line) => line.trim());
|
|
44
|
-
if (lines.length === 0)
|
|
45
|
-
return rows;
|
|
46
|
-
const header = lines[0].split(",").map((cell) => cell.trim().toLowerCase());
|
|
47
|
-
// Accept the canonical names plus common shorthand (study, effect, se/g/d).
|
|
48
|
-
const ALIASES = {
|
|
49
|
-
study_id: ["study_id", "study", "id"],
|
|
50
|
-
effect_size: ["effect_size", "effect", "es", "g", "d"],
|
|
51
|
-
standard_error: ["standard_error", "se", "std_error", "std_err"],
|
|
52
|
-
};
|
|
53
|
-
const indexOf = (name) => {
|
|
54
|
-
const aliases = ALIASES[name] ?? [name];
|
|
55
|
-
return header.findIndex((cell) => aliases.includes(cell) || cell.endsWith(name));
|
|
56
|
-
};
|
|
57
|
-
const studyIdx = indexOf("study_id");
|
|
58
|
-
const effectIdx = indexOf("effect_size");
|
|
59
|
-
const seIdx = indexOf("standard_error");
|
|
60
|
-
if (studyIdx < 0 || effectIdx < 0 || seIdx < 0)
|
|
61
|
-
return rows;
|
|
62
|
-
for (const line of lines.slice(1)) {
|
|
63
|
-
const cells = line.split(",").map((cell) => cell.trim());
|
|
64
|
-
const effectSize = Number(cells[effectIdx]);
|
|
65
|
-
const standardError = Number(cells[seIdx]);
|
|
66
|
-
if (!Number.isFinite(effectSize) || !Number.isFinite(standardError) || standardError <= 0)
|
|
67
|
-
continue;
|
|
68
|
-
const n = Number(cells[header.indexOf("n")]);
|
|
69
|
-
rows.push({
|
|
70
|
-
studyId: cells[studyIdx] ?? `study_${rows.length + 1}`,
|
|
71
|
-
effectSize,
|
|
72
|
-
standardError,
|
|
73
|
-
...(Number.isFinite(n) && n > 0 ? { n } : {}),
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
return rows;
|
|
77
|
-
}
|
|
78
|
-
export async function loadEffectDataset(root) {
|
|
79
|
-
const candidates = ["data/clean/effects.csv", "analysis/outputs/effects.csv", "outputs/effects.csv"];
|
|
80
|
-
for (const candidate of candidates) {
|
|
81
|
-
try {
|
|
82
|
-
const rows = parseEffectCsv(await readFile(join(root, candidate), "utf8"));
|
|
83
|
-
if (rows.length > 0)
|
|
84
|
-
return rows;
|
|
85
|
-
}
|
|
86
|
-
catch { /* try next */ }
|
|
87
|
-
}
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
/** R metafor script that computes the random-effects model, I², Egger's test, and the forest plot. */
|
|
91
|
-
export function metaforScript(datasetPath) {
|
|
92
|
-
return [
|
|
93
|
-
"# metafor.R — 随机效应元分析(委托 R 执行;psyclaw 不在核心计算统计量)",
|
|
94
|
-
"suppressMessages(library(metafor))",
|
|
95
|
-
`d <- read.csv("${datasetPath.replaceAll("\\", "/")}", stringsAsFactors = FALSE)`,
|
|
96
|
-
"fit <- rma(yi = d$effect_size, vi = d$standard_error^2, method = \"REML\")",
|
|
97
|
-
'cat(sprintf("I2=%.1f%%\\n", fit$I2))',
|
|
98
|
-
'cat(sprintf("k=%d\\n", fit$k))',
|
|
99
|
-
'res <- regtest(fit, predictor = "sei")',
|
|
100
|
-
'cat(sprintf("egger_p=%.3f\\n", res$pval))',
|
|
101
|
-
'dir.create("outputs/figures", recursive = TRUE, showWarnings = FALSE)',
|
|
102
|
-
'png("outputs/figures/forest.png", width = 800, height = 480, res = 110)',
|
|
103
|
-
"forest(fit)",
|
|
104
|
-
"dev.off()",
|
|
105
|
-
'dir.create("analysis/outputs", recursive = TRUE, showWarnings = FALSE)',
|
|
106
|
-
'saveRDS(fit, "analysis/outputs/meta_fit.rds")',
|
|
107
|
-
"",
|
|
108
|
-
].join("\n");
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Real meta-analysis pipeline. Statistics are never computed in core: the
|
|
112
|
-
* audit stage writes an R (metafor) script and the brief records what was
|
|
113
|
-
* found and what must run externally. Effect sizes come from the project's
|
|
114
|
-
* dataset; without one the workflow blocks honestly instead of faking numbers.
|
|
115
|
-
*/
|
|
116
|
-
export async function runMetaAnalysis(root, options) {
|
|
117
|
-
const runner = options.runner ?? createStageRunner();
|
|
118
|
-
const project = await readProject(root);
|
|
119
|
-
const gates = [];
|
|
120
|
-
const studies = await runner.stage("intake", `检索 OpenAlex 数据库并提取 "${options.target}" 的实证研究`, async () => searchOpenAlex(options.target, options.nStudies, options.fetchFn ?? fetch), (found) => `命中 ${found.length} 项研究,登记为证据账本条目`);
|
|
121
|
-
if (studies.length < 2) {
|
|
122
|
-
gates.push({ gateId: "meta:insufficient-studies", ok: false, severity: "block", reason: `需要至少 2 项研究,实际 ${studies.length}` });
|
|
123
|
-
}
|
|
124
|
-
const dataset = await runner.stage("capture", "绑定效应量数据集(Hedges' g / SE)", async () => loadEffectDataset(root), (rows) => rows === undefined ? "未找到数据集,进入数据契约状态" : `解析 ${rows.length} 条效应量记录`);
|
|
125
|
-
if (dataset === undefined) {
|
|
126
|
-
gates.push({ gateId: "meta:effect-data-missing", ok: false, severity: "block", reason: "缺少效应量数据集(data/clean/effects.csv:study_id,effect_size,standard_error)" });
|
|
127
|
-
}
|
|
128
|
-
const datasetPath = dataset === undefined ? null : `data/clean/effects.csv`;
|
|
129
|
-
await runner.stage("audit", "委托 R (metafor) 生成随机效应模型、I² 与 Egger 检验", async () => {
|
|
130
|
-
const scriptPath = join(root, "analysis", "scripts", "metafor.R");
|
|
131
|
-
await atomicWriteFile(scriptPath, metaforScript(datasetPath ?? "data/clean/effects.csv"));
|
|
132
|
-
return scriptPath;
|
|
133
|
-
}, (path) => `已写入 ${path};统计由 R 执行,psyclaw 不伪造 I²/Egger 数值`);
|
|
134
|
-
const auditNote = dataset === undefined
|
|
135
|
-
? "数据集缺失:I² 与 Egger 检验待 R 在有数据后执行"
|
|
136
|
-
: `数据集就绪(${dataset.length} 条):运行 analysis/scripts/metafor.R 得到 I² 与 Egger p 值`;
|
|
137
|
-
await runner.stage("brief", "生成元分析报告与账本条目", async () => {
|
|
138
|
-
for (const study of studies) {
|
|
139
|
-
await appendJsonlIfMissing(projectPaths(root).evidence, {
|
|
140
|
-
id: `meta:${sha256Text(study.title).slice(0, 16)}`,
|
|
141
|
-
source: { kind: "url", locator: study.doi ?? study.id, title: study.title },
|
|
142
|
-
level: "metadata",
|
|
143
|
-
retrievedAt: new Date().toISOString(),
|
|
144
|
-
accessStatus: "partial",
|
|
145
|
-
locators: [{ kind: "url", value: study.doi ?? "" }],
|
|
146
|
-
}, (item) => item.id);
|
|
147
|
-
}
|
|
148
|
-
const summary = {
|
|
149
|
-
schemaVersion: "psyclaw/meta-analysis/v1",
|
|
150
|
-
target: options.target,
|
|
151
|
-
nStudiesRequested: options.nStudies,
|
|
152
|
-
studiesFound: studies.length,
|
|
153
|
-
effectRows: dataset?.length ?? 0,
|
|
154
|
-
audit: { delegatedTo: "R metafor", script: "analysis/scripts/metafor.R", note: auditNote },
|
|
155
|
-
generatedAt: new Date().toISOString(),
|
|
156
|
-
};
|
|
157
|
-
const markdown = [
|
|
158
|
-
`# Meta-Analysis: ${options.target}`,
|
|
159
|
-
"",
|
|
160
|
-
`- 检索:OpenAlex,目标 "${options.target}",${studies.length} 项研究`,
|
|
161
|
-
`- 效应量数据集:${dataset === undefined ? "缺失(需 data/clean/effects.csv)" : `${dataset.length} 条`}`,
|
|
162
|
-
`- 统计:委托 R metafor(REML 随机效应、I²、Egger 漏斗回归、森林图)`,
|
|
163
|
-
`- 审计:${auditNote}`,
|
|
164
|
-
"",
|
|
165
|
-
"## 研究清单",
|
|
166
|
-
"",
|
|
167
|
-
...studies.map((study) => `- ${study.title}${study.year ? ` (${study.year})` : ""}${study.doi ? ` · ${study.doi}` : ""}`),
|
|
168
|
-
"",
|
|
169
|
-
"> 统计数值由 R (metafor) 在数据集就绪后计算,本文件不伪造任何效应量或检验结果。",
|
|
170
|
-
"",
|
|
171
|
-
].join("\n");
|
|
172
|
-
await atomicWriteFile(join(root, "analysis", "outputs", "meta-analysis.json"), `${JSON.stringify(summary, null, 2)}\n`);
|
|
173
|
-
await atomicWriteFile(join(root, "analysis", "outputs", "meta-analysis.md"), markdown);
|
|
174
|
-
return { studies: studies.length, rows: dataset?.length ?? 0 };
|
|
175
|
-
}, (result) => `签发 ${result.studies} 条研究账本条目,报告落盘`);
|
|
176
|
-
return finalizeWorkflow(root, metaAnalysisSpec, {
|
|
177
|
-
gates,
|
|
178
|
-
outputs: [
|
|
179
|
-
{ path: "meta-analysis.md", contents: `# Meta-Analysis: ${options.target}\n\n见 analysis/outputs/meta-analysis.md\n` },
|
|
180
|
-
{ path: "meta-analysis.json", contents: `${JSON.stringify({ target: options.target, studies: studies.length, effectRows: dataset?.length ?? 0 }, null, 2)}\n` },
|
|
181
|
-
],
|
|
182
|
-
completed: ["literature intake", "effect-size contract", "metafor delegation", "report written"],
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
//# sourceMappingURL=meta-analysis.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"meta-analysis.js","sourceRoot":"","sources":["../../../src/workflows/meta-analysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generation-time manuscript publishing with versioning (convention:
|
|
3
|
-
* docs/文档规范.md).
|
|
4
|
-
*
|
|
5
|
-
* paper/<name>.md latest editable Markdown source
|
|
6
|
-
* paper/<name>_APA7.docx latest APA-7 DOCX export
|
|
7
|
-
* paper/archive/<name>_v{n}.md archived previous versions
|
|
8
|
-
* .psyclaw/versions.jsonl version allocation (allocateProjectVersion,
|
|
9
|
-
* kind "manuscript")
|
|
10
|
-
* .psyclaw/publish.jsonl published-version records (idempotent by sha)
|
|
11
|
-
*
|
|
12
|
-
* Re-publishing identical content is a no-op (no new version); changed content
|
|
13
|
-
* archives the previous files and bumps the version. Both files are registered
|
|
14
|
-
* in the evidence ledger with their SHA-256 fingerprints.
|
|
15
|
-
*/
|
|
16
|
-
/** A published manuscript version (one record per publish). */
|
|
17
|
-
export interface PublishedVersion {
|
|
18
|
-
schemaVersion: "psyclaw/publish/v1";
|
|
19
|
-
version: number;
|
|
20
|
-
name: string;
|
|
21
|
-
markdownPath: string;
|
|
22
|
-
docxPath: string | null;
|
|
23
|
-
markdownSha256: string;
|
|
24
|
-
docxSha256: string | null;
|
|
25
|
-
sourcePath: string | null;
|
|
26
|
-
publishedAt: string;
|
|
27
|
-
}
|
|
28
|
-
export declare function readPublishedVersions(root: string): Promise<PublishedVersion[]>;
|
|
29
|
-
/** Find a black-and-white reference document (paper/apa7-bw-reference.docx or similar). */
|
|
30
|
-
export declare function findReferenceDoc(root: string): Promise<string | null>;
|
|
31
|
-
export interface PublishOptions {
|
|
32
|
-
/** Base file name, e.g. "论文初稿" (default). */
|
|
33
|
-
name?: string;
|
|
34
|
-
/** Manuscript source (Markdown). If omitted, the discovered manuscript is used. */
|
|
35
|
-
markdown?: string;
|
|
36
|
-
/** Export the APA-7 DOCX (default true). */
|
|
37
|
-
exportDocx?: boolean;
|
|
38
|
-
}
|
|
39
|
-
export interface PublishResult {
|
|
40
|
-
schemaVersion: "psyclaw/publish/v1";
|
|
41
|
-
version: number;
|
|
42
|
-
name: string;
|
|
43
|
-
markdownPath: string;
|
|
44
|
-
docxPath: string | null;
|
|
45
|
-
markdownSha256: string;
|
|
46
|
-
docxSha256: string | null;
|
|
47
|
-
evidenceIds: string[];
|
|
48
|
-
sourcePath: string | null;
|
|
49
|
-
publishedAt: string;
|
|
50
|
-
}
|
|
51
|
-
export declare function publishManuscript(root: string, options?: PublishOptions): Promise<PublishResult>;
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { lstat, readFile, readdir } from "node:fs/promises";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { markdownToDocx } from "../core/docx.js";
|
|
5
|
-
import { sha256File, sha256Text } from "../core/hash.js";
|
|
6
|
-
import { atomicWriteFile, appendJsonlIfMissing, readJsonl } from "../project/jsonl.js";
|
|
7
|
-
import { assertSafeProjectPath, projectPaths } from "../project/paths.js";
|
|
8
|
-
import { readManuscript } from "../project/manuscript.js";
|
|
9
|
-
import { allocateProjectVersion } from "../project/versions.js";
|
|
10
|
-
export async function readPublishedVersions(root) {
|
|
11
|
-
return readJsonl(await assertSafeProjectPath(root, ".psyclaw/publish.jsonl"));
|
|
12
|
-
}
|
|
13
|
-
async function archiveFile(root, sourceRel, targetRel) {
|
|
14
|
-
try {
|
|
15
|
-
const source = await assertSafeProjectPath(root, sourceRel);
|
|
16
|
-
const contents = await readFile(source, "utf8");
|
|
17
|
-
await atomicWriteFile(await assertSafeProjectPath(root, targetRel), contents);
|
|
18
|
-
}
|
|
19
|
-
catch { /* nothing to archive */ }
|
|
20
|
-
}
|
|
21
|
-
/** Find a black-and-white reference document (paper/apa7-bw-reference.docx or similar). */
|
|
22
|
-
export async function findReferenceDoc(root) {
|
|
23
|
-
let entries = [];
|
|
24
|
-
try {
|
|
25
|
-
entries = await readdir(join(root, "paper"), { withFileTypes: true });
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
for (const entry of entries) {
|
|
31
|
-
if (!entry.isFile() || !/\.docx$/i.test(entry.name))
|
|
32
|
-
continue;
|
|
33
|
-
if (/reference|模板|template/i.test(entry.name)) {
|
|
34
|
-
const path = `paper/${entry.name}`;
|
|
35
|
-
const stat = await lstat(await assertSafeProjectPath(root, path)).catch(() => undefined);
|
|
36
|
-
if (stat?.isFile())
|
|
37
|
-
return path;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
export async function publishManuscript(root, options = {}) {
|
|
43
|
-
const name = (options.name ?? "论文初稿").trim().replace(/\.(md|docx)$/i, "");
|
|
44
|
-
if (!name)
|
|
45
|
-
throw new Error("manuscript name is required");
|
|
46
|
-
const exportDocx = options.exportDocx ?? true;
|
|
47
|
-
const existing = await readManuscript(root);
|
|
48
|
-
const sourcePath = existing.exists ? existing.path : null;
|
|
49
|
-
const markdown = options.markdown ?? existing.markdown;
|
|
50
|
-
if (!markdown.trim()) {
|
|
51
|
-
throw new Error("没有可发布的手稿内容:请先在编辑器写入内容,或先运行工作流生成论文初稿");
|
|
52
|
-
}
|
|
53
|
-
const markdownPath = `paper/${name}.md`;
|
|
54
|
-
const markdownTarget = await assertSafeProjectPath(root, markdownPath);
|
|
55
|
-
const written = markdown.endsWith("\n") ? markdown : `${markdown}\n`;
|
|
56
|
-
const markdownSha256 = sha256Text(written);
|
|
57
|
-
const published = await readPublishedVersions(root);
|
|
58
|
-
const last = published.at(-1);
|
|
59
|
-
if (last && last.markdownSha256 === markdownSha256) {
|
|
60
|
-
// Re-publishing identical content is a no-op: no new version, no rewrite.
|
|
61
|
-
return {
|
|
62
|
-
schemaVersion: "psyclaw/publish/v1",
|
|
63
|
-
version: last.version,
|
|
64
|
-
name: last.name,
|
|
65
|
-
markdownPath: last.markdownPath,
|
|
66
|
-
docxPath: last.docxPath,
|
|
67
|
-
markdownSha256,
|
|
68
|
-
docxSha256: last.docxSha256,
|
|
69
|
-
evidenceIds: [],
|
|
70
|
-
sourcePath,
|
|
71
|
-
publishedAt: last.publishedAt,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
// Archive the current files under the version they were last published as.
|
|
75
|
-
if (last) {
|
|
76
|
-
await archiveFile(root, markdownPath, `paper/archive/${name}_v${last.version}.md`);
|
|
77
|
-
if (last.docxPath)
|
|
78
|
-
await archiveFile(root, last.docxPath, `paper/archive/${name}_v${last.version}_APA7.docx`);
|
|
79
|
-
}
|
|
80
|
-
// Allocate the next manuscript version through the shared project allocator.
|
|
81
|
-
const runId = `publish_${randomUUID().replaceAll("-", "")}`;
|
|
82
|
-
const versionLabel = await allocateProjectVersion(root, "manuscript", runId);
|
|
83
|
-
const version = Number(versionLabel.replace(/^v/i, ""));
|
|
84
|
-
await atomicWriteFile(markdownTarget, written);
|
|
85
|
-
const evidenceIds = [];
|
|
86
|
-
const recordEvidence = async (path, sha256) => {
|
|
87
|
-
const id = `evidence_${sha256.slice(0, 16)}`;
|
|
88
|
-
// Idempotent by evidence id: publishing and importing the same file must
|
|
89
|
-
// not create duplicate ledger entries.
|
|
90
|
-
await appendJsonlIfMissing(projectPaths(root).evidence, {
|
|
91
|
-
id,
|
|
92
|
-
source: { kind: "file", locator: path, title: path.split("/").pop() ?? path },
|
|
93
|
-
level: "fulltext",
|
|
94
|
-
retrievedAt: new Date().toISOString(),
|
|
95
|
-
sha256,
|
|
96
|
-
accessStatus: "partial",
|
|
97
|
-
locators: [{ kind: "file", value: path }],
|
|
98
|
-
}, (item) => item.id);
|
|
99
|
-
return id;
|
|
100
|
-
};
|
|
101
|
-
evidenceIds.push(await recordEvidence(markdownPath, markdownSha256));
|
|
102
|
-
let docxPath = null;
|
|
103
|
-
let docxSha256 = null;
|
|
104
|
-
if (exportDocx) {
|
|
105
|
-
docxPath = `paper/${name}_APA7.docx`;
|
|
106
|
-
const docxTarget = await assertSafeProjectPath(root, docxPath);
|
|
107
|
-
const referenceDoc = await findReferenceDoc(root);
|
|
108
|
-
const referenceTarget = referenceDoc ? await assertSafeProjectPath(root, referenceDoc) : undefined;
|
|
109
|
-
await markdownToDocx(markdownTarget, docxTarget, referenceTarget);
|
|
110
|
-
docxSha256 = await sha256File(docxTarget);
|
|
111
|
-
evidenceIds.push(await recordEvidence(docxPath, docxSha256));
|
|
112
|
-
}
|
|
113
|
-
const publishedAt = new Date().toISOString();
|
|
114
|
-
const versionRecord = {
|
|
115
|
-
schemaVersion: "psyclaw/publish/v1",
|
|
116
|
-
version,
|
|
117
|
-
name,
|
|
118
|
-
markdownPath,
|
|
119
|
-
docxPath,
|
|
120
|
-
markdownSha256,
|
|
121
|
-
docxSha256,
|
|
122
|
-
sourcePath,
|
|
123
|
-
publishedAt,
|
|
124
|
-
};
|
|
125
|
-
await appendJsonlIfMissing(await assertSafeProjectPath(root, ".psyclaw/publish.jsonl"), versionRecord, (record) => record.markdownSha256);
|
|
126
|
-
const result = {
|
|
127
|
-
schemaVersion: "psyclaw/publish/v1",
|
|
128
|
-
version,
|
|
129
|
-
name,
|
|
130
|
-
markdownPath,
|
|
131
|
-
docxPath,
|
|
132
|
-
markdownSha256,
|
|
133
|
-
docxSha256,
|
|
134
|
-
evidenceIds,
|
|
135
|
-
sourcePath,
|
|
136
|
-
publishedAt,
|
|
137
|
-
};
|
|
138
|
-
const receipt = {
|
|
139
|
-
schemaVersion: "psyclaw/tool-receipt/v1",
|
|
140
|
-
runId,
|
|
141
|
-
taskId: "workflow.publish.manuscript",
|
|
142
|
-
tool: "workflow.publish.manuscript",
|
|
143
|
-
effect: "write",
|
|
144
|
-
approval: "approved",
|
|
145
|
-
idempotencyKey: `publish:${markdownSha256}`,
|
|
146
|
-
ok: true,
|
|
147
|
-
startedAt: publishedAt,
|
|
148
|
-
finishedAt: publishedAt,
|
|
149
|
-
};
|
|
150
|
-
await atomicWriteFile(await assertSafeProjectPath(root, `.psyclaw/manifests/${runId}.receipt.json`), `${JSON.stringify(receipt, null, 2)}\n`);
|
|
151
|
-
return result;
|
|
152
|
-
}
|
|
153
|
-
//# sourceMappingURL=publish.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../../src/workflows/publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { GateResult, Handoff, ResearchParadigm } from "../core/contracts.js";
|
|
2
|
-
export declare const WORKFLOW_SCHEMA: "psyclaw/workflow/v1";
|
|
3
|
-
export type WorkflowRole = "researcher" | "analyst" | "critic" | "writer" | "verifier";
|
|
4
|
-
export type WorkflowEffect = "read" | "write";
|
|
5
|
-
export interface WorkflowStep {
|
|
6
|
-
id: string;
|
|
7
|
-
role: WorkflowRole;
|
|
8
|
-
effect: WorkflowEffect;
|
|
9
|
-
description: string;
|
|
10
|
-
}
|
|
11
|
-
export interface WorkflowSpec {
|
|
12
|
-
id: string;
|
|
13
|
-
version: string;
|
|
14
|
-
description: string;
|
|
15
|
-
paradigms: readonly ResearchParadigm[];
|
|
16
|
-
steps: readonly WorkflowStep[];
|
|
17
|
-
requiredArtifacts: readonly string[];
|
|
18
|
-
}
|
|
19
|
-
export interface WorkflowOutputRecord {
|
|
20
|
-
path: string;
|
|
21
|
-
sha256: string;
|
|
22
|
-
artifactVersion: string;
|
|
23
|
-
format: "json" | "markdown" | "text" | "unknown";
|
|
24
|
-
status: "verified" | "draft-blocked";
|
|
25
|
-
}
|
|
26
|
-
export interface WorkflowResult {
|
|
27
|
-
runId: string;
|
|
28
|
-
workflowId: string;
|
|
29
|
-
verdict: "pass" | "blocked";
|
|
30
|
-
gates: GateResult[];
|
|
31
|
-
outputPaths: string[];
|
|
32
|
-
manifestPath: string;
|
|
33
|
-
verdictPath: string;
|
|
34
|
-
outputIndexPath: string;
|
|
35
|
-
handoff: Handoff;
|
|
36
|
-
}
|
|
37
|
-
export declare const allParadigms: readonly ResearchParadigm[];
|
|
38
|
-
/**
|
|
39
|
-
* Shared tail for every workflow pack. Outputs are written to safe project
|
|
40
|
-
* paths, the spec's required artifacts are actually checked, every output is
|
|
41
|
-
* SHA-pinned with a workflow version and input fingerprint, and `completed`
|
|
42
|
-
* is emitted only after outputs, manifest, and verdict are all on disk.
|
|
43
|
-
*/
|
|
44
|
-
export declare function finalizeWorkflow(root: string, workflow: WorkflowSpec, options: {
|
|
45
|
-
gates: GateResult[];
|
|
46
|
-
outputs: {
|
|
47
|
-
path: string;
|
|
48
|
-
contents: string;
|
|
49
|
-
}[];
|
|
50
|
-
completed: string[];
|
|
51
|
-
}): Promise<WorkflowResult>;
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { mkdir } from "node:fs/promises";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { sha256Text } from "../core/hash.js";
|
|
5
|
-
import { assertSafeProjectPath, projectPaths } from "../project/paths.js";
|
|
6
|
-
import { writeHandoff } from "../project/bootstrap.js";
|
|
7
|
-
import { atomicWriteFile } from "../project/jsonl.js";
|
|
8
|
-
import { readProject } from "../research/ledger.js";
|
|
9
|
-
import { RunEventLog } from "../panel/events.js";
|
|
10
|
-
export const WORKFLOW_SCHEMA = "psyclaw/workflow/v1";
|
|
11
|
-
const ALL_PARADIGMS = [
|
|
12
|
-
"survey-observational",
|
|
13
|
-
"qualitative-thematic",
|
|
14
|
-
"experimental",
|
|
15
|
-
"quasi-experimental",
|
|
16
|
-
"longitudinal-panel",
|
|
17
|
-
"meta-analysis",
|
|
18
|
-
"ethnographic",
|
|
19
|
-
"historical-documentary",
|
|
20
|
-
"policy-legal",
|
|
21
|
-
"mixed-methods",
|
|
22
|
-
];
|
|
23
|
-
export const allParadigms = ALL_PARADIGMS;
|
|
24
|
-
/**
|
|
25
|
-
* Reject a workflow output path before it is resolved, so a `..` segment or
|
|
26
|
-
* drive/ADS form cannot be collapsed away before the containment check.
|
|
27
|
-
*/
|
|
28
|
-
async function safeOutputPath(root, outputPath) {
|
|
29
|
-
const normalized = outputPath.trim().replaceAll("\\", "/");
|
|
30
|
-
if (normalized.length === 0 ||
|
|
31
|
-
normalized.startsWith("/") ||
|
|
32
|
-
/^[a-z]:/.test(normalized) ||
|
|
33
|
-
normalized.includes("\0") ||
|
|
34
|
-
normalized.split("/").some((segment) => segment === ".." || segment === "")) {
|
|
35
|
-
throw new Error(`unsafe output path: ${outputPath}`);
|
|
36
|
-
}
|
|
37
|
-
return assertSafeProjectPath(root, join("outputs", normalized));
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Shared tail for every workflow pack. Outputs are written to safe project
|
|
41
|
-
* paths, the spec's required artifacts are actually checked, every output is
|
|
42
|
-
* SHA-pinned with a workflow version and input fingerprint, and `completed`
|
|
43
|
-
* is emitted only after outputs, manifest, and verdict are all on disk.
|
|
44
|
-
*/
|
|
45
|
-
export async function finalizeWorkflow(root, workflow, options) {
|
|
46
|
-
const paths = projectPaths(root);
|
|
47
|
-
const project = await readProject(root);
|
|
48
|
-
const runId = `run_${randomUUID().replaceAll("-", "")}`;
|
|
49
|
-
const gates = [...options.gates];
|
|
50
|
-
const eventLog = new RunEventLog(root, runId);
|
|
51
|
-
const eventAt = new Date().toISOString();
|
|
52
|
-
// planned first; any later failure only ever emits blocked/unknown.
|
|
53
|
-
await eventLog.append({ type: "planned", at: eventAt });
|
|
54
|
-
await mkdir(paths.manifests, { recursive: true });
|
|
55
|
-
await mkdir(paths.outputs, { recursive: true });
|
|
56
|
-
const outputPaths = [];
|
|
57
|
-
const outputRecords = [];
|
|
58
|
-
const artifactVersion = workflow.version;
|
|
59
|
-
const formatOf = (path) => {
|
|
60
|
-
const lower = path.toLowerCase();
|
|
61
|
-
if (lower.endsWith(".json"))
|
|
62
|
-
return "json";
|
|
63
|
-
if (lower.endsWith(".md") || lower.endsWith(".markdown"))
|
|
64
|
-
return "markdown";
|
|
65
|
-
if (lower.endsWith(".txt"))
|
|
66
|
-
return "text";
|
|
67
|
-
return "unknown";
|
|
68
|
-
};
|
|
69
|
-
for (const output of options.outputs) {
|
|
70
|
-
const target = await safeOutputPath(paths.root, output.path);
|
|
71
|
-
await atomicWriteFile(target, output.contents);
|
|
72
|
-
outputPaths.push(target);
|
|
73
|
-
outputRecords.push({ path: output.path, sha256: sha256Text(output.contents), artifactVersion, format: formatOf(output.path), status: "draft-blocked" });
|
|
74
|
-
}
|
|
75
|
-
// The spec's required artifacts must actually be produced.
|
|
76
|
-
for (const required of workflow.requiredArtifacts) {
|
|
77
|
-
if (!outputRecords.some((record) => record.path === required)) {
|
|
78
|
-
gates.push({
|
|
79
|
-
gateId: "workflow:missing-artifact",
|
|
80
|
-
ok: false,
|
|
81
|
-
severity: "block",
|
|
82
|
-
reason: `required artifact not produced: ${required}`,
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
const blocked = gates.filter((gate) => !gate.ok);
|
|
87
|
-
for (const gate of gates)
|
|
88
|
-
await eventLog.append({ type: "gate", at: eventAt, message: gate.reason });
|
|
89
|
-
const verifiedRecords = outputRecords.map((record) => ({
|
|
90
|
-
...record,
|
|
91
|
-
status: blocked.length === 0 ? "verified" : "draft-blocked",
|
|
92
|
-
}));
|
|
93
|
-
const manifestPath = join(paths.manifests, `${runId}.json`);
|
|
94
|
-
const manifest = {
|
|
95
|
-
schemaVersion: "psyclaw/workflow-manifest/v1",
|
|
96
|
-
workflow: workflow.id,
|
|
97
|
-
workflowVersion: workflow.version,
|
|
98
|
-
runId,
|
|
99
|
-
inputDigest: sha256Text(`${project.goal}\u0000${project.paradigm}`),
|
|
100
|
-
outputs: verifiedRecords,
|
|
101
|
-
gates,
|
|
102
|
-
generatedAt: new Date().toISOString(),
|
|
103
|
-
};
|
|
104
|
-
await atomicWriteFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
105
|
-
const verdictPath = join(paths.manifests, `${runId}.verdict.json`);
|
|
106
|
-
const verdict = {
|
|
107
|
-
schemaVersion: "psyclaw/verdict/v1",
|
|
108
|
-
runId,
|
|
109
|
-
verdict: blocked.length === 0 ? "pass" : "blocked",
|
|
110
|
-
workflow: workflow.id,
|
|
111
|
-
manifestPath,
|
|
112
|
-
gateCount: gates.length,
|
|
113
|
-
blockedGateCount: blocked.length,
|
|
114
|
-
generatedAt: new Date().toISOString(),
|
|
115
|
-
};
|
|
116
|
-
await atomicWriteFile(verdictPath, `${JSON.stringify(verdict, null, 2)}\n`);
|
|
117
|
-
const outputIndexPath = await assertSafeProjectPath(root, "outputs/index.json");
|
|
118
|
-
await atomicWriteFile(outputIndexPath, `${JSON.stringify({
|
|
119
|
-
schemaVersion: "psyclaw/output-index/v1",
|
|
120
|
-
runId,
|
|
121
|
-
workflow: workflow.id,
|
|
122
|
-
workflowVersion: workflow.version,
|
|
123
|
-
artifacts: verifiedRecords,
|
|
124
|
-
generatedAt: new Date().toISOString(),
|
|
125
|
-
}, null, 2)}\n`);
|
|
126
|
-
const handoff = await writeHandoff(root, {
|
|
127
|
-
projectId: project.id,
|
|
128
|
-
runId,
|
|
129
|
-
goal: project.goal,
|
|
130
|
-
completed: options.completed,
|
|
131
|
-
verified: blocked.length === 0
|
|
132
|
-
? ["outputs", "output index", "manifest", "verdict"]
|
|
133
|
-
: ["manifest", "verdict"],
|
|
134
|
-
blocked: blocked.map((gate) => gate.reason),
|
|
135
|
-
nextSteps: blocked.length === 0 ? ["human review before external use"] : ["resolve blocked workflow gates"],
|
|
136
|
-
verificationCommands: ["pnpm typecheck", "pnpm test"],
|
|
137
|
-
generatedAt: new Date().toISOString(),
|
|
138
|
-
});
|
|
139
|
-
// completed/blocked is emitted last, only after every artifact is on disk.
|
|
140
|
-
await eventLog.append({
|
|
141
|
-
type: blocked.length === 0 ? "completed" : "blocked",
|
|
142
|
-
at: eventAt,
|
|
143
|
-
message: blocked.length === 0 ? `${workflow.id} completed` : `${workflow.id} blocked`,
|
|
144
|
-
});
|
|
145
|
-
return {
|
|
146
|
-
runId,
|
|
147
|
-
workflowId: workflow.id,
|
|
148
|
-
verdict: blocked.length === 0 ? "pass" : "blocked",
|
|
149
|
-
gates,
|
|
150
|
-
outputPaths,
|
|
151
|
-
manifestPath,
|
|
152
|
-
verdictPath,
|
|
153
|
-
outputIndexPath,
|
|
154
|
-
handoff,
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
//# sourceMappingURL=spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../../src/workflows/spec.ts"],"names":[],"mappings":"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"}
|