@pugi/cli 0.1.0-beta.99 → 1.0.0-alpha.1
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,201 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* `pugi jobs --watch` Ink TUI — live progress .
|
|
4
|
-
*
|
|
5
|
-
* Tails `~/.pugi/agent-progress/*.json` via chokidar and re-renders a
|
|
6
|
-
* grid of <AgentProgressCard> components. Mirrors the the upstream tool
|
|
7
|
-
* `/compact` layout pattern — one card per agent, sorted by status
|
|
8
|
-
* (running → completed → failed) then by lastUpdate descending so the
|
|
9
|
-
* freshest activity floats к the top.
|
|
10
|
-
*
|
|
11
|
-
* Lifecycle:
|
|
12
|
-
* 1. Resolve dir via resolveProgressDir() (env-aware).
|
|
13
|
-
* 2. Initial scan with readdirSync — populate the map.
|
|
14
|
-
* 3. chokidar.watch(dir, { ignoreInitial: true }) for add/change/unlink.
|
|
15
|
-
* 4. setInterval(1000) tick re-renders to keep elapsed labels live
|
|
16
|
-
* WITHOUT re-reading files.
|
|
17
|
-
* 5. SIGINT (Ctrl+C) triggers `app.unmount()` + process.exit(0).
|
|
18
|
-
*
|
|
19
|
-
* Layout: single column under 100 cols, two columns at 100+ cols
|
|
20
|
-
* (Ink's flexbox computes the responsive split automatically — we just
|
|
21
|
-
* set `flexDirection="row" flexWrap="wrap"` and bound each card к 50%
|
|
22
|
-
* width when stdout is wide enough).
|
|
23
|
-
*
|
|
24
|
-
* The TUI is opt-in (operator runs `pugi jobs --watch`); the bare
|
|
25
|
-
* `pugi jobs` continues to print the legacy job-registry table.
|
|
26
|
-
*/
|
|
27
|
-
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
28
|
-
import { join } from 'node:path';
|
|
29
|
-
import chokidar from 'chokidar';
|
|
30
|
-
import { useEffect, useMemo, useState } from 'react';
|
|
31
|
-
import { Box, Text, render, useApp, useInput, useStdout } from 'ink';
|
|
32
|
-
import { resolveProgressDir } from '../core/agent-progress/writer.js';
|
|
33
|
-
import { runCleanup } from '../core/agent-progress/cleanup.js';
|
|
34
|
-
import { validateAgentProgress, } from '../core/agent-progress/schema.js';
|
|
35
|
-
import { AgentProgressCard } from '../tui/agent-progress-card.js';
|
|
36
|
-
/** Cleanup pass cadence inside the watcher. Cheap (readdir on a small
|
|
37
|
-
* dir); 60s is the operator-tested sweet spot — fast enough to feel
|
|
38
|
-
* live, slow enough к never burn CPU. */
|
|
39
|
-
const CLEANUP_INTERVAL_MS = 60_000;
|
|
40
|
-
const STATUS_RANK = {
|
|
41
|
-
running: 0,
|
|
42
|
-
completed: 1,
|
|
43
|
-
failed: 2,
|
|
44
|
-
};
|
|
45
|
-
/**
|
|
46
|
-
* Read + validate one progress file. Returns undefined on any failure
|
|
47
|
-
* — the watcher prefers к skip a malformed entry rather than crash.
|
|
48
|
-
* Exported for the spec.
|
|
49
|
-
*/
|
|
50
|
-
export function readProgressFile(path) {
|
|
51
|
-
if (!existsSync(path))
|
|
52
|
-
return undefined;
|
|
53
|
-
try {
|
|
54
|
-
const body = readFileSync(path, 'utf8');
|
|
55
|
-
const parsed = JSON.parse(body);
|
|
56
|
-
const result = validateAgentProgress(parsed);
|
|
57
|
-
return result.ok ? result.value : undefined;
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Sort progress entries for stable, operator-friendly display:
|
|
65
|
-
* 1. Running first.
|
|
66
|
-
* 2. Then by lastUpdate (most recent first).
|
|
67
|
-
* 3. Tiebreak on agentId for snapshot stability.
|
|
68
|
-
*/
|
|
69
|
-
export function sortProgressEntries(entries) {
|
|
70
|
-
return [...entries].sort((a, b) => {
|
|
71
|
-
const rank = STATUS_RANK[a.status] - STATUS_RANK[b.status];
|
|
72
|
-
if (rank !== 0)
|
|
73
|
-
return rank;
|
|
74
|
-
const tsDiff = Date.parse(b.lastUpdate) - Date.parse(a.lastUpdate);
|
|
75
|
-
if (tsDiff !== 0)
|
|
76
|
-
return tsDiff;
|
|
77
|
-
return a.agentId.localeCompare(b.agentId);
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
export function JobsWatch(props) {
|
|
81
|
-
const { dir, nowEpochMs, staticMode = false } = props;
|
|
82
|
-
const resolvedDir = useMemo(() => resolveProgressDir(dir), [dir]);
|
|
83
|
-
const [agents, setAgents] = useState(() => initialScan(resolvedDir));
|
|
84
|
-
const [tick, setTick] = useState(0);
|
|
85
|
-
const { exit } = useApp();
|
|
86
|
-
const { stdout } = useStdout();
|
|
87
|
-
const cols = stdout?.columns ?? 80;
|
|
88
|
-
const twoColumns = cols >= 100;
|
|
89
|
-
useInput((_input, key) => {
|
|
90
|
-
if (key.escape || key.ctrl) {
|
|
91
|
-
// Ink's useInput passes ctrl=true for Ctrl+<x>; we exit on Ctrl+C
|
|
92
|
-
// (key.ctrl alone is too broad — actual key char arrives in `input`).
|
|
93
|
-
// Practically, raw mode passes Ctrl+C as SIGINT to the process so
|
|
94
|
-
// this is a belt-and-suspenders catch.
|
|
95
|
-
if (key.escape)
|
|
96
|
-
exit();
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
if (staticMode)
|
|
101
|
-
return;
|
|
102
|
-
let watcher;
|
|
103
|
-
try {
|
|
104
|
-
watcher = chokidar.watch(resolvedDir, {
|
|
105
|
-
ignoreInitial: true,
|
|
106
|
-
depth: 0,
|
|
107
|
-
// The agent writer uses atomic rename — chokidar reports `add`
|
|
108
|
-
// when the final filename appears, never the *.tmp-* intermediate.
|
|
109
|
-
ignored: /\.tmp-/,
|
|
110
|
-
});
|
|
111
|
-
const onChange = (path) => {
|
|
112
|
-
if (!/\.json$/.test(path))
|
|
113
|
-
return;
|
|
114
|
-
const progress = readProgressFile(path);
|
|
115
|
-
if (!progress)
|
|
116
|
-
return;
|
|
117
|
-
setAgents((prev) => ({ ...prev, [progress.agentId]: progress }));
|
|
118
|
-
};
|
|
119
|
-
const onRemove = (path) => {
|
|
120
|
-
const match = /([^/\\]+)\.json$/.exec(path);
|
|
121
|
-
if (!match)
|
|
122
|
-
return;
|
|
123
|
-
const id = match[1];
|
|
124
|
-
if (!id)
|
|
125
|
-
return;
|
|
126
|
-
setAgents((prev) => {
|
|
127
|
-
if (!(id in prev))
|
|
128
|
-
return prev;
|
|
129
|
-
const next = { ...prev };
|
|
130
|
-
delete next[id];
|
|
131
|
-
return next;
|
|
132
|
-
});
|
|
133
|
-
};
|
|
134
|
-
watcher.on('add', onChange);
|
|
135
|
-
watcher.on('change', onChange);
|
|
136
|
-
watcher.on('unlink', onRemove);
|
|
137
|
-
}
|
|
138
|
-
catch {
|
|
139
|
-
// Watcher failures degrade gracefully — initial scan still rendered.
|
|
140
|
-
}
|
|
141
|
-
const interval = setInterval(() => setTick((t) => t + 1), 1000);
|
|
142
|
-
// Auto-cleanup completed/failed entries older than the TTL. The
|
|
143
|
-
// sweep moves them к `<dir>/archive/` so operators can still
|
|
144
|
-
// forensic; the watcher's chokidar `unlink` handler drops them
|
|
145
|
-
// from the live grid as the rename fires.
|
|
146
|
-
const cleanupInterval = setInterval(() => {
|
|
147
|
-
try {
|
|
148
|
-
runCleanup({ dir: resolvedDir });
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
151
|
-
// best-effort housekeeping; never crash the TUI
|
|
152
|
-
}
|
|
153
|
-
}, CLEANUP_INTERVAL_MS);
|
|
154
|
-
return () => {
|
|
155
|
-
clearInterval(interval);
|
|
156
|
-
clearInterval(cleanupInterval);
|
|
157
|
-
if (watcher) {
|
|
158
|
-
void watcher.close();
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
}, [resolvedDir, staticMode]);
|
|
162
|
-
const sorted = useMemo(() => sortProgressEntries(Object.values(agents)), [agents]);
|
|
163
|
-
const effectiveNow = nowEpochMs ?? Date.now() + tick * 0; // tick triggers re-render only
|
|
164
|
-
if (sorted.length === 0) {
|
|
165
|
-
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Text, { dimColor: true, children: ["No agents broadcasting progress yet. Watching", ' ', _jsx(Text, { bold: true, children: resolvedDir }), " for `<id>.json` files\u2026"] }), _jsx(Text, { dimColor: true, children: "(Press Esc / Ctrl+C \u043A exit.)" })] }));
|
|
166
|
-
}
|
|
167
|
-
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, children: "pugi jobs --watch" }), _jsxs(Text, { dimColor: true, children: [' ', "\u00B7 ", sorted.length, " ", sorted.length === 1 ? 'agent' : 'agents', " \u00B7", ' ', resolvedDir] })] }), _jsx(Box, { flexDirection: "row", flexWrap: "wrap", children: sorted.map((progress) => (_jsx(Box, { width: twoColumns ? '50%' : '100%', flexDirection: "column", children: _jsx(AgentProgressCard, { progress: progress, nowEpochMs: effectiveNow }) }, progress.agentId))) }), _jsx(Text, { dimColor: true, children: "(Esc / Ctrl+C \u043A exit.)" })] }));
|
|
168
|
-
}
|
|
169
|
-
function initialScan(dir) {
|
|
170
|
-
const map = {};
|
|
171
|
-
if (!existsSync(dir))
|
|
172
|
-
return map;
|
|
173
|
-
let entries;
|
|
174
|
-
try {
|
|
175
|
-
entries = readdirSync(dir);
|
|
176
|
-
}
|
|
177
|
-
catch {
|
|
178
|
-
return map;
|
|
179
|
-
}
|
|
180
|
-
for (const name of entries) {
|
|
181
|
-
if (!name.endsWith('.json'))
|
|
182
|
-
continue;
|
|
183
|
-
if (/\.tmp-/.test(name))
|
|
184
|
-
continue;
|
|
185
|
-
const progress = readProgressFile(join(dir, name));
|
|
186
|
-
if (progress)
|
|
187
|
-
map[progress.agentId] = progress;
|
|
188
|
-
}
|
|
189
|
-
return map;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Entry-point for `pugi jobs --watch`. Mounts the Ink app and returns
|
|
193
|
-
* a Promise that resolves when the user exits (Ctrl+C / Esc).
|
|
194
|
-
*/
|
|
195
|
-
export async function runJobsWatch(options = {}) {
|
|
196
|
-
return new Promise((resolve) => {
|
|
197
|
-
const app = render(_jsx(JobsWatch, { dir: options.dir }), { exitOnCtrlC: true });
|
|
198
|
-
void app.waitUntilExit().then(() => resolve(0));
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
//# sourceMappingURL=jobs-watch.js.map
|
package/dist/commands/jobs.js
DELETED
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `pugi jobs` command surface — Sprint .
|
|
3
|
-
*
|
|
4
|
-
* Subcommands:
|
|
5
|
-
* pugi jobs list — table of all tracked jobs (or JSON envelope)
|
|
6
|
-
* pugi jobs status <id> — full record + tail of overflow artifact
|
|
7
|
-
* pugi jobs tail <id> — stream the overflow artifact
|
|
8
|
-
* pugi jobs kill <id> — SIGTERM then SIGKILL after a grace
|
|
9
|
-
* pugi jobs kill --all — kill every running job in this session
|
|
10
|
-
*
|
|
11
|
-
* Power-word voice rules (per Pugi brand guide):
|
|
12
|
-
* - status names render as "on watch" (running), "shipped" (finished),
|
|
13
|
-
* "stood down" (killed), "blocked" (failed), "lost" (abandoned).
|
|
14
|
-
* - JSON envelopes keep the machine-friendly enum so consumers do
|
|
15
|
-
* not have to map back.
|
|
16
|
-
*/
|
|
17
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
18
|
-
import { formatDuration, getJobRegistry, relativeAge, } from '../core/jobs/registry.js';
|
|
19
|
-
import { runJobsWatch } from './jobs-watch.js';
|
|
20
|
-
const HUMAN_STATUS = {
|
|
21
|
-
running: 'on watch',
|
|
22
|
-
finished: 'shipped',
|
|
23
|
-
killed: 'stood down',
|
|
24
|
-
failed: 'blocked',
|
|
25
|
-
abandoned: 'lost',
|
|
26
|
-
};
|
|
27
|
-
export async function runJobsCommand(args, flags, io, sessionId) {
|
|
28
|
-
// live progress : `pugi jobs --watch` mounts the live
|
|
29
|
-
// agent-progress TUI. The flag may sit anywhere in the arg list
|
|
30
|
-
// (`pugi jobs --watch` or `pugi jobs watch`) — both forms route к
|
|
31
|
-
// the watcher. JSON mode is incompatible (it would never return); we
|
|
32
|
-
// bail with a helpful error instead of silently swallowing the flag.
|
|
33
|
-
const wantsWatch = args.includes('--watch') || args[0] === 'watch';
|
|
34
|
-
if (wantsWatch) {
|
|
35
|
-
if (flags.json) {
|
|
36
|
-
io.writeError('pugi jobs --watch is interactive; --json is not supported.');
|
|
37
|
-
return 2;
|
|
38
|
-
}
|
|
39
|
-
return runJobsWatch();
|
|
40
|
-
}
|
|
41
|
-
const sub = args[0] ?? 'list';
|
|
42
|
-
switch (sub) {
|
|
43
|
-
case 'list':
|
|
44
|
-
return runList(flags, io);
|
|
45
|
-
case 'status':
|
|
46
|
-
return runStatus(args[1], flags, io);
|
|
47
|
-
case 'tail':
|
|
48
|
-
return runTail(args[1], flags, io);
|
|
49
|
-
case 'kill':
|
|
50
|
-
return runKill(args.slice(1), flags, io, sessionId);
|
|
51
|
-
default:
|
|
52
|
-
io.writeError(`Unknown subcommand: ${sub}`);
|
|
53
|
-
io.writeError(usage());
|
|
54
|
-
return 2;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function usage() {
|
|
58
|
-
return [
|
|
59
|
-
'Usage:',
|
|
60
|
-
' pugi jobs list [--json] Table of background jobs.',
|
|
61
|
-
' pugi jobs status <id> [--json] Full record + tail of artifact.',
|
|
62
|
-
' pugi jobs tail <id> Stream the captured artifact.',
|
|
63
|
-
' pugi jobs kill <id> [--json] SIGTERM, escalate to SIGKILL.',
|
|
64
|
-
' pugi jobs kill --all [--json] Stand down every running job.',
|
|
65
|
-
' pugi jobs --watch Live Ink TUI of agent progress.',
|
|
66
|
-
].join('\n');
|
|
67
|
-
}
|
|
68
|
-
async function runList(flags, io) {
|
|
69
|
-
const registry = getJobRegistry();
|
|
70
|
-
const entries = await registry.list();
|
|
71
|
-
if (flags.json) {
|
|
72
|
-
io.write(`${JSON.stringify({
|
|
73
|
-
command: 'jobs.list',
|
|
74
|
-
count: entries.length,
|
|
75
|
-
jobs: entries.map(serializeForJson),
|
|
76
|
-
}, null, 2)}\n`);
|
|
77
|
-
return 0;
|
|
78
|
-
}
|
|
79
|
-
io.write(`${renderTable(entries)}\n`);
|
|
80
|
-
return 0;
|
|
81
|
-
}
|
|
82
|
-
async function runStatus(id, flags, io) {
|
|
83
|
-
if (!id) {
|
|
84
|
-
io.writeError('pugi jobs status requires a job id');
|
|
85
|
-
return 2;
|
|
86
|
-
}
|
|
87
|
-
const registry = getJobRegistry();
|
|
88
|
-
const entry = await registry.get(id);
|
|
89
|
-
if (!entry) {
|
|
90
|
-
if (flags.json) {
|
|
91
|
-
io.write(`${JSON.stringify({ command: 'jobs.status', error: 'not_found', id }, null, 2)}\n`);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
io.writeError(`Job not found: ${id}`);
|
|
95
|
-
}
|
|
96
|
-
return 1;
|
|
97
|
-
}
|
|
98
|
-
const tail = entry.outputArtifactRef ? readArtifactTail(entry.outputArtifactRef, 4_096) : '';
|
|
99
|
-
if (flags.json) {
|
|
100
|
-
io.write(`${JSON.stringify({
|
|
101
|
-
command: 'jobs.status',
|
|
102
|
-
job: serializeForJson(entry),
|
|
103
|
-
tail,
|
|
104
|
-
}, null, 2)}\n`);
|
|
105
|
-
return 0;
|
|
106
|
-
}
|
|
107
|
-
const lines = [
|
|
108
|
-
`Job ${entry.id}`,
|
|
109
|
-
` PID: ${entry.pid}`,
|
|
110
|
-
` Command: ${entry.command}`,
|
|
111
|
-
` Class: ${entry.bashClass}`,
|
|
112
|
-
` Status: ${HUMAN_STATUS[entry.status]} (${entry.status})`,
|
|
113
|
-
` CWD: ${entry.cwd}`,
|
|
114
|
-
` Started: ${entry.startedAt} (${relativeAge(entry.startedAt)} ago)`,
|
|
115
|
-
` Duration: ${formatDuration(entry.startedAt, entry.finishedAt)}`,
|
|
116
|
-
];
|
|
117
|
-
if (entry.finishedAt)
|
|
118
|
-
lines.push(` Finished: ${entry.finishedAt}`);
|
|
119
|
-
if (entry.exitCode !== undefined)
|
|
120
|
-
lines.push(` Exit code: ${entry.exitCode}`);
|
|
121
|
-
if (entry.outputArtifactRef)
|
|
122
|
-
lines.push(` Artifact: ${entry.outputArtifactRef}`);
|
|
123
|
-
if (tail) {
|
|
124
|
-
lines.push('', '--- output tail ---', tail);
|
|
125
|
-
}
|
|
126
|
-
io.write(`${lines.join('\n')}\n`);
|
|
127
|
-
return 0;
|
|
128
|
-
}
|
|
129
|
-
async function runTail(id, _flags, io) {
|
|
130
|
-
if (!id) {
|
|
131
|
-
io.writeError('pugi jobs tail requires a job id');
|
|
132
|
-
return 2;
|
|
133
|
-
}
|
|
134
|
-
const registry = getJobRegistry();
|
|
135
|
-
const entry = await registry.get(id);
|
|
136
|
-
if (!entry) {
|
|
137
|
-
io.writeError(`Job not found: ${id}`);
|
|
138
|
-
return 1;
|
|
139
|
-
}
|
|
140
|
-
if (!entry.outputArtifactRef) {
|
|
141
|
-
io.writeError(`Job ${id} has no captured output artifact yet (background jobs spawn with stdio=ignore by default).`);
|
|
142
|
-
return 1;
|
|
143
|
-
}
|
|
144
|
-
if (!existsSync(entry.outputArtifactRef)) {
|
|
145
|
-
io.writeError(`Artifact missing on disk: ${entry.outputArtifactRef}`);
|
|
146
|
-
return 1;
|
|
147
|
-
}
|
|
148
|
-
const body = readFileSync(entry.outputArtifactRef, 'utf8');
|
|
149
|
-
io.write(body.endsWith('\n') ? body : `${body}\n`);
|
|
150
|
-
return 0;
|
|
151
|
-
}
|
|
152
|
-
async function runKill(args, flags, io, sessionId) {
|
|
153
|
-
const registry = getJobRegistry();
|
|
154
|
-
const killAll = flags.all || args.includes('--all');
|
|
155
|
-
if (killAll) {
|
|
156
|
-
const entries = await registry.list();
|
|
157
|
-
const targets = entries.filter((entry) => {
|
|
158
|
-
if (entry.status !== 'running')
|
|
159
|
-
return false;
|
|
160
|
-
if (sessionId && entry.sessionId !== sessionId)
|
|
161
|
-
return false;
|
|
162
|
-
return true;
|
|
163
|
-
});
|
|
164
|
-
const results = [];
|
|
165
|
-
for (const target of targets) {
|
|
166
|
-
const result = await registry.kill(target.id);
|
|
167
|
-
results.push({ id: target.id, ...result });
|
|
168
|
-
}
|
|
169
|
-
if (flags.json) {
|
|
170
|
-
io.write(`${JSON.stringify({ command: 'jobs.kill', scope: 'all', results }, null, 2)}\n`);
|
|
171
|
-
}
|
|
172
|
-
else if (results.length === 0) {
|
|
173
|
-
io.write('No running jobs to stand down.\n');
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
for (const result of results) {
|
|
177
|
-
io.write(` ${result.id} ${result.killed ? 'stood down' : 'noop'} (${result.method})\n`);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return 0;
|
|
181
|
-
}
|
|
182
|
-
const id = args[0];
|
|
183
|
-
if (!id) {
|
|
184
|
-
io.writeError('pugi jobs kill requires a job id (or --all)');
|
|
185
|
-
return 2;
|
|
186
|
-
}
|
|
187
|
-
const result = await registry.kill(id);
|
|
188
|
-
if (flags.json) {
|
|
189
|
-
io.write(`${JSON.stringify({ command: 'jobs.kill', id, ...result }, null, 2)}\n`);
|
|
190
|
-
return result.killed || result.method === 'noop' ? 0 : 1;
|
|
191
|
-
}
|
|
192
|
-
if (result.killed) {
|
|
193
|
-
io.write(`Job ${id} stood down (${result.method}).\n`);
|
|
194
|
-
return 0;
|
|
195
|
-
}
|
|
196
|
-
io.writeError(`Job ${id} was not running or could not be signalled.`);
|
|
197
|
-
return 1;
|
|
198
|
-
}
|
|
199
|
-
function serializeForJson(entry) {
|
|
200
|
-
const ageSeconds = Math.max(0, Math.floor((Date.now() - Date.parse(entry.startedAt)) / 1000));
|
|
201
|
-
let durationSeconds;
|
|
202
|
-
if (entry.finishedAt) {
|
|
203
|
-
const start = Date.parse(entry.startedAt);
|
|
204
|
-
const end = Date.parse(entry.finishedAt);
|
|
205
|
-
if (!Number.isNaN(start) && !Number.isNaN(end) && end >= start) {
|
|
206
|
-
durationSeconds = Math.floor((end - start) / 1000);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
return {
|
|
210
|
-
...entry,
|
|
211
|
-
humanStatus: HUMAN_STATUS[entry.status],
|
|
212
|
-
ageSeconds,
|
|
213
|
-
durationSeconds,
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
function readArtifactTail(path, byteBudget) {
|
|
217
|
-
if (!existsSync(path))
|
|
218
|
-
return '';
|
|
219
|
-
try {
|
|
220
|
-
const body = readFileSync(path, 'utf8');
|
|
221
|
-
if (body.length <= byteBudget)
|
|
222
|
-
return body;
|
|
223
|
-
return `(...truncated; tail ${byteBudget} bytes of ${body.length})\n${body.slice(-byteBudget)}`;
|
|
224
|
-
}
|
|
225
|
-
catch {
|
|
226
|
-
return '';
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
function renderTable(entries) {
|
|
230
|
-
if (entries.length === 0) {
|
|
231
|
-
return 'No background jobs tracked. Spawn one via the bash tool (background: true) and it lands here.';
|
|
232
|
-
}
|
|
233
|
-
const header = ['ID', 'COMMAND', 'CLASS', 'STATUS', 'STARTED', 'DURATION'];
|
|
234
|
-
const rows = [header];
|
|
235
|
-
for (const entry of entries) {
|
|
236
|
-
rows.push([
|
|
237
|
-
entry.id.replace(/^pj-/, '').slice(0, 8),
|
|
238
|
-
truncate(entry.command, 24),
|
|
239
|
-
entry.bashClass,
|
|
240
|
-
HUMAN_STATUS[entry.status],
|
|
241
|
-
`${relativeAge(entry.startedAt)} ago`,
|
|
242
|
-
formatDuration(entry.startedAt, entry.finishedAt),
|
|
243
|
-
]);
|
|
244
|
-
}
|
|
245
|
-
const widths = header.map((_, i) => Math.max(...rows.map((row) => (row[i] ?? '').length)));
|
|
246
|
-
// Reserve a little headroom so the right-hand columns do not bleed
|
|
247
|
-
// past 80 chars when the command column hits its 24-char ceiling.
|
|
248
|
-
return rows
|
|
249
|
-
.map((row) => row
|
|
250
|
-
.map((cell, i) => cell.padEnd(widths[i] ?? cell.length))
|
|
251
|
-
.join(' ')
|
|
252
|
-
.trimEnd())
|
|
253
|
-
.join('\n');
|
|
254
|
-
}
|
|
255
|
-
function truncate(value, max) {
|
|
256
|
-
if (value.length <= max)
|
|
257
|
-
return value;
|
|
258
|
-
return `${value.slice(0, max - 1)}…`;
|
|
259
|
-
}
|
|
260
|
-
//# sourceMappingURL=jobs.js.map
|
package/dist/commands/retro.js
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Text, render } from 'ink';
|
|
3
|
-
import { collectGitContext, countCommitsAheadOfBase, } from '../core/retro/git-collector.js';
|
|
4
|
-
import { ensurePugiGitIgnore } from '../core/pugi-gitignore.js';
|
|
5
|
-
import { computeMetrics } from '../core/retro/metrics.js';
|
|
6
|
-
import { persistRetro } from '../core/retro/narrative.js';
|
|
7
|
-
import { collectPlaneSlice, postRetroToPlane, resolvePlaneConfig, } from '../core/retro/plane-collector.js';
|
|
8
|
-
import { enrichLinks } from '../core/retro/pr-issue-link.js';
|
|
9
|
-
import { computeHealthCard } from '../core/retro/health-card.js';
|
|
10
|
-
/** Parse `7d` | `14d` | `30d` | `24h` into a duration in days
|
|
11
|
-
* (fractional for sub-day windows). Defaults to 7 days when omitted.
|
|
12
|
-
*/
|
|
13
|
-
function parseDurationToken(token) {
|
|
14
|
-
if (!token)
|
|
15
|
-
return undefined;
|
|
16
|
-
const match = /^(\d+)(h|d)$/.exec(token);
|
|
17
|
-
if (!match)
|
|
18
|
-
return undefined;
|
|
19
|
-
const value = Number.parseInt(match[1] ?? '0', 10);
|
|
20
|
-
const unit = match[2];
|
|
21
|
-
if (!Number.isFinite(value) || value <= 0)
|
|
22
|
-
return undefined;
|
|
23
|
-
const days = unit === 'h' ? value / 24 : value;
|
|
24
|
-
return { days, label: token };
|
|
25
|
-
}
|
|
26
|
-
function buildWindow(durationDays, label, now) {
|
|
27
|
-
const until = now;
|
|
28
|
-
const sinceMs = until.getTime() - durationDays * 24 * 60 * 60 * 1000;
|
|
29
|
-
const since = new Date(sinceMs);
|
|
30
|
-
// Midnight-align the lower bound to keep `--since` deterministic per day.
|
|
31
|
-
since.setHours(0, 0, 0, 0);
|
|
32
|
-
return { since, until, label, days: Math.max(1, Math.round(durationDays)) };
|
|
33
|
-
}
|
|
34
|
-
function buildPriorWindow(current) {
|
|
35
|
-
const until = new Date(current.since.getTime());
|
|
36
|
-
const sinceMs = until.getTime() - current.days * 24 * 60 * 60 * 1000;
|
|
37
|
-
const since = new Date(sinceMs);
|
|
38
|
-
since.setHours(0, 0, 0, 0);
|
|
39
|
-
return { since, until, label: `prior ${current.label}`, days: current.days };
|
|
40
|
-
}
|
|
41
|
-
function parseRetroArgs(rawArgs, now) {
|
|
42
|
-
const args = [...rawArgs];
|
|
43
|
-
const postPlane = args.includes('--post-plane');
|
|
44
|
-
const enrichPlane = args.includes('--plane') || postPlane;
|
|
45
|
-
const positional = args.filter((a) => !a.startsWith('-'));
|
|
46
|
-
let compare = false;
|
|
47
|
-
let durationToken;
|
|
48
|
-
if (positional[0] === 'compare') {
|
|
49
|
-
compare = true;
|
|
50
|
-
durationToken = positional[1];
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
durationToken = positional[0];
|
|
54
|
-
}
|
|
55
|
-
const parsed = parseDurationToken(durationToken) ?? { days: 7, label: '7d' };
|
|
56
|
-
return {
|
|
57
|
-
window: buildWindow(parsed.days, parsed.label, now),
|
|
58
|
-
compare,
|
|
59
|
-
enrichPlane,
|
|
60
|
-
postPlane,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
function SummaryCard(props) {
|
|
64
|
-
const { persisted, metrics, plane, planePostUrl } = props;
|
|
65
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderRight: false, borderTop: false, borderBottom: false, paddingLeft: 1, children: [_jsxs(Text, { bold: true, children: ["pugi retro \u00B7 ", metrics.window.label] }), _jsxs(Text, { dimColor: true, children: ["Branch ", metrics.branch.current, " over ", metrics.branch.base] }), _jsxs(Text, { children: [metrics.commits.total, " commits \u00B7 +", metrics.loc.insertions, " / -", metrics.loc.deletions, " LOC \u00B7 ", metrics.activeDays, " active days"] }), _jsxs(Text, { children: ["Focus ", metrics.focus.score, "% on ", metrics.focus.topDir ?? 'n/a', " \u00B7 Streak ", metrics.streak.personalDays, "d personal / ", metrics.streak.teamDays, "d team"] }), metrics.shipOfTheWeek ? (_jsxs(Text, { children: ["Ship of the week: ", metrics.shipOfTheWeek.subject.slice(0, 60)] })) : null, plane ? (_jsxs(Text, { children: ["Plane: closed ", plane.closedIssues.length, " \u00B7 created ", plane.createdIssues.length, " \u00B7 oversized modules ", plane.oversizedModules.length] })) : null, _jsxs(Text, { dimColor: true, children: ["Markdown: ", persisted.markdownPath] }), _jsxs(Text, { dimColor: true, children: ["JSON: ", persisted.jsonPath] }), planePostUrl ? _jsxs(Text, { children: ["Posted to Plane: ", planePostUrl] }) : null] }));
|
|
66
|
-
}
|
|
67
|
-
function renderSummary(props) {
|
|
68
|
-
const app = render(_jsx(SummaryCard, { ...props }));
|
|
69
|
-
app.unmount();
|
|
70
|
-
}
|
|
71
|
-
export async function runRetroCommand(ctx) {
|
|
72
|
-
const now = ctx.now ?? new Date();
|
|
73
|
-
const parsed = parseRetroArgs(ctx.args, now);
|
|
74
|
-
const gitCtx = await collectGitContext({ cwd: ctx.cwd, window: parsed.window });
|
|
75
|
-
if (!gitCtx.hasGit) {
|
|
76
|
-
const msg = 'pugi retro: not a git workspace - initialise git or cd into one.';
|
|
77
|
-
if (ctx.flags.json) {
|
|
78
|
-
ctx.io.write(`${JSON.stringify({ ok: false, error: 'no_git_workspace' })}\n`);
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
ctx.io.writeError(msg);
|
|
82
|
-
}
|
|
83
|
-
return 2;
|
|
84
|
-
}
|
|
85
|
-
// Triple-review P1.2 (): before we write anything
|
|
86
|
-
// under `.pugi/retros/`, guarantee `.gitignore` covers `.pugi/`. Without
|
|
87
|
-
// this, the first customer run of `pugi retro` in a fresh repo would
|
|
88
|
-
// leave retros (and any future `.pugi/settings.json` secret store)
|
|
89
|
-
// tracked by git on the next `git add -A`. Idempotent.
|
|
90
|
-
//
|
|
91
|
-
// Round 2 P1 (2026-06-04): surface failure к stderr — silent catch
|
|
92
|
-
// defeats the gate's purpose. If `.gitignore` is read-only or perms
|
|
93
|
-
// refuse, the operator must know retros may be tracked by git.
|
|
94
|
-
const gitIgnoreCreated = [];
|
|
95
|
-
const gitIgnoreSkipped = [];
|
|
96
|
-
try {
|
|
97
|
-
ensurePugiGitIgnore(ctx.cwd, gitIgnoreCreated, gitIgnoreSkipped);
|
|
98
|
-
}
|
|
99
|
-
catch (err) {
|
|
100
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
101
|
-
ctx.io.writeError(`pugi retro: could not update .gitignore (${reason}). ` +
|
|
102
|
-
`Manually add ".pugi/" to .gitignore so retros are not tracked.`);
|
|
103
|
-
}
|
|
104
|
-
const toBaseHeadCount = await countCommitsAheadOfBase(ctx.cwd, gitCtx.baseBranch, parsed.window.since);
|
|
105
|
-
const metrics = computeMetrics({
|
|
106
|
-
window: parsed.window,
|
|
107
|
-
currentBranch: gitCtx.currentBranch,
|
|
108
|
-
baseBranch: gitCtx.baseBranch,
|
|
109
|
-
toBaseHeadCount,
|
|
110
|
-
currentUserName: gitCtx.userName,
|
|
111
|
-
currentUserEmail: gitCtx.userEmail,
|
|
112
|
-
commits: gitCtx.commits,
|
|
113
|
-
});
|
|
114
|
-
let compare;
|
|
115
|
-
if (parsed.compare) {
|
|
116
|
-
const priorWindow = buildPriorWindow(parsed.window);
|
|
117
|
-
const priorCtx = await collectGitContext({ cwd: ctx.cwd, window: priorWindow });
|
|
118
|
-
const priorAhead = await countCommitsAheadOfBase(ctx.cwd, gitCtx.baseBranch, priorWindow.since);
|
|
119
|
-
const priorMetrics = computeMetrics({
|
|
120
|
-
window: priorWindow,
|
|
121
|
-
currentBranch: gitCtx.currentBranch,
|
|
122
|
-
baseBranch: gitCtx.baseBranch,
|
|
123
|
-
toBaseHeadCount: priorAhead,
|
|
124
|
-
currentUserName: gitCtx.userName,
|
|
125
|
-
currentUserEmail: gitCtx.userEmail,
|
|
126
|
-
commits: priorCtx.commits,
|
|
127
|
-
});
|
|
128
|
-
compare = { current: metrics, prior: priorMetrics };
|
|
129
|
-
}
|
|
130
|
-
let plane;
|
|
131
|
-
let planeUnavailableReason;
|
|
132
|
-
if (parsed.enrichPlane) {
|
|
133
|
-
const cfgResult = resolvePlaneConfig(ctx.cwd);
|
|
134
|
-
if (!cfgResult.ok) {
|
|
135
|
-
planeUnavailableReason = cfgResult.reason;
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
try {
|
|
139
|
-
const slice = await collectPlaneSlice({
|
|
140
|
-
config: cfgResult.config,
|
|
141
|
-
since: parsed.window.since,
|
|
142
|
-
});
|
|
143
|
-
const links = enrichLinks(gitCtx.commits, slice.closedIssues.concat(slice.createdIssues));
|
|
144
|
-
const health = computeHealthCard(slice.modules);
|
|
145
|
-
plane = {
|
|
146
|
-
...slice,
|
|
147
|
-
prToIssueLinks: links,
|
|
148
|
-
oversizedModules: health.oversized,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
catch (err) {
|
|
152
|
-
planeUnavailableReason = err instanceof Error ? err.message : String(err);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
const persisted = persistRetro({
|
|
157
|
-
root: ctx.cwd,
|
|
158
|
-
metrics,
|
|
159
|
-
plane,
|
|
160
|
-
compare,
|
|
161
|
-
now,
|
|
162
|
-
});
|
|
163
|
-
let planePostUrl;
|
|
164
|
-
if (parsed.postPlane) {
|
|
165
|
-
if (!plane) {
|
|
166
|
-
ctx.io.writeError(`pugi retro --post-plane: Plane unavailable (${planeUnavailableReason ?? 'unknown'}).`);
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
const cfgResult = resolvePlaneConfig(ctx.cwd);
|
|
170
|
-
if (cfgResult.ok) {
|
|
171
|
-
try {
|
|
172
|
-
const result = await postRetroToPlane({
|
|
173
|
-
config: cfgResult.config,
|
|
174
|
-
markdown: persisted.markdown,
|
|
175
|
-
sequence: persisted.sequence,
|
|
176
|
-
dateLabel: persisted.dateLabel,
|
|
177
|
-
});
|
|
178
|
-
planePostUrl = result.url;
|
|
179
|
-
if (result.alreadyExists) {
|
|
180
|
-
ctx.io.write(`pugi retro: already exists at ${result.url}\n`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
catch (err) {
|
|
184
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
185
|
-
ctx.io.writeError(`pugi retro --post-plane failed: ${msg}`);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
if (ctx.flags.json) {
|
|
191
|
-
ctx.io.write(`${JSON.stringify({
|
|
192
|
-
ok: true,
|
|
193
|
-
markdownPath: persisted.markdownPath,
|
|
194
|
-
jsonPath: persisted.jsonPath,
|
|
195
|
-
sequence: persisted.sequence,
|
|
196
|
-
metrics,
|
|
197
|
-
plane: plane ?? null,
|
|
198
|
-
planePostUrl: planePostUrl ?? null,
|
|
199
|
-
planeUnavailableReason: planeUnavailableReason ?? null,
|
|
200
|
-
}, null, 2)}\n`);
|
|
201
|
-
}
|
|
202
|
-
else {
|
|
203
|
-
renderSummary({ persisted, metrics, plane, planePostUrl });
|
|
204
|
-
if (planeUnavailableReason && !plane) {
|
|
205
|
-
ctx.io.writeError(`pugi retro: Plane integration unavailable (${planeUnavailableReason}).`);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return 0;
|
|
209
|
-
}
|
|
210
|
-
//# sourceMappingURL=retro.js.map
|