@hassangameryt/freeflow 0.7.3 → 0.9.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/.agents/plugins/marketplace.json +2 -2
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +3 -3
- package/.cursor-plugin/plugin.json +1 -1
- package/NOTICE +14 -0
- package/README.md +101 -159
- package/capabilities/cognitive-routing/SKILL.md +47 -210
- package/capabilities/cognitive-routing/references/coordinator.md +163 -0
- package/capabilities/cognitive-routing/references/worker.md +38 -0
- package/capabilities/compaction/SKILL.md +49 -0
- package/capabilities/compaction/references/summary-format.md +250 -0
- package/capabilities/messaging/SKILL.md +49 -0
- package/capabilities/task-memory/SKILL.md +87 -0
- package/command-surface.json +8 -52
- package/gemini-extension.json +1 -1
- package/hooks/claude/hooks.json +13 -3
- package/hooks/codex/hooks.json +2 -1
- package/hooks/shared/runtime-context.mjs +73 -83
- package/licenses/Apache-2.0.txt +55 -0
- package/package.json +42 -12
- package/pi-extension/README.md +41 -0
- package/pi-extension/dist/ask-user/ask.js +108 -0
- package/pi-extension/dist/ask-user/form.js +250 -0
- package/pi-extension/dist/ask-user/questions.js +66 -0
- package/pi-extension/dist/ask-user/tool.js +124 -0
- package/pi-extension/dist/cognitive-routing/assembler.js +417 -0
- package/pi-extension/dist/cognitive-routing/bootstrap.js +90 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/config.js +8 -6
- 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} +107 -41
- package/pi-extension/dist/cognitive-routing/gate.js +256 -0
- package/pi-extension/dist/cognitive-routing/handlers.js +901 -0
- package/pi-extension/dist/cognitive-routing/handoffs.js +350 -0
- package/pi-extension/dist/cognitive-routing/model-control.js +476 -0
- package/pi-extension/dist/cognitive-routing/projection.js +520 -0
- package/pi-extension/dist/cognitive-routing/provenance.js +83 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/render.js +15 -15
- package/pi-extension/dist/cognitive-routing/runtime.js +398 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/schemas.js +47 -11
- package/pi-extension/dist/cognitive-routing/session.js +223 -0
- package/pi-extension/dist/{session-sources → cognitive-routing}/sources.js +126 -87
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/state.js +55 -386
- package/pi-extension/dist/cognitive-routing/status.js +81 -0
- package/pi-extension/dist/cognitive-routing/tools.js +74 -0
- package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/types.js +14 -11
- package/pi-extension/dist/compaction/carry.js +205 -0
- package/pi-extension/dist/compaction/config.js +24 -0
- package/pi-extension/dist/compaction/controller.js +494 -0
- package/pi-extension/dist/compaction/harness.js +93 -0
- package/pi-extension/dist/compaction/results.js +159 -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 +62 -0
- package/pi-extension/dist/host/config-validation.js +233 -0
- package/pi-extension/dist/host/config.js +361 -0
- package/pi-extension/dist/host/inbound.js +142 -0
- package/pi-extension/dist/host/projection-tags.js +60 -0
- package/pi-extension/dist/host/prompts.js +93 -0
- package/pi-extension/dist/{session-sources → host}/read-only-session.js +117 -1
- package/pi-extension/dist/{runtime → host}/request-history.js +125 -39
- package/pi-extension/dist/host/rows.js +25 -0
- package/pi-extension/dist/host/runtime-state.js +204 -0
- package/pi-extension/dist/host/section-keeper.js +85 -0
- package/pi-extension/dist/host/settings/freeflow-command.js +2323 -0
- package/pi-extension/dist/{settings/settings-tui.js → host/settings/settings-view.js} +205 -73
- package/pi-extension/dist/host/staging.js +28 -0
- package/pi-extension/dist/host/status.js +115 -0
- package/pi-extension/dist/index.js +1004 -188
- package/pi-extension/dist/messaging/config.js +27 -0
- package/pi-extension/dist/messaging/messaging.js +398 -0
- package/pi-extension/dist/messaging/registry.js +57 -0
- package/pi-extension/dist/messaging/render.js +90 -0
- package/pi-extension/dist/messaging/tools.js +109 -0
- package/pi-extension/dist/messaging/transport.js +101 -0
- 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 +222 -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/task-memory/config.js +49 -0
- package/pi-extension/dist/task-memory/registry.js +119 -0
- package/pi-extension/dist/task-memory/render.js +107 -0
- package/pi-extension/dist/task-memory/runtime.js +994 -0
- package/pi-extension/dist/task-memory/tool.js +233 -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 +430 -0
- package/pi-extension/dist/tool-execution/bash-guard.js +23 -0
- package/pi-extension/dist/tool-execution/config.js +33 -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 +163 -0
- package/pi-extension/dist/tool-execution/guidance-notices.js +124 -0
- package/pi-extension/dist/tool-execution/prompt.js +54 -0
- package/pi-extension/dist/tool-execution/skill-reads.js +143 -0
- package/pi-extension/dist/tool-execution/tools.js +16 -0
- package/pi-extension/freeflow/README.md +9 -0
- package/runtime/prompts/cognitive-routing.md +4 -4
- package/runtime/prompts/core.md +29 -72
- package/runtime/prompts/interaction-contract.md +18 -8
- package/runtime/prompts/tool-execution.md +25 -0
- package/runtime/prompts/working-method.md +25 -0
- package/skills/deliver-work/SKILL.md +76 -0
- package/skills/deliver-work/references/branch-closeout.md +134 -0
- package/skills/deliver-work/references/commit.md +83 -0
- package/skills/deliver-work/references/launch.md +94 -0
- package/skills/deliver-work/references/release.md +85 -0
- package/skills/deliver-work/scripts/commit-state.mjs +139 -0
- package/skills/deliver-work/scripts/delivery-state.mjs +107 -0
- package/skills/deliver-work/scripts/lib/git-state.mjs +178 -0
- package/skills/deliver-work/scripts/push-route.mjs +122 -0
- package/skills/deliver-work/scripts/release-preflight.mjs +177 -0
- package/skills/discuss-work/SKILL.md +148 -0
- package/skills/{discuss → discuss-work}/references/discussion-continuity.md +13 -50
- package/skills/discuss-work/references/learning-action.md +36 -0
- package/skills/discuss-work/scripts/choices.mjs +101 -0
- package/skills/discuss-work/scripts/lib/choices.mjs +159 -0
- package/skills/evaluate-behavior/SKILL.md +107 -0
- package/skills/evaluate-behavior/references/authoring.md +381 -0
- package/skills/evaluate-behavior/references/coding-tasks.md +145 -0
- package/skills/evaluate-behavior/references/conversations-pipelines-judges.md +177 -0
- package/skills/evaluate-behavior/references/design-and-measurement.md +273 -0
- package/skills/evaluate-behavior/references/running-and-evidence.md +245 -0
- package/skills/evaluate-behavior/scripts/claude-guard.mjs +76 -0
- package/skills/evaluate-behavior/scripts/guard-rules.mjs +309 -0
- package/skills/evaluate-behavior/scripts/lib/agreement.mjs +90 -0
- package/skills/evaluate-behavior/scripts/lib/arms.mjs +55 -0
- package/skills/evaluate-behavior/scripts/lib/budget.mjs +87 -0
- package/skills/evaluate-behavior/scripts/lib/build-source.mjs +287 -0
- package/skills/evaluate-behavior/scripts/lib/clear.mjs +74 -0
- package/skills/evaluate-behavior/scripts/lib/container.mjs +395 -0
- package/skills/evaluate-behavior/scripts/lib/decision.mjs +418 -0
- package/skills/evaluate-behavior/scripts/lib/definitions.mjs +1072 -0
- package/skills/evaluate-behavior/scripts/lib/freeflow.mjs +103 -0
- package/skills/evaluate-behavior/scripts/lib/grade-command.mjs +591 -0
- package/skills/evaluate-behavior/scripts/lib/grade-comparison.mjs +90 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-interaction.mjs +19 -18
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-support.mjs +32 -5
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-workspace.mjs +28 -12
- package/skills/evaluate-behavior/scripts/lib/grade.mjs +101 -0
- package/skills/evaluate-behavior/scripts/lib/hooks.mjs +98 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/confinement.mjs +196 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/constraints.mjs +111 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/index.mjs +48 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/isolation.mjs +74 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/launch.mjs +123 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/model-call.mjs +73 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/recorder.mjs +178 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/session.mjs +494 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/skills.mjs +81 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/index.mjs +31 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/names.mjs +3 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/confinement.mjs +173 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/host.mjs +148 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/index.mjs +70 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/isolation.mjs +81 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/model-call.mjs +79 -0
- package/skills/evaluate-behavior/scripts/lib/hosts/pi/process.mjs +241 -0
- package/skills/{evaluate-skill/scripts/lib → evaluate-behavior/scripts/lib/hosts/pi}/rpc.mjs +144 -26
- package/skills/evaluate-behavior/scripts/lib/identity.mjs +82 -0
- package/skills/evaluate-behavior/scripts/lib/judge.mjs +688 -0
- package/skills/evaluate-behavior/scripts/lib/metrics.mjs +332 -0
- package/skills/evaluate-behavior/scripts/lib/model-call.mjs +17 -0
- package/skills/evaluate-behavior/scripts/lib/participants.mjs +616 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/process.mjs +22 -0
- package/skills/evaluate-behavior/scripts/lib/queue.mjs +54 -0
- package/skills/evaluate-behavior/scripts/lib/reference.mjs +343 -0
- package/skills/evaluate-behavior/scripts/lib/reuse.mjs +277 -0
- package/skills/evaluate-behavior/scripts/lib/review.mjs +933 -0
- package/skills/evaluate-behavior/scripts/lib/runner.mjs +732 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/sandbox.mjs +121 -14
- package/skills/evaluate-behavior/scripts/lib/scan-shell.mjs +457 -0
- package/skills/evaluate-behavior/scripts/lib/scan.mjs +479 -0
- package/skills/evaluate-behavior/scripts/lib/seal.mjs +91 -0
- package/skills/evaluate-behavior/scripts/lib/shell.mjs +560 -0
- package/skills/evaluate-behavior/scripts/lib/source-override.mjs +64 -0
- package/skills/evaluate-behavior/scripts/lib/subject-file.mjs +88 -0
- package/skills/{evaluate-skill/scripts/lib/pi.mjs → evaluate-behavior/scripts/lib/subject.mjs} +239 -262
- package/skills/evaluate-behavior/scripts/lib/task-copy.mjs +124 -0
- package/skills/evaluate-behavior/scripts/lib/trials.mjs +524 -0
- package/skills/evaluate-behavior/scripts/lib/validity.mjs +68 -0
- package/skills/evaluate-behavior/scripts/lib/view-html.mjs +454 -0
- package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/view.mjs +218 -11
- package/skills/evaluate-behavior/scripts/pi-command-tool.mjs +159 -0
- package/skills/evaluate-behavior/scripts/pi-container-route.mjs +23 -0
- package/skills/evaluate-behavior/scripts/pi-guard.mjs +77 -0
- package/skills/evaluate-behavior/scripts/pi-login-refresh.mjs +31 -0
- package/skills/evaluate-behavior/scripts/skill-eval.mjs +586 -0
- package/skills/execute-work/SKILL.md +96 -72
- package/skills/execute-work/references/code-practices.md +27 -49
- package/skills/execute-work/references/design.md +271 -0
- package/skills/execute-work/references/diagnose.md +117 -0
- package/skills/execute-work/references/migration.md +108 -0
- package/skills/execute-work/references/simplify.md +65 -0
- package/skills/execute-work/scripts/self-review.mjs +422 -0
- package/skills/execute-work/scripts/touch-map.mjs +290 -0
- package/skills/review-work/SKILL.md +94 -64
- package/skills/review-work/references/adjudication.md +94 -0
- package/skills/review-work/references/artifact.md +198 -0
- package/skills/review-work/references/evals-and-judges.md +66 -0
- package/skills/review-work/references/work.md +177 -0
- package/skills/review-work/scripts/check-brief.mjs +128 -0
- package/skills/review-work/scripts/review-packet.mjs +233 -0
- package/skills/setup-freeflow/SKILL.md +69 -16
- package/skills/track-work/SKILL.md +135 -151
- package/skills/track-work/references/handoff.md +190 -0
- package/skills/track-work/references/projects.md +51 -0
- package/skills/track-work/references/working-record-format.md +201 -344
- package/skills/track-work/scripts/lib/document.mjs +79 -19
- package/skills/track-work/scripts/lib/format.mjs +18 -1
- package/skills/track-work/scripts/lib/recover.mjs +254 -0
- package/skills/track-work/scripts/lib/registry.mjs +656 -0
- package/skills/track-work/scripts/lib/search.mjs +40 -0
- package/skills/track-work/scripts/lib/store.mjs +53 -21
- package/skills/track-work/scripts/lib/transitions.mjs +79 -4
- package/skills/track-work/scripts/lib/views.mjs +50 -1
- package/skills/track-work/scripts/working-record.mjs +263 -22
- package/skills/verify-work/SKILL.md +64 -47
- package/skills/verify-work/references/feature-map.md +120 -0
- package/skills/verify-work/references/runtime-evidence.md +203 -0
- package/skills/verify-work/references/test-design.md +27 -6
- package/skills/verify-work/scripts/test-changes.mjs +246 -0
- package/skills/write-docs/SKILL.md +171 -0
- package/skills/write-docs/references/documentation-shapes.md +184 -0
- package/skills/write-docs/references/spec-and-plan-shapes.md +308 -0
- package/skills/write-docs/scripts/artifact-check.mjs +148 -0
- package/skills/write-docs/scripts/docs-check.mjs +229 -0
- package/skills/write-docs/scripts/plan-lint.mjs +123 -0
- package/skills/write-skill/SKILL.md +165 -165
- package/skills/write-skill/references/activation-and-wording.md +143 -0
- package/skills/write-skill/references/placement-and-dependencies.md +154 -0
- package/skills/write-skill/scripts/lib/compare.mjs +701 -0
- package/skills/write-skill/scripts/lib/similarity.mjs +56 -0
- package/skills/write-skill/scripts/lib/skill-author.mjs +197 -3
- package/skills/write-skill/scripts/skill-author.mjs +67 -8
- 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/projection.js +0 -330
- package/pi-extension/dist/cognitive-routing-v2/runtime.js +0 -2181
- package/pi-extension/dist/cognitive-routing-v2/tools.js +0 -60
- 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/settings/settings-ui.js +0 -1360
- 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/plugin.json +0 -33
- package/runtime/prompts/context-virtualization.md +0 -3
- package/runtime/prompts/conversation-history.md +0 -3
- package/skills/action-selection/SKILL.md +0 -100
- package/skills/action-selection/references/trajectory-stalls.md +0 -71
- package/skills/bypass/SKILL.md +0 -153
- package/skills/commit-work/SKILL.md +0 -145
- package/skills/commit-work/references/git-state-edges.md +0 -94
- package/skills/commit-work/references/simple-push.md +0 -92
- package/skills/commit-work/references/staging-decisions.md +0 -106
- package/skills/decision-gate/SKILL.md +0 -106
- package/skills/design-for-depth/SKILL.md +0 -117
- package/skills/design-for-depth/references/design-pressure-signals.md +0 -182
- package/skills/design-for-depth/references/implementation-decisions.md +0 -76
- package/skills/design-for-depth/references/interface-design-loop.md +0 -136
- package/skills/design-for-depth/references/module-and-dependency-design.md +0 -147
- package/skills/design-for-depth/references/software-design-philosophy.md +0 -202
- package/skills/design-for-depth/references/state-and-failure-boundaries.md +0 -136
- package/skills/diagnose-failure/SKILL.md +0 -125
- package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +0 -48
- package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +0 -51
- package/skills/discuss/SKILL.md +0 -116
- package/skills/evaluate-skill/SKILL.md +0 -219
- package/skills/evaluate-skill/references/evaluation-definition-schema.md +0 -385
- package/skills/evaluate-skill/references/evaluation-design.md +0 -112
- package/skills/evaluate-skill/references/execution-and-evidence.md +0 -90
- package/skills/evaluate-skill/references/review-and-revision.md +0 -92
- package/skills/evaluate-skill/scripts/lib/definitions.mjs +0 -407
- package/skills/evaluate-skill/scripts/lib/grade-comparison.mjs +0 -60
- package/skills/evaluate-skill/scripts/lib/grade.mjs +0 -64
- package/skills/evaluate-skill/scripts/lib/runner.mjs +0 -368
- package/skills/evaluate-skill/scripts/pi-guard.mjs +0 -164
- package/skills/evaluate-skill/scripts/skill-eval.mjs +0 -102
- package/skills/execute-work/references/execute-work-edges.md +0 -68
- package/skills/finish-branch/SKILL.md +0 -117
- package/skills/finish-branch/references/integration-options.md +0 -80
- package/skills/handoff/SKILL.md +0 -82
- package/skills/handoff/references/handoff-templates.md +0 -150
- package/skills/launch-work/SKILL.md +0 -116
- package/skills/launch-work/references/launch-readiness.md +0 -85
- package/skills/migration-work/SKILL.md +0 -115
- package/skills/migration-work/references/migration-lifecycle.md +0 -82
- package/skills/release-work/SKILL.md +0 -118
- package/skills/release-work/references/release-evidence.md +0 -78
- package/skills/review-artifact/SKILL.md +0 -142
- package/skills/review-artifact/references/adjudicate-artifact-review.md +0 -101
- package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +0 -159
- package/skills/review-work/references/adjudicate-work-review.md +0 -97
- package/skills/review-work/references/independent-work-reviewer-contract.md +0 -139
- package/skills/review-work/references/security-risk-lens.md +0 -69
- package/skills/setup-freeflow/references/activation-contract.md +0 -109
- package/skills/setup-freeflow/references/host-setup.md +0 -67
- package/skills/simplify-code/SKILL.md +0 -85
- package/skills/simplify-code/references/simplification-patterns.md +0 -70
- package/skills/verify-work/references/browser-runtime-evidence.md +0 -55
- package/skills/verify-work/references/integration-evidence.md +0 -47
- package/skills/verify-work/references/performance-evidence.md +0 -57
- package/skills/workflow/SKILL.md +0 -127
- package/skills/workflow/references/domain-skill-composition.md +0 -43
- package/skills/write-plan/SKILL.md +0 -92
- package/skills/write-plan/references/plan-shapes.md +0 -156
- package/skills/write-skill/references/activation-boundaries.md +0 -104
- package/skills/write-skill/references/agent-first-instructions.md +0 -121
- package/skills/write-skill/references/progressive-disclosure.md +0 -127
- package/skills/write-skill/references/skill-dependency-graphs.md +0 -190
- package/skills/write-spec/SKILL.md +0 -92
- package/skills/write-spec/references/artifact-standards.md +0 -86
- package/skills/write-spec/references/decision-records.md +0 -78
- package/skills/write-spec/references/spec-shapes.md +0 -143
- /package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/budget.js +0 -0
- /package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/evidence.mjs +0 -0
- /package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-observer.mjs +0 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { Sources } from "./sources.js";
|
|
3
|
+
import { ViewCache } from "./projection.js";
|
|
4
|
+
import { pairFromProfile } from "./config.js";
|
|
5
|
+
import { initialState } from "./state.js";
|
|
6
|
+
import { RoutingError, isWorkerProfile, requireCondition as check, samePair, workersForDelegation } from "./types.js";
|
|
7
|
+
import { cachedBranch } from "../host/branch.js";
|
|
8
|
+
const STAGED_CONTROL = new Set(["control", "profile-overrides", "delegation-override"]);
|
|
9
|
+
export const ROUTING_RECOVERY_HINT =
|
|
10
|
+
"Run /freeflow profile auto to reconcile routing, or /freeflow resume to continue saved work.";
|
|
11
|
+
/**
|
|
12
|
+
* State and identity shared by every part of routing for one bound session: the event journal, the host
|
|
13
|
+
* context, the current turn, blocking errors, control mode, and the queue that orders control changes.
|
|
14
|
+
*/
|
|
15
|
+
export class RoutingSession {
|
|
16
|
+
store;
|
|
17
|
+
ctx;
|
|
18
|
+
capability;
|
|
19
|
+
token = randomUUID();
|
|
20
|
+
turn;
|
|
21
|
+
/** The packaged routing skill and role references the bootstrap read must cover; undefined when the skill cannot be read. */
|
|
22
|
+
routingSkill;
|
|
23
|
+
messages = [];
|
|
24
|
+
error;
|
|
25
|
+
projectionError;
|
|
26
|
+
suppressed = false;
|
|
27
|
+
operations = Promise.resolve();
|
|
28
|
+
revision = 0;
|
|
29
|
+
manualHold;
|
|
30
|
+
automaticControl = false;
|
|
31
|
+
sourceCache;
|
|
32
|
+
/** Rendered view messages reused across requests (see ViewCache); rebuilt after a rebind or ancestry change. */
|
|
33
|
+
viewCache = new ViewCache();
|
|
34
|
+
/** Replayed tool results for the current turn, keyed by operation id. */
|
|
35
|
+
receipts = new Map();
|
|
36
|
+
/** Recently served inspection pages, keyed by request; at most eight are kept. */
|
|
37
|
+
pages = new Map();
|
|
38
|
+
get projectionEnabled() {
|
|
39
|
+
return this.supported() && this.capability?.projection === true && this.stateData().control === "automatic";
|
|
40
|
+
}
|
|
41
|
+
/** Forgets everything derived for the current turn: its context view, sources, replay receipts, and pages. */
|
|
42
|
+
resetTurn() {
|
|
43
|
+
this.turn = undefined;
|
|
44
|
+
this.messages = [];
|
|
45
|
+
this.sourceCache = undefined;
|
|
46
|
+
this.viewCache = new ViewCache();
|
|
47
|
+
this.receipts.clear();
|
|
48
|
+
this.pages.clear();
|
|
49
|
+
}
|
|
50
|
+
subject() {
|
|
51
|
+
const branch = cachedBranch(this.store?.reader) ?? [];
|
|
52
|
+
return {
|
|
53
|
+
token: this.token,
|
|
54
|
+
revision: this.revision,
|
|
55
|
+
store: this.store,
|
|
56
|
+
leafId: branch.at(-1)?.id ?? null,
|
|
57
|
+
userId: branch.filter((e) => e.message?.role === "user").at(-1)?.id ?? null,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
current(s) {
|
|
61
|
+
if (s.token !== this.token || s.revision !== this.revision || s.store !== this.store) return false;
|
|
62
|
+
const branch = cachedBranch(this.store?.reader) ?? [];
|
|
63
|
+
return (
|
|
64
|
+
(!s.leafId || branch.some((e) => e.id === s.leafId)) &&
|
|
65
|
+
(branch.filter((e) => e.message?.role === "user").at(-1)?.id ?? null) === s.userId
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
guard(s) {
|
|
69
|
+
check(
|
|
70
|
+
this.current(s),
|
|
71
|
+
"stale_operation",
|
|
72
|
+
"Routing state changed while the operation was waiting; no further effects applied.",
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
taskBasis(state, assignmentId) {
|
|
76
|
+
return state.resumeBasis.has(assignmentId)
|
|
77
|
+
? state.resumeBasis.get(assignmentId)
|
|
78
|
+
: state.assignments.get(assignmentId)?.basisUserEntryId;
|
|
79
|
+
}
|
|
80
|
+
delegation(state = this.stateData()) {
|
|
81
|
+
return state.delegationOverride ?? this.capability?.delegation ?? "executor";
|
|
82
|
+
}
|
|
83
|
+
enabledWorkers(state = this.stateData()) {
|
|
84
|
+
return workersForDelegation(this.delegation(state));
|
|
85
|
+
}
|
|
86
|
+
assignedWorker(state, assignmentId = state.assignmentId) {
|
|
87
|
+
const assignment = assignmentId ? state.assignments.get(assignmentId) : undefined;
|
|
88
|
+
const handoff = assignment ? state.handoffs.get(assignment.delegateHandoffId) : undefined;
|
|
89
|
+
check(
|
|
90
|
+
handoff?.kind === "delegate" && handoff.assignmentId === assignment?.id && isWorkerProfile(handoff.to),
|
|
91
|
+
"assignment_worker_missing",
|
|
92
|
+
"The current assignment has no valid recorded worker.",
|
|
93
|
+
);
|
|
94
|
+
return handoff.to;
|
|
95
|
+
}
|
|
96
|
+
requiredProfiles(state = this.stateData(), delegation = this.delegation(state)) {
|
|
97
|
+
const profiles = new Set(["coordinator", ...workersForDelegation(delegation)]);
|
|
98
|
+
if (state.profile) profiles.add(state.profile);
|
|
99
|
+
if (this.manualHold) profiles.add(this.manualHold);
|
|
100
|
+
const assignment = state.assignmentId ? state.assignments.get(state.assignmentId) : undefined;
|
|
101
|
+
if (assignment?.state === "outstanding" || state.recoveryId) profiles.add(this.assignedWorker(state));
|
|
102
|
+
const pending = state.pendingId ? state.handoffs.get(state.pendingId) : undefined;
|
|
103
|
+
if (pending && isWorkerProfile(pending.to)) profiles.add(pending.to);
|
|
104
|
+
return [...profiles];
|
|
105
|
+
}
|
|
106
|
+
retireUnbound(reason) {
|
|
107
|
+
for (const execution of this.stateData().executions.values()) {
|
|
108
|
+
if (!execution.assistantEntryId && !execution.interrupted)
|
|
109
|
+
this.append({ type: "execution-interrupted", executionId: execution.id, reason });
|
|
110
|
+
}
|
|
111
|
+
this.turn = undefined;
|
|
112
|
+
}
|
|
113
|
+
openTurn() {
|
|
114
|
+
if (!this.turn || this.turn.opened) return;
|
|
115
|
+
const t = this.turn;
|
|
116
|
+
this.append({
|
|
117
|
+
type: "execution-opened",
|
|
118
|
+
execution: {
|
|
119
|
+
id: t.id,
|
|
120
|
+
profile: t.profile,
|
|
121
|
+
assignmentId: t.assignmentId,
|
|
122
|
+
recoveryId: t.recoveryId,
|
|
123
|
+
basisUserEntryId: t.basisUserEntryId,
|
|
124
|
+
pair: t.pair,
|
|
125
|
+
resultEntryIds: [],
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
t.opened = true;
|
|
129
|
+
}
|
|
130
|
+
stateData() {
|
|
131
|
+
return this.store?.state() ?? initialState();
|
|
132
|
+
}
|
|
133
|
+
sources(state = this.stateData()) {
|
|
134
|
+
const branch = cachedBranch(this.ctx.sessionManager);
|
|
135
|
+
const cache = this.sourceCache;
|
|
136
|
+
// The cached branch is the same array until the leaf moves, so an unchanged branch needs no filtering.
|
|
137
|
+
if (cache && cache.branch === branch && cache.authors === state.authors.size) return cache.source;
|
|
138
|
+
const entries = branch.filter((e) =>
|
|
139
|
+
["message", "custom_message", "compaction", "branch_summary"].includes(e.type),
|
|
140
|
+
);
|
|
141
|
+
if (
|
|
142
|
+
cache &&
|
|
143
|
+
cache.authors === state.authors.size &&
|
|
144
|
+
entries.length === cache.entries.length &&
|
|
145
|
+
entries.every((e, i) => e === cache.entries[i])
|
|
146
|
+
) {
|
|
147
|
+
cache.branch = branch;
|
|
148
|
+
return cache.source;
|
|
149
|
+
}
|
|
150
|
+
const active = this.ctx.sessionManager.buildContextEntries?.();
|
|
151
|
+
const activeIds = active ? new Set(active.map((e) => e.id)) : undefined;
|
|
152
|
+
const source = cache?.source ?? new Sources([], state);
|
|
153
|
+
source.refresh(entries, state, activeIds);
|
|
154
|
+
this.sourceCache = { branch, entries, authors: state.authors.size, source };
|
|
155
|
+
return source;
|
|
156
|
+
}
|
|
157
|
+
observed(ctx = this.ctx) {
|
|
158
|
+
return ctx?.model?.provider && ctx?.model?.id && ctx?.thinkingLevel
|
|
159
|
+
? { provider: ctx.model.provider, modelId: ctx.model.id, thinking: ctx.thinkingLevel }
|
|
160
|
+
: undefined;
|
|
161
|
+
}
|
|
162
|
+
supported() {
|
|
163
|
+
return !!this.capability?.effective && !this.suppressed;
|
|
164
|
+
}
|
|
165
|
+
append(data, op, step) {
|
|
166
|
+
check(this.store, "routing_unavailable");
|
|
167
|
+
// Control changes made while no run is active affect no request until the next prompt; stage them there.
|
|
168
|
+
const stage = STAGED_CONTROL.has(data.type) && this.ctx?.isIdle?.() !== false;
|
|
169
|
+
return this.store.append(this.store.make(data, op, step), stage);
|
|
170
|
+
}
|
|
171
|
+
enqueue(action) {
|
|
172
|
+
const token = this.token;
|
|
173
|
+
const result = this.operations.then(() => {
|
|
174
|
+
check(token === this.token, "stale_instance");
|
|
175
|
+
return action();
|
|
176
|
+
});
|
|
177
|
+
this.operations = result.catch(() => {});
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
mark(error) {
|
|
181
|
+
if (this.error && error instanceof RoutingError && error.code === "routing_blocked") return;
|
|
182
|
+
this.error =
|
|
183
|
+
error instanceof RoutingError
|
|
184
|
+
? `${error.code}: ${error.message}`
|
|
185
|
+
: error instanceof Error
|
|
186
|
+
? error.message
|
|
187
|
+
: String(error);
|
|
188
|
+
}
|
|
189
|
+
announced;
|
|
190
|
+
// Tell the user once per distinct block; routing stays blocked until an explicit control clears it.
|
|
191
|
+
announceBlock(ctx) {
|
|
192
|
+
if (!this.error || this.announced === this.error) return;
|
|
193
|
+
this.announced = this.error;
|
|
194
|
+
ctx?.ui?.notify?.(`Cognitive Routing blocked: ${this.error}. ${ROUTING_RECOVERY_HINT}`, "warning");
|
|
195
|
+
}
|
|
196
|
+
assertAvailable(profile) {
|
|
197
|
+
check(
|
|
198
|
+
this.supported() && this.store && !this.error && !this.store.blocked,
|
|
199
|
+
"routing_unavailable",
|
|
200
|
+
this.error ?? this.store?.blocked ?? "Routing is inactive.",
|
|
201
|
+
);
|
|
202
|
+
const state = this.stateData();
|
|
203
|
+
check(state.control === "automatic", "manual_control");
|
|
204
|
+
if (profile) check(state.profile === profile && this.turn?.profile === profile, "wrong_profile");
|
|
205
|
+
if (state.profile) check(samePair(this.observed(), this.profilePair(state.profile)), "configuration_mismatch");
|
|
206
|
+
}
|
|
207
|
+
configuredProfilePair(profile) {
|
|
208
|
+
const configured = this.capability?.profiles[profile];
|
|
209
|
+
check(configured, "profile_missing");
|
|
210
|
+
return pairFromProfile(configured);
|
|
211
|
+
}
|
|
212
|
+
profilePair(profile) {
|
|
213
|
+
return this.stateData().profileOverrides.get(profile) ?? this.configuredProfilePair(profile);
|
|
214
|
+
}
|
|
215
|
+
profilePairs(profiles = this.requiredProfiles()) {
|
|
216
|
+
return Object.fromEntries(profiles.map((profile) => [profile, this.profilePair(profile)]));
|
|
217
|
+
}
|
|
218
|
+
workerBasis(state, assignmentId) {
|
|
219
|
+
const recovery = state.recoveryId ? state.recoveries.get(state.recoveryId) : undefined;
|
|
220
|
+
if (recovery?.state === "reading") return state.handoffs.get(recovery.requestHandoffId)?.basisUserEntryId ?? null;
|
|
221
|
+
return this.taskBasis(state, assignmentId) ?? null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -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, ROUTING_TOOLS, routingToolName } 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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
+
}
|
|
14
|
+
const routingTools = new Set(ROUTING_TOOLS);
|
|
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(routingToolName(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
|
-
|
|
74
|
-
hash: bodyHash(message),
|
|
75
|
-
producer: "common",
|
|
76
|
-
active: false,
|
|
77
|
-
};
|
|
78
|
-
if (message.role === "toolResult" && message.toolName === "freeflow_return") {
|
|
83
|
+
const source = lazyHash({ ref: refFor(entry.id), entry, message, producer: "common", active: false }, () =>
|
|
84
|
+
bodyHash(message),
|
|
85
|
+
);
|
|
86
|
+
if (message.role === "toolResult" && routingToolName(message.toolName) === "return_work") {
|
|
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") ?? [];
|
|
@@ -266,12 +281,36 @@ export class Sources {
|
|
|
266
281
|
);
|
|
267
282
|
return matches.length === 1 ? locatorForCall(group.assistant, matches[0], this.locatorProvider) : undefined;
|
|
268
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* What a tool result's call did, in a few words: its path, command or first short string argument. Coordinator
|
|
286
|
+
* matches a selected ref to the result in its view by this label (Task 004 S-005); undefined when unknown.
|
|
287
|
+
*/
|
|
288
|
+
callLabel(ref) {
|
|
289
|
+
const source = this.byRef.get(ref);
|
|
290
|
+
if (!source || source.message.role !== "toolResult") return undefined;
|
|
291
|
+
const call = (this.owners.get(source.ref)?.assistant.message.content ?? []).find(
|
|
292
|
+
(block) =>
|
|
293
|
+
block.type === "toolCall" && block.id === source.message.toolCallId && block.name === source.message.toolName,
|
|
294
|
+
);
|
|
295
|
+
const args = call?.arguments;
|
|
296
|
+
if (!args || typeof args !== "object") return undefined;
|
|
297
|
+
// A path keeps its end, where the file name is; anything else keeps its start.
|
|
298
|
+
const path = typeof args.path === "string" ? args.path.trim() : "";
|
|
299
|
+
if (path) return path.length > 100 ? `...${path.slice(-97)}` : path;
|
|
300
|
+
const chosen =
|
|
301
|
+
["command", "pattern", "query", "url"]
|
|
302
|
+
.map((key) => args[key])
|
|
303
|
+
.find((value) => typeof value === "string" && value.trim()) ??
|
|
304
|
+
Object.values(args).find((value) => typeof value === "string" && value.trim() && value.length <= 200);
|
|
305
|
+
const label = normalizeLabel(chosen)?.label;
|
|
306
|
+
if (!label) return undefined;
|
|
307
|
+
return label.length > 100 ? `${label.slice(0, 97)}...` : label;
|
|
308
|
+
}
|
|
269
309
|
ordered(sources) {
|
|
270
310
|
const ids = new Set([...sources].map((s) => s.ref));
|
|
271
|
-
return this.entries.flatMap((entry) =>
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
);
|
|
311
|
+
return this.entries.flatMap((entry) => {
|
|
312
|
+
const source = this.byRef.get(refFor(entry.id));
|
|
313
|
+
return source && ids.has(source.ref) ? [source] : [];
|
|
314
|
+
});
|
|
276
315
|
}
|
|
277
316
|
}
|