@fieldwangai/agentflow 0.1.93 → 0.1.95
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/bin/lib/ui-server.mjs
CHANGED
|
@@ -2713,15 +2713,42 @@ function displayShareOutputUrl(shareId, baseUrl = "") {
|
|
|
2713
2713
|
}
|
|
2714
2714
|
}
|
|
2715
2715
|
|
|
2716
|
+
function normalizePublicBaseUrl(baseUrl = "") {
|
|
2717
|
+
const raw = String(baseUrl || "").trim();
|
|
2718
|
+
if (!raw) return "";
|
|
2719
|
+
try {
|
|
2720
|
+
const url = new URL(raw);
|
|
2721
|
+
if (url.hostname === "0.0.0.0" || url.hostname === "::" || url.hostname === "[::]") {
|
|
2722
|
+
url.hostname = "127.0.0.1";
|
|
2723
|
+
}
|
|
2724
|
+
return url.origin;
|
|
2725
|
+
} catch {
|
|
2726
|
+
return "";
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
|
|
2716
2730
|
function requestPublicBaseUrl(req) {
|
|
2717
2731
|
const origin = String(req?.headers?.origin || "").trim();
|
|
2718
|
-
if (/^https?:\/\//i.test(origin)) return origin;
|
|
2732
|
+
if (/^https?:\/\//i.test(origin)) return normalizePublicBaseUrl(origin);
|
|
2719
2733
|
const forwardedHost = String(req?.headers?.["x-forwarded-host"] || "").split(",")[0].trim();
|
|
2720
2734
|
const host = forwardedHost || String(req?.headers?.host || "").trim();
|
|
2721
2735
|
if (!host) return "";
|
|
2722
2736
|
const forwardedProto = String(req?.headers?.["x-forwarded-proto"] || "").split(",")[0].trim();
|
|
2723
2737
|
const proto = /^https?$/i.test(forwardedProto) ? forwardedProto.toLowerCase() : "http";
|
|
2724
|
-
return `${proto}://${host}
|
|
2738
|
+
return normalizePublicBaseUrl(`${proto}://${host}`);
|
|
2739
|
+
}
|
|
2740
|
+
|
|
2741
|
+
function configuredPublicBaseUrl(payload = null) {
|
|
2742
|
+
const envBase = normalizePublicBaseUrl(process.env.AGENTFLOW_PUBLIC_BASE_URL || process.env.AGENTFLOW_SHARE_BASE_URL || "");
|
|
2743
|
+
if (envBase) return envBase;
|
|
2744
|
+
const payloadBase = payload && typeof payload === "object" && !Array.isArray(payload)
|
|
2745
|
+
? normalizePublicBaseUrl(payload.publicBaseUrl || payload.public_base_url || payload.reviewBaseUrl || payload.review_base_url || "")
|
|
2746
|
+
: "";
|
|
2747
|
+
return payloadBase;
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2750
|
+
function serverPublicBaseUrl(req, host, port, payload = null) {
|
|
2751
|
+
return configuredPublicBaseUrl(payload) || requestPublicBaseUrl(req) || normalizePublicBaseUrl(`http://${host}:${port}`);
|
|
2725
2752
|
}
|
|
2726
2753
|
|
|
2727
2754
|
function normalizeRunEnvKey(key) {
|
|
@@ -7046,6 +7073,11 @@ function prdWorkflowEventsPath(scopedRoot, tapdId) {
|
|
|
7046
7073
|
return path.join(rootDir, ".workspace", "prd-flow", "workflow-state", `${prdWorkflowSafeStateId(tapdId)}.events.json`);
|
|
7047
7074
|
}
|
|
7048
7075
|
|
|
7076
|
+
function prdWorkflowAuditPath(scopedRoot, tapdId) {
|
|
7077
|
+
const rootDir = scopedRoot || process.cwd();
|
|
7078
|
+
return path.join(rootDir, ".workspace", "prd-flow", "workflow-state", `${prdWorkflowSafeStateId(tapdId)}.audit.jsonl`);
|
|
7079
|
+
}
|
|
7080
|
+
|
|
7049
7081
|
function prdWorkflowReviewDir(scopedRoot, tapdId) {
|
|
7050
7082
|
const rootDir = path.resolve(scopedRoot || process.cwd());
|
|
7051
7083
|
return path.join(rootDir, ".workspace", "prd-flow", "reviews", prdWorkflowSafeStateId(tapdId));
|
|
@@ -7116,13 +7148,48 @@ function prdWorkflowReviewSplitFrontmatter(markdown) {
|
|
|
7116
7148
|
|
|
7117
7149
|
function prdWorkflowReviewRenderFrontmatter(frontmatter) {
|
|
7118
7150
|
if (!String(frontmatter || "").trim()) return "";
|
|
7119
|
-
const rows =
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
.
|
|
7151
|
+
const rows = [];
|
|
7152
|
+
const lines = String(frontmatter || "").split(/\r?\n/);
|
|
7153
|
+
let current = null;
|
|
7154
|
+
const flush = () => {
|
|
7155
|
+
if (!current) return;
|
|
7156
|
+
let valueHtml = "";
|
|
7157
|
+
if (current.items.length) {
|
|
7158
|
+
valueHtml = `<ul class="frontmatter-list">${current.items.map((item) => `<li>${prdWorkflowReviewInlineMarkdown(item)}</li>`).join("")}</ul>`;
|
|
7159
|
+
} else {
|
|
7160
|
+
valueHtml = prdWorkflowReviewInlineMarkdown(current.value);
|
|
7161
|
+
}
|
|
7162
|
+
rows.push(`<tr><th>${htmlEscapeAttribute(current.key)}</th><td>${valueHtml}</td></tr>`);
|
|
7163
|
+
current = null;
|
|
7164
|
+
};
|
|
7165
|
+
for (const rawLine of lines) {
|
|
7166
|
+
const line = String(rawLine || "");
|
|
7167
|
+
const keyValue = line.match(/^([^:\s][^:]*):\s*(.*)$/);
|
|
7168
|
+
if (keyValue) {
|
|
7169
|
+
flush();
|
|
7170
|
+
const key = keyValue[1].trim();
|
|
7171
|
+
const value = keyValue[2].trim();
|
|
7172
|
+
const inlineList = value.match(/^\[(.*)\]$/);
|
|
7173
|
+
current = {
|
|
7174
|
+
key,
|
|
7175
|
+
value: inlineList ? "" : value,
|
|
7176
|
+
items: inlineList
|
|
7177
|
+
? inlineList[1].split(",").map((item) => item.trim()).filter(Boolean)
|
|
7178
|
+
: [],
|
|
7179
|
+
};
|
|
7180
|
+
continue;
|
|
7181
|
+
}
|
|
7182
|
+
const listItem = line.match(/^\s*-\s+(.+)$/);
|
|
7183
|
+
if (listItem && current) {
|
|
7184
|
+
current.items.push(listItem[1].trim());
|
|
7185
|
+
continue;
|
|
7186
|
+
}
|
|
7187
|
+
if (line.trim()) {
|
|
7188
|
+
flush();
|
|
7189
|
+
rows.push(`<tr><td colspan="2">${prdWorkflowReviewInlineMarkdown(line.trim())}</td></tr>`);
|
|
7190
|
+
}
|
|
7191
|
+
}
|
|
7192
|
+
flush();
|
|
7126
7193
|
return `<details class="frontmatter" open><summary>文档元数据</summary><table>${rows}</table></details>`;
|
|
7127
7194
|
}
|
|
7128
7195
|
|
|
@@ -7233,6 +7300,13 @@ function prdWorkflowReviewHtml(title, markdown, meta = {}) {
|
|
|
7233
7300
|
meta.issueKey ? `issue ${meta.issueKey}` : "",
|
|
7234
7301
|
meta.createdAt || "",
|
|
7235
7302
|
].filter(Boolean).join(" · "));
|
|
7303
|
+
const durability = String(meta.durability || "").trim().toLowerCase();
|
|
7304
|
+
const lifecycle = [
|
|
7305
|
+
durability === "temporary" ? "Temporary review link" : durability === "durable" ? "Durable preview" : "",
|
|
7306
|
+
meta.expiresAt ? `Expires ${meta.expiresAt}` : "",
|
|
7307
|
+
meta.persistence ? `persistence ${meta.persistence}` : "",
|
|
7308
|
+
].filter(Boolean).join(" · ");
|
|
7309
|
+
const escapedLifecycle = htmlEscapeAttribute(lifecycle);
|
|
7236
7310
|
const renderedMarkdown = prdWorkflowReviewMarkdownToHtml(markdown || "");
|
|
7237
7311
|
const rawHref = htmlEscapeAttribute(meta.rawHref || "?raw=1");
|
|
7238
7312
|
return `<!doctype html>
|
|
@@ -7294,6 +7368,7 @@ function prdWorkflowReviewHtml(title, markdown, meta = {}) {
|
|
|
7294
7368
|
.toolbar { flex: 0 0 auto; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; }
|
|
7295
7369
|
.raw, .theme-toggle { border: 1px solid rgba(124,58,237,.34); border-radius: 999px; color: var(--button-text); background: var(--button); padding: 9px 14px; text-decoration: none; font-size: 13px; font-weight: 800; line-height: 1.2; }
|
|
7296
7370
|
.theme-toggle { cursor: pointer; font-family: inherit; }
|
|
7371
|
+
.lifecycle { margin-top: 10px; display: inline-flex; max-width: 100%; border: 1px solid rgba(124,58,237,.30); border-radius: 999px; background: rgba(124,58,237,.12); color: var(--button-text); padding: 6px 10px; font-size: 12px; font-weight: 800; line-height: 1.35; overflow-wrap: anywhere; }
|
|
7297
7372
|
article { min-width: 0; border: 1px solid var(--border); border-radius: 14px; background: var(--panel); box-shadow: 0 28px 80px var(--shadow); padding: clamp(20px, 4vw, 34px); }
|
|
7298
7373
|
article > *:first-child { margin-top: 0; }
|
|
7299
7374
|
article > *:last-child { margin-bottom: 0; }
|
|
@@ -7319,6 +7394,7 @@ function prdWorkflowReviewHtml(title, markdown, meta = {}) {
|
|
|
7319
7394
|
.frontmatter summary { cursor: pointer; color: var(--body); font-weight: 800; }
|
|
7320
7395
|
.frontmatter table { min-width: 0; margin-top: .7rem; }
|
|
7321
7396
|
.frontmatter th { width: min(34%, 12rem); background: var(--panel-soft); color: var(--body); }
|
|
7397
|
+
.frontmatter-list { margin: 0; padding-left: 1.1rem; }
|
|
7322
7398
|
@media (max-width: 720px) { main { padding: 28px 14px 48px; } header { display: block; } .toolbar { justify-content: flex-start; margin-top: 14px; } article { padding: 18px; } th, td { padding: .58rem .65rem; } }
|
|
7323
7399
|
</style>
|
|
7324
7400
|
</head>
|
|
@@ -7328,6 +7404,7 @@ function prdWorkflowReviewHtml(title, markdown, meta = {}) {
|
|
|
7328
7404
|
<div>
|
|
7329
7405
|
<h1>${escapedTitle}</h1>
|
|
7330
7406
|
${escapedMeta ? `<p class="meta">${escapedMeta}</p>` : ""}
|
|
7407
|
+
${escapedLifecycle ? `<p class="lifecycle">${escapedLifecycle}</p>` : ""}
|
|
7331
7408
|
</div>
|
|
7332
7409
|
<div class="toolbar">
|
|
7333
7410
|
<button class="theme-toggle" type="button" data-theme-toggle>明亮模式</button>
|
|
@@ -7396,6 +7473,19 @@ function prdWorkflowCreateReview(scopedRoot, tapdId, payload = {}, urlBase = "")
|
|
|
7396
7473
|
fs.writeFileSync(paths.markdownPath, content.trimEnd() + "\n", "utf-8");
|
|
7397
7474
|
fs.writeFileSync(paths.metaPath, JSON.stringify(meta, null, 2) + "\n", "utf-8");
|
|
7398
7475
|
prdWorkflowPruneReviews(scopedRoot, tapdId);
|
|
7476
|
+
prdWorkflowAppendAudit(scopedRoot, tapdId, {
|
|
7477
|
+
type: "review-created",
|
|
7478
|
+
reviewId: paths.id,
|
|
7479
|
+
title,
|
|
7480
|
+
stage: meta.stage,
|
|
7481
|
+
action: meta.action,
|
|
7482
|
+
issueKey: meta.issueKey,
|
|
7483
|
+
durability,
|
|
7484
|
+
persistence: "runtime",
|
|
7485
|
+
sourceKind: String(meta.source?.kind || ""),
|
|
7486
|
+
expiresAt,
|
|
7487
|
+
contentBytes: Buffer.byteLength(content, "utf-8"),
|
|
7488
|
+
});
|
|
7399
7489
|
const url = `${String(urlBase || "").replace(/\/+$/, "")}/api/prd-workflow/review/${encodeURIComponent(prdWorkflowSafeStateId(tapdId))}/${encodeURIComponent(paths.id)}`;
|
|
7400
7490
|
return { ...meta, url, markdownPath: paths.markdownPath };
|
|
7401
7491
|
}
|
|
@@ -7445,6 +7535,19 @@ function prdWorkflowWriteJsonFile(filePath, data) {
|
|
|
7445
7535
|
return data;
|
|
7446
7536
|
}
|
|
7447
7537
|
|
|
7538
|
+
function prdWorkflowAppendAudit(scopedRoot, tapdId, event = {}) {
|
|
7539
|
+
try {
|
|
7540
|
+
const p = prdWorkflowAuditPath(scopedRoot, tapdId);
|
|
7541
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
7542
|
+
const entry = {
|
|
7543
|
+
at: new Date().toISOString(),
|
|
7544
|
+
tapdId: String(tapdId || ""),
|
|
7545
|
+
...event,
|
|
7546
|
+
};
|
|
7547
|
+
fs.appendFileSync(p, JSON.stringify(entry) + "\n", "utf-8");
|
|
7548
|
+
} catch (_) {}
|
|
7549
|
+
}
|
|
7550
|
+
|
|
7448
7551
|
function prdWorkflowReadProjectState(scopedRoot, tapdId) {
|
|
7449
7552
|
return prdWorkflowReadJsonFile(prdWorkflowProjectPath(scopedRoot, tapdId), {
|
|
7450
7553
|
version: 1,
|
|
@@ -7685,12 +7788,25 @@ function prdWorkflowMergedClientIssues(clientRows = []) {
|
|
|
7685
7788
|
return out;
|
|
7686
7789
|
}
|
|
7687
7790
|
|
|
7791
|
+
function prdWorkflowArrayCount(value) {
|
|
7792
|
+
return Array.isArray(value) ? value.length : 0;
|
|
7793
|
+
}
|
|
7794
|
+
|
|
7795
|
+
function prdWorkflowSnapshotActionCount(snapshot = {}) {
|
|
7796
|
+
return prdWorkflowArrayCount(snapshot?.actions) +
|
|
7797
|
+
prdWorkflowArrayCount(snapshot?.workflowActions) +
|
|
7798
|
+
prdWorkflowArrayCount(snapshot?.workflow_actions) +
|
|
7799
|
+
prdWorkflowArrayCount(snapshot?.timeline) +
|
|
7800
|
+
prdWorkflowArrayCount(snapshot?.history);
|
|
7801
|
+
}
|
|
7802
|
+
|
|
7688
7803
|
function prdWorkflowMaterializeSnapshot(root, scopedRoot, tapdId, userCtx = {}, opts = {}) {
|
|
7689
7804
|
const flowSource = String(opts.flowSource || "user").trim() || "user";
|
|
7690
7805
|
const flowId = String(opts.flowId || "").trim();
|
|
7691
7806
|
const project = prdWorkflowReadProjectStateWithFallback(root, scopedRoot, tapdId);
|
|
7692
7807
|
const legacy = prdWorkflowReadCachedSnapshotWithFallback(root, scopedRoot, tapdId);
|
|
7693
7808
|
const latestClient = prdWorkflowLatestClientSnapshot(root, scopedRoot, tapdId);
|
|
7809
|
+
const baseSource = project?.snapshot ? "project" : latestClient ? "client-observations" : legacy?.snapshot ? "legacy-cache" : "empty";
|
|
7694
7810
|
const base = (
|
|
7695
7811
|
project?.snapshot ||
|
|
7696
7812
|
latestClient ||
|
|
@@ -7716,6 +7832,45 @@ function prdWorkflowMaterializeSnapshot(root, scopedRoot, tapdId, userCtx = {},
|
|
|
7716
7832
|
}));
|
|
7717
7833
|
const clientRows = prdWorkflowClientObservationRows(root, scopedRoot, tapdId);
|
|
7718
7834
|
const clientIssues = prdWorkflowMergedClientIssues(clientRows);
|
|
7835
|
+
const runtimeState = prdWorkflowReadRuntimeEvents(scopedRoot, tapdId);
|
|
7836
|
+
const projectionAudit = [
|
|
7837
|
+
{
|
|
7838
|
+
step: "select-base",
|
|
7839
|
+
source: baseSource,
|
|
7840
|
+
reason: project?.snapshot
|
|
7841
|
+
? "project materialized snapshot is available"
|
|
7842
|
+
: latestClient
|
|
7843
|
+
? "no project snapshot; latest client current observation is used as display base"
|
|
7844
|
+
: legacy?.snapshot
|
|
7845
|
+
? "no project/client snapshot; legacy projection cache is used"
|
|
7846
|
+
: "no stored workflow projection exists",
|
|
7847
|
+
projectSnapshot: Boolean(project?.snapshot),
|
|
7848
|
+
latestClientSnapshot: Boolean(latestClient),
|
|
7849
|
+
legacySnapshot: Boolean(legacy?.snapshot),
|
|
7850
|
+
clientObservationCount: clientRows.length,
|
|
7851
|
+
runtimeEventCount: runtimeState.events.length,
|
|
7852
|
+
baseActionCount: prdWorkflowSnapshotActionCount(base),
|
|
7853
|
+
latestClientRevision: String(latestClient?.revision || ""),
|
|
7854
|
+
projectRevision: String(project?.snapshot?.revision || ""),
|
|
7855
|
+
},
|
|
7856
|
+
{
|
|
7857
|
+
step: "merge-client-issues",
|
|
7858
|
+
source: "clients",
|
|
7859
|
+
applied: !project?.snapshot && clientIssues.length > 0,
|
|
7860
|
+
issueCount: clientIssues.length,
|
|
7861
|
+
reason: project?.snapshot
|
|
7862
|
+
? "project snapshot owns issue projection"
|
|
7863
|
+
: clientIssues.length
|
|
7864
|
+
? "merged issue views from client observations"
|
|
7865
|
+
: "no client issue projection available",
|
|
7866
|
+
},
|
|
7867
|
+
{
|
|
7868
|
+
step: "merge-runtime-events",
|
|
7869
|
+
source: "runtime-events",
|
|
7870
|
+
eventCount: runtimeState.events.length,
|
|
7871
|
+
reason: "runtime events are merged after base selection and must not replace durable facts",
|
|
7872
|
+
},
|
|
7873
|
+
];
|
|
7719
7874
|
const materialized = prdWorkflowMergeRuntimeEvents(scopedRoot, tapdId, {
|
|
7720
7875
|
...base,
|
|
7721
7876
|
issues: project?.snapshot ? base.issues : clientIssues.length ? clientIssues : base.issues,
|
|
@@ -7731,6 +7886,32 @@ function prdWorkflowMaterializeSnapshot(root, scopedRoot, tapdId, userCtx = {},
|
|
|
7731
7886
|
clientsUpdatedAt: prdWorkflowReadClientStateWithFallback(root, scopedRoot, tapdId).updatedAt || "",
|
|
7732
7887
|
checkedAt: new Date().toISOString(),
|
|
7733
7888
|
},
|
|
7889
|
+
projectionAudit,
|
|
7890
|
+
});
|
|
7891
|
+
materialized.projectionAudit = [
|
|
7892
|
+
...projectionAudit,
|
|
7893
|
+
{
|
|
7894
|
+
step: "result",
|
|
7895
|
+
source: "materialized",
|
|
7896
|
+
phase: String(materialized.phase || ""),
|
|
7897
|
+
pointer: String(materialized.pointer || ""),
|
|
7898
|
+
actionCount: prdWorkflowSnapshotActionCount(materialized) + prdWorkflowArrayCount(materialized.runtimeEvents) + prdWorkflowArrayCount(materialized.runtime_events),
|
|
7899
|
+
revision: String(materialized.revision || ""),
|
|
7900
|
+
},
|
|
7901
|
+
];
|
|
7902
|
+
prdWorkflowAppendAudit(scopedRoot, tapdId, {
|
|
7903
|
+
type: "projection-materialized",
|
|
7904
|
+
flowSource,
|
|
7905
|
+
flowId,
|
|
7906
|
+
baseSource,
|
|
7907
|
+
projectSnapshot: Boolean(project?.snapshot),
|
|
7908
|
+
latestClientSnapshot: Boolean(latestClient),
|
|
7909
|
+
legacySnapshot: Boolean(legacy?.snapshot),
|
|
7910
|
+
clientObservationCount: clientRows.length,
|
|
7911
|
+
runtimeEventCount: runtimeState.events.length,
|
|
7912
|
+
baseActionCount: prdWorkflowSnapshotActionCount(base),
|
|
7913
|
+
resultActionCount: prdWorkflowSnapshotActionCount(materialized) + prdWorkflowArrayCount(materialized.runtimeEvents) + prdWorkflowArrayCount(materialized.runtime_events),
|
|
7914
|
+
revision: String(materialized.revision || ""),
|
|
7734
7915
|
});
|
|
7735
7916
|
if (!project?.snapshot && latestClient) {
|
|
7736
7917
|
materialized.optionalGaps = [
|
|
@@ -7992,13 +8173,15 @@ function prdWorkflowAppendRuntimeEvent(scopedRoot, tapdId, event = {}) {
|
|
|
7992
8173
|
if (String(item?.idempotencyKey || "").trim() === entryIdem) return true;
|
|
7993
8174
|
return Array.isArray(item?.idempotencyHistory) && item.idempotencyHistory.includes(entryIdem);
|
|
7994
8175
|
});
|
|
8176
|
+
const updatedExisting = index >= 0;
|
|
8177
|
+
let artifactConflict = false;
|
|
7995
8178
|
const events = [...current.events];
|
|
7996
8179
|
if (index >= 0) {
|
|
7997
8180
|
const prevArtifact = prdWorkflowRuntimeEventArtifactSignature(events[index]);
|
|
7998
8181
|
const nextArtifact = prdWorkflowRuntimeEventArtifactSignature(entry);
|
|
7999
|
-
|
|
8182
|
+
artifactConflict = Boolean(prevArtifact && nextArtifact && prevArtifact !== nextArtifact &&
|
|
8000
8183
|
prdWorkflowRuntimeEventShouldConflictOnArtifact(events[index]) &&
|
|
8001
|
-
prdWorkflowRuntimeEventShouldConflictOnArtifact(entry);
|
|
8184
|
+
prdWorkflowRuntimeEventShouldConflictOnArtifact(entry));
|
|
8002
8185
|
const idempotencyHistory = [
|
|
8003
8186
|
...(events[index].idempotencyKey ? [events[index].idempotencyKey] : []),
|
|
8004
8187
|
...(entry.idempotencyKey ? [entry.idempotencyKey] : []),
|
|
@@ -8033,6 +8216,26 @@ function prdWorkflowAppendRuntimeEvent(scopedRoot, tapdId, event = {}) {
|
|
|
8033
8216
|
events.push(entry);
|
|
8034
8217
|
}
|
|
8035
8218
|
prdWorkflowWriteRuntimeEvents(scopedRoot, tapdId, events);
|
|
8219
|
+
prdWorkflowAppendAudit(scopedRoot, tapdId, {
|
|
8220
|
+
type: "runtime-event-stored",
|
|
8221
|
+
eventId: entry.id,
|
|
8222
|
+
eventType: entry.type,
|
|
8223
|
+
source: entry.source,
|
|
8224
|
+
scope: entry.scope || "",
|
|
8225
|
+
issueKey: entry.issueKey || entry.issue_key || entry.issue || "",
|
|
8226
|
+
platform: entry.platform || "",
|
|
8227
|
+
stage: entry.stage || entry.stageKey || entry.stage_key || "",
|
|
8228
|
+
action: entry.action || entry.actionId || entry.action_id || "",
|
|
8229
|
+
status: entry.status || "",
|
|
8230
|
+
truth: entry.truth || "",
|
|
8231
|
+
authority: entry.authority || "",
|
|
8232
|
+
persistence: entry.persistence || "",
|
|
8233
|
+
idempotencyKey: entry.idempotencyKey || "",
|
|
8234
|
+
updatedExisting,
|
|
8235
|
+
artifactConflict,
|
|
8236
|
+
eventCount: events.length,
|
|
8237
|
+
note: "runtime event stored as append-only workflow event; projection may merge it into the visible timeline",
|
|
8238
|
+
});
|
|
8036
8239
|
return entry;
|
|
8037
8240
|
} catch {
|
|
8038
8241
|
return null;
|
|
@@ -9488,6 +9691,23 @@ export function startUiServer({
|
|
|
9488
9691
|
};
|
|
9489
9692
|
const storedObservationSnapshot = prdWorkflowStoredObservationSnapshot(normalizedSnapshot, reportSource);
|
|
9490
9693
|
prdWorkflowWriteClientObservation(scopedRoot, tapdId, reportMeta, storedObservationSnapshot);
|
|
9694
|
+
prdWorkflowAppendAudit(scopedRoot, tapdId, {
|
|
9695
|
+
type: "client-observation-stored",
|
|
9696
|
+
flowSource,
|
|
9697
|
+
flowId,
|
|
9698
|
+
clientId: reportMeta.clientId,
|
|
9699
|
+
userId: reportMeta.userId,
|
|
9700
|
+
observedAt: reportMeta.observedAt,
|
|
9701
|
+
reportedAt: reportMeta.reportedAt,
|
|
9702
|
+
phase: String(storedObservationSnapshot?.phase || ""),
|
|
9703
|
+
pointer: String(storedObservationSnapshot?.pointer || ""),
|
|
9704
|
+
revision: String(storedObservationSnapshot?.revision || ""),
|
|
9705
|
+
actionCount: prdWorkflowSnapshotActionCount(storedObservationSnapshot),
|
|
9706
|
+
truth: "observation",
|
|
9707
|
+
authority: "client",
|
|
9708
|
+
persistence: "runtime",
|
|
9709
|
+
note: "ordinary current snapshot stored as client observation; it must not overwrite project state",
|
|
9710
|
+
});
|
|
9491
9711
|
|
|
9492
9712
|
const projectFactSource = reportMeta.scope === "project"
|
|
9493
9713
|
? prdWorkflowProjectFactSource(payload, rawSnapshot)
|
|
@@ -9546,6 +9766,20 @@ export function startUiServer({
|
|
|
9546
9766
|
observedAt: reportMeta.observedAt,
|
|
9547
9767
|
},
|
|
9548
9768
|
});
|
|
9769
|
+
prdWorkflowAppendAudit(scopedRoot, tapdId, {
|
|
9770
|
+
type: "project-fact-stored",
|
|
9771
|
+
flowSource,
|
|
9772
|
+
flowId,
|
|
9773
|
+
clientId: reportMeta.clientId,
|
|
9774
|
+
observedAt: reportMeta.observedAt,
|
|
9775
|
+
phase: String(projectFactSnapshot?.phase || ""),
|
|
9776
|
+
pointer: String(projectFactSnapshot?.pointer || ""),
|
|
9777
|
+
revision: String(projectFactSnapshot?.revision || ""),
|
|
9778
|
+
actionCount: prdWorkflowSnapshotActionCount(projectFactSnapshot),
|
|
9779
|
+
truth: projectFactSource.truth,
|
|
9780
|
+
authority: projectFactSource.authority,
|
|
9781
|
+
persistence: projectFactSource.persistence,
|
|
9782
|
+
});
|
|
9549
9783
|
}
|
|
9550
9784
|
const materialized = prdWorkflowMaterializeSnapshot(root, scopedRoot, tapdId, userCtx, { flowSource, flowId });
|
|
9551
9785
|
const withDiagnostic = prdWorkflowWithAgentflowTokenDiagnostic(materialized, getSessionTokenFromRequest(req) || "");
|
|
@@ -9814,7 +10048,7 @@ export function startUiServer({
|
|
|
9814
10048
|
json(res, 200, result);
|
|
9815
10049
|
return;
|
|
9816
10050
|
}
|
|
9817
|
-
const runtimeEventUrl =
|
|
10051
|
+
const runtimeEventUrl = `${serverPublicBaseUrl(req, host, uiPort)}/api/prd-workflow/event`;
|
|
9818
10052
|
const commandResult = await runPrdWorkflowCommand(root, scopedRoot, normalized.args, userCtx, {
|
|
9819
10053
|
timeout: 300000,
|
|
9820
10054
|
env: {
|
|
@@ -10105,7 +10339,7 @@ export function startUiServer({
|
|
|
10105
10339
|
}
|
|
10106
10340
|
scopedRoot = scoped.root;
|
|
10107
10341
|
}
|
|
10108
|
-
const review = prdWorkflowCreateReview(scopedRoot, tapdId, payload,
|
|
10342
|
+
const review = prdWorkflowCreateReview(scopedRoot, tapdId, payload, serverPublicBaseUrl(req, host, uiPort, payload));
|
|
10109
10343
|
const query = new URLSearchParams();
|
|
10110
10344
|
if (flowId) query.set("flowId", flowId);
|
|
10111
10345
|
if (flowSource) query.set("flowSource", flowSource);
|