@pugi/cli 0.1.0-beta.99 → 1.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +11 -191
- package/bin/pugi +8 -0
- package/package.json +15 -71
- package/postinstall.mjs +31 -0
- package/CHANGELOG.md +0 -132
- package/THIRD_PARTY_NOTICES.md +0 -40
- package/assets/pugi-mascot.ansi +0 -16
- package/assets/pugi-prozr2-mascot.ansi +0 -9
- package/bin/run.js +0 -34
- package/dist/commands/deploy.js +0 -439
- package/dist/commands/flatten.js +0 -191
- package/dist/commands/jobs-watch.js +0 -201
- package/dist/commands/jobs.js +0 -260
- package/dist/commands/retro.js +0 -210
- package/dist/commands/smoke.js +0 -133
- package/dist/core/agent-progress/cleanup.js +0 -134
- package/dist/core/agent-progress/schema.js +0 -144
- package/dist/core/agent-progress/writer.js +0 -101
- package/dist/core/agents/adaptive-router.js +0 -330
- package/dist/core/agents/loader.js +0 -104
- package/dist/core/agents/query-decomposer.js +0 -297
- package/dist/core/agents/registry.js +0 -69
- package/dist/core/approvals/shortcut-resolver.js +0 -98
- package/dist/core/artifact-chain/dispatcher.js +0 -148
- package/dist/core/artifact-chain/exporter.js +0 -164
- package/dist/core/artifact-chain/state.js +0 -243
- package/dist/core/artifact-chain/steps.js +0 -169
- package/dist/core/ask-user/question.js +0 -92
- package/dist/core/audit/audit-trail.js +0 -275
- package/dist/core/auth/ensure-authenticated.js +0 -129
- package/dist/core/auth/env-provider.js +0 -238
- package/dist/core/auto-open-browser.js +0 -128
- package/dist/core/auto-update/channels.js +0 -122
- package/dist/core/auto-update/checker.js +0 -241
- package/dist/core/auto-update/state.js +0 -235
- package/dist/core/bare-mode/index.js +0 -107
- package/dist/core/bash/redirect.js +0 -281
- package/dist/core/bash-classifier.js +0 -1397
- package/dist/core/checkpoint/resumer.js +0 -149
- package/dist/core/checkpoint/rewinder.js +0 -291
- package/dist/core/checkpoints/shadow-git.js +0 -670
- package/dist/core/citations/parser.js +0 -109
- package/dist/core/classifier/yolo-classifier.js +0 -88
- package/dist/core/clipboard.js +0 -70
- package/dist/core/codegraph/decision-store.js +0 -248
- package/dist/core/codegraph/detect-repo.js +0 -459
- package/dist/core/codegraph/install.js +0 -134
- package/dist/core/codegraph/offer-hook.js +0 -220
- package/dist/core/compact/auto-trigger.js +0 -96
- package/dist/core/compact/buffer-rewriter.js +0 -115
- package/dist/core/compact/summarizer.js +0 -208
- package/dist/core/compact/token-counter.js +0 -108
- package/dist/core/consensus/anvil-fanout.js +0 -276
- package/dist/core/consensus/diff-capture.js +0 -491
- package/dist/core/consensus/rubric.js +0 -233
- package/dist/core/context/builder.js +0 -114
- package/dist/core/context/compaction-events.js +0 -99
- package/dist/core/context/compaction.js +0 -602
- package/dist/core/context/index.js +0 -28
- package/dist/core/context/invariants.js +0 -250
- package/dist/core/context/markdown-loader.js +0 -288
- package/dist/core/context/markdown-traverse.js +0 -255
- package/dist/core/context/pugiignore.js +0 -316
- package/dist/core/context/repo-skeleton.js +0 -533
- package/dist/core/context/tool-eviction.js +0 -55
- package/dist/core/context/watcher.js +0 -342
- package/dist/core/context/working-set.js +0 -165
- package/dist/core/coordinator/agent-tools.js +0 -77
- package/dist/core/coordinator/agent-toolset.js +0 -65
- package/dist/core/coordinator/fsm.js +0 -73
- package/dist/core/coordinator/mode-fsm.js +0 -70
- package/dist/core/cost/rate-card.js +0 -129
- package/dist/core/cost/tracker.js +0 -221
- package/dist/core/credentials.js +0 -355
- package/dist/core/cron/scheduler.js +0 -138
- package/dist/core/denial-tracking/index.js +0 -8
- package/dist/core/denial-tracking/state.js +0 -264
- package/dist/core/diagnostics/probe-runner.js +0 -93
- package/dist/core/diagnostics/probes/api.js +0 -46
- package/dist/core/diagnostics/probes/auth.js +0 -93
- package/dist/core/diagnostics/probes/bare-mode.js +0 -42
- package/dist/core/diagnostics/probes/cli-version.js +0 -127
- package/dist/core/diagnostics/probes/config.js +0 -72
- package/dist/core/diagnostics/probes/denial-tracking.js +0 -57
- package/dist/core/diagnostics/probes/disk.js +0 -81
- package/dist/core/diagnostics/probes/engine-live.js +0 -46
- package/dist/core/diagnostics/probes/git.js +0 -65
- package/dist/core/diagnostics/probes/hooks.js +0 -118
- package/dist/core/diagnostics/probes/mcp.js +0 -75
- package/dist/core/diagnostics/probes/node.js +0 -59
- package/dist/core/diagnostics/probes/pnpm.js +0 -36
- package/dist/core/diagnostics/probes/pugi-md.js +0 -89
- package/dist/core/diagnostics/probes/sandbox.js +0 -72
- package/dist/core/diagnostics/probes/session.js +0 -74
- package/dist/core/diagnostics/probes/status-snapshot.js +0 -488
- package/dist/core/diagnostics/probes/workspace.js +0 -63
- package/dist/core/diagnostics/types.js +0 -70
- package/dist/core/dispatch/cache-cleanup.js +0 -197
- package/dist/core/dispatch/cache-handoff.js +0 -295
- package/dist/core/edits/apply-patch-layer-e.js +0 -189
- package/dist/core/edits/dispatch.js +0 -511
- package/dist/core/edits/format-detector.js +0 -260
- package/dist/core/edits/format-matrix.js +0 -26
- package/dist/core/edits/fuzzy-ladder.js +0 -650
- package/dist/core/edits/index.js +0 -19
- package/dist/core/edits/journal.js +0 -199
- package/dist/core/edits/layer-a-apply.js +0 -217
- package/dist/core/edits/layer-a-fuzzy-apply.js +0 -198
- package/dist/core/edits/layer-b-apply.js +0 -211
- package/dist/core/edits/layer-c-apply.js +0 -160
- package/dist/core/edits/layer-d-ast.js +0 -572
- package/dist/core/edits/marker-parser.js +0 -401
- package/dist/core/edits/security-gate.js +0 -223
- package/dist/core/edits/verify-hook.js +0 -273
- package/dist/core/edits/worktree.js +0 -322
- package/dist/core/engine/adapter-runner.js +0 -8
- package/dist/core/engine/anvil-client.js +0 -344
- package/dist/core/engine/auto-compact.js +0 -179
- package/dist/core/engine/budgets.js +0 -195
- package/dist/core/engine/context-prefix.js +0 -155
- package/dist/core/engine/index.js +0 -12
- package/dist/core/engine/intensity.js +0 -163
- package/dist/core/engine/intent.js +0 -260
- package/dist/core/engine/native-pugi.js +0 -1616
- package/dist/core/engine/noop.js +0 -27
- package/dist/core/engine/prompts.js +0 -236
- package/dist/core/engine/strip-internal-fields.js +0 -124
- package/dist/core/engine/tool-bridge.js +0 -2173
- package/dist/core/engine/verification-patterns.js +0 -195
- package/dist/core/evaluation/golden-dataset.js +0 -293
- package/dist/core/feedback/queue.js +0 -177
- package/dist/core/feedback/submitter.js +0 -145
- package/dist/core/file-cache.js +0 -141
- package/dist/core/flatten/flatten-repo.js +0 -439
- package/dist/core/format/osc8-link.js +0 -28
- package/dist/core/hook-chains.js +0 -392
- package/dist/core/hooks/citation-verify-hook.js +0 -138
- package/dist/core/hooks/citation-verify.js +0 -112
- package/dist/core/hooks/events.js +0 -46
- package/dist/core/hooks/index.js +0 -15
- package/dist/core/hooks/registry.js +0 -216
- package/dist/core/hooks/runner.js +0 -236
- package/dist/core/hooks/v2/event-emitter.js +0 -115
- package/dist/core/hooks/v2/executor.js +0 -282
- package/dist/core/hooks/v2/index.js +0 -25
- package/dist/core/hooks/v2/lifecycle.js +0 -104
- package/dist/core/hooks/v2/loader.js +0 -216
- package/dist/core/hooks/v2/matcher.js +0 -125
- package/dist/core/hooks/v2/trust.js +0 -143
- package/dist/core/hooks/v2/types.js +0 -86
- package/dist/core/hooks/worktree-events.js +0 -158
- package/dist/core/hooks.js +0 -415
- package/dist/core/image/renderer.js +0 -71
- package/dist/core/index-store.js +0 -260
- package/dist/core/init/detector.js +0 -582
- package/dist/core/init/template-renderer.js +0 -242
- package/dist/core/jobs/registry.js +0 -462
- package/dist/core/ledger/results-tsv.js +0 -142
- package/dist/core/log-discipline/stdout-redirect.js +0 -51
- package/dist/core/lsp/cache.js +0 -105
- package/dist/core/lsp/client.js +0 -1229
- package/dist/core/lsp/language-detect.js +0 -66
- package/dist/core/lsp/post-edit-diagnostics.js +0 -171
- package/dist/core/lsp/server-detect.js +0 -173
- package/dist/core/lsp/symbol-cache.js +0 -162
- package/dist/core/lsp/symbol-tools.js +0 -664
- package/dist/core/mcp/client.js +0 -385
- package/dist/core/mcp/http-server.js +0 -553
- package/dist/core/mcp/orchestrator-config.js +0 -192
- package/dist/core/mcp/orchestrator-tools.js +0 -806
- package/dist/core/mcp/permission.js +0 -190
- package/dist/core/mcp/registry.js +0 -193
- package/dist/core/mcp/server-tools.js +0 -219
- package/dist/core/mcp/server.js +0 -397
- package/dist/core/mcp/trust.js +0 -91
- package/dist/core/memory/dual-write.js +0 -416
- package/dist/core/memory/passive-extract.js +0 -130
- package/dist/core/memory/phase1-kinds.js +0 -20
- package/dist/core/memory/secret-scanner.js +0 -304
- package/dist/core/memory-sync/queue.js +0 -170
- package/dist/core/metrics/extract.js +0 -113
- package/dist/core/modes/roo-modes.js +0 -68
- package/dist/core/onboarding/ensure-initialized.js +0 -133
- package/dist/core/onboarding/marker.js +0 -111
- package/dist/core/onboarding/telemetry-state.js +0 -108
- package/dist/core/output-style/presets.js +0 -176
- package/dist/core/output-style/state.js +0 -185
- package/dist/core/path-security.js +0 -345
- package/dist/core/permission.js +0 -369
- package/dist/core/permissions/auto-classifier.js +0 -124
- package/dist/core/permissions/bash-parser.js +0 -371
- package/dist/core/permissions/circuit-breaker.js +0 -83
- package/dist/core/permissions/constrained-edit.js +0 -91
- package/dist/core/permissions/gate.js +0 -278
- package/dist/core/permissions/index.js +0 -20
- package/dist/core/permissions/mode.js +0 -174
- package/dist/core/permissions/network-egress.js +0 -137
- package/dist/core/permissions/state.js +0 -241
- package/dist/core/permissions/tool-class.js +0 -107
- package/dist/core/plan-mode/ui-state.js +0 -51
- package/dist/core/plans/plan-artifact.js +0 -721
- package/dist/core/policy-limits/etag-store.js +0 -122
- package/dist/core/prd-check/parser.js +0 -215
- package/dist/core/prd-check/reporter.js +0 -127
- package/dist/core/prd-check/session-review.js +0 -557
- package/dist/core/prd-check/verifiers.js +0 -223
- package/dist/core/prompt-cache/client-cache.js +0 -99
- package/dist/core/prompts/assembly.js +0 -29
- package/dist/core/prompts/registry.js +0 -364
- package/dist/core/pugi-gitignore.js +0 -52
- package/dist/core/pugi-md/cc-compat-rules.js +0 -735
- package/dist/core/pugi-md/context-injector.js +0 -76
- package/dist/core/pugi-md/walk-up.js +0 -207
- package/dist/core/python/uv-installer.js +0 -270
- package/dist/core/python/uv-resolver.js +0 -83
- package/dist/core/rate-limit/narrator.js +0 -146
- package/dist/core/recipes/cli-types.js +0 -20
- package/dist/core/recipes/loader.js +0 -103
- package/dist/core/recipes/runner.js +0 -345
- package/dist/core/recipes/schema.js +0 -587
- package/dist/core/release-notes/parser.js +0 -241
- package/dist/core/release-notes/state.js +0 -116
- package/dist/core/repl/ask.js +0 -512
- package/dist/core/repl/cancellation.js +0 -98
- package/dist/core/repl/cap-warning.js +0 -91
- package/dist/core/repl/clipboard-read.js +0 -174
- package/dist/core/repl/dispatch-fsm.js +0 -220
- package/dist/core/repl/engine-bridge.js +0 -303
- package/dist/core/repl/history-search.js +0 -175
- package/dist/core/repl/history.js +0 -182
- package/dist/core/repl/kill-ring.js +0 -138
- package/dist/core/repl/model-pricing.js +0 -135
- package/dist/core/repl/privacy-banner.js +0 -71
- package/dist/core/repl/session.js +0 -4962
- package/dist/core/repl/slash-commands.js +0 -747
- package/dist/core/repl/store/index.js +0 -12
- package/dist/core/repl/store/jsonl-log.js +0 -321
- package/dist/core/repl/store/lockfile.js +0 -155
- package/dist/core/repl/store/session-store.js +0 -821
- package/dist/core/repl/store/types.js +0 -44
- package/dist/core/repl/store/uuid-v7.js +0 -68
- package/dist/core/repl/tool-route.js +0 -382
- package/dist/core/repl/workspace-context.js +0 -206
- package/dist/core/repo-map/build.js +0 -125
- package/dist/core/repo-map/cache.js +0 -185
- package/dist/core/repo-map/extractor.js +0 -254
- package/dist/core/repo-map/formatter.js +0 -145
- package/dist/core/repo-map/page-rank.js +0 -105
- package/dist/core/repo-map/scanner.js +0 -211
- package/dist/core/retro/git-collector.js +0 -251
- package/dist/core/retro/health-card.js +0 -25
- package/dist/core/retro/metrics.js +0 -342
- package/dist/core/retro/narrative.js +0 -249
- package/dist/core/retro/plane-collector.js +0 -274
- package/dist/core/retro/pr-issue-link.js +0 -65
- package/dist/core/retro/types.js +0 -16
- package/dist/core/retry-budget/budget.js +0 -284
- package/dist/core/retry-budget/index.js +0 -5
- package/dist/core/retry-budget/retry-cap.js +0 -74
- package/dist/core/routing/lead-worker.js +0 -43
- package/dist/core/routing/pre-flight-estimator.js +0 -108
- package/dist/core/runs/run-tree.js +0 -103
- package/dist/core/sandboxing/adapter.js +0 -29
- package/dist/core/sandboxing/index.js +0 -49
- package/dist/core/sandboxing/none.js +0 -19
- package/dist/core/sandboxing/seatbelt.js +0 -183
- package/dist/core/security/injection-scanner.js +0 -367
- package/dist/core/security/output-filter.js +0 -418
- package/dist/core/session/env-file.js +0 -105
- package/dist/core/session/section-budgets.js +0 -140
- package/dist/core/session.js +0 -377
- package/dist/core/settings.js +0 -400
- package/dist/core/share/formatter.js +0 -271
- package/dist/core/share/redactor.js +0 -221
- package/dist/core/share/uploader.js +0 -267
- package/dist/core/skills/defaults.js +0 -457
- package/dist/core/skills/loader.js +0 -454
- package/dist/core/skills/sources.js +0 -480
- package/dist/core/skills/trust.js +0 -172
- package/dist/core/smoke/headless-driver.js +0 -174
- package/dist/core/smoke/orchestrator.js +0 -194
- package/dist/core/smoke/runner.js +0 -238
- package/dist/core/smoke/scenario-parser.js +0 -316
- package/dist/core/statusline.js +0 -99
- package/dist/core/subagents/dispatcher-real.js +0 -600
- package/dist/core/subagents/dispatcher.js +0 -352
- package/dist/core/subagents/index.js +0 -39
- package/dist/core/subagents/isolation-matrix.js +0 -213
- package/dist/core/subagents/spawn.js +0 -101
- package/dist/core/telemetry/emitter.js +0 -229
- package/dist/core/telemetry/queue.js +0 -251
- package/dist/core/theme/context.js +0 -91
- package/dist/core/theme/presets.js +0 -228
- package/dist/core/theme/state.js +0 -181
- package/dist/core/todos/invariant.js +0 -10
- package/dist/core/todos/state.js +0 -177
- package/dist/core/tool-schema/compressor.js +0 -89
- package/dist/core/transport/version-interceptor.js +0 -166
- package/dist/core/trust.js +0 -109
- package/dist/core/tui/thinking-block.js +0 -64
- package/dist/core/vim/keymap.js +0 -288
- package/dist/core/vim/state.js +0 -92
- package/dist/core/watch-markers/marker-watcher.js +0 -133
- package/dist/core/worktree/include-parser.js +0 -249
- package/dist/core/worktree-manager/cleanup.js +0 -123
- package/dist/core/worktree-manager/manager.js +0 -303
- package/dist/index.js +0 -44
- package/dist/runtime/bootstrap.js +0 -190
- package/dist/runtime/cli.js +0 -8121
- package/dist/runtime/commands/agents.js +0 -385
- package/dist/runtime/commands/budget.js +0 -192
- package/dist/runtime/commands/cancel.js +0 -231
- package/dist/runtime/commands/chain.js +0 -489
- package/dist/runtime/commands/codegraph-status.js +0 -227
- package/dist/runtime/commands/compact.js +0 -297
- package/dist/runtime/commands/config.js +0 -595
- package/dist/runtime/commands/cost.js +0 -199
- package/dist/runtime/commands/delegate.js +0 -312
- package/dist/runtime/commands/dispatch.js +0 -126
- package/dist/runtime/commands/doctor.js +0 -579
- package/dist/runtime/commands/feedback.js +0 -184
- package/dist/runtime/commands/hooks.js +0 -187
- package/dist/runtime/commands/init.js +0 -254
- package/dist/runtime/commands/lsp.js +0 -368
- package/dist/runtime/commands/mcp.js +0 -935
- package/dist/runtime/commands/memory.js +0 -582
- package/dist/runtime/commands/model.js +0 -237
- package/dist/runtime/commands/onboarding.js +0 -275
- package/dist/runtime/commands/patch.js +0 -128
- package/dist/runtime/commands/permissions.js +0 -112
- package/dist/runtime/commands/plan.js +0 -143
- package/dist/runtime/commands/prd-check.js +0 -285
- package/dist/runtime/commands/privacy.js +0 -107
- package/dist/runtime/commands/recipe.js +0 -325
- package/dist/runtime/commands/redo-blob-store.js +0 -92
- package/dist/runtime/commands/redo.js +0 -361
- package/dist/runtime/commands/release-notes.js +0 -229
- package/dist/runtime/commands/repo-map.js +0 -95
- package/dist/runtime/commands/report.js +0 -299
- package/dist/runtime/commands/resume.js +0 -118
- package/dist/runtime/commands/review-consensus.js +0 -414
- package/dist/runtime/commands/rewind.js +0 -333
- package/dist/runtime/commands/roster.js +0 -117
- package/dist/runtime/commands/sessions.js +0 -163
- package/dist/runtime/commands/share.js +0 -316
- package/dist/runtime/commands/skills.js +0 -401
- package/dist/runtime/commands/status.js +0 -186
- package/dist/runtime/commands/stickers.js +0 -82
- package/dist/runtime/commands/style.js +0 -194
- package/dist/runtime/commands/theme.js +0 -196
- package/dist/runtime/commands/undo.js +0 -361
- package/dist/runtime/commands/update.js +0 -289
- package/dist/runtime/commands/vim.js +0 -140
- package/dist/runtime/commands/worktree.js +0 -177
- package/dist/runtime/commands/worktrees.js +0 -155
- package/dist/runtime/deprecation-warning.js +0 -69
- package/dist/runtime/engine-exit-code.js +0 -50
- package/dist/runtime/headless-repl.js +0 -195
- package/dist/runtime/headless.js +0 -548
- package/dist/runtime/load-hooks-or-exit.js +0 -71
- package/dist/runtime/plan-decompose.js +0 -531
- package/dist/runtime/sigint-guard.js +0 -272
- package/dist/runtime/stream-renderer.js +0 -195
- package/dist/runtime/update-check.js +0 -294
- package/dist/runtime/version.js +0 -65
- package/dist/runtime/worktree-bootstrap.js +0 -579
- package/dist/skills/bundled/batch.js +0 -617
- package/dist/skills/bundled/index.js +0 -45
- package/dist/skills/bundled/loop.js +0 -358
- package/dist/skills/bundled/remember.js +0 -383
- package/dist/skills/bundled/simplify.js +0 -289
- package/dist/skills/bundled/skillify.js +0 -373
- package/dist/skills/bundled/stuck.js +0 -558
- package/dist/skills/bundled/verify.js +0 -439
- package/dist/testing/vcr.js +0 -486
- package/dist/tools/agent-tool.js +0 -229
- package/dist/tools/apply-patch.js +0 -556
- package/dist/tools/ask-user-question.js +0 -337
- package/dist/tools/ask-user.js +0 -115
- package/dist/tools/bash.js +0 -1238
- package/dist/tools/brief.js +0 -224
- package/dist/tools/cron.js +0 -433
- package/dist/tools/enter-worktree.js +0 -250
- package/dist/tools/exit-worktree.js +0 -147
- package/dist/tools/file-tools.js +0 -553
- package/dist/tools/http-request.js +0 -336
- package/dist/tools/lsp-tools.js +0 -565
- package/dist/tools/mcp-tool.js +0 -260
- package/dist/tools/multi-edit.js +0 -361
- package/dist/tools/powershell.js +0 -268
- package/dist/tools/registry.js +0 -166
- package/dist/tools/server-tools.js +0 -892
- package/dist/tools/skill-tool.js +0 -96
- package/dist/tools/sleep.js +0 -99
- package/dist/tools/synthetic-output.js +0 -133
- package/dist/tools/tasks.js +0 -208
- package/dist/tools/todo-write.js +0 -184
- package/dist/tools/verify-plan-execution.js +0 -295
- package/dist/tools/web-fetch-injection-scanner.js +0 -207
- package/dist/tools/web-fetch.js +0 -720
- package/dist/tools/web-search.js +0 -458
- package/dist/tui/agent-progress-card.js +0 -111
- package/dist/tui/agent-tree-pane.js +0 -9
- package/dist/tui/agent-tree.js +0 -87
- package/dist/tui/ask-cli.js +0 -52
- package/dist/tui/ask-modal.js +0 -211
- package/dist/tui/ask-user-question-chips.js +0 -315
- package/dist/tui/ask-user-question-prompt.js +0 -203
- package/dist/tui/compact-banner.js +0 -81
- package/dist/tui/conversation-pane.js +0 -164
- package/dist/tui/cost-table.js +0 -111
- package/dist/tui/device-flow.js +0 -142
- package/dist/tui/doctor-table.js +0 -46
- package/dist/tui/feedback-prompt.js +0 -156
- package/dist/tui/input-box.js +0 -732
- package/dist/tui/login-picker.js +0 -69
- package/dist/tui/markdown-render.js +0 -266
- package/dist/tui/multi-file-diff-approval.js +0 -375
- package/dist/tui/onboarding-wizard.js +0 -240
- package/dist/tui/permissions-picker.js +0 -86
- package/dist/tui/render.js +0 -160
- package/dist/tui/repl-render.js +0 -770
- package/dist/tui/repl-splash-art.js +0 -64
- package/dist/tui/repl-splash-mascot.js +0 -154
- package/dist/tui/repl-splash.js +0 -117
- package/dist/tui/repl.js +0 -378
- package/dist/tui/slash-palette.js +0 -106
- package/dist/tui/splash-data.js +0 -61
- package/dist/tui/splash.js +0 -31
- package/dist/tui/status-bar.js +0 -209
- package/dist/tui/status-table.js +0 -7
- package/dist/tui/stickers-art.js +0 -136
- package/dist/tui/style-table.js +0 -28
- package/dist/tui/theme-table.js +0 -29
- package/dist/tui/thinking-spinner.js +0 -123
- package/dist/tui/tool-stream-pane.js +0 -140
- package/dist/tui/update-banner.js +0 -33
- package/dist/tui/vim-input.js +0 -267
- package/dist/tui/welcome-banner.js +0 -107
- package/dist/tui/welcome-data.js +0 -293
- package/dist/tui/workspace-context.js +0 -105
- package/docs/examples/codegraph.mcp.json +0 -10
- package/test/scenarios/codegen-create-file.scenario.txt +0 -13
- package/test/scenarios/compact-force.scenario.txt +0 -12
- package/test/scenarios/identity.scenario.txt +0 -11
- package/test/scenarios/persona-handoff.scenario.txt +0 -12
- package/test/scenarios/walkback.scenario.txt +0 -12
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Workspace context resolver — Sprint wave 4.
|
|
3
|
-
*
|
|
4
|
-
* Reads the operator's cwd and synthesises the workspace bundle the CLI
|
|
5
|
-
* forwards to admin-api on POST /api/pugi/sessions. Pugi's prompt v1.1
|
|
6
|
-
* consumes the bundle so "what repo is this?" / "а изучи репо…" answers
|
|
7
|
-
* from the live cwd instead of bouncing back "репо не привязано" (CEO
|
|
8
|
-
* dogfood).
|
|
9
|
-
*
|
|
10
|
-
* Three fields:
|
|
11
|
-
*
|
|
12
|
-
* - `workspaceCwd` — absolute path the CLI was launched from.
|
|
13
|
-
* - `workspaceSlug` — a stable short identifier (slugForCwd).
|
|
14
|
-
* - `workspaceSummary` — first ~200 chars of `.pugi/PUGI.md` if the
|
|
15
|
-
* repo has one, else the directory basename.
|
|
16
|
-
*
|
|
17
|
-
* The helper is pure-ish (reads the filesystem but does not mutate it)
|
|
18
|
-
* so the production caller in `runtime/cli.ts` can call it eagerly at
|
|
19
|
-
* REPL launch without touching the network. Tests pass an explicit cwd
|
|
20
|
-
* + `fs` stub so the resolver stays deterministic.
|
|
21
|
-
*
|
|
22
|
-
* Failure mode: any FS error (permission denied, missing PUGI.md,
|
|
23
|
-
* symlink loop) returns the basename fallback. The CLI never bubbles
|
|
24
|
-
* the error to the operator — workspace context is a best-effort hint,
|
|
25
|
-
* not a precondition for opening the session.
|
|
26
|
-
*/
|
|
27
|
-
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
28
|
-
import { basename, resolve as resolvePath } from 'node:path';
|
|
29
|
-
import { slugForCwd } from './history.js';
|
|
30
|
-
import { isBareMode } from '../bare-mode/index.js';
|
|
31
|
-
/**
|
|
32
|
-
* Workspace summary shown when the operator launched with `--bare` (or
|
|
33
|
-
* `PUGI_BARE=1`). bare mode disables project auto-discovery
|
|
34
|
-
* across the CLI, so we never read `.pugi/PUGI.md` and never advertise
|
|
35
|
-
* a real workspace label to admin-api. Explicit string so the splash +
|
|
36
|
-
* status bar agree, and so operators triaging "why is Pugi ignoring
|
|
37
|
-
* my repo" see a clear cause.
|
|
38
|
-
*/
|
|
39
|
-
export const BARE_MODE_WORKSPACE_LABEL = '(bare mode - auto-discovery disabled)';
|
|
40
|
-
/** Cap on the PUGI.md head we forward. Mirrors the admin-api clamp. */
|
|
41
|
-
const PUGI_MD_HEAD_LIMIT = 200;
|
|
42
|
-
/**
|
|
43
|
-
* Workspace label shown when the cwd has no project markers (no .git,
|
|
44
|
-
* no package.json, no PUGI.md). Per CEO dogfood, the
|
|
45
|
-
* previous behaviour leaked the parent directory basename (e.g.
|
|
46
|
-
* `codeforge-io`) into the splash as if it were a real workspace,
|
|
47
|
-
* confusing Pugi/Pugi about what repo she was looking at. The
|
|
48
|
-
* unbound label is a single explicit string so the splash + status bar
|
|
49
|
-
* read the same warning.
|
|
50
|
-
*/
|
|
51
|
-
export const UNBOUND_WORKSPACE_LABEL = '(not bound - run /init OR cd into project)';
|
|
52
|
-
/**
|
|
53
|
-
* Resolve a `ReplWorkspaceContext` from the operator's working directory.
|
|
54
|
-
* Returns a bundle with at least `workspaceCwd` + `workspaceSlug` +
|
|
55
|
-
* `workspaceSummary` populated. The summary is the PUGI.md head when
|
|
56
|
-
* available, else the directory basename.
|
|
57
|
-
*/
|
|
58
|
-
export function resolveWorkspaceContext(cwd) {
|
|
59
|
-
const normalised = resolvePath(cwd);
|
|
60
|
-
const slug = slugForCwd(normalised);
|
|
61
|
-
// `--bare` short-circuits BEFORE any PUGI.md
|
|
62
|
-
// / project-marker reads so the resolver never advertises a real
|
|
63
|
-
// workspace summary to admin-api. The cwd + slug still travel for
|
|
64
|
-
// telemetry, but the model + Pugi treat the session as if launched
|
|
65
|
-
// from a fresh, unbound directory.
|
|
66
|
-
if (isBareMode()) {
|
|
67
|
-
return {
|
|
68
|
-
workspaceCwd: normalised,
|
|
69
|
-
workspaceSlug: slug,
|
|
70
|
-
workspaceSummary: BARE_MODE_WORKSPACE_LABEL,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
// wave 5: when the cwd has no project markers, prefer the
|
|
74
|
-
// explicit "not bound" summary so admin-api's prompt builder knows
|
|
75
|
-
// not to fabricate a workspace context for Pugi/Pugi. The cwd +
|
|
76
|
-
// slug still travel so the server can record where the operator
|
|
77
|
-
// launched from for telemetry, but the summary no longer leaks a
|
|
78
|
-
// stray parent-dir basename as if it were a real workspace.
|
|
79
|
-
const summary = isBoundWorkspace(normalised)
|
|
80
|
-
? (readPugiSummary(normalised) ?? basename(normalised) ?? 'workspace')
|
|
81
|
-
: UNBOUND_WORKSPACE_LABEL;
|
|
82
|
-
return {
|
|
83
|
-
workspaceCwd: normalised,
|
|
84
|
-
workspaceSlug: slug,
|
|
85
|
-
workspaceSummary: summary,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Project-marker probe used by the REPL splash + status bar to decide
|
|
90
|
-
* whether the cwd is a real workspace or a stray parent dir the
|
|
91
|
-
* operator wandered into. The probe is intentionally cheap — three
|
|
92
|
-
* `existsSync` calls — and the order matches the brand convention:
|
|
93
|
-
*
|
|
94
|
-
* 1. `.git` — any clone of a real repo
|
|
95
|
-
* 2. `package.json` — JS/TS workspace root
|
|
96
|
-
* 3. `PUGI.md` — a Pugi-initialised workspace (root or
|
|
97
|
-
* `.pugi/PUGI.md`)
|
|
98
|
-
*
|
|
99
|
-
* Hitting any one of these counts the cwd as "bound" — the operator
|
|
100
|
-
* intentionally landed in a project. Hitting none means they ran
|
|
101
|
-
* `pugi` from `$HOME` or from the parent of a checkout; in that case
|
|
102
|
-
* the splash surfaces an explicit "not bound" label instead of leaking
|
|
103
|
-
* the parent-dir basename as if it were a workspace. The check
|
|
104
|
-
* mirrors the the upstream tool "no CLAUDE.md → silent context" rule —
|
|
105
|
-
* never fake-bind.
|
|
106
|
-
*/
|
|
107
|
-
export function isBoundWorkspace(cwd) {
|
|
108
|
-
const normalised = resolvePath(cwd);
|
|
109
|
-
// Case-sensitive checks; the resolver lower-cases PUGI.md when it
|
|
110
|
-
// reads the head, but the existence probe stays strict so a stray
|
|
111
|
-
// `pugi.md` does not accidentally pass without `pugi init` having
|
|
112
|
-
// run.
|
|
113
|
-
if (existsSync(resolvePath(normalised, '.git')))
|
|
114
|
-
return true;
|
|
115
|
-
if (existsSync(resolvePath(normalised, 'package.json')))
|
|
116
|
-
return true;
|
|
117
|
-
if (existsSync(resolvePath(normalised, 'PUGI.md')))
|
|
118
|
-
return true;
|
|
119
|
-
if (existsSync(resolvePath(normalised, '.pugi', 'PUGI.md')))
|
|
120
|
-
return true;
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Resolve the workspace label shown on the splash + the REPL header.
|
|
125
|
-
* When the cwd has project markers, returns the directory basename;
|
|
126
|
-
* otherwise returns the explicit "not bound" warning so the operator
|
|
127
|
-
* understands no real workspace was detected. The label is the only
|
|
128
|
-
* string the splash and status bar agree on, so we centralise the
|
|
129
|
-
* decision here instead of re-deriving in two places.
|
|
130
|
-
*
|
|
131
|
-
*/
|
|
132
|
-
export function resolveWorkspaceLabel(cwd) {
|
|
133
|
-
if (!isBoundWorkspace(cwd))
|
|
134
|
-
return UNBOUND_WORKSPACE_LABEL;
|
|
135
|
-
const normalised = resolvePath(cwd);
|
|
136
|
-
const segment = basename(normalised);
|
|
137
|
-
if (!segment || segment.length === 0)
|
|
138
|
-
return 'workspace';
|
|
139
|
-
return segment;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Read the first ~200 chars of `.pugi/PUGI.md` if the file exists. The
|
|
143
|
-
* project's own description is the highest-signal one-line summary we
|
|
144
|
-
* can hand to Pugi — `pugi init` writes it on workspace creation, and
|
|
145
|
-
* the operator may have edited it since.
|
|
146
|
-
*
|
|
147
|
-
* Returns null on any FS error so the caller falls back to the
|
|
148
|
-
* basename. We never throw — workspace context is best-effort.
|
|
149
|
-
*/
|
|
150
|
-
function readPugiSummary(cwd) {
|
|
151
|
-
const candidate = resolvePath(cwd, '.pugi', 'PUGI.md');
|
|
152
|
-
try {
|
|
153
|
-
if (!existsSync(candidate))
|
|
154
|
-
return null;
|
|
155
|
-
const st = statSync(candidate);
|
|
156
|
-
if (!st.isFile())
|
|
157
|
-
return null;
|
|
158
|
-
// Cap the read at 2 KB — even a malformed PUGI.md will not be
|
|
159
|
-
// bigger than that's worth on a one-line summary, and capping
|
|
160
|
-
// bounds the slice cost on a giant file.
|
|
161
|
-
const raw = readFileSync(candidate, 'utf8').slice(0, 2048);
|
|
162
|
-
return summariseMarkdown(raw);
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Reduce a PUGI.md head to one short summary line: strip the front-
|
|
170
|
-
* matter and the leading H1 marker, take the first non-empty line,
|
|
171
|
-
* cap at PUGI_MD_HEAD_LIMIT. Whitespace collapses to single spaces so
|
|
172
|
-
* the summary survives the admin-api clamp without weird wrap.
|
|
173
|
-
*/
|
|
174
|
-
export function summariseMarkdown(raw) {
|
|
175
|
-
if (!raw || raw.trim().length === 0)
|
|
176
|
-
return null;
|
|
177
|
-
const body = stripFrontmatter(raw);
|
|
178
|
-
const lines = body.split(/\r?\n/);
|
|
179
|
-
for (const line of lines) {
|
|
180
|
-
// Strip leading `#` markers + trim whitespace. A heading like
|
|
181
|
-
// "# My Project" becomes "My Project".
|
|
182
|
-
const stripped = line.replace(/^#+\s*/, '').trim();
|
|
183
|
-
if (stripped.length === 0)
|
|
184
|
-
continue;
|
|
185
|
-
const oneLine = stripped.replace(/\s+/g, ' ');
|
|
186
|
-
return oneLine.length > PUGI_MD_HEAD_LIMIT
|
|
187
|
-
? oneLine.slice(0, PUGI_MD_HEAD_LIMIT)
|
|
188
|
-
: oneLine;
|
|
189
|
-
}
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Drop a YAML front-matter block (`---\n…\n---`) from the head of a
|
|
194
|
-
* Markdown file. Pugi does not need to see the metadata; the prose body
|
|
195
|
-
* carries the project description.
|
|
196
|
-
*/
|
|
197
|
-
function stripFrontmatter(raw) {
|
|
198
|
-
if (!raw.startsWith('---'))
|
|
199
|
-
return raw;
|
|
200
|
-
const end = raw.indexOf('\n---', 3);
|
|
201
|
-
if (end === -1)
|
|
202
|
-
return raw;
|
|
203
|
-
const afterFrontmatter = raw.slice(end + 4);
|
|
204
|
-
return afterFrontmatter.replace(/^\r?\n/, '');
|
|
205
|
-
}
|
|
206
|
-
//# sourceMappingURL=workspace-context.js.map
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Repo-map build orchestrator — .
|
|
3
|
-
*
|
|
4
|
-
* Single entry point that the CLI command + the engine boot path both
|
|
5
|
-
* call. Wires the scanner → extractor → cache → formatter pipeline
|
|
6
|
-
* together and surfaces a structured result the caller can render or
|
|
7
|
-
* inject without knowing the inner module shapes.
|
|
8
|
-
*
|
|
9
|
-
* The orchestrator is split out от cache.ts and the command handler
|
|
10
|
-
* so:
|
|
11
|
-
*
|
|
12
|
-
* 1. The CLI command + the engine system-prompt injector share one
|
|
13
|
-
* code path. Drift between the two would silently change what
|
|
14
|
-
* the model sees vs. what the operator sees.
|
|
15
|
-
*
|
|
16
|
-
* 2. The spec can exercise the full pipeline against a temp dir
|
|
17
|
-
* without mounting Ink or the engine.
|
|
18
|
-
*
|
|
19
|
-
* Pure-ish: reads from disk (the source files + the cache), but never
|
|
20
|
-
* mutates anything outside `.pugi/repo-map.json` and never logs. The
|
|
21
|
-
* caller decides whether к persist the cache (`writeCache: true`) or
|
|
22
|
-
* к compute the map в-memory (`writeCache: false` — useful for
|
|
23
|
-
* non-interactive `--json` invocations on read-only fs).
|
|
24
|
-
*/
|
|
25
|
-
import { readFileSync } from 'node:fs';
|
|
26
|
-
import { loadPugiIgnore } from '../context/pugiignore.js';
|
|
27
|
-
import { defaultCachePath, diffCacheAgainstScan, mergeCache, readRepoMapCache, writeRepoMapCache, } from './cache.js';
|
|
28
|
-
import { extractFromFile } from './extractor.js';
|
|
29
|
-
import { scanRepoForMap } from './scanner.js';
|
|
30
|
-
import { formatRepoMap } from './formatter.js';
|
|
31
|
-
/**
|
|
32
|
-
* Run the full pipeline. Returns a structured verdict; never throws.
|
|
33
|
-
* The 'too-large' branch fires when the workspace exceeds the file
|
|
34
|
-
* cap — callers surface a hint к the operator ("repo too large for
|
|
35
|
-
* inline map — try .pugiignore") and skip injection.
|
|
36
|
-
*/
|
|
37
|
-
export function buildRepoMap(options) {
|
|
38
|
-
const root = options.root;
|
|
39
|
-
const refresh = options.refresh === true;
|
|
40
|
-
const writeCache = options.writeCache !== false;
|
|
41
|
-
const cachePath = options.cachePath ?? defaultCachePath(root);
|
|
42
|
-
const readFile = options.readFile ?? ((path) => readFileSync(path, 'utf8'));
|
|
43
|
-
const ignore = loadPugiIgnore(root);
|
|
44
|
-
const scan = scanRepoForMap({ root, ignore });
|
|
45
|
-
if (!scan.ok) {
|
|
46
|
-
return {
|
|
47
|
-
ok: false,
|
|
48
|
-
root,
|
|
49
|
-
reason: scan.skipped.reason,
|
|
50
|
-
walked: scan.skipped.walked,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
const prior = refresh ? null : readCacheOrNull(cachePath);
|
|
54
|
-
const diff = diffCacheAgainstScan(prior, scan.files);
|
|
55
|
-
const freshExtracts = new Map();
|
|
56
|
-
for (const file of diff.toRebuild) {
|
|
57
|
-
let source;
|
|
58
|
-
try {
|
|
59
|
-
source = readFile(file.absPath);
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
// File vanished или became unreadable mid-build — skip. The
|
|
63
|
-
// cache layer will just not have an entry for it; next refresh
|
|
64
|
-
// picks it up if it reappears.
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
freshExtracts.set(file.relPath, extractFromFile(file, source));
|
|
68
|
-
}
|
|
69
|
-
const cache = mergeCache({
|
|
70
|
-
root,
|
|
71
|
-
prior,
|
|
72
|
-
scanned: scan.files,
|
|
73
|
-
freshExtracts,
|
|
74
|
-
});
|
|
75
|
-
let cacheWritten = false;
|
|
76
|
-
if (writeCache) {
|
|
77
|
-
const writeResult = writeRepoMapCache(cachePath, cache);
|
|
78
|
-
cacheWritten = writeResult.ok;
|
|
79
|
-
}
|
|
80
|
-
// Surface the extracts в the same order the scanner produced (sorted
|
|
81
|
-
// by POSIX path) so callers iterating the result render deterministic
|
|
82
|
-
// output. The formatter does its own priority sort, so a different
|
|
83
|
-
// order here would only affect callers that iterate manually.
|
|
84
|
-
const extracts = [];
|
|
85
|
-
for (const file of scan.files) {
|
|
86
|
-
const entry = cache.entries[file.relPath];
|
|
87
|
-
if (entry)
|
|
88
|
-
extracts.push(entry.extract);
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
ok: true,
|
|
92
|
-
root,
|
|
93
|
-
cache,
|
|
94
|
-
extracts,
|
|
95
|
-
scanStats: scan.stats,
|
|
96
|
-
diffStats: {
|
|
97
|
-
rebuilt: diff.toRebuild.length,
|
|
98
|
-
reused: diff.reuse.length,
|
|
99
|
-
dropped: diff.toDrop.length,
|
|
100
|
-
},
|
|
101
|
-
cachePath,
|
|
102
|
-
cacheWritten,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Convenience wrapper: build + format в one call. The engine boot
|
|
107
|
-
* path uses this so it does not have к know the formatter shape.
|
|
108
|
-
*/
|
|
109
|
-
export function buildAndFormatRepoMap(options) {
|
|
110
|
-
const build = buildRepoMap(options);
|
|
111
|
-
if (!build.ok)
|
|
112
|
-
return { build };
|
|
113
|
-
const format = formatRepoMap(build.extracts, {
|
|
114
|
-
maxBytes: options.formatBytesCap,
|
|
115
|
-
omitHeader: options.omitHeader,
|
|
116
|
-
});
|
|
117
|
-
return { build, format };
|
|
118
|
-
}
|
|
119
|
-
function readCacheOrNull(path) {
|
|
120
|
-
const verdict = readRepoMapCache(path);
|
|
121
|
-
if (verdict.ok)
|
|
122
|
-
return verdict.cache;
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=build.js.map
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Repo-map cache — .
|
|
3
|
-
*
|
|
4
|
-
* Persists the result of the scan + extract passes к
|
|
5
|
-
* `.pugi/repo-map.json` so subsequent boots reuse the symbol table
|
|
6
|
-
* without re-walking the workspace. The cache key is `(mtimeMs, size)`
|
|
7
|
-
* per file, matching the heuristic used by Node's own native
|
|
8
|
-
* `node:fs.statSync` cache and Git's index format. A file whose mtime
|
|
9
|
-
* AND size match the cached entry is presumed unchanged; otherwise the
|
|
10
|
-
* extractor re-runs against the fresh contents.
|
|
11
|
-
*
|
|
12
|
-
* Why not a content hash:
|
|
13
|
-
*
|
|
14
|
-
* The file-cache module already hashes by content for the
|
|
15
|
-
* working-set heuristic, and the L28 use case is different — repo-
|
|
16
|
-
* map invalidation is "should we re-parse" not "is this content
|
|
17
|
-
* identical to the last cached version". A content-hash sweep would
|
|
18
|
-
* re-read every source file on every boot, defeating the purpose of
|
|
19
|
-
* a cache. mtime + size matches the cost profile (one stat call per
|
|
20
|
-
* file, no read) while catching every realistic edit pattern
|
|
21
|
-
* (editors universally update mtime; even `truncate` updates size).
|
|
22
|
-
*
|
|
23
|
-
* Why JSON not SQLite:
|
|
24
|
-
*
|
|
25
|
-
* The index-store ships as a flat JSON blob and parses в <50 ms
|
|
26
|
-
* for typical repos (~2000 files); we match the format так the
|
|
27
|
-
* doctor probe + cabinet sync tools can read repo-map.json without
|
|
28
|
-
* spinning up a SQLite driver. The blob is gzip-friendly if a future
|
|
29
|
-
* sprint wants к ship it across the wire.
|
|
30
|
-
*
|
|
31
|
-
* Schema versioning: every cache entry carries `schemaVersion`. When
|
|
32
|
-
* the extractor surface changes (new symbol kinds, new summary
|
|
33
|
-
* format), bump the constant and existing caches are dropped on the
|
|
34
|
-
* next boot — same pattern as the migration runner.
|
|
35
|
-
*
|
|
36
|
-
* Pure-ish surface: reads / writes use `node:fs` sync, no logging.
|
|
37
|
-
* Errors are converted к structured results so the caller can decide
|
|
38
|
-
* whether к surface them or fall back к a cold rebuild.
|
|
39
|
-
*/
|
|
40
|
-
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
41
|
-
import { dirname, join } from 'node:path';
|
|
42
|
-
/**
|
|
43
|
-
* Cache format version. Bump when:
|
|
44
|
-
* - `RepoMapSymbol` adds / renames a field
|
|
45
|
-
* - `RepoMapFileExtract` adds / renames a field
|
|
46
|
-
* - The mtime + size invalidation contract changes
|
|
47
|
-
*
|
|
48
|
-
* Old caches with a mismatched version are dropped on read.
|
|
49
|
-
*/
|
|
50
|
-
export const REPO_MAP_CACHE_VERSION = 1;
|
|
51
|
-
/**
|
|
52
|
-
* Default location for the workspace cache file. Mirrors the rest of
|
|
53
|
-
* the `.pugi/` convention: `<workspace>/.pugi/repo-map.json`.
|
|
54
|
-
*/
|
|
55
|
-
export function defaultCachePath(workspaceRoot) {
|
|
56
|
-
return join(workspaceRoot, '.pugi', 'repo-map.json');
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Read the cache file from disk. Returns a structured verdict; never
|
|
60
|
-
* throws. The 'missing' branch is the cold-boot happy path. The
|
|
61
|
-
* 'parse-error' branch signals corruption — the caller drops the
|
|
62
|
-
* cache and rebuilds. The 'version-mismatch' branch fires after an
|
|
63
|
-
* extractor schema bump.
|
|
64
|
-
*/
|
|
65
|
-
export function readRepoMapCache(path) {
|
|
66
|
-
if (!existsSync(path)) {
|
|
67
|
-
return { ok: false, reason: 'missing' };
|
|
68
|
-
}
|
|
69
|
-
let raw;
|
|
70
|
-
try {
|
|
71
|
-
raw = readFileSync(path, 'utf8');
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
return { ok: false, reason: 'parse-error' };
|
|
75
|
-
}
|
|
76
|
-
let parsed;
|
|
77
|
-
try {
|
|
78
|
-
parsed = JSON.parse(raw);
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
return { ok: false, reason: 'parse-error' };
|
|
82
|
-
}
|
|
83
|
-
if (!isCacheShape(parsed)) {
|
|
84
|
-
return { ok: false, reason: 'parse-error' };
|
|
85
|
-
}
|
|
86
|
-
if (parsed.schemaVersion !== REPO_MAP_CACHE_VERSION) {
|
|
87
|
-
return { ok: false, reason: 'version-mismatch' };
|
|
88
|
-
}
|
|
89
|
-
return { ok: true, cache: parsed };
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Write the cache atomically (write-then-rename) so a concurrent
|
|
93
|
-
* reader never sees a half-flushed JSON blob. Errors are surfaced as
|
|
94
|
-
* a structured boolean so the caller can decide whether к escalate —
|
|
95
|
-
* the engine boot path silently swallows write failures because
|
|
96
|
-
* repo-map is a best-effort enrichment.
|
|
97
|
-
*/
|
|
98
|
-
export function writeRepoMapCache(path, cache) {
|
|
99
|
-
try {
|
|
100
|
-
const dir = dirname(path);
|
|
101
|
-
if (!existsSync(dir)) {
|
|
102
|
-
mkdirSync(dir, { recursive: true });
|
|
103
|
-
}
|
|
104
|
-
const body = JSON.stringify(cache, null, 2) + '\n';
|
|
105
|
-
const tmp = path + '.tmp';
|
|
106
|
-
writeFileSync(tmp, body, { encoding: 'utf8' });
|
|
107
|
-
// Atomic rename. `fs.renameSync` is atomic on POSIX + on NTFS when
|
|
108
|
-
// src + dst live on the same volume, which is always true for
|
|
109
|
-
// `.pugi/`-local writes.
|
|
110
|
-
renameSync(tmp, path);
|
|
111
|
-
return { ok: true };
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
return {
|
|
115
|
-
ok: false,
|
|
116
|
-
error: error instanceof Error ? error.message : String(error),
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
export function diffCacheAgainstScan(prior, scanned) {
|
|
121
|
-
const toRebuild = [];
|
|
122
|
-
const reuse = [];
|
|
123
|
-
const seen = new Set();
|
|
124
|
-
for (const file of scanned) {
|
|
125
|
-
seen.add(file.relPath);
|
|
126
|
-
const entry = prior?.entries[file.relPath];
|
|
127
|
-
if (!entry
|
|
128
|
-
|| entry.mtimeMs !== file.mtimeMs
|
|
129
|
-
|| entry.sizeBytes !== file.sizeBytes) {
|
|
130
|
-
toRebuild.push(file);
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
reuse.push(file.relPath);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
const toDrop = [];
|
|
137
|
-
if (prior) {
|
|
138
|
-
for (const key of Object.keys(prior.entries)) {
|
|
139
|
-
if (!seen.has(key))
|
|
140
|
-
toDrop.push(key);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return { toRebuild, toDrop, reuse };
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Stitch a fresh cache object together from the prior surviving
|
|
147
|
-
* entries + the newly-extracted ones. Pure helper — the caller is
|
|
148
|
-
* responsible for actually writing the result.
|
|
149
|
-
*/
|
|
150
|
-
export function mergeCache(args) {
|
|
151
|
-
const { root, prior, scanned, freshExtracts } = args;
|
|
152
|
-
const entries = {};
|
|
153
|
-
for (const file of scanned) {
|
|
154
|
-
const fresh = freshExtracts.get(file.relPath);
|
|
155
|
-
if (fresh) {
|
|
156
|
-
entries[file.relPath] = {
|
|
157
|
-
mtimeMs: file.mtimeMs,
|
|
158
|
-
sizeBytes: file.sizeBytes,
|
|
159
|
-
extract: fresh,
|
|
160
|
-
};
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
const priorEntry = prior?.entries[file.relPath];
|
|
164
|
-
if (priorEntry) {
|
|
165
|
-
entries[file.relPath] = priorEntry;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return {
|
|
169
|
-
schemaVersion: REPO_MAP_CACHE_VERSION,
|
|
170
|
-
root,
|
|
171
|
-
builtAtMs: args.nowMs ?? Date.now(),
|
|
172
|
-
entries,
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
function isCacheShape(value) {
|
|
176
|
-
if (typeof value !== 'object' || value === null)
|
|
177
|
-
return false;
|
|
178
|
-
const v = value;
|
|
179
|
-
return (typeof v.schemaVersion === 'number'
|
|
180
|
-
&& typeof v.root === 'string'
|
|
181
|
-
&& typeof v.builtAtMs === 'number'
|
|
182
|
-
&& typeof v.entries === 'object'
|
|
183
|
-
&& v.entries !== null);
|
|
184
|
-
}
|
|
185
|
-
//# sourceMappingURL=cache.js.map
|