karajan-code 4.70.4 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +6 -14
- package/packages/hu-board/package.json +1 -1
- package/packages/hu-board/public/app.js +4 -18
- package/packages/hu-board/public/index.html +5 -2
- package/packages/hu-board/public/styles.css +26 -0
- package/packages/hu-board/public/utils/api.js +0 -74
- package/packages/hu-board/public/utils/board-tour.js +62 -0
- package/packages/hu-board/public/utils/board-view.js +49 -144
- package/packages/hu-board/public/utils/command-launcher.js +8 -70
- package/packages/hu-board/public/utils/formatters.js +10 -0
- package/packages/hu-board/public/utils/governance-view.js +13 -1
- package/packages/hu-board/public/utils/hu-actions.js +17 -68
- package/packages/hu-board/public/utils/init-listeners.js +7 -8
- package/packages/hu-board/public/utils/log-panel.js +3 -16
- package/packages/hu-board/public/utils/maggle-mode.js +2 -12
- package/packages/hu-board/public/utils/modals.js +7 -0
- package/packages/hu-board/public/utils/project-picker-view.js +1 -1
- package/packages/hu-board/public/utils/server-push.js +3 -22
- package/packages/hu-board/public/utils/shared-board-notice.js +33 -0
- package/packages/hu-board/public/utils/story-detail-view.js +5 -19
- package/packages/hu-board/src/cleanup-zombies.js +0 -1
- package/packages/hu-board/src/command-runner.js +36 -25
- package/packages/hu-board/src/db-connection.js +282 -0
- package/packages/hu-board/src/db-paths.js +113 -0
- package/packages/hu-board/src/db-queries.js +188 -0
- package/packages/hu-board/src/db-tombstones.js +51 -0
- package/packages/hu-board/src/db.js +28 -619
- package/packages/hu-board/src/ephemeral-cleaner.js +2 -3
- package/packages/hu-board/src/hu-zombie-reaper.js +5 -1
- package/packages/hu-board/src/plan-mutations.js +3 -153
- package/packages/hu-board/src/plans-service.js +55 -0
- package/packages/hu-board/src/routes/api/commands.js +122 -0
- package/packages/hu-board/src/routes/api/plans.js +55 -0
- package/packages/hu-board/src/routes/api/projects.js +267 -0
- package/packages/hu-board/src/routes/api/prompts.js +135 -0
- package/packages/hu-board/src/routes/api/sessions.js +95 -0
- package/packages/hu-board/src/routes/api/stories.js +183 -0
- package/packages/hu-board/src/routes/api/system.js +241 -0
- package/packages/hu-board/src/routes/api/tombstones.js +38 -0
- package/packages/hu-board/src/routes/api.js +24 -1371
- package/packages/hu-board/src/routes/governance.js +23 -1
- package/packages/hu-board/src/routes/lanes.js +40 -0
- package/packages/hu-board/src/routes/rag.js +4 -3
- package/packages/hu-board/src/server.js +20 -34
- package/packages/hu-board/src/sync-files.js +318 -0
- package/packages/hu-board/src/sync-project.js +99 -0
- package/packages/hu-board/src/sync.js +22 -566
- package/packages/hu-board/src/zombie-reaper.js +1 -1
- package/scripts/dual-publish.mjs +19 -3
- package/scripts/postinstall.js +15 -2
- package/scripts/verify-pack-mcp.mjs +11 -7
- package/scripts/verify-pack.mjs +4 -4
- package/src/audit/audit-history.js +3 -2
- package/src/audit/dead-exports.js +68 -59
- package/src/audit/deterministic-summary.js +33 -13
- package/src/audit/npm-signatures.js +41 -0
- package/src/audit/sbom.js +35 -0
- package/src/checks/agent-token.js +112 -0
- package/src/checks/dir-setup.js +34 -1
- package/src/checks/native-build.js +21 -39
- package/src/checks/runner.js +128 -142
- package/src/cli/advanced-commands.js +6 -6
- package/src/cli/register-meta.js +42 -82
- package/src/cli/register-pipeline.js +8 -143
- package/src/cli/register-plan.js +9 -100
- package/src/cli/retired-commands.js +49 -0
- package/src/cli.js +18 -5
- package/src/commands/agent-run.js +40 -26
- package/src/commands/audit.js +127 -124
- package/src/commands/board.js +5 -9
- package/src/commands/check.js +29 -16
- package/src/commands/doctor.js +2 -0
- package/src/commands/env.js +176 -150
- package/src/commands/go.js +71 -53
- package/src/commands/harden.js +90 -81
- package/src/commands/hu-start.js +52 -0
- package/src/commands/hu.js +288 -221
- package/src/commands/identity.js +111 -78
- package/src/commands/init-atril.js +47 -0
- package/src/commands/init.js +11 -40
- package/src/commands/install-tools.js +70 -85
- package/src/commands/main-guard.js +78 -0
- package/src/commands/policy.js +226 -184
- package/src/commands/qmd.js +27 -21
- package/src/commands/rag.js +75 -48
- package/src/commands/review-gate.js +421 -341
- package/src/commands/start.js +4 -5
- package/src/commands/steward.js +96 -47
- package/src/commands/tournament.js +46 -37
- package/src/commands/worktree.js +94 -25
- package/src/config/loader.js +34 -17
- package/src/config/secrets.js +36 -0
- package/src/config.js +1 -0
- package/src/environment/adr.js +16 -2
- package/src/git/karajan-label.js +20 -8
- package/src/guards/main-guard.js +54 -0
- package/src/harden/hook-templates.js +16 -1
- package/src/harden/sentinel/posttooluse.mjs +18 -6
- package/src/harden/sentinel/pretooluse-sentinel.mjs +64 -36
- package/src/harden/sentinel/sentinel-lib.mjs +129 -26
- package/src/harden/sentinel/sentinel-shell.mjs +5 -16
- package/src/harden/sentinel/sessionstart.mjs +3 -2
- package/src/harden/sentinel/stop.mjs +5 -4
- package/src/harden/workflow-templates.js +1 -1
- package/src/hu/board-lookup.js +29 -0
- package/src/hu/gh-identity.js +23 -0
- package/src/hu/github-board.js +4 -2
- package/src/hu/lane-prune.js +15 -7
- package/src/hu/lane-setup.js +65 -0
- package/src/hu/lanes.js +66 -0
- package/src/hu/team-board-mirror.js +3 -2
- package/src/infrastructure/command-runner.js +1 -1
- package/src/infrastructure/file-system-service.js +1 -1
- package/src/mcp/handlers/direct-handlers.js +2 -292
- package/src/mcp/handlers/hu-handlers.js +1 -35
- package/src/mcp/handlers/management-handlers.js +2 -42
- package/src/mcp/server-handlers.js +16 -22
- package/src/mcp/tools.js +1 -196
- package/src/plan/lane-plans.js +54 -0
- package/src/plan/plan-store.js +7 -4
- package/src/policy/add.js +26 -12
- package/src/policy/adr-number-check.js +31 -0
- package/src/prompts/audit.js +299 -339
- package/src/prompts/card-context.js +10 -5
- package/src/prompts/reviewer.js +5 -2
- package/src/rag/auto-update.js +56 -43
- package/src/rag/bootstrap-index.js +28 -54
- package/src/rag/migrate.js +1 -1
- package/src/rag/onnx-fallback.js +2 -2
- package/src/rag/pid-lease.js +70 -0
- package/src/rag/project-store.js +2 -12
- package/src/review/card-first.js +57 -46
- package/src/review/gate-gitignore.js +23 -4
- package/src/review/gate-hook.js +12 -4
- package/src/review/one-shot-review.js +45 -35
- package/src/review/publish-pr.js +14 -2
- package/src/review/repo-docs.js +73 -0
- package/src/review/repo-stack.js +59 -0
- package/src/review/reviewer-fallback.js +19 -4
- package/src/review/seal-commit.js +29 -0
- package/src/review/sonar-pregate.js +59 -44
- package/src/review/third-party-review.js +90 -16
- package/src/review/third-party-size.js +43 -0
- package/src/review/third-party-skills.js +54 -0
- package/src/review/verify-pr.js +1 -24
- package/src/roles/audit-role.js +106 -125
- package/src/skills/atril-skills.js +5 -4
- package/src/sonar/scanner.js +116 -101
- package/src/steward/invariants.js +5 -4
- package/src/steward/phantom-sweep.js +66 -0
- package/src/tournament/judge.js +60 -53
- package/src/utils/gh-account.js +37 -0
- package/src/utils/git.js +0 -13
- package/src/utils/home-migration.js +7 -1
- package/src/utils/main-checkout.js +53 -0
- package/src/utils/qmd-collection.js +3 -1
- package/src/utils/welcome.js +3 -3
- package/templates/{skills → atril/commands}/kj-architect.md +5 -0
- package/templates/{skills → atril/commands}/kj-audit.md +5 -0
- package/templates/{skills → atril/commands}/kj-board.md +5 -0
- package/templates/{skills → atril/commands}/kj-code.md +5 -0
- package/templates/{skills → atril/commands}/kj-csv-transform.md +5 -0
- package/templates/{skills → atril/commands}/kj-data-report.md +5 -0
- package/templates/{skills → atril/commands}/kj-discover.md +5 -0
- package/templates/{skills → atril/commands}/kj-rag-query.md +5 -0
- package/templates/{skills → atril/commands}/kj-review.md +5 -0
- package/templates/{skills → atril/commands}/kj-security.md +5 -0
- package/templates/{skills → atril/commands}/kj-sonar.md +5 -0
- package/templates/{skills → atril/commands}/kj-sql-analysis.md +5 -0
- package/templates/{skills → atril/commands}/kj-test.md +5 -0
- package/packages/hu-board/public/utils/run-launcher.js +0 -169
- package/packages/hu-board/src/run-tracker.js +0 -121
- package/src/activity-log.js +0 -59
- package/src/agents/host-agent.js +0 -38
- package/src/agents/model-registry.js +0 -142
- package/src/audit/plan-adherence.js +0 -224
- package/src/autonomy/arbiter-role.js +0 -71
- package/src/autonomy/arbiter.js +0 -22
- package/src/autonomy/decider.js +0 -18
- package/src/autonomy/decision-resolver.js +0 -58
- package/src/autonomy/outcome-report.js +0 -55
- package/src/autonomy/stage-ask.js +0 -30
- package/src/brain/decision-tracker.js +0 -125
- package/src/brain/decisor.js +0 -243
- package/src/brain/solomon-consult.js +0 -171
- package/src/brain/standby-scheduler.js +0 -8
- package/src/budget/comparison.js +0 -96
- package/src/canvas/parse-md.js +0 -238
- package/src/canvas/schema.js +0 -101
- package/src/canvas/to-flat.js +0 -85
- package/src/canvas/validate.js +0 -163
- package/src/ci/dispatch.js +0 -99
- package/src/ci/index.js +0 -3
- package/src/ci/pr-diff.js +0 -26
- package/src/cli/register-standby.js +0 -26
- package/src/commands/architect.js +0 -111
- package/src/commands/autorun.js +0 -49
- package/src/commands/researcher.js +0 -54
- package/src/commands/resume.js +0 -72
- package/src/commands/review.js +0 -89
- package/src/commands/run.js +0 -185
- package/src/commands/standby.js +0 -117
- package/src/commands/status.js +0 -36
- package/src/commands/triage.js +0 -78
- package/src/commands/undo.js +0 -62
- package/src/domains/domain-loader.js +0 -245
- package/src/domains/domain-registry.js +0 -140
- package/src/domains/domain-synthesizer.js +0 -129
- package/src/git/automation.js +0 -433
- package/src/git/coder-commit-guard.js +0 -40
- package/src/git/hu-automation.js +0 -243
- package/src/git/hu-snapshot.js +0 -10
- package/src/git/symlink-targets.js +0 -57
- package/src/golden/asserter.js +0 -92
- package/src/golden/loader.js +0 -52
- package/src/golden/runner.js +0 -92
- package/src/golden/schema.js +0 -41
- package/src/guards/duplicate-members.js +0 -86
- package/src/guards/intent-guard.js +0 -161
- package/src/guards/perf-guard.js +0 -126
- package/src/guards/policy-guard.js +0 -90
- package/src/guards/policy-resolver.js +0 -85
- package/src/guards/secret-redactor.js +0 -71
- package/src/hu/acceptance-runner.js +0 -138
- package/src/hu/lazy-planner.js +0 -109
- package/src/hu/parallel-executor.js +0 -94
- package/src/hu/routing-metrics.js +0 -17
- package/src/hu/split-validator.js +0 -143
- package/src/hu/splitting-detector.js +0 -158
- package/src/hu/splitting-generator.js +0 -175
- package/src/hu/store.js +0 -394
- package/src/infrastructure/mocks.js +0 -182
- package/src/mcp/handlers/run-handler.js +0 -318
- package/src/mcp/sovereignty-guard.js +0 -113
- package/src/mcp/tool-arg-normalizers.js +0 -16
- package/src/mutate/reviewer-signal.js +0 -76
- package/src/orchestrator/agent-fallback.js +0 -81
- package/src/orchestrator/brain-coordinator.js +0 -186
- package/src/orchestrator/ci-integration.js +0 -139
- package/src/orchestrator/config-init.js +0 -426
- package/src/orchestrator/direct-actions.js +0 -217
- package/src/orchestrator/drivers/error-recovery.js +0 -287
- package/src/orchestrator/drivers/init-context.js +0 -238
- package/src/orchestrator/drivers/iteration-loop.js +0 -382
- package/src/orchestrator/drivers/iteration-phases/coder-and-refactorer.js +0 -69
- package/src/orchestrator/drivers/iteration-phases/guards.js +0 -91
- package/src/orchestrator/drivers/iteration-phases/handle-approved.js +0 -29
- package/src/orchestrator/drivers/iteration-phases/quality-gates.js +0 -125
- package/src/orchestrator/drivers/iteration-phases/reviewer-gate.js +0 -62
- package/src/orchestrator/drivers/post-loop.js +0 -404
- package/src/orchestrator/drivers/pre-loop-phases/auto-hu-batch.js +0 -137
- package/src/orchestrator/drivers/pre-loop-phases/config-deprecations.js +0 -47
- package/src/orchestrator/drivers/pre-loop-phases/ensure-addyosmani-skills.js +0 -84
- package/src/orchestrator/drivers/pre-loop-phases/inject-loaded-plan.js +0 -393
- package/src/orchestrator/drivers/pre-loop.js +0 -524
- package/src/orchestrator/drivers/run-hu-batch.js +0 -468
- package/src/orchestrator/feedback-enrichment.js +0 -140
- package/src/orchestrator/feedback-queue.js +0 -151
- package/src/orchestrator/flow-control.js +0 -170
- package/src/orchestrator/flow-runner.js +0 -365
- package/src/orchestrator/fs-leak-detector.js +0 -228
- package/src/orchestrator/hu-scheduler.js +0 -114
- package/src/orchestrator/hu-sub-pipeline.js +0 -642
- package/src/orchestrator/iteration-gate.js +0 -73
- package/src/orchestrator/iteration-stages.js +0 -9
- package/src/orchestrator/parallel-limiter.js +0 -74
- package/src/orchestrator/pipeline-context.js +0 -72
- package/src/orchestrator/post-loop-stages.js +0 -468
- package/src/orchestrator/pre-loop-stages.js +0 -11
- package/src/orchestrator/preflight-checks.js +0 -487
- package/src/orchestrator/repair/repair-detector.js +0 -117
- package/src/orchestrator/repair/repair-runner.js +0 -142
- package/src/orchestrator/reviewer-fallback.js +0 -45
- package/src/orchestrator/role-output-compressor.js +0 -189
- package/src/orchestrator/session-journal.js +0 -308
- package/src/orchestrator/solomon-escalation.js +0 -331
- package/src/orchestrator/solomon-rules.js +0 -212
- package/src/orchestrator/stages/acceptance-coverage-stage.js +0 -47
- package/src/orchestrator/stages/architect-stage.js +0 -172
- package/src/orchestrator/stages/coder-stage.js +0 -506
- package/src/orchestrator/stages/domain-curator-stage.js +0 -82
- package/src/orchestrator/stages/format-stage.js +0 -61
- package/src/orchestrator/stages/hu-reviewer-phases/detect-and-apply-splits.js +0 -127
- package/src/orchestrator/stages/hu-reviewer-stage.js +0 -419
- package/src/orchestrator/stages/perf-stage.js +0 -140
- package/src/orchestrator/stages/planner-stage.js +0 -85
- package/src/orchestrator/stages/rag-context-stage.js +0 -80
- package/src/orchestrator/stages/rag-preload-decisor.js +0 -58
- package/src/orchestrator/stages/research-stage.js +0 -69
- package/src/orchestrator/stages/reviewer-stage.js +0 -431
- package/src/orchestrator/stages/sonar-stage.js +0 -439
- package/src/orchestrator/stages/stage-classes.js +0 -84
- package/src/orchestrator/stages/stage-executor.js +0 -155
- package/src/orchestrator/stages/suite-green-stage.js +0 -62
- package/src/orchestrator/stages/tdd-discipline-stage.js +0 -56
- package/src/orchestrator/stages/tool-judge-stage.js +0 -53
- package/src/orchestrator/stages/triage-stage.js +0 -172
- package/src/orchestrator/standby.js +0 -71
- package/src/orchestrator/verification-gate.js +0 -183
- package/src/orchestrator.js +0 -22
- package/src/plan/adr-generator.js +0 -170
- package/src/plan/adr-loader.js +0 -60
- package/src/plan/plan-executor.js +0 -100
- package/src/plan/plan-validation.js +0 -4
- package/src/prompts/acceptance-coverage.js +0 -32
- package/src/prompts/arbiter.js +0 -38
- package/src/prompts/architect.js +0 -103
- package/src/prompts/hu-reviewer.js +0 -244
- package/src/prompts/tool-correctness-judge.js +0 -31
- package/src/prompts/triage.js +0 -57
- package/src/rag/embedder.js +0 -2
- package/src/rag/embedders/_cloud-base.js +0 -2
- package/src/rag/embedders/cohere.js +0 -2
- package/src/rag/embedders/mistral.js +0 -2
- package/src/rag/embedders/onnx.js +0 -2
- package/src/rag/embedders/openai.js +0 -2
- package/src/rag/embedders/voyage.js +0 -2
- package/src/rag/rerank.js +0 -4
- package/src/rag/where-parser.js +0 -4
- package/src/repeat-detector.js +0 -88
- package/src/review/diff-generator.js +0 -112
- package/src/review/git-stash-helper.js +0 -104
- package/src/review/schema.js +0 -31
- package/src/review/scope-filter.js +0 -152
- package/src/review/snapshot-diff.js +0 -122
- package/src/review/tdd-discipline.js +0 -90
- package/src/review/tdd-policy.js +0 -69
- package/src/roles/acceptance-coverage-role.js +0 -78
- package/src/roles/architect-role.js +0 -77
- package/src/roles/coder-role.js +0 -113
- package/src/roles/commiter-role.js +0 -113
- package/src/roles/domain-curator-role.js +0 -134
- package/src/roles/hu-reviewer-role.js +0 -64
- package/src/roles/impeccable-role.js +0 -85
- package/src/roles/index.js +0 -18
- package/src/roles/karajan-brain-role.js +0 -134
- package/src/roles/perf-role.js +0 -122
- package/src/roles/planner-role.js +0 -151
- package/src/roles/refactorer-role.js +0 -30
- package/src/roles/repairer-role.js +0 -181
- package/src/roles/researcher-role.js +0 -70
- package/src/roles/reviewer-role.js +0 -115
- package/src/roles/security-role.js +0 -73
- package/src/roles/solomon-role.js +0 -271
- package/src/roles/sonar-role.js +0 -72
- package/src/roles/tester-role.js +0 -235
- package/src/roles/tool-correctness-judge-role.js +0 -78
- package/src/roles/triage-role.js +0 -99
- package/src/session/journal/decisions-writer.js +0 -200
- package/src/session/journal/iteration-logger.js +0 -194
- package/src/session/journal/summary-writer.js +0 -320
- package/src/session/journal/tree-writer.js +0 -164
- package/src/session/journal/write-all.js +0 -89
- package/src/session-cleanup.js +0 -116
- package/src/skills/semantic-detector.js +0 -167
- package/src/skills/skill-detector.js +0 -385
- package/src/sonar/cloud-scanner.js +0 -78
- package/src/tracker-bootstrap.js +0 -44
- package/src/types/index.js +0 -38
- package/src/types/policy.js +0 -43
- package/src/types/solomon.js +0 -87
- package/src/utils/async-lock.js +0 -31
- package/src/utils/budget.js +0 -229
- package/src/utils/cwd-confirm.js +0 -39
- package/src/utils/display/event-handlers.js +0 -403
- package/src/utils/display/formatters.js +0 -132
- package/src/utils/display/header.js +0 -47
- package/src/utils/display/session-summary.js +0 -118
- package/src/utils/display/solomon.js +0 -42
- package/src/utils/pricing.js +0 -29
- package/src/utils/quota-simulator.js +0 -56
- package/src/utils/role-assigner.js +0 -137
- package/src/utils/rtk-wrapper.js +0 -87
- package/src/utils/run-registry.js +0 -9
- package/src/utils/status-dashboard.js +0 -254
- package/src/utils/tool-call-extractor.js +0 -56
- package/src/webperf/devtools-detect.js +0 -112
- package/src/webperf/webperf-role-integration.js +0 -66
- package/templates/skills/kj-run.md +0 -73
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
export const ANSI = {
|
|
2
|
-
reset: "\x1b[0m",
|
|
3
|
-
bold: "\x1b[1m",
|
|
4
|
-
dim: "\x1b[2m",
|
|
5
|
-
cyan: "\x1b[36m",
|
|
6
|
-
green: "\x1b[32m",
|
|
7
|
-
yellow: "\x1b[33m",
|
|
8
|
-
red: "\x1b[31m",
|
|
9
|
-
gray: "\x1b[90m",
|
|
10
|
-
white: "\x1b[37m",
|
|
11
|
-
magenta: "\x1b[35m"
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export const ICONS = {
|
|
15
|
-
"session:start": "\u25b6",
|
|
16
|
-
"planner:start": "\ud83e\udde0",
|
|
17
|
-
"planner:end": "\ud83e\udde0",
|
|
18
|
-
"researcher:start": "\ud83d\udd2c",
|
|
19
|
-
"researcher:end": "\ud83d\udd2c",
|
|
20
|
-
"iteration:start": "\u25b6",
|
|
21
|
-
"coder:start": "\ud83d\udd28",
|
|
22
|
-
"coder:end": "\ud83d\udd28",
|
|
23
|
-
"refactorer:start": "\u267b\ufe0f",
|
|
24
|
-
"refactorer:end": "\u267b\ufe0f",
|
|
25
|
-
"tdd:result": "\ud83d\udccb",
|
|
26
|
-
"sonar:start": "\ud83d\udd0d",
|
|
27
|
-
"sonar:end": "\ud83d\udd0d",
|
|
28
|
-
"reviewer:start": "\ud83d\udc41\ufe0f",
|
|
29
|
-
"reviewer:end": "\ud83d\udc41\ufe0f",
|
|
30
|
-
"tester:start": "\ud83e\uddea",
|
|
31
|
-
"tester:end": "\ud83e\uddea",
|
|
32
|
-
"security:start": "\ud83d\udd12",
|
|
33
|
-
"security:end": "\ud83d\udd12",
|
|
34
|
-
"solomon:start": "\u2696\ufe0f",
|
|
35
|
-
"solomon:end": "\u2696\ufe0f",
|
|
36
|
-
"solomon:escalate": "\u26a0\ufe0f",
|
|
37
|
-
"agent:heartbeat": "\u23f3",
|
|
38
|
-
"coder:standby": "\u23f3",
|
|
39
|
-
"coder:standby_heartbeat": "\u23f3",
|
|
40
|
-
"coder:standby_resume": "\u25b6\ufe0f",
|
|
41
|
-
"budget:update": "\ud83d\udcb8",
|
|
42
|
-
"iteration:end": "\u23f1\ufe0f",
|
|
43
|
-
"session:end": "\ud83c\udfc1",
|
|
44
|
-
"discover:start": "\ud83d\udd0e",
|
|
45
|
-
"discover:end": "\ud83d\udd0e",
|
|
46
|
-
"architect:start": "\ud83c\udfdb\ufe0f",
|
|
47
|
-
"architect:end": "\ud83c\udfdb\ufe0f",
|
|
48
|
-
"hu-reviewer:start": "\ud83d\udcdd",
|
|
49
|
-
"hu-reviewer:end": "\ud83d\udcdd",
|
|
50
|
-
"impeccable:start": "\ud83c\udfa8",
|
|
51
|
-
"impeccable:end": "\ud83c\udfa8",
|
|
52
|
-
"audit:start": "\ud83d\udccb",
|
|
53
|
-
"audit:end": "\ud83d\udccb",
|
|
54
|
-
"sonarcloud:start": "\u2601\ufe0f",
|
|
55
|
-
"sonarcloud:end": "\u2601\ufe0f",
|
|
56
|
-
"preflight:start": "\ud83d\udee1\ufe0f",
|
|
57
|
-
"preflight:end": "\ud83d\udee1\ufe0f",
|
|
58
|
-
question: "\u2753"
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export const STATUS_ICON = {
|
|
62
|
-
ok: `${ANSI.green}\u2705${ANSI.reset}`,
|
|
63
|
-
fail: `${ANSI.red}\u274c${ANSI.reset}`,
|
|
64
|
-
paused: `${ANSI.yellow}\u23f8\ufe0f${ANSI.reset}`,
|
|
65
|
-
running: `${ANSI.cyan}\u25b6${ANSI.reset}`
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
export const TRACKER_STATUS = {
|
|
69
|
-
done: { icon: "\u2713", color: ANSI.green },
|
|
70
|
-
running: { icon: "\u25b6", color: ANSI.cyan },
|
|
71
|
-
failed: { icon: "\u2717", color: ANSI.red }
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
export const TRACKER_DEFAULT = { icon: "\u00b7", color: ANSI.dim };
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Format milliseconds into MM:SS string
|
|
78
|
-
* @param {number} ms
|
|
79
|
-
* @returns {string}
|
|
80
|
-
*/
|
|
81
|
-
export function formatElapsed(ms) {
|
|
82
|
-
const totalSec = Math.floor((ms || 0) / 1000);
|
|
83
|
-
const min = String(Math.floor(totalSec / 60)).padStart(2, "0");
|
|
84
|
-
const sec = String(totalSec % 60).padStart(2, "0");
|
|
85
|
-
return `${min}:${sec}`;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Format executor details into a display string
|
|
90
|
-
* @param {Object} detail
|
|
91
|
-
* @returns {string}
|
|
92
|
-
*/
|
|
93
|
-
export function formatExecutor(detail) {
|
|
94
|
-
if (!detail) return '';
|
|
95
|
-
const provider = detail.provider || '';
|
|
96
|
-
const type = detail.executorType || '';
|
|
97
|
-
if (provider) return ` ${ANSI.dim}${provider}${ANSI.reset}`;
|
|
98
|
-
if (type === 'local') return ` ${ANSI.dim}local${ANSI.reset}`;
|
|
99
|
-
if (type === 'system') return ` ${ANSI.dim}system${ANSI.reset}`;
|
|
100
|
-
return '';
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Calculate budget ANSI color based on usage
|
|
105
|
-
* @param {number} max
|
|
106
|
-
* @param {number} pct
|
|
107
|
-
* @param {number} warn
|
|
108
|
-
* @returns {string}
|
|
109
|
-
*/
|
|
110
|
-
export function budgetColor(max, pct, warn) {
|
|
111
|
-
if (max > 0 && pct >= 100) return ANSI.red;
|
|
112
|
-
if (max > 0 && pct >= warn) return ANSI.yellow;
|
|
113
|
-
return ANSI.green;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function roleStart(icon, label, provider) {
|
|
117
|
-
console.log(` \u251c\u2500 ${icon} ${label} (${provider || "?"}) running...`);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function roleEnd(status, label, elapsed, executor) {
|
|
121
|
-
console.log(` \u251c\u2500 ${status} ${label} completed${executor || ''} ${elapsed}`);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export function passFailStage(detail, label, failDefault, elapsed) {
|
|
125
|
-
const executor = formatExecutor(detail);
|
|
126
|
-
if (detail?.ok === false) {
|
|
127
|
-
const summary = detail?.summary || failDefault;
|
|
128
|
-
console.log(` \u251c\u2500 ${ANSI.red}\u274c ${label}: ${summary}${ANSI.reset}${executor} ${elapsed}`);
|
|
129
|
-
} else {
|
|
130
|
-
console.log(` \u251c\u2500 ${ANSI.green}\u2705 ${label}: passed${ANSI.reset}${executor} ${elapsed}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { printBanner } from "../banner.js";
|
|
5
|
-
import { ANSI } from "./formatters.js";
|
|
6
|
-
|
|
7
|
-
const DISPLAY_PKG_PATH = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../../package.json");
|
|
8
|
-
const DISPLAY_VERSION = JSON.parse(readFileSync(DISPLAY_PKG_PATH, "utf8")).version;
|
|
9
|
-
|
|
10
|
-
const BAR = `${ANSI.dim}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${ANSI.reset}`;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Print task, configuration and pipeline header
|
|
14
|
-
* @param {Object} params
|
|
15
|
-
* @param {string} params.task
|
|
16
|
-
* @param {Object} params.config
|
|
17
|
-
*/
|
|
18
|
-
export function printHeader({ task, config }) {
|
|
19
|
-
const version = DISPLAY_VERSION;
|
|
20
|
-
// Force banner: caller already gates on !jsonMode, so if we're here it's a human-readable run
|
|
21
|
-
printBanner(version, { force: true });
|
|
22
|
-
console.log(`${ANSI.bold}Task:${ANSI.reset} ${task}`);
|
|
23
|
-
console.log(
|
|
24
|
-
`${ANSI.bold}Coder:${ANSI.reset} ${config.roles?.coder?.provider || config.coder} ${ANSI.dim}|${ANSI.reset} ${ANSI.bold}Reviewer:${ANSI.reset} ${config.roles?.reviewer?.provider || config.reviewer}`
|
|
25
|
-
);
|
|
26
|
-
console.log(
|
|
27
|
-
`${ANSI.bold}Max iterations:${ANSI.reset} ${config.max_iterations} ${ANSI.dim}|${ANSI.reset} ${ANSI.bold}Timeout:${ANSI.reset} ${config.session.max_total_minutes}min`
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
const pipeline = config.pipeline || {};
|
|
31
|
-
const activeRoles = [];
|
|
32
|
-
if (pipeline.planner?.enabled) activeRoles.push(`Planner (${config.roles?.planner?.provider || "?"})`);
|
|
33
|
-
if (pipeline.researcher?.enabled) activeRoles.push(`Researcher (${config.roles?.researcher?.provider || "?"})`);
|
|
34
|
-
if (pipeline.tester?.enabled) activeRoles.push("Tester");
|
|
35
|
-
if (pipeline.security?.enabled) activeRoles.push("Security");
|
|
36
|
-
if (pipeline.solomon?.enabled) {
|
|
37
|
-
const solomonProvider = config.roles?.solomon?.provider;
|
|
38
|
-
activeRoles.push(solomonProvider ? `Solomon (${solomonProvider})` : "Solomon");
|
|
39
|
-
}
|
|
40
|
-
if (activeRoles.length > 0) {
|
|
41
|
-
const separator = ` ${ANSI.dim}|${ANSI.reset} `;
|
|
42
|
-
console.log(`${ANSI.bold}Pipeline:${ANSI.reset} ${activeRoles.join(separator)}`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
console.log(BAR);
|
|
46
|
-
console.log();
|
|
47
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { ANSI } from "./formatters.js";
|
|
2
|
-
|
|
3
|
-
export function printSessionStages(stages) {
|
|
4
|
-
if (!stages) return;
|
|
5
|
-
if (stages.researcher?.summary) {
|
|
6
|
-
console.log(` ${ANSI.dim}\ud83d\udd2c Research: ${stages.researcher.summary}${ANSI.reset}`);
|
|
7
|
-
}
|
|
8
|
-
printSessionPlanner(stages.planner);
|
|
9
|
-
if (stages.tester?.summary) {
|
|
10
|
-
console.log(` ${ANSI.dim}\ud83e\uddea Tester: ${stages.tester.summary}${ANSI.reset}`);
|
|
11
|
-
}
|
|
12
|
-
if (stages.security?.summary) {
|
|
13
|
-
console.log(` ${ANSI.dim}\ud83d\udd12 Security: ${stages.security.summary}${ANSI.reset}`);
|
|
14
|
-
}
|
|
15
|
-
printSessionSonar(stages.sonar);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function printSessionPlanner(planner) {
|
|
19
|
-
if (!planner?.title && !planner?.approach && !planner?.completedSteps?.length) return;
|
|
20
|
-
const planParts = [];
|
|
21
|
-
if (planner.title) planParts.push(planner.title);
|
|
22
|
-
if (planner.approach) planParts.push(`approach: ${planner.approach}`);
|
|
23
|
-
console.log(` ${ANSI.dim}\ud83d\uddfa Plan: ${planParts.join(" | ")}${ANSI.reset}`);
|
|
24
|
-
for (const step of planner.completedSteps || []) {
|
|
25
|
-
console.log(` ${ANSI.dim} \u2713 ${step}${ANSI.reset}`);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function printSessionSonar(sonar) {
|
|
30
|
-
if (!sonar) return;
|
|
31
|
-
// Three buckets so the banner reads correctly:
|
|
32
|
-
// - OK \u2192 green (real pass).
|
|
33
|
-
// - SKIPPED / PENDING \u2192 gray (informational; sonar
|
|
34
|
-
// wasn't gated against, this is NOT a fail). Pre-2026-05-07 N4
|
|
35
|
-
// dogfooding these were rendered red, which made a clean run
|
|
36
|
-
// look like a sonar failure during the live demo.
|
|
37
|
-
// - everything else (ERROR, WARN, ...) \u2192 red (real fail).
|
|
38
|
-
let gateLabel;
|
|
39
|
-
if (sonar.gateStatus === "OK") gateLabel = ANSI.green;
|
|
40
|
-
else if (sonar.gateStatus === "SKIPPED" || sonar.gateStatus === "PENDING") gateLabel = ANSI.gray;
|
|
41
|
-
else gateLabel = ANSI.red;
|
|
42
|
-
console.log(` ${ANSI.dim}\ud83d\udd0d Sonar: ${gateLabel}${sonar.gateStatus}${ANSI.reset}${ANSI.dim} (${sonar.openIssues ?? 0} issues)${ANSI.reset}`);
|
|
43
|
-
if (typeof sonar.issuesInitial === "number" || typeof sonar.issuesResolved === "number") {
|
|
44
|
-
const issuesInitial = sonar.issuesInitial ?? sonar.openIssues ?? 0;
|
|
45
|
-
const issuesFinal = sonar.issuesFinal ?? sonar.openIssues ?? 0;
|
|
46
|
-
const issuesResolved = sonar.issuesResolved ?? Math.max(issuesInitial - issuesFinal, 0);
|
|
47
|
-
console.log(` ${ANSI.dim}\ud83d\udee0 Issues: ${issuesInitial} detected, ${issuesFinal} open, ${issuesResolved} resolved${ANSI.reset}`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function printSessionGit(git) {
|
|
52
|
-
if (!git?.branch) return;
|
|
53
|
-
const parts = [`branch: ${git.branch}`];
|
|
54
|
-
if (git.committed) parts.push("committed");
|
|
55
|
-
if (git.pushed) parts.push("pushed");
|
|
56
|
-
if (git.pr || git.prUrl) parts.push(`PR: ${git.pr || git.prUrl}`);
|
|
57
|
-
console.log(` ${ANSI.dim}\ud83d\udcce Git: ${parts.join(", ")}${ANSI.reset}`);
|
|
58
|
-
if (Array.isArray(git.commits) && git.commits.length > 0) {
|
|
59
|
-
console.log(` ${ANSI.dim}\ud83e\uddfe Commits:${ANSI.reset}`);
|
|
60
|
-
for (const commit of git.commits) {
|
|
61
|
-
const shortHash = (commit.hash || "").slice(0, 7) || "unknown";
|
|
62
|
-
const message = commit.message || "";
|
|
63
|
-
console.log(` ${ANSI.dim} - ${shortHash} ${message}${ANSI.reset}`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function isBudgetUnavailable(budget) {
|
|
69
|
-
return budget.usage_available === false ||
|
|
70
|
-
(budget.total_tokens === 0 && budget.total_cost_usd === 0 && Object.keys(budget.breakdown_by_role || {}).length > 0);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function printSessionRtkSavings(rtkSavings) {
|
|
74
|
-
if (!rtkSavings || !rtkSavings.callCount) return;
|
|
75
|
-
const tokens = rtkSavings.estimatedTokensSaved ?? 0;
|
|
76
|
-
const ratio = rtkSavings.savedPct ?? 0;
|
|
77
|
-
const commands = rtkSavings.callCount ?? 0;
|
|
78
|
-
const original = rtkSavings.originalBytes ?? 0;
|
|
79
|
-
const compressed = rtkSavings.rtkBytes ?? 0;
|
|
80
|
-
|
|
81
|
-
if (tokens === 0 || ratio === 0) {
|
|
82
|
-
console.log(` ${ANSI.dim}⚡ RTK: ${commands} commands wrapped, 0% savings — output was already minimal (${original} bytes in, ${compressed} bytes out)${ANSI.reset}`);
|
|
83
|
-
} else {
|
|
84
|
-
console.log(` ${ANSI.dim}⚡ RTK: saved ~${tokens.toLocaleString()} tokens (${ratio}% compression, ${commands} commands, ${original.toLocaleString()} → ${compressed.toLocaleString()} bytes)${ANSI.reset}`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function printSessionBudget(budget) {
|
|
89
|
-
if (!budget) return;
|
|
90
|
-
if (isBudgetUnavailable(budget)) {
|
|
91
|
-
console.log(` ${ANSI.dim}\ud83d\udcb0 Budget: N/A (provider does not report usage)${ANSI.reset}`);
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const estPrefix = budget.includes_estimates ? "~" : "";
|
|
95
|
-
const estNote = budget.includes_estimates ? " (includes estimates)" : "";
|
|
96
|
-
const fmtTokens = (n) => Number(n || 0).toLocaleString("en-US");
|
|
97
|
-
console.log(` ${ANSI.dim}\ud83d\udcb0 Total tokens: ${estPrefix}${fmtTokens(budget.total_tokens)}${estNote}${ANSI.reset}`);
|
|
98
|
-
console.log(` ${ANSI.dim}\ud83d\udcb0 Total cost: ${estPrefix}$${Number(budget.total_cost_usd || 0).toFixed(2)}${ANSI.reset}`);
|
|
99
|
-
// KJC-TSK-0274: KJ-vs-non-KJ comparison line when compression data exists.
|
|
100
|
-
const cmp = budget.kj_comparison;
|
|
101
|
-
if (cmp?.hasCompression) {
|
|
102
|
-
const wkCost = `$${Number(cmp.withKj?.cost || 0).toFixed(2)}`;
|
|
103
|
-
const wkTok = fmtTokens(Number(cmp.withKj?.tokens || 0));
|
|
104
|
-
const wnCost = `$${Number(cmp.withoutKj?.cost || 0).toFixed(2)}`;
|
|
105
|
-
const wnTok = fmtTokens(Number(cmp.withoutKj?.tokens || 0));
|
|
106
|
-
const pct = Math.round(Number(cmp.savedPct || 0));
|
|
107
|
-
console.log(` ${ANSI.dim} \u2937 With KJ: ${wkCost} / ${wkTok} tokens${ANSI.reset}`);
|
|
108
|
-
console.log(` ${ANSI.dim} \u2937 Without KJ: ~${wnCost} / ~${wnTok} tokens (-${pct}%)${ANSI.reset}`);
|
|
109
|
-
}
|
|
110
|
-
for (const [role, metrics] of Object.entries(budget.breakdown_by_role || {})) {
|
|
111
|
-
const tokens = Number(metrics.total_tokens || 0);
|
|
112
|
-
const cost = Number(metrics.total_cost_usd || 0);
|
|
113
|
-
if (tokens === 0 && cost === 0) continue; // skip roles with no usage
|
|
114
|
-
console.log(
|
|
115
|
-
` ${ANSI.dim} - ${role}: ${estPrefix}${fmtTokens(tokens)} tokens, ${estPrefix}$${cost.toFixed(2)}${ANSI.reset}`
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { ANSI } from "./formatters.js";
|
|
2
|
-
|
|
3
|
-
const SOLOMON_RULING_HANDLERS = {
|
|
4
|
-
approve(detail, elapsed) {
|
|
5
|
-
const dismissedCount = detail?.dismissed?.length || 0;
|
|
6
|
-
const dismissedSuffix = dismissedCount > 0 ? ` (${dismissedCount} dismissed)` : "";
|
|
7
|
-
console.log(` \u251c\u2500 ${ANSI.green}\u2696\ufe0f Solomon: APPROVE${dismissedSuffix}${ANSI.reset} ${elapsed}`);
|
|
8
|
-
},
|
|
9
|
-
approve_with_conditions(detail, elapsed) {
|
|
10
|
-
const condCount = detail?.conditions?.length || 0;
|
|
11
|
-
console.log(` \u251c\u2500 ${ANSI.yellow}\u2696\ufe0f Solomon: ${condCount} condition${condCount === 1 ? "" : "s"}${ANSI.reset} ${elapsed}`);
|
|
12
|
-
if (detail?.conditions) {
|
|
13
|
-
for (const cond of detail.conditions) {
|
|
14
|
-
console.log(` \u2502 ${ANSI.dim}${cond}${ANSI.reset}`);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
escalate_human(detail, elapsed) {
|
|
19
|
-
const reason = detail?.escalate_reason || "unknown reason";
|
|
20
|
-
console.log(` \u251c\u2500 ${ANSI.red}\u2696\ufe0f Solomon: ESCALATE \u2014 ${reason}${ANSI.reset} ${elapsed}`);
|
|
21
|
-
},
|
|
22
|
-
create_subtask(detail, elapsed) {
|
|
23
|
-
const subtaskTitle = detail?.subtask?.title || "untitled";
|
|
24
|
-
console.log(` \u251c\u2500 ${ANSI.magenta}\u2696\ufe0f Solomon: SUBTASK \u2014 ${subtaskTitle}${ANSI.reset} ${elapsed}`);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Print Solomon ruling details
|
|
30
|
-
* @param {Object} detail
|
|
31
|
-
* @param {string} elapsed
|
|
32
|
-
*/
|
|
33
|
-
export function printSolomonRuling(detail, elapsed) {
|
|
34
|
-
const ruling = detail?.ruling || "unknown";
|
|
35
|
-
const handler = SOLOMON_RULING_HANDLERS[ruling];
|
|
36
|
-
if (handler) {
|
|
37
|
-
handler(detail, elapsed);
|
|
38
|
-
} else {
|
|
39
|
-
const rulingUpper = ruling.toUpperCase().replaceAll("_", " ");
|
|
40
|
-
console.log(` \u251c\u2500 \u2696\ufe0f Solomon: ${rulingUpper} ${elapsed}`);
|
|
41
|
-
}
|
|
42
|
-
}
|
package/src/utils/pricing.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { buildDefaultPricingTable } from "../agents/model-registry.js";
|
|
2
|
-
|
|
3
|
-
export const DEFAULT_MODEL_PRICING = buildDefaultPricingTable();
|
|
4
|
-
|
|
5
|
-
export function calculateUsageCostUsd({ provider, model, tokens_in, tokens_out, pricing }) {
|
|
6
|
-
const table = pricing || DEFAULT_MODEL_PRICING;
|
|
7
|
-
|
|
8
|
-
let entry = table[model];
|
|
9
|
-
|
|
10
|
-
if (!entry && provider && model) {
|
|
11
|
-
entry = table[`${provider}/${model}`];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (!entry && model && model.includes("/")) {
|
|
15
|
-
const [, actualModel] = model.split("/");
|
|
16
|
-
entry = table[actualModel];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (!entry) return 0;
|
|
20
|
-
|
|
21
|
-
const inputCost = (tokens_in * entry.input_per_million) / 1_000_000;
|
|
22
|
-
const outputCost = (tokens_out * entry.output_per_million) / 1_000_000;
|
|
23
|
-
return inputCost + outputCost;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function mergePricing(defaults, overrides) {
|
|
27
|
-
if (!overrides || typeof overrides !== "object") return { ...defaults };
|
|
28
|
-
return { ...defaults, ...overrides };
|
|
29
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// KJ_SIMULATE_QUOTA — testing hook for the standby flow. See
|
|
2
|
-
// docs/quota-simulation.md. KJC-TSK-0493.
|
|
3
|
-
|
|
4
|
-
let _warned = false;
|
|
5
|
-
|
|
6
|
-
export function parseQuotaSimulationConfig(env = process.env) {
|
|
7
|
-
const trigger = env.KJ_SIMULATE_QUOTA;
|
|
8
|
-
if (!trigger) return null;
|
|
9
|
-
const m = /^after-iter-(\d+)$/i.exec(String(trigger).trim());
|
|
10
|
-
if (!m) {
|
|
11
|
-
if (!_warned) {
|
|
12
|
-
// eslint-disable-next-line no-console
|
|
13
|
-
console.warn(`[KJ_SIMULATE_QUOTA] Ignoring malformed value "${trigger}". Expected "after-iter-<N>".`);
|
|
14
|
-
_warned = true;
|
|
15
|
-
}
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
afterIter: Number.parseInt(m[1], 10),
|
|
20
|
-
resetIso: env.KJ_SIMULATE_QUOTA_RESET || new Date(Date.now() + 3600_000).toISOString(),
|
|
21
|
-
agent: String(env.KJ_SIMULATE_QUOTA_AGENT || "claude").toLowerCase(),
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const SYNTHETIC_MSG = {
|
|
26
|
-
claude: (iso) => `[KJ_SIMULATE_QUOTA] Claude Pro usage limit reached. weekly limit. resets at ${iso}`,
|
|
27
|
-
codex: () => `[KJ_SIMULATE_QUOTA] You have exceeded your current quota. retry after 60 seconds`,
|
|
28
|
-
gemini: () => `[KJ_SIMULATE_QUOTA] Resource exhausted: quota exceeded. retry after 60 seconds`,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export function buildSyntheticQuotaMessage(agent, resetIso) {
|
|
32
|
-
return (SYNTHETIC_MSG[agent] || SYNTHETIC_MSG.claude)(resetIso);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function shouldSimulateQuota({ iteration, agent }, env = process.env) {
|
|
36
|
-
const cfg = parseQuotaSimulationConfig(env);
|
|
37
|
-
if (!cfg) return null;
|
|
38
|
-
if (Number(iteration) < cfg.afterIter) return null;
|
|
39
|
-
const a = String(agent || "").toLowerCase();
|
|
40
|
-
if (cfg.agent !== "any" && cfg.agent !== a) return null;
|
|
41
|
-
return { resetIso: cfg.resetIso, agent: a || cfg.agent };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Mutates execResult: forces ok=false and prepends the synthetic quota
|
|
45
|
-
// line to result.error so the existing detectRateLimit branch fires.
|
|
46
|
-
export function applyQuotaSimulation(execResult, { iteration, agent }, env = process.env) {
|
|
47
|
-
const fire = shouldSimulateQuota({ iteration, agent }, env);
|
|
48
|
-
if (!fire || !execResult || typeof execResult !== "object") return false;
|
|
49
|
-
if (!execResult.result || typeof execResult.result !== "object") execResult.result = {};
|
|
50
|
-
execResult.result.error = `${buildSyntheticQuotaMessage(fire.agent, fire.resetIso)}\n${execResult.result.error || ""}`;
|
|
51
|
-
execResult.ok = false;
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Test seam — reset the one-shot warning between unit tests.
|
|
56
|
-
export function _resetSimulatorWarning() { _warned = false; }
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
// Smart role assignment based on available AI agents.
|
|
2
|
-
// Used by both kj init (interactive) and auto-init (non-interactive).
|
|
3
|
-
|
|
4
|
-
import { detectAvailableAgents } from "./agent-detect.js";
|
|
5
|
-
|
|
6
|
-
// Agent capability tiers (higher = more capable for complex reasoning)
|
|
7
|
-
const CAPABILITY_TIERS = {
|
|
8
|
-
claude: 5, // Best for reasoning, orchestration, complex tasks
|
|
9
|
-
codex: 4, // Strong coder, good reviewer
|
|
10
|
-
gemini: 3, // Good general purpose
|
|
11
|
-
aider: 2, // Good coder, limited reasoning
|
|
12
|
-
opencode: 2 // Similar to aider
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
// Role requirements: what capability level is ideal for each role
|
|
16
|
-
const ROLE_PREFERENCES = {
|
|
17
|
-
brain: { minTier: 4, prefer: "claude", description: "Karajan Brain (orchestrator)" },
|
|
18
|
-
// KJC-BUG-0113: Solomon preferred gemini, but Google retired the Gemini
|
|
19
|
-
// Code Assist CLI for individuals — a binary that answers --version yet
|
|
20
|
-
// dies with IneligibleTierError on every real call. Any machine with the
|
|
21
|
-
// stale CLI on PATH got a judge that could never rule. Claude matches
|
|
22
|
-
// the brain default; diversifyReviewer still picks a different agent
|
|
23
|
-
// when more than one healthy option exists.
|
|
24
|
-
solomon: { minTier: 3, prefer: "claude", description: "Solomon (judge/arbiter)" },
|
|
25
|
-
coder: { minTier: 2, prefer: "claude", description: "Coder" },
|
|
26
|
-
reviewer: { minTier: 3, prefer: "codex", description: "Reviewer" },
|
|
27
|
-
planner: { minTier: 4, prefer: "claude", description: "Planner" },
|
|
28
|
-
researcher: { minTier: 3, prefer: "claude", description: "Researcher" },
|
|
29
|
-
architect: { minTier: 4, prefer: "claude", description: "Architect" },
|
|
30
|
-
tester: { minTier: 3, prefer: "claude", description: "Tester" },
|
|
31
|
-
security: { minTier: 3, prefer: "claude", description: "Security" },
|
|
32
|
-
triage: { minTier: 3, prefer: "claude", description: "Triage" }
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Assign the best available agent to a role.
|
|
37
|
-
* Prefers the role's preferred agent if available, then falls back by capability tier.
|
|
38
|
-
*/
|
|
39
|
-
function assignRole(roleName, availableAgents) {
|
|
40
|
-
const pref = ROLE_PREFERENCES[roleName];
|
|
41
|
-
if (!pref) return availableAgents[0]?.name || "claude";
|
|
42
|
-
|
|
43
|
-
// Preferred agent available?
|
|
44
|
-
if (availableAgents.find(a => a.name === pref.prefer)) {
|
|
45
|
-
return pref.prefer;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Sort by capability tier (descending) and pick the best available
|
|
49
|
-
const sorted = [...availableAgents].sort(
|
|
50
|
-
(a, b) => (CAPABILITY_TIERS[b.name] || 1) - (CAPABILITY_TIERS[a.name] || 1)
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
return sorted[0]?.name || "claude";
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Try to diversify: if possible, use a different agent for reviewer than coder.
|
|
58
|
-
*/
|
|
59
|
-
function diversifyReviewer(coderAgent, availableAgents) {
|
|
60
|
-
const alternatives = availableAgents.filter(a => a.name !== coderAgent);
|
|
61
|
-
if (alternatives.length === 0) return coderAgent;
|
|
62
|
-
|
|
63
|
-
const sorted = [...alternatives].sort(
|
|
64
|
-
(a, b) => (CAPABILITY_TIERS[b.name] || 1) - (CAPABILITY_TIERS[a.name] || 1)
|
|
65
|
-
);
|
|
66
|
-
return sorted[0].name;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Auto-assign all roles based on detected agents. Non-interactive.
|
|
71
|
-
* Returns a config-ready object with role assignments.
|
|
72
|
-
*/
|
|
73
|
-
export async function autoAssignRoles(logger) {
|
|
74
|
-
const agents = await detectAvailableAgents();
|
|
75
|
-
const available = agents.filter(a => a.available);
|
|
76
|
-
|
|
77
|
-
if (available.length === 0) {
|
|
78
|
-
logger?.warn?.("No AI agents detected. Using claude as default for all roles.");
|
|
79
|
-
return { assignments: getDefaultAssignments("claude"), agents, available: [] };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
logger?.info?.(`Detected ${available.length} AI agent(s): ${available.map(a => `${a.name} (${a.version})`).join(", ")}`);
|
|
83
|
-
|
|
84
|
-
const coder = assignRole("coder", available);
|
|
85
|
-
const reviewer = available.length > 1 ? diversifyReviewer(coder, available) : coder;
|
|
86
|
-
const brain = assignRole("brain", available);
|
|
87
|
-
const solomon = available.length > 1 ? diversifyReviewer(brain, available) : brain;
|
|
88
|
-
|
|
89
|
-
const assignments = {
|
|
90
|
-
brain,
|
|
91
|
-
solomon,
|
|
92
|
-
coder,
|
|
93
|
-
reviewer,
|
|
94
|
-
planner: assignRole("planner", available),
|
|
95
|
-
researcher: assignRole("researcher", available),
|
|
96
|
-
architect: assignRole("architect", available),
|
|
97
|
-
tester: assignRole("tester", available),
|
|
98
|
-
security: assignRole("security", available),
|
|
99
|
-
triage: assignRole("triage", available)
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
logger?.info?.(`Role assignments: Brain=${brain}, Solomon=${solomon}, Coder=${coder}, Reviewer=${reviewer}`);
|
|
103
|
-
|
|
104
|
-
return { assignments, agents, available };
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function getDefaultAssignments(agent) {
|
|
108
|
-
return {
|
|
109
|
-
brain: agent, solomon: agent, coder: agent, reviewer: agent,
|
|
110
|
-
planner: agent, researcher: agent, architect: agent,
|
|
111
|
-
tester: agent, security: agent, triage: agent
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Apply role assignments to a Karajan config object.
|
|
117
|
-
*/
|
|
118
|
-
export function applyRoleAssignments(config, assignments) {
|
|
119
|
-
config.coder = assignments.coder;
|
|
120
|
-
config.reviewer = assignments.reviewer;
|
|
121
|
-
|
|
122
|
-
const roleNames = ["coder", "reviewer", "planner", "researcher", "architect",
|
|
123
|
-
"tester", "security", "triage", "solomon"];
|
|
124
|
-
|
|
125
|
-
for (const role of roleNames) {
|
|
126
|
-
config.roles = config.roles || {};
|
|
127
|
-
config.roles[role] = config.roles[role] || {};
|
|
128
|
-
config.roles[role].provider = assignments[role] || assignments.coder;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Brain is a new top-level config (not in roles yet — will be when KarajanBrainRole is implemented)
|
|
132
|
-
config.brain = { provider: assignments.brain };
|
|
133
|
-
|
|
134
|
-
return config;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export { CAPABILITY_TIERS };
|
package/src/utils/rtk-wrapper.js
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { runCommand } from "./process.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Commands that RTK can safely wrap for token-optimized output.
|
|
5
|
-
*/
|
|
6
|
-
export const RTK_SUPPORTED_COMMANDS = [
|
|
7
|
-
"git", "ls", "find", "grep", "cat", "head", "tail",
|
|
8
|
-
"wc", "diff", "tree", "du", "file"
|
|
9
|
-
];
|
|
10
|
-
|
|
11
|
-
const supportedSet = new Set(RTK_SUPPORTED_COMMANDS);
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Wrap a command with RTK if available and the command is in the whitelist.
|
|
15
|
-
* @param {string} command
|
|
16
|
-
* @param {string[]} args
|
|
17
|
-
* @param {boolean} rtkAvailable
|
|
18
|
-
* @returns {{ command: string, args: string[] }}
|
|
19
|
-
*/
|
|
20
|
-
export function wrapWithRtk(command, args, rtkAvailable) {
|
|
21
|
-
if (rtkAvailable && supportedSet.has(command)) {
|
|
22
|
-
return { command: "rtk", args: [command, ...args] };
|
|
23
|
-
}
|
|
24
|
-
return { command, args };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Session-level accumulator for RTK byte savings.
|
|
29
|
-
*/
|
|
30
|
-
export class RtkSavingsTracker {
|
|
31
|
-
constructor() {
|
|
32
|
-
this.originalBytes = 0;
|
|
33
|
-
this.rtkBytes = 0;
|
|
34
|
-
this.callCount = 0;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
record(originalSize, rtkSize) {
|
|
38
|
-
this.originalBytes += originalSize;
|
|
39
|
-
this.rtkBytes += rtkSize;
|
|
40
|
-
this.callCount += 1;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
summary() {
|
|
44
|
-
const savedBytes = this.originalBytes - this.rtkBytes;
|
|
45
|
-
const savedPct = this.originalBytes > 0
|
|
46
|
-
? Number(((savedBytes / this.originalBytes) * 100).toFixed(1))
|
|
47
|
-
: 0;
|
|
48
|
-
const estimatedTokensSaved = Math.floor(savedBytes / 4);
|
|
49
|
-
return {
|
|
50
|
-
originalBytes: this.originalBytes,
|
|
51
|
-
rtkBytes: this.rtkBytes,
|
|
52
|
-
savedBytes,
|
|
53
|
-
savedPct,
|
|
54
|
-
estimatedTokensSaved,
|
|
55
|
-
callCount: this.callCount
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** Returns true if any commands were recorded. */
|
|
60
|
-
hasData() {
|
|
61
|
-
return this.callCount > 0;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Create a runner function that transparently wraps supported commands with RTK.
|
|
67
|
-
* @param {boolean} rtkAvailable
|
|
68
|
-
* @param {RtkSavingsTracker} [tracker] - Optional savings tracker
|
|
69
|
-
* @returns {(command: string, args?: string[], options?: object) => Promise<object>}
|
|
70
|
-
*/
|
|
71
|
-
export function createRtkRunner(rtkAvailable, tracker = null) {
|
|
72
|
-
return async (command, args = [], options = {}) => {
|
|
73
|
-
const wrapped = wrapWithRtk(command, args, rtkAvailable);
|
|
74
|
-
const result = await runCommand(wrapped.command, wrapped.args, options);
|
|
75
|
-
|
|
76
|
-
if (tracker && rtkAvailable && supportedSet.has(command)) {
|
|
77
|
-
const outputSize = Buffer.byteLength(result.stdout || "", "utf8");
|
|
78
|
-
// For RTK-wrapped calls, the output is already compressed.
|
|
79
|
-
// We estimate the original size as outputSize (conservative — real savings
|
|
80
|
-
// would require running the command without RTK, which defeats the purpose).
|
|
81
|
-
// The tracker is useful when the caller provides real estimates externally.
|
|
82
|
-
tracker.record(outputSize, outputSize);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return result;
|
|
86
|
-
};
|
|
87
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// Shim: run-registry now lives in karajan-core/run-registry so the
|
|
2
|
-
// hu-board workspace can consume it without a relative dep on the CLI
|
|
3
|
-
// src tree. KJC-TSK-0511 PR3.
|
|
4
|
-
export {
|
|
5
|
-
runsDir,
|
|
6
|
-
registerRun,
|
|
7
|
-
unregisterRun,
|
|
8
|
-
listActiveRuns,
|
|
9
|
-
} from "karajan-core/run-registry";
|