@hassangameryt/freeflow 0.7.3 → 0.8.0
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/NOTICE +14 -0
- package/README.md +26 -31
- package/capabilities/cognitive-routing/SKILL.md +106 -161
- package/capabilities/cognitive-routing/references/both-mode.md +36 -0
- package/capabilities/cognitive-routing/references/executor-mode.md +48 -0
- package/capabilities/cognitive-routing/references/helper-mode.md +47 -0
- package/capabilities/compaction/SKILL.md +49 -0
- package/capabilities/compaction/references/summary-format.md +239 -0
- package/command-surface.json +4 -0
- package/gemini-extension.json +1 -1
- package/hooks/shared/runtime-context.mjs +28 -30
- package/licenses/Apache-2.0.txt +55 -0
- package/package.json +22 -9
- package/pi-extension/README.md +41 -0
- package/pi-extension/dist/cognitive-routing/assembler.js +393 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/config.js +5 -2
- package/pi-extension/dist/cognitive-routing/economics.js +45 -0
- package/pi-extension/dist/cognitive-routing/event-schema.js +388 -0
- package/pi-extension/dist/{session-sources/events.js → cognitive-routing/event-store.js} +103 -40
- package/pi-extension/dist/cognitive-routing/gate.js +241 -0
- package/pi-extension/dist/cognitive-routing/handlers.js +899 -0
- package/pi-extension/dist/cognitive-routing/handoffs.js +350 -0
- package/pi-extension/dist/cognitive-routing/model-control.js +467 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/projection.js +229 -56
- package/pi-extension/dist/cognitive-routing/provenance.js +81 -0
- package/pi-extension/dist/cognitive-routing/runtime.js +396 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/schemas.js +43 -7
- package/pi-extension/dist/cognitive-routing/session.js +221 -0
- package/pi-extension/dist/{session-sources → cognitive-routing}/sources.js +99 -85
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/state.js +37 -378
- package/pi-extension/dist/cognitive-routing/status.js +80 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/tools.js +12 -12
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/types.js +5 -11
- package/pi-extension/dist/compaction/carry.js +191 -0
- package/pi-extension/dist/compaction/config.js +22 -0
- package/pi-extension/dist/compaction/controller.js +471 -0
- package/pi-extension/dist/compaction/harness.js +77 -0
- package/pi-extension/dist/compaction/results.js +158 -0
- package/pi-extension/dist/compaction/thresholds.js +35 -0
- package/pi-extension/dist/compaction/tool.js +57 -0
- package/pi-extension/dist/host/branch.js +13 -0
- package/pi-extension/dist/host/canonical.js +12 -0
- package/pi-extension/dist/host/catalog.js +77 -0
- package/pi-extension/dist/host/config.js +374 -0
- package/pi-extension/dist/host/projection-tags.js +60 -0
- package/pi-extension/dist/host/prompts.js +82 -0
- package/pi-extension/dist/{session-sources → host}/read-only-session.js +112 -1
- package/pi-extension/dist/{runtime → host}/request-history.js +121 -39
- package/pi-extension/dist/host/runtime-state.js +189 -0
- package/pi-extension/dist/{settings/settings-ui.js → host/settings/freeflow-command.js} +620 -410
- package/pi-extension/dist/{settings/settings-tui.js → host/settings/settings-view.js} +186 -73
- package/pi-extension/dist/host/staging.js +28 -0
- package/pi-extension/dist/host/status.js +101 -0
- package/pi-extension/dist/index.js +423 -173
- package/pi-extension/dist/provider-support/cache/anchor.js +21 -0
- package/pi-extension/dist/provider-support/cache/anthropic.js +102 -0
- package/pi-extension/dist/provider-support/cache/health.js +73 -0
- package/pi-extension/dist/provider-support/cache/index.js +58 -0
- package/pi-extension/dist/provider-support/cache/keepalive.js +210 -0
- package/pi-extension/dist/provider-support/cache/monitor.js +17 -0
- package/pi-extension/dist/provider-support/cache/openai-responses.js +48 -0
- package/pi-extension/dist/provider-support/effort.js +13 -0
- package/pi-extension/dist/provider-support/index.js +44 -3
- package/pi-extension/dist/provider-support/{astra → openai}/adapter.js +46 -29
- package/pi-extension/dist/provider-support/{astra → openai}/history.js +10 -8
- package/pi-extension/dist/provider-support/{astra → openai}/index.js +8 -4
- package/pi-extension/dist/provider-support/{astra → openai}/session-state.js +29 -38
- package/pi-extension/dist/provider-support/routes.js +17 -0
- package/pi-extension/dist/tool-execution/apply-patch/grammar.js +23 -0
- package/pi-extension/dist/tool-execution/apply-patch/match.js +38 -0
- package/pi-extension/dist/tool-execution/apply-patch/parser.js +177 -0
- package/pi-extension/dist/tool-execution/apply-patch/plan.js +201 -0
- package/pi-extension/dist/tool-execution/apply-patch/tool.js +84 -0
- package/pi-extension/dist/tool-execution/background.js +238 -0
- package/pi-extension/dist/tool-execution/bash-guard.js +23 -0
- package/pi-extension/dist/tool-execution/config.js +22 -0
- package/pi-extension/dist/tool-execution/edit-messages.js +120 -0
- package/pi-extension/dist/tool-execution/file-state.js +138 -0
- package/pi-extension/dist/tool-execution/file-tracking.js +143 -0
- package/pi-extension/dist/tool-execution/prompt.js +54 -0
- package/pi-extension/dist/tool-execution/tools.js +16 -0
- package/pi-extension/freeflow/README.md +9 -0
- package/plugin.json +1 -1
- package/runtime/prompts/cognitive-routing.md +4 -4
- package/runtime/prompts/core.md +22 -75
- package/runtime/prompts/interaction-contract.md +15 -8
- package/runtime/prompts/tool-execution.md +38 -0
- package/runtime/prompts/working-method.md +108 -0
- package/skills/action-selection/SKILL.md +39 -47
- package/skills/action-selection/references/trajectory-stalls.md +2 -0
- package/skills/bypass/SKILL.md +2 -2
- package/skills/commit-work/SKILL.md +31 -83
- package/skills/commit-work/references/git-state-edges.md +1 -1
- package/skills/commit-work/references/simple-push.md +2 -0
- package/skills/commit-work/references/staging-decisions.md +1 -1
- package/skills/decision-gate/SKILL.md +31 -50
- package/skills/design-for-depth/SKILL.md +44 -53
- package/skills/design-for-depth/references/design-pressure-signals.md +46 -144
- package/skills/design-for-depth/references/implementation-decisions.md +1 -1
- package/skills/design-for-depth/references/interface-design-loop.md +5 -36
- package/skills/design-for-depth/references/module-and-dependency-design.md +2 -32
- package/skills/design-for-depth/references/state-and-failure-boundaries.md +2 -13
- package/skills/diagnose-failure/SKILL.md +39 -24
- package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +2 -0
- package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +2 -2
- package/skills/discuss/SKILL.md +35 -11
- package/skills/discuss/references/discussion-continuity.md +7 -27
- package/skills/evaluate-skill/SKILL.md +49 -80
- package/skills/evaluate-skill/references/evaluation-definition-schema.md +35 -5
- package/skills/evaluate-skill/references/evaluation-design.md +14 -14
- package/skills/evaluate-skill/references/execution-and-evidence.md +26 -5
- package/skills/evaluate-skill/references/review-and-revision.md +3 -1
- package/skills/evaluate-skill/scripts/lib/definitions.mjs +49 -8
- package/skills/evaluate-skill/scripts/lib/pi.mjs +14 -7
- package/skills/evaluate-skill/scripts/lib/review.mjs +196 -0
- package/skills/evaluate-skill/scripts/lib/runner.mjs +45 -8
- package/skills/evaluate-skill/scripts/lib/sandbox.mjs +2 -0
- package/skills/evaluate-skill/scripts/lib/trials.mjs +103 -0
- package/skills/evaluate-skill/scripts/lib/view.mjs +67 -1
- package/skills/evaluate-skill/scripts/pi-command-tool.mjs +144 -0
- package/skills/evaluate-skill/scripts/pi-guard.mjs +30 -13
- package/skills/evaluate-skill/scripts/skill-eval.mjs +114 -34
- package/skills/execute-work/SKILL.md +41 -9
- package/skills/execute-work/references/code-practices.md +2 -0
- package/skills/execute-work/references/execute-work-edges.md +11 -1
- package/skills/handoff/SKILL.md +1 -1
- package/skills/handoff/references/handoff-templates.md +1 -1
- package/skills/review-artifact/SKILL.md +42 -41
- package/skills/review-artifact/references/adjudicate-artifact-review.md +1 -1
- package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +1 -1
- package/skills/review-work/SKILL.md +38 -32
- package/skills/review-work/references/adjudicate-work-review.md +1 -1
- package/skills/review-work/references/independent-work-reviewer-contract.md +1 -1
- package/skills/review-work/references/security-risk-lens.md +2 -4
- package/skills/setup-freeflow/SKILL.md +3 -1
- package/skills/setup-freeflow/references/activation-contract.md +7 -13
- package/skills/setup-freeflow/references/host-setup.md +3 -3
- package/skills/track-work/SKILL.md +113 -161
- package/skills/track-work/references/working-record-format.md +189 -350
- package/skills/track-work/scripts/lib/document.mjs +62 -6
- package/skills/track-work/scripts/lib/format.mjs +16 -1
- package/skills/track-work/scripts/lib/store.mjs +9 -8
- package/skills/track-work/scripts/lib/transitions.mjs +79 -4
- package/skills/track-work/scripts/working-record.mjs +34 -12
- package/skills/verify-work/SKILL.md +29 -20
- package/skills/verify-work/references/browser-runtime-evidence.md +1 -5
- package/skills/verify-work/references/integration-evidence.md +2 -0
- package/skills/verify-work/references/performance-evidence.md +3 -1
- package/skills/verify-work/references/test-design.md +3 -1
- package/skills/workflow/SKILL.md +65 -21
- package/skills/workflow/references/domain-skill-composition.md +5 -3
- package/skills/write-docs/SKILL.md +83 -0
- package/skills/write-docs/references/documentation-shapes.md +119 -0
- package/skills/write-docs/scripts/docs-check.mjs +139 -0
- package/skills/write-plan/SKILL.md +40 -40
- package/skills/write-plan/references/plan-shapes.md +1 -1
- package/skills/write-skill/SKILL.md +107 -147
- package/skills/write-skill/references/activation-boundaries.md +2 -0
- package/skills/write-skill/references/agent-first-instructions.md +22 -10
- package/skills/write-skill/references/progressive-disclosure.md +4 -2
- package/skills/write-skill/references/skill-dependency-graphs.md +2 -0
- package/skills/write-skill/scripts/lib/similarity.mjs +56 -0
- package/skills/write-skill/scripts/skill-author.mjs +18 -2
- package/skills/write-spec/SKILL.md +34 -41
- package/skills/write-spec/references/artifact-standards.md +1 -1
- package/skills/write-spec/references/decision-records.md +2 -0
- package/skills/write-spec/references/spec-shapes.md +1 -1
- package/capabilities/context-virtualization/SKILL.md +0 -103
- package/capabilities/conversation-history/SKILL.md +0 -53
- package/hooks/tests/check-host-adapters.test.mjs +0 -82
- package/hooks/tests/check-runtime-context-hook.sh +0 -212
- package/pi-extension/dist/cognitive-routing-v2/runtime.js +0 -2181
- package/pi-extension/dist/context-virtualization/commands.js +0 -89
- package/pi-extension/dist/context-virtualization/projector.js +0 -42
- package/pi-extension/dist/context-virtualization/runtime.js +0 -378
- package/pi-extension/dist/context-virtualization/state.js +0 -57
- package/pi-extension/dist/context-virtualization/types.js +0 -10
- package/pi-extension/dist/conversation-history/passages.js +0 -66
- package/pi-extension/dist/conversation-history/ranking.js +0 -105
- package/pi-extension/dist/conversation-history/runtime.js +0 -226
- package/pi-extension/dist/conversation-history/search.js +0 -56
- package/pi-extension/dist/conversation-history/types.js +0 -1
- package/pi-extension/dist/freeflow-context/resolver.js +0 -120
- package/pi-extension/dist/freeflow-context/runtime.js +0 -80
- package/pi-extension/dist/freeflow-context/source-projector.js +0 -95
- package/pi-extension/dist/freeflow-context/tool.js +0 -314
- package/pi-extension/dist/freeflow-context/types.js +0 -12
- package/pi-extension/dist/freeflow-context/visibility.js +0 -28
- package/pi-extension/dist/integrations/mcp-config.js +0 -29
- package/pi-extension/dist/runtime/runtime-context.js +0 -754
- package/pi-extension/dist/runtime/runtime-identity.js +0 -5
- package/pi-extension/dist/session-sources/provenance.js +0 -32
- package/pi-extension/dist/ui/text-component.js +0 -57
- package/pi-extension/src/cognitive-routing-v2/budget.ts +0 -42
- package/pi-extension/src/cognitive-routing-v2/config.ts +0 -173
- package/pi-extension/src/cognitive-routing-v2/projection.ts +0 -375
- package/pi-extension/src/cognitive-routing-v2/render.ts +0 -277
- package/pi-extension/src/cognitive-routing-v2/runtime.ts +0 -2241
- package/pi-extension/src/cognitive-routing-v2/schemas.ts +0 -180
- package/pi-extension/src/cognitive-routing-v2/state.ts +0 -839
- package/pi-extension/src/cognitive-routing-v2/tools.ts +0 -62
- package/pi-extension/src/cognitive-routing-v2/types.ts +0 -254
- package/pi-extension/src/context-virtualization/commands.ts +0 -111
- package/pi-extension/src/context-virtualization/projector.ts +0 -62
- package/pi-extension/src/context-virtualization/runtime.ts +0 -428
- package/pi-extension/src/context-virtualization/state.ts +0 -79
- package/pi-extension/src/context-virtualization/types.ts +0 -92
- package/pi-extension/src/conversation-history/passages.ts +0 -81
- package/pi-extension/src/conversation-history/ranking.ts +0 -155
- package/pi-extension/src/conversation-history/runtime.ts +0 -250
- package/pi-extension/src/conversation-history/search.ts +0 -79
- package/pi-extension/src/conversation-history/types.ts +0 -31
- package/pi-extension/src/freeflow-context/resolver.ts +0 -139
- package/pi-extension/src/freeflow-context/runtime.ts +0 -100
- package/pi-extension/src/freeflow-context/source-projector.ts +0 -106
- package/pi-extension/src/freeflow-context/tool.ts +0 -366
- package/pi-extension/src/freeflow-context/types.ts +0 -70
- package/pi-extension/src/freeflow-context/visibility.ts +0 -53
- package/pi-extension/src/index.ts +0 -390
- package/pi-extension/src/integrations/mcp-config.ts +0 -32
- package/pi-extension/src/provider-support/astra/adapter.ts +0 -108
- package/pi-extension/src/provider-support/astra/history.ts +0 -145
- package/pi-extension/src/provider-support/astra/index.ts +0 -12
- package/pi-extension/src/provider-support/astra/session-state.ts +0 -113
- package/pi-extension/src/provider-support/index.ts +0 -5
- package/pi-extension/src/runtime/request-history.ts +0 -243
- package/pi-extension/src/runtime/runtime-context.ts +0 -860
- package/pi-extension/src/runtime/runtime-identity.ts +0 -8
- package/pi-extension/src/session-sources/events.ts +0 -230
- package/pi-extension/src/session-sources/provenance.ts +0 -39
- package/pi-extension/src/session-sources/read-only-session.ts +0 -170
- package/pi-extension/src/session-sources/sources.ts +0 -334
- package/pi-extension/src/settings/settings-tui.ts +0 -501
- package/pi-extension/src/settings/settings-ui.ts +0 -1652
- package/pi-extension/src/ui/text-component.ts +0 -66
- package/pi-extension/tests/cache-reuse/history.test.js +0 -117
- package/pi-extension/tests/cache-reuse/native.test.js +0 -91
- package/pi-extension/tests/cache-reuse/settings.test.js +0 -211
- package/pi-extension/tests/cognitive-routing-v2/communication.test.js +0 -577
- package/pi-extension/tests/cognitive-routing-v2/compaction-input.test.js +0 -183
- package/pi-extension/tests/cognitive-routing-v2/delegation.test.js +0 -557
- package/pi-extension/tests/cognitive-routing-v2/native.test.js +0 -474
- package/pi-extension/tests/cognitive-routing-v2/performance.test.js +0 -87
- package/pi-extension/tests/cognitive-routing-v2/persistence.test.js +0 -300
- package/pi-extension/tests/cognitive-routing-v2/projection.test.js +0 -241
- package/pi-extension/tests/cognitive-routing-v2/recovery.test.js +0 -1034
- package/pi-extension/tests/cognitive-routing-v2/render.test.js +0 -244
- package/pi-extension/tests/cognitive-routing-v2/runtime.test.js +0 -423
- package/pi-extension/tests/cognitive-routing-v2/stabilization.test.js +0 -521
- package/pi-extension/tests/cognitive-routing-v2/state.test.js +0 -586
- package/pi-extension/tests/context-virtualization/extension.test.js +0 -775
- package/pi-extension/tests/context-virtualization/projector.test.js +0 -110
- package/pi-extension/tests/context-virtualization/runtime.test.js +0 -230
- package/pi-extension/tests/conversation-history/runtime.test.js +0 -98
- package/pi-extension/tests/conversation-history/search.test.js +0 -97
- package/pi-extension/tests/fixtures/pi-host.js +0 -4
- package/pi-extension/tests/fixtures/routing-native.js +0 -191
- package/pi-extension/tests/integration/mode-free-core.test.js +0 -220
- package/pi-extension/tests/integration/pi-extension.test.js +0 -1447
- package/pi-extension/tests/integration/prompt-architecture.test.js +0 -447
- package/pi-extension/tests/integration/unaffected-regressions.test.js +0 -478
- package/pi-extension/tests/provider-support/astra-boundaries.test.js +0 -75
- package/pi-extension/tests/provider-support/astra.test.js +0 -306
- package/pi-extension/tests/provider-support/cli.test.js +0 -92
- package/pi-extension/tests/provider-support/native.test.js +0 -183
- package/pi-extension/tests/settings/settings-tui.test.js +0 -243
- package/pi-extension/tsconfig.json +0 -16
- package/runtime/prompts/context-virtualization.md +0 -3
- package/runtime/prompts/conversation-history.md +0 -3
- package/skills/design-for-depth/references/software-design-philosophy.md +0 -202
- /package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/budget.js +0 -0
- /package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/render.js +0 -0
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { sessionEntryToContextMessages } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import { canonical, idFor, isWorkerProfile, refFor } from "
|
|
3
|
+
import { canonical, idFor, isWorkerProfile, refFor } from "./types.js";
|
|
4
|
+
import { isHostEdited, isProjected, projectedEntryId } from "../host/projection-tags.js";
|
|
4
5
|
export const bodyHash = (value) => createHash("sha256").update(canonical(value)).digest("hex");
|
|
5
|
-
|
|
6
|
+
/** Define a memoized hash so history is hashed only when a consumer needs it. */
|
|
7
|
+
function lazyHash(target, compute) {
|
|
8
|
+
let value;
|
|
9
|
+
return Object.defineProperty(target, "hash", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: () => (value ??= compute()),
|
|
12
|
+
});
|
|
13
|
+
}
|
|
6
14
|
const routingTools = new Set(["freeflow_delegate", "freeflow_return", "freeflow_project", "freeflow_unit"]);
|
|
7
|
-
// Discovery
|
|
8
|
-
//
|
|
15
|
+
// Discovery, new selections, and delivery share this policy: evidence is what tools produced. What a worker
|
|
16
|
+
// says belongs in its report, so its assistant messages are never evidence.
|
|
9
17
|
export function isTaskEvidence(source) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
source.message.content?.some((b) => b.type === "text" && b.text?.trim())
|
|
16
|
-
);
|
|
18
|
+
return source.message.role === "toolResult" && !routingTools.has(source.message.toolName);
|
|
19
|
+
}
|
|
20
|
+
/** Saved selections keep their delivery, except assistant messages (whole or `#text`), which are never evidence. */
|
|
21
|
+
export function deliveredSelection(sources, ref) {
|
|
22
|
+
return !ref.endsWith("#text") && sources.byRef.get(ref)?.message.role !== "assistant";
|
|
17
23
|
}
|
|
18
24
|
const callKey = (id, name) => JSON.stringify([id, name]);
|
|
19
25
|
const locatorLimit = 160;
|
|
@@ -39,11 +45,15 @@ export class Sources {
|
|
|
39
45
|
byRef = new Map();
|
|
40
46
|
ambiguous = new Set();
|
|
41
47
|
byBody = new Map();
|
|
48
|
+
// Sources not yet placed in byBody; the content index is only needed for unprojected association.
|
|
49
|
+
unindexed = [];
|
|
42
50
|
exchanges = new Map();
|
|
43
51
|
owners = new Map();
|
|
44
52
|
tail;
|
|
45
53
|
associated;
|
|
46
54
|
entries = [];
|
|
55
|
+
ranks;
|
|
56
|
+
nonWorker;
|
|
47
57
|
activeIds;
|
|
48
58
|
locatorProvider;
|
|
49
59
|
constructor(entries, state, activeIds, locatorProvider) {
|
|
@@ -54,9 +64,12 @@ export class Sources {
|
|
|
54
64
|
const prefix = this.entries.length <= entries.length && this.entries.every((e, i) => e === entries[i]);
|
|
55
65
|
const start = prefix ? this.entries.length : 0;
|
|
56
66
|
this.associated = undefined;
|
|
67
|
+
this.ranks = undefined;
|
|
68
|
+
this.nonWorker = undefined;
|
|
57
69
|
if (!prefix) {
|
|
58
70
|
this.byRef.clear();
|
|
59
71
|
this.byBody.clear();
|
|
72
|
+
this.unindexed = [];
|
|
60
73
|
this.exchanges.clear();
|
|
61
74
|
this.owners.clear();
|
|
62
75
|
this.tail = undefined;
|
|
@@ -67,22 +80,20 @@ export class Sources {
|
|
|
67
80
|
if (messages.length !== 1 || ["compaction", "branch_summary"].includes(entry.type)) continue;
|
|
68
81
|
const message = messages[0];
|
|
69
82
|
if (!message) continue;
|
|
70
|
-
const source = {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
message,
|
|
74
|
-
hash: bodyHash(message),
|
|
75
|
-
producer: "common",
|
|
76
|
-
active: false,
|
|
77
|
-
};
|
|
83
|
+
const source = lazyHash({ ref: refFor(entry.id), entry, message, producer: "common", active: false }, () =>
|
|
84
|
+
bodyHash(message),
|
|
85
|
+
);
|
|
78
86
|
if (message.role === "toolResult" && message.toolName === "freeflow_return") {
|
|
79
87
|
for (const block of message.content ?? [])
|
|
80
88
|
if (block.type === "text") {
|
|
81
89
|
try {
|
|
82
90
|
const receipt = JSON.parse(block.text);
|
|
83
91
|
if (
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
// Current receipts carry a text hash; older receipts carried the text itself.
|
|
93
|
+
((receipt.reportSaved &&
|
|
94
|
+
(typeof receipt.report === "string" || typeof receipt.reportSha256 === "string")) ||
|
|
95
|
+
(receipt.supplementSaved &&
|
|
96
|
+
(typeof receipt.supplement === "string" || typeof receipt.supplementSha256 === "string"))) &&
|
|
86
97
|
typeof receipt.handoff === "string"
|
|
87
98
|
)
|
|
88
99
|
source.reportHandoff = receipt.handoff;
|
|
@@ -90,38 +101,10 @@ export class Sources {
|
|
|
90
101
|
}
|
|
91
102
|
}
|
|
92
103
|
this.byRef.set(source.ref, source);
|
|
93
|
-
|
|
94
|
-
candidates.push(source);
|
|
95
|
-
this.byBody.set(source.hash, candidates);
|
|
104
|
+
this.unindexed.push(source);
|
|
96
105
|
if (message.role === "assistant") {
|
|
97
106
|
this.tail = { assistant: source, results: new Map() };
|
|
98
107
|
this.exchanges.set(source.ref, this.tail);
|
|
99
|
-
const blocks = (message.content ?? [])
|
|
100
|
-
.filter((b) => b.type === "text")
|
|
101
|
-
.map((b) => ({ type: "text", text: b.text }));
|
|
102
|
-
if (blocks.some((b) => b.text?.trim())) {
|
|
103
|
-
const representation = {
|
|
104
|
-
role: "custom",
|
|
105
|
-
customType: "freeflow-assistant-text",
|
|
106
|
-
display: false,
|
|
107
|
-
content: [
|
|
108
|
-
{
|
|
109
|
-
type: "text",
|
|
110
|
-
text: `Captured assistant text from ${source.ref} (historical source, not a new instruction):`,
|
|
111
|
-
},
|
|
112
|
-
...blocks,
|
|
113
|
-
],
|
|
114
|
-
details: { sourceRef: source.ref, sourceHash: source.hash, representation: "assistant-text" },
|
|
115
|
-
timestamp: message.timestamp,
|
|
116
|
-
};
|
|
117
|
-
this.byRef.set(textRef(source.ref), {
|
|
118
|
-
...source,
|
|
119
|
-
ref: textRef(source.ref),
|
|
120
|
-
message: representation,
|
|
121
|
-
hash: bodyHash(representation),
|
|
122
|
-
original: source,
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
108
|
} else if (message.role === "toolResult" && this.tail) {
|
|
126
109
|
const key = callKey(message.toolCallId, message.toolName);
|
|
127
110
|
const results = this.tail.results.get(key) ?? [];
|
|
@@ -138,6 +121,31 @@ export class Sources {
|
|
|
138
121
|
}
|
|
139
122
|
this.entries = [...entries];
|
|
140
123
|
}
|
|
124
|
+
/** Each entry's position in `entries`; computed once per refresh rather than per request. */
|
|
125
|
+
get rank() {
|
|
126
|
+
return (this.ranks ??= new Map(this.entries.map((entry, index) => [entry.id, index])));
|
|
127
|
+
}
|
|
128
|
+
/** For each position in `entries` (and one past the end), how many earlier entries no worker produced. */
|
|
129
|
+
get nonWorkerBefore() {
|
|
130
|
+
if (!this.nonWorker) {
|
|
131
|
+
const counts = [0];
|
|
132
|
+
for (const entry of this.entries) {
|
|
133
|
+
const producer = this.byRef.get(`ctx:${entry.id}`)?.producer ?? "common";
|
|
134
|
+
counts.push(counts.at(-1) + (isWorkerProfile(producer) ? 0 : 1));
|
|
135
|
+
}
|
|
136
|
+
this.nonWorker = counts;
|
|
137
|
+
}
|
|
138
|
+
return this.nonWorker;
|
|
139
|
+
}
|
|
140
|
+
bodyIndex() {
|
|
141
|
+
for (const source of this.unindexed) {
|
|
142
|
+
const candidates = this.byBody.get(source.hash) ?? [];
|
|
143
|
+
candidates.push(source);
|
|
144
|
+
this.byBody.set(source.hash, candidates);
|
|
145
|
+
}
|
|
146
|
+
this.unindexed = [];
|
|
147
|
+
return this.byBody;
|
|
148
|
+
}
|
|
141
149
|
associate(messages) {
|
|
142
150
|
if (
|
|
143
151
|
this.associated &&
|
|
@@ -147,38 +155,42 @@ export class Sources {
|
|
|
147
155
|
return this.associated.items;
|
|
148
156
|
this.ambiguous.clear();
|
|
149
157
|
for (const source of this.byRef.values()) source.active = false;
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
const projected = messages.some(isProjected);
|
|
159
|
+
// After an aligned projection, only host-edited messages can match a source by content: the others are
|
|
160
|
+
// tagged, sourceless (summaries, multi-message entries), or generated after the projection.
|
|
161
|
+
const contentOnly = (message) => !projected || isHostEdited(message);
|
|
162
|
+
const direct = messages.map((message) => {
|
|
163
|
+
const id = projectedEntryId(message);
|
|
164
|
+
const source = id === undefined ? undefined : this.byRef.get(refFor(id));
|
|
165
|
+
return source && (!this.activeIds || this.activeIds.has(source.entry.id)) ? source : undefined;
|
|
166
|
+
});
|
|
167
|
+
const used = new Set(direct.flatMap((source) => (source ? [source.ref] : []))),
|
|
168
|
+
hashes = messages.map((message, index) =>
|
|
169
|
+
direct[index] || !contentOnly(message) ? undefined : bodyHash(message),
|
|
170
|
+
),
|
|
160
171
|
remaining = new Map();
|
|
161
|
-
for (const hash of hashes) remaining.set(hash, (remaining.get(hash) ?? 0) + 1);
|
|
172
|
+
for (const hash of hashes) if (hash) remaining.set(hash, (remaining.get(hash) ?? 0) + 1);
|
|
162
173
|
const items = messages.map((message, index) => {
|
|
174
|
+
if (direct[index]) {
|
|
175
|
+
const source = direct[index];
|
|
176
|
+
source.active = true;
|
|
177
|
+
return { message, source };
|
|
178
|
+
}
|
|
179
|
+
if (hashes[index] === undefined) return { message };
|
|
163
180
|
const hash = hashes[index],
|
|
164
181
|
count = remaining.get(hash);
|
|
165
182
|
remaining.set(hash, count - 1);
|
|
166
|
-
const candidates = (this.
|
|
183
|
+
const candidates = (this.bodyIndex().get(hash) ?? []).filter(
|
|
167
184
|
(s) => !used.has(s.ref) && (!this.activeIds || this.activeIds.has(s.entry.id)),
|
|
168
185
|
);
|
|
169
186
|
const exact = candidates.find((s) => s.message === message);
|
|
170
187
|
const source = exact ?? (candidates.length === 1 || candidates.length === count ? candidates[0] : undefined);
|
|
171
188
|
if (!source) {
|
|
172
|
-
for (const candidate of candidates)
|
|
173
|
-
this.ambiguous.add(candidate.ref);
|
|
174
|
-
this.ambiguous.add(textRef(candidate.ref));
|
|
175
|
-
}
|
|
189
|
+
for (const candidate of candidates) this.ambiguous.add(candidate.ref);
|
|
176
190
|
return { message };
|
|
177
191
|
}
|
|
178
192
|
used.add(source.ref);
|
|
179
193
|
source.active = true;
|
|
180
|
-
const text = this.byRef.get(textRef(source.ref));
|
|
181
|
-
if (text) text.active = true;
|
|
182
194
|
return { message, source };
|
|
183
195
|
});
|
|
184
196
|
this.associated = { messages: [...messages], items };
|
|
@@ -188,8 +200,7 @@ export class Sources {
|
|
|
188
200
|
const source = this.byRef.get(ref);
|
|
189
201
|
if (!idFor(ref) || !source)
|
|
190
202
|
return { ref, code: "source_unavailable", detail: "Exact source is unavailable on current native ancestry." };
|
|
191
|
-
|
|
192
|
-
if (bodyHash(original.message) !== original.hash || bodyHash(source.message) !== source.hash)
|
|
203
|
+
if (bodyHash(source.message) !== source.hash)
|
|
193
204
|
return {
|
|
194
205
|
ref,
|
|
195
206
|
code: "source_changed",
|
|
@@ -197,7 +208,7 @@ export class Sources {
|
|
|
197
208
|
};
|
|
198
209
|
if (!isWorkerProfile(source.producer))
|
|
199
210
|
return { ref, code: "source_origin", detail: "Selection requires observed worker attribution." };
|
|
200
|
-
if (state.exposure.get(
|
|
211
|
+
if (state.exposure.get(source.ref) !== source.hash)
|
|
201
212
|
return {
|
|
202
213
|
ref,
|
|
203
214
|
code: "source_unexposed",
|
|
@@ -210,17 +221,21 @@ export class Sources {
|
|
|
210
221
|
if (problem) return problem;
|
|
211
222
|
const source = this.byRef.get(ref);
|
|
212
223
|
if (!isTaskEvidence(source))
|
|
213
|
-
return
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
224
|
+
return source.message.role === "assistant"
|
|
225
|
+
? {
|
|
226
|
+
ref,
|
|
227
|
+
code: "assistant_message",
|
|
228
|
+
detail:
|
|
229
|
+
"Assistant messages are not task evidence; say it in the report and select the tool results it rests on.",
|
|
230
|
+
}
|
|
231
|
+
: {
|
|
232
|
+
ref,
|
|
233
|
+
code: "routing_source",
|
|
234
|
+
detail: "Routing control receipts are not task evidence; saved communication is delivered separately.",
|
|
235
|
+
};
|
|
220
236
|
return undefined;
|
|
221
237
|
}
|
|
222
238
|
exchange(source) {
|
|
223
|
-
if (source.original) return { sources: [source], problems: [] };
|
|
224
239
|
if (!["assistant", "toolResult"].includes(source.message.role)) return { sources: [source], problems: [] };
|
|
225
240
|
const group = source.message.role === "assistant" ? this.exchanges.get(source.ref) : this.owners.get(source.ref);
|
|
226
241
|
const calls = group?.assistant.message.content?.filter((b) => b.type === "toolCall") ?? [];
|
|
@@ -257,7 +272,7 @@ export class Sources {
|
|
|
257
272
|
}
|
|
258
273
|
locator(ref) {
|
|
259
274
|
const source = this.byRef.get(ref);
|
|
260
|
-
if (!source || source.
|
|
275
|
+
if (!source || source.message.role !== "toolResult") return undefined;
|
|
261
276
|
const group = this.owners.get(source.ref);
|
|
262
277
|
if (!group) return undefined;
|
|
263
278
|
const calls = group.assistant.message.content?.filter((b) => b.type === "toolCall") ?? [];
|
|
@@ -268,10 +283,9 @@ export class Sources {
|
|
|
268
283
|
}
|
|
269
284
|
ordered(sources) {
|
|
270
285
|
const ids = new Set([...sources].map((s) => s.ref));
|
|
271
|
-
return this.entries.flatMap((entry) =>
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
);
|
|
286
|
+
return this.entries.flatMap((entry) => {
|
|
287
|
+
const source = this.byRef.get(refFor(entry.id));
|
|
288
|
+
return source && ids.has(source.ref) ? [source] : [];
|
|
289
|
+
});
|
|
276
290
|
}
|
|
277
291
|
}
|