@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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ACTIVE_SLICE_FIELDS,
|
|
3
3
|
CHECKPOINT_TYPES,
|
|
4
|
+
CONTEXT_HEADINGS,
|
|
4
5
|
CURRENT_SLICE_STATES,
|
|
5
6
|
DECISION_FIELDS,
|
|
6
7
|
DECISION_STATES,
|
|
@@ -11,11 +12,16 @@ import {
|
|
|
11
12
|
HISTORICAL_SLICE_FIELDS,
|
|
12
13
|
HISTORICAL_SLICE_STATES,
|
|
13
14
|
HISTORY_HEADINGS,
|
|
15
|
+
LEGACY_CHECKPOINT_TYPES,
|
|
16
|
+
OCCURRED_PATTERN,
|
|
14
17
|
PROPOSED_SLICE_FIELDS,
|
|
18
|
+
RECORDED_PATTERN,
|
|
15
19
|
SCHEMA_VERSION,
|
|
16
20
|
SLICE_TYPES,
|
|
17
21
|
TASK_STATES,
|
|
18
22
|
TOP_LEVEL_SECTIONS,
|
|
23
|
+
WORK_AGREEMENT_HEADING,
|
|
24
|
+
isCalendarDate,
|
|
19
25
|
joinLines,
|
|
20
26
|
nextId,
|
|
21
27
|
parseId,
|
|
@@ -251,34 +257,53 @@ function parseTopLevelSections(lines) {
|
|
|
251
257
|
);
|
|
252
258
|
}
|
|
253
259
|
|
|
260
|
+
const CONTEXT_LAYOUTS = [CONTEXT_HEADINGS, [CONTEXT_HEADINGS[0], WORK_AGREEMENT_HEADING, ...CONTEXT_HEADINGS.slice(1)]];
|
|
261
|
+
|
|
254
262
|
function parseContext(lines, section) {
|
|
255
263
|
const headings = findHeadings(lines, section.start, section.end, 3);
|
|
256
|
-
|
|
257
|
-
|
|
264
|
+
const titles = headings.map((heading) => heading.title);
|
|
265
|
+
if (!CONTEXT_LAYOUTS.some((layout) => layout.join("\n") === titles.join("\n")))
|
|
266
|
+
fail(
|
|
267
|
+
"invalid-context",
|
|
268
|
+
`Current Context must contain the seven canonical headings, with an optional ${WORK_AGREEMENT_HEADING} directly after Goal`,
|
|
269
|
+
);
|
|
258
270
|
const statements = new Map();
|
|
259
271
|
for (let index = 0; index < headings.length; index += 1) {
|
|
260
|
-
const expected = [
|
|
261
|
-
"Goal",
|
|
262
|
-
"What defines this task",
|
|
263
|
-
"Settled",
|
|
264
|
-
"Tentative",
|
|
265
|
-
"Open",
|
|
266
|
-
"Current direction",
|
|
267
|
-
"Boundaries",
|
|
268
|
-
][index];
|
|
269
|
-
if (headings[index].title !== expected) fail("invalid-context", `Expected Current Context heading ${expected}`);
|
|
270
272
|
const end = headings[index + 1]?.index ?? section.end;
|
|
271
|
-
statements.set(
|
|
273
|
+
statements.set(titles[index], { headingIndex: headings[index].index, start: headings[index].index + 1, end });
|
|
272
274
|
}
|
|
273
275
|
return { ...section, headings: statements };
|
|
274
276
|
}
|
|
275
277
|
|
|
278
|
+
const CURRENT_WORK_LAYOUTS = [
|
|
279
|
+
["Current Slice", "Next useful action"],
|
|
280
|
+
["Current Slice", "Recovery sources", "Next useful action"],
|
|
281
|
+
];
|
|
282
|
+
|
|
276
283
|
function parseCurrentWork(lines, section) {
|
|
277
284
|
const headings = findHeadings(lines, section.start, section.end, 3);
|
|
278
|
-
|
|
279
|
-
|
|
285
|
+
const titles = headings.map((heading) => heading.title);
|
|
286
|
+
if (!CURRENT_WORK_LAYOUTS.some((layout) => layout.join("\n") === titles.join("\n")))
|
|
287
|
+
fail(
|
|
288
|
+
"invalid-current-work",
|
|
289
|
+
"Current Work must contain Current Slice, optional Recovery sources, then Next useful action",
|
|
290
|
+
);
|
|
291
|
+
const nextActionHeading = headings[headings.length - 1];
|
|
292
|
+
const recoveryHeading = headings.length === 3 ? headings[1] : null;
|
|
280
293
|
const sliceContentStart = headings[0].index + 1;
|
|
281
294
|
const sliceContentEnd = headings[1].index;
|
|
295
|
+
let recoverySources = null;
|
|
296
|
+
if (recoveryHeading) {
|
|
297
|
+
recoverySources = {
|
|
298
|
+
headingIndex: recoveryHeading.index,
|
|
299
|
+
start: recoveryHeading.index + 1,
|
|
300
|
+
end: nextActionHeading.index,
|
|
301
|
+
};
|
|
302
|
+
for (let index = recoverySources.start; index < recoverySources.end; index += 1) {
|
|
303
|
+
if (lineHeading(lines[index]))
|
|
304
|
+
fail("invalid-recovery-sources", `Recovery sources cannot contain headings: ${lines[index]}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
282
307
|
const content = nonBlankLines(lines.slice(sliceContentStart, sliceContentEnd));
|
|
283
308
|
let currentSlice = null;
|
|
284
309
|
if (content.length === 1 && content[0] === "None") {
|
|
@@ -304,9 +329,11 @@ function parseCurrentWork(lines, section) {
|
|
|
304
329
|
return {
|
|
305
330
|
...section,
|
|
306
331
|
sliceHeadingIndex: headings[0].index,
|
|
307
|
-
|
|
332
|
+
sliceEnd: sliceContentEnd,
|
|
333
|
+
nextActionHeadingIndex: nextActionHeading.index,
|
|
308
334
|
currentSlice,
|
|
309
|
-
|
|
335
|
+
recoverySources,
|
|
336
|
+
nextAction: { start: nextActionHeading.index + 1, end: section.end },
|
|
310
337
|
};
|
|
311
338
|
}
|
|
312
339
|
|
|
@@ -385,6 +412,8 @@ function parseHistory(lines, section) {
|
|
|
385
412
|
};
|
|
386
413
|
}
|
|
387
414
|
|
|
415
|
+
const READABLE_CHECKPOINT_TYPES = new Set([...CHECKPOINT_TYPES, ...LEGACY_CHECKPOINT_TYPES]);
|
|
416
|
+
|
|
388
417
|
function validateChoice(block, field, choices, required = true) {
|
|
389
418
|
const value = scalarValue(block, field);
|
|
390
419
|
if (!value && !required) return "";
|
|
@@ -459,16 +488,46 @@ function validateReferences(document) {
|
|
|
459
488
|
}
|
|
460
489
|
}
|
|
461
490
|
|
|
491
|
+
export function validateOccurred(value, path) {
|
|
492
|
+
const match = OCCURRED_PATTERN.exec(value ?? "");
|
|
493
|
+
if (!match || !isCalendarDate(match[1]) || (match[2] && !isCalendarDate(match[2])))
|
|
494
|
+
fail("invalid-occurred", `Occurred in ${path} must be YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD: ${value}`);
|
|
495
|
+
if (match[2] && match[2] < match[1]) fail("invalid-occurred", `Occurred in ${path} ends before it starts: ${value}`);
|
|
496
|
+
return match[2] ?? match[1];
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function validateRecordedTime(slice) {
|
|
500
|
+
const occurred = scalarValue(slice, "Occurred");
|
|
501
|
+
const recorded = scalarValue(slice, "Recorded");
|
|
502
|
+
if (!occurred && !recorded) return;
|
|
503
|
+
if (!occurred || !recorded)
|
|
504
|
+
fail("missing-field", `Occurred and Recorded appear together in ${slice.path}; only slice record writes them`);
|
|
505
|
+
const end = validateOccurred(occurred, slice.path);
|
|
506
|
+
const match = RECORDED_PATTERN.exec(recorded);
|
|
507
|
+
if (!match || !isCalendarDate(match[1]))
|
|
508
|
+
fail("invalid-recorded", `Recorded in ${slice.path} must be "retroactively on YYYY-MM-DD": ${recorded}`);
|
|
509
|
+
if (end > match[1]) fail("invalid-occurred", `Occurred in ${slice.path} ends after it was recorded: ${occurred}`);
|
|
510
|
+
}
|
|
511
|
+
|
|
462
512
|
export function validateDocument(document) {
|
|
463
513
|
const { header, context, current, future, history } = document;
|
|
464
514
|
if (!header.name) fail("malformed-header", "Task name cannot be empty");
|
|
465
515
|
const goal = context.headings.get("Goal");
|
|
466
516
|
if (!hasMeaningfulContent(document.lines, goal.start, goal.end))
|
|
467
517
|
fail("missing-field", "Current Context Goal must contain meaningful content");
|
|
518
|
+
const agreement = context.headings.get(WORK_AGREEMENT_HEADING);
|
|
519
|
+
if (agreement && !hasMeaningfulContent(document.lines, agreement.start, agreement.end))
|
|
520
|
+
fail(
|
|
521
|
+
"missing-field",
|
|
522
|
+
`Current Context ${WORK_AGREEMENT_HEADING} must contain meaningful content; omit the heading until something is agreed`,
|
|
523
|
+
);
|
|
468
524
|
if (!hasMeaningfulContent(document.lines, current.nextAction.start, current.nextAction.end))
|
|
469
525
|
fail("missing-field", "Next useful action must contain meaningful content");
|
|
470
526
|
for (const block of allBlocks(document)) {
|
|
471
527
|
if (block.id && !parseId(block.id, block.kind)) fail("invalid-id", `Invalid ${block.kind} ID ${block.id}`);
|
|
528
|
+
for (const [name, field] of block.fields) {
|
|
529
|
+
if (!valueText(field)) fail("empty-field", `Empty field ${name} in ${block.path}; omit fields without a value`);
|
|
530
|
+
}
|
|
472
531
|
}
|
|
473
532
|
|
|
474
533
|
const ids = new Set();
|
|
@@ -489,7 +548,7 @@ export function validateDocument(document) {
|
|
|
489
548
|
} else {
|
|
490
549
|
validateFields(item, ["State"], {});
|
|
491
550
|
validateChoice(item, "State", FUTURE_CHECKPOINT_STATES);
|
|
492
|
-
validateChoice(item, "Type",
|
|
551
|
+
validateChoice(item, "Type", READABLE_CHECKPOINT_TYPES);
|
|
493
552
|
validateFields(item, ["Condition", "Applies to"]);
|
|
494
553
|
if (item.id && !parseId(item.id, "checkpoint")) fail("invalid-id", `Invalid Checkpoint ID ${item.id}`);
|
|
495
554
|
const checkpointState = scalarValue(item, "State");
|
|
@@ -530,7 +589,7 @@ export function validateDocument(document) {
|
|
|
530
589
|
|
|
531
590
|
for (const checkpoint of history.checkpoints.blocks) {
|
|
532
591
|
validateChoice(checkpoint, "State", HISTORICAL_CHECKPOINT_STATES);
|
|
533
|
-
validateChoice(checkpoint, "Type",
|
|
592
|
+
validateChoice(checkpoint, "Type", READABLE_CHECKPOINT_TYPES);
|
|
534
593
|
validateFields(checkpoint, ["Condition", "Applies to", "Result", "Task effect"]);
|
|
535
594
|
const state = scalarValue(checkpoint, "State");
|
|
536
595
|
if (state === "cancelled" || state === "replaced") requiredValue(checkpoint, "Reason");
|
|
@@ -543,6 +602,7 @@ export function validateDocument(document) {
|
|
|
543
602
|
const state = scalarValue(slice, "State");
|
|
544
603
|
if (state === "blocked") requiredValue(slice, "Resume when");
|
|
545
604
|
if (state === "abandoned") requiredValue(slice, "Reason");
|
|
605
|
+
validateRecordedTime(slice);
|
|
546
606
|
}
|
|
547
607
|
|
|
548
608
|
if (header.state === "paused" && current.currentSlice && scalarValue(current.currentSlice, "State") !== "paused")
|
|
@@ -10,13 +10,17 @@ export const CONTEXT_HEADINGS = [
|
|
|
10
10
|
"Current direction",
|
|
11
11
|
"Boundaries",
|
|
12
12
|
];
|
|
13
|
+
// Optional: allowed only directly after Goal, and never empty.
|
|
14
|
+
export const WORK_AGREEMENT_HEADING = "Work agreement";
|
|
13
15
|
export const HISTORY_HEADINGS = ["Decisions", "Checkpoints", "Slices"];
|
|
14
16
|
|
|
15
17
|
export const TASK_STATES = new Set(["active", "paused", "completed", "abandoned"]);
|
|
16
18
|
export const SLICE_TYPES = new Set(["learning", "delivery", "deepening"]);
|
|
17
19
|
export const CURRENT_SLICE_STATES = new Set(["in_progress", "paused"]);
|
|
18
20
|
export const HISTORICAL_SLICE_STATES = new Set(["completed", "blocked", "abandoned"]);
|
|
19
|
-
export const CHECKPOINT_TYPES = new Set(["
|
|
21
|
+
export const CHECKPOINT_TYPES = new Set(["preserve", "publish", "review", "decision", "continuity"]);
|
|
22
|
+
// Earlier type names remain readable so existing records stay valid.
|
|
23
|
+
export const LEGACY_CHECKPOINT_TYPES = new Set(["local_commit", "independent_review", "user_decision"]);
|
|
20
24
|
export const FUTURE_CHECKPOINT_STATES = new Set(["proposed", "pending", "deferred"]);
|
|
21
25
|
export const HISTORICAL_CHECKPOINT_STATES = new Set(["completed", "cancelled", "replaced"]);
|
|
22
26
|
export const DECISION_STATES = new Set(["active", "superseded", "retired"]);
|
|
@@ -60,6 +64,8 @@ export const DECISION_FIELDS = new Set([
|
|
|
60
64
|
export const HISTORICAL_SLICE_FIELDS = new Set([
|
|
61
65
|
"State",
|
|
62
66
|
"Type",
|
|
67
|
+
"Occurred",
|
|
68
|
+
"Recorded",
|
|
63
69
|
"Intended result",
|
|
64
70
|
"Authority source",
|
|
65
71
|
"Result",
|
|
@@ -71,6 +77,15 @@ export const HISTORICAL_SLICE_FIELDS = new Set([
|
|
|
71
77
|
"Residual effects",
|
|
72
78
|
]);
|
|
73
79
|
|
|
80
|
+
// A Slice recorded after the fact carries when it happened and the date it was recorded.
|
|
81
|
+
export const OCCURRED_PATTERN = /^(\d{4}-\d{2}-\d{2})(?: to (\d{4}-\d{2}-\d{2}))?$/;
|
|
82
|
+
export const RECORDED_PATTERN = /^retroactively on (\d{4}-\d{2}-\d{2})$/;
|
|
83
|
+
|
|
84
|
+
export function isCalendarDate(value) {
|
|
85
|
+
const date = new Date(`${value}T00:00:00Z`);
|
|
86
|
+
return !Number.isNaN(date.getTime()) && date.toISOString().slice(0, 10) === value;
|
|
87
|
+
}
|
|
88
|
+
|
|
74
89
|
export const IDS = {
|
|
75
90
|
slice: /^S-(\d{3,})$/,
|
|
76
91
|
checkpoint: /^C-(\d{3,})$/,
|
|
@@ -111,6 +126,8 @@ export function canonicalLines(name, state = "active", lastUpdated = new Date().
|
|
|
111
126
|
"",
|
|
112
127
|
"None",
|
|
113
128
|
"",
|
|
129
|
+
"### Recovery sources",
|
|
130
|
+
"",
|
|
114
131
|
"### Next useful action",
|
|
115
132
|
"",
|
|
116
133
|
"## Future Work",
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
5
|
+
import { parseDocument, sectionContentLines } from "./document.mjs";
|
|
6
|
+
import { renderResume } from "./views.mjs";
|
|
7
|
+
|
|
8
|
+
// Recovery in one call (Track Work, "Recover After Context Loss"): the resume view, then what each defining artifact
|
|
9
|
+
// and Recovery source points to and whether it can be read now, then where live Git state disagrees with the record.
|
|
10
|
+
// It reports; reading the sources and reconciling stays the agent's work.
|
|
11
|
+
//
|
|
12
|
+
// It also finds the evidence pointers in Material updates for `validate`: files and commits a later context will
|
|
13
|
+
// rely on. A pointer inside the repository that does not resolve is a problem; one outside it is reported, not checked.
|
|
14
|
+
|
|
15
|
+
const PATH_TOKEN = /^(~\/|\/|\.{1,2}\/)?[A-Za-z0-9_@.-]+(\/[A-Za-z0-9_@.()-]+)*\/?(#[^\s]*)?$/;
|
|
16
|
+
const COMMIT = /^[0-9a-f]{7,40}$/;
|
|
17
|
+
const URL = /^[a-z][a-z0-9+.-]*:\/\//i;
|
|
18
|
+
|
|
19
|
+
function git(root, args) {
|
|
20
|
+
try {
|
|
21
|
+
return execFileSync("git", args, { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// A path names a file with an extension, a directory with a trailing "/", or starts like one (./, ../, ~/, /). Slashed
|
|
28
|
+
// words such as "lost/weakened" or "17/9" are not paths.
|
|
29
|
+
const looksLikePath = (token) =>
|
|
30
|
+
PATH_TOKEN.test(token) &&
|
|
31
|
+
!COMMIT.test(token) &&
|
|
32
|
+
!token.includes("*") &&
|
|
33
|
+
(/^(~\/|\/|\.{1,2}\/)/.test(token) ||
|
|
34
|
+
/\/$/.test(token) ||
|
|
35
|
+
(/\.[A-Za-z][A-Za-z0-9]{0,7}(#.*)?$/.test(token) && (token.includes("/") || /^[^.]+\.[A-Za-z]/.test(token))));
|
|
36
|
+
const looksLikeCommit = (token) => COMMIT.test(token) && /\d/.test(token) && /[a-f]/.test(token);
|
|
37
|
+
|
|
38
|
+
// The pointers a line names: backticked tokens, Markdown link targets, a leading "pointer — ..." token, typed
|
|
39
|
+
// trail pointers (commit:<sha>, file:<path>), and bare commit hashes.
|
|
40
|
+
export function pointersIn(line) {
|
|
41
|
+
const found = [];
|
|
42
|
+
const add = (kind, value) => {
|
|
43
|
+
if (!found.some((each) => each.kind === kind && each.value === value)) found.push({ kind, value });
|
|
44
|
+
};
|
|
45
|
+
const text = line.replace(/^\s*[-*]\s+/, "");
|
|
46
|
+
for (const match of text.matchAll(/\]\(([^)\s]+)\)/g)) classify(match[1], add);
|
|
47
|
+
for (const match of text.matchAll(/`([^`\n]+)`/g)) classify(match[1].trim(), add);
|
|
48
|
+
const lead = /^(\S+)\s+[—–-]\s/.exec(text);
|
|
49
|
+
if (lead) classify(lead[1].replace(/[,;:]$/, ""), add);
|
|
50
|
+
const prose = text.replace(/`[^`\n]*`/g, " ").replace(/\]\([^)]*\)/g, " ");
|
|
51
|
+
for (const match of prose.matchAll(/\b(?:commit|file|path):([^\s,;)]+)/g))
|
|
52
|
+
classify(match[1], add, match[0].startsWith("commit:"));
|
|
53
|
+
for (const word of prose.split(/[\s,;()[\]"'“”]+/)) {
|
|
54
|
+
const token = word.replace(/[.:]+$/, "");
|
|
55
|
+
if (looksLikeCommit(token)) add("commit", token);
|
|
56
|
+
// A bare path in prose must name a file: a slashed word ending in "/" is usually a folder named in passing.
|
|
57
|
+
else if (token.includes("/") && !token.endsWith("/") && looksLikePath(token) && !URL.test(token))
|
|
58
|
+
add("path", token.replace(/#.*$/, ""));
|
|
59
|
+
}
|
|
60
|
+
return found;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function classify(raw, add, commitOnly = false) {
|
|
64
|
+
const token = raw.replace(/^(file|path|commit):/, "");
|
|
65
|
+
if (URL.test(token)) return add("url", token);
|
|
66
|
+
if (commitOnly || looksLikeCommit(token)) return add("commit", token);
|
|
67
|
+
const range = /^([0-9a-f]{7,40})\.\.\.?([0-9a-f]{7,40}|HEAD)$/.exec(token);
|
|
68
|
+
if (range) {
|
|
69
|
+
add("commit", range[1]);
|
|
70
|
+
if (range[2] !== "HEAD") add("commit", range[2]);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (looksLikePath(token)) add("path", token.replace(/#.*$/, ""));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Where a path pointer resolves: the repository root, the task folder, or as given when absolute or home-relative.
|
|
77
|
+
export function resolvePointer(pointer, { root, taskDir }) {
|
|
78
|
+
if (pointer.startsWith("~/")) return { outside: true, path: join(homedir(), pointer.slice(2)) };
|
|
79
|
+
if (isAbsolute(pointer)) {
|
|
80
|
+
const inside = !relative(root, pointer).startsWith("..");
|
|
81
|
+
return { outside: !inside, path: pointer };
|
|
82
|
+
}
|
|
83
|
+
const candidates = [join(taskDir, pointer), join(root, pointer)];
|
|
84
|
+
const hit = candidates.find((candidate) => existsSync(candidate));
|
|
85
|
+
return { outside: false, path: hit ?? candidates[1] };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function describe(path) {
|
|
89
|
+
try {
|
|
90
|
+
const stat = statSync(path);
|
|
91
|
+
if (stat.isDirectory()) return `directory, ${readdirSync(path).length} entries`;
|
|
92
|
+
const text = readFileSync(path, "utf8");
|
|
93
|
+
return `${text.split("\n").length} lines, ${text.split(/\s+/).filter(Boolean).length} words`;
|
|
94
|
+
} catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function checkPointer(pointer, context) {
|
|
100
|
+
if (pointer.kind === "url") return { ...pointer, state: "not checked (URL)" };
|
|
101
|
+
if (pointer.kind === "commit") {
|
|
102
|
+
if (!context.isGit) return { ...pointer, state: "not checked (not a Git repository)" };
|
|
103
|
+
const full = git(context.root, ["rev-parse", "--verify", "--quiet", `${pointer.value}^{commit}`]);
|
|
104
|
+
return full
|
|
105
|
+
? { ...pointer, state: "resolves", commit: full }
|
|
106
|
+
: { ...pointer, state: "missing", problem: `commit ${pointer.value} is not in this repository` };
|
|
107
|
+
}
|
|
108
|
+
const where = resolvePointer(pointer.value, context);
|
|
109
|
+
const size = describe(where.path);
|
|
110
|
+
if (size) return { ...pointer, state: "resolves", size, ...(where.outside ? { outside: true } : {}) };
|
|
111
|
+
if (where.outside) return { ...pointer, state: "not checked (outside the repository)", outside: true };
|
|
112
|
+
return { ...pointer, state: "missing", problem: `${pointer.value} does not exist` };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const bullets = (lines) => lines.filter((line) => /^\s*[-*]\s+\S/.test(line));
|
|
116
|
+
|
|
117
|
+
function sourceEntries(lines, context) {
|
|
118
|
+
return bullets(lines).map((line) => {
|
|
119
|
+
const text = line.trim().replace(/^[-*]\s+/, "");
|
|
120
|
+
const trigger = /\bread (?:only )?(?:when|if) ([^.;]+)/i.exec(text)?.[1]?.trim() ?? null;
|
|
121
|
+
return { text, trigger, pointers: pointersIn(line).map((pointer) => checkPointer(pointer, context)) };
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function liveState(document, context) {
|
|
126
|
+
const { root } = context;
|
|
127
|
+
if (!context.isGit) return { git: false, mismatches: [], notes: ["not a Git repository: no live state to compare"] };
|
|
128
|
+
const branch = git(root, ["branch", "--show-current"]) || null;
|
|
129
|
+
const head = git(root, ["rev-parse", "--short=12", "HEAD"]);
|
|
130
|
+
const subject = head ? git(root, ["log", "-1", "--format=%s"]) : null;
|
|
131
|
+
const dirty = (git(root, ["status", "--porcelain"]) ?? "").split("\n").filter(Boolean).length;
|
|
132
|
+
const mismatches = [];
|
|
133
|
+
const notes = [];
|
|
134
|
+
const current = document.sections["Current Work"];
|
|
135
|
+
const sliceText = current ? document.lines.slice(current.start, current.end).join("\n") : "";
|
|
136
|
+
const contextText = sectionContentLines(document, "Current Context").join("\n");
|
|
137
|
+
const branches = (git(root, ["for-each-ref", "--format=%(refname:short)", "refs/heads"]) ?? "")
|
|
138
|
+
.split("\n")
|
|
139
|
+
.filter(Boolean);
|
|
140
|
+
const named = branches.filter((name) =>
|
|
141
|
+
new RegExp(`(^|[\\s\`(])${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}([\\s\`),.;:]|$)`).test(
|
|
142
|
+
`${sliceText}\n${contextText}`,
|
|
143
|
+
),
|
|
144
|
+
);
|
|
145
|
+
if (!branch) mismatches.push(`HEAD is detached at ${head}`);
|
|
146
|
+
else if (named.length && !named.includes(branch))
|
|
147
|
+
mismatches.push(`the record names branch ${named.join(", ")}; HEAD is on ${branch}`);
|
|
148
|
+
const commits = [...new Set(pointersIn(sliceText.replace(/\n/g, " ")).filter((each) => each.kind === "commit"))];
|
|
149
|
+
for (const { value } of commits) {
|
|
150
|
+
const full = git(root, ["rev-parse", "--verify", "--quiet", `${value}^{commit}`]);
|
|
151
|
+
if (!full) mismatches.push(`the Current Slice names commit ${value}, which this repository does not have`);
|
|
152
|
+
else if (head && git(root, ["merge-base", "--is-ancestor", full, "HEAD"]) === null)
|
|
153
|
+
mismatches.push(`the Current Slice names commit ${value}, which is not in HEAD's history`);
|
|
154
|
+
}
|
|
155
|
+
const updated = /^Last updated:\s*(\S+)/m.exec(document.lines.slice(0, 10).join("\n"))?.[1];
|
|
156
|
+
if (updated && head) {
|
|
157
|
+
const since = (git(root, ["log", "--oneline", `--since=${updated}`, "HEAD"]) ?? "").split("\n").filter(Boolean);
|
|
158
|
+
if (since.length)
|
|
159
|
+
notes.push(
|
|
160
|
+
`${since.length} commit(s) on HEAD since the record's Last updated (${updated}); it may not describe them`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
if (dirty) notes.push(`${dirty} uncommitted or untracked path(s)`);
|
|
164
|
+
return { git: true, branch, head, subject, dirty, namedBranches: named, mismatches, notes };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function contextFor(root, recordPath) {
|
|
168
|
+
return {
|
|
169
|
+
root,
|
|
170
|
+
taskDir: dirname(recordPath),
|
|
171
|
+
isGit: git(root, ["rev-parse", "--is-inside-work-tree"]) === "true",
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function gitRoot(root) {
|
|
176
|
+
return git(root, ["rev-parse", "--show-toplevel"]) ?? root;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function renderRecover(text, { root, recordPath }) {
|
|
180
|
+
const document = parseDocument(text);
|
|
181
|
+
const context = contextFor(gitRoot(root), recordPath);
|
|
182
|
+
const defines = document.context.headings.get("What defines this task");
|
|
183
|
+
const defining = sourceEntries(document.lines.slice(defines.start, defines.end), context);
|
|
184
|
+
const sources = document.current.recoverySources;
|
|
185
|
+
const recovery = sources ? sourceEntries(document.lines.slice(sources.start, sources.end), context) : [];
|
|
186
|
+
const live = liveState(document, context);
|
|
187
|
+
const pointerLine = (pointer) =>
|
|
188
|
+
`${pointer.value}: ${pointer.state}${pointer.size ? ` (${pointer.size})` : ""}${pointer.outside && pointer.size ? ", outside the repository" : ""}`;
|
|
189
|
+
const entryLines = (entries, withTrigger) =>
|
|
190
|
+
entries.length
|
|
191
|
+
? entries.flatMap((entry) => [
|
|
192
|
+
`- ${entry.text}`,
|
|
193
|
+
...(withTrigger ? [` - ${entry.trigger ? `read when ${entry.trigger}` : "read now"}`] : []),
|
|
194
|
+
...(entry.pointers.length
|
|
195
|
+
? entry.pointers.map((pointer) => ` - ${pointerLine(pointer)}`)
|
|
196
|
+
: [" - no pointer found: recover it from the text"]),
|
|
197
|
+
])
|
|
198
|
+
: ["None."];
|
|
199
|
+
const lines = [
|
|
200
|
+
"## Recovery",
|
|
201
|
+
"",
|
|
202
|
+
"Read in this order: every defining artifact, then each Recovery source whose trigger applies, then the History entries the next action depends on (`view entry <ID>`).",
|
|
203
|
+
"",
|
|
204
|
+
"### Defining artifacts",
|
|
205
|
+
"",
|
|
206
|
+
...entryLines(defining, false),
|
|
207
|
+
"",
|
|
208
|
+
"### Recovery sources",
|
|
209
|
+
"",
|
|
210
|
+
...entryLines(recovery, true),
|
|
211
|
+
"",
|
|
212
|
+
"### Live state",
|
|
213
|
+
"",
|
|
214
|
+
...(live.git
|
|
215
|
+
? [
|
|
216
|
+
`- ${live.branch ? `branch ${live.branch}` : "detached HEAD"}, HEAD ${live.head ?? "none"}${live.subject ? ` (${live.subject})` : ""}`,
|
|
217
|
+
]
|
|
218
|
+
: []),
|
|
219
|
+
...live.notes.map((note) => `- ${note}`),
|
|
220
|
+
...(live.mismatches.length
|
|
221
|
+
? ["", "Mismatches: resolve each from sources before acting.", ...live.mismatches.map((each) => `- ${each}`)]
|
|
222
|
+
: ["- no mismatch found between the record and live Git state"]),
|
|
223
|
+
];
|
|
224
|
+
const resume = renderResume(text);
|
|
225
|
+
return `${resume.trimEnd()}${document.newline}${document.newline}${lines.join(document.newline)}${document.newline}`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Evidence pointers in every Material updates list. An unresolved pointer inside the repository is a problem on an
|
|
229
|
+
// Evidence or Result line, which claims it exists, and a warning on any other line (an Extension may name a planned
|
|
230
|
+
// path); the caller decides whether problems fail. Pointers outside the repository are listed, not checked.
|
|
231
|
+
export function checkEvidencePointers(text, { root, recordPath }) {
|
|
232
|
+
const document = parseDocument(text);
|
|
233
|
+
const context = contextFor(gitRoot(root), recordPath);
|
|
234
|
+
const lines = document.lines;
|
|
235
|
+
const problems = [];
|
|
236
|
+
const warnings = [];
|
|
237
|
+
const outside = [];
|
|
238
|
+
let checked = 0;
|
|
239
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
240
|
+
if (!/^#####\s+Material updates\s*$/.test(lines[index])) continue;
|
|
241
|
+
for (let at = index + 1; at < lines.length && !/^#{1,5}\s/.test(lines[at]); at += 1) {
|
|
242
|
+
for (const pointer of pointersIn(lines[at])) {
|
|
243
|
+
if (pointer.kind === "url") continue;
|
|
244
|
+
const result = checkPointer(pointer, context);
|
|
245
|
+
const claims = /^\s*[-*]\s+(Evidence|Result)\b/.test(lines[at]);
|
|
246
|
+
if (result.problem) (claims ? problems : warnings).push(`line ${at + 1}: ${result.problem}`);
|
|
247
|
+
else if (result.outside || result.state.startsWith("not checked"))
|
|
248
|
+
outside.push(`line ${at + 1}: ${pointer.value}`);
|
|
249
|
+
if (!result.outside && !result.state.startsWith("not checked")) checked += 1;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return { checked, problems, warnings, outside };
|
|
254
|
+
}
|