@pennyfarthing/core 11.2.0 → 11.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -40
- package/package.json +2 -1
- package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/doctor.js +474 -66
- package/packages/core/dist/cli/commands/doctor.js.map +1 -1
- package/packages/core/dist/cli/commands/init.js +4 -4
- package/packages/core/dist/cli/commands/init.js.map +1 -1
- package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/update.js +4 -5
- package/packages/core/dist/cli/commands/update.js.map +1 -1
- package/packages/core/dist/cli/utils/constants.d.ts +3 -8
- package/packages/core/dist/cli/utils/constants.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/constants.js +3 -4
- package/packages/core/dist/cli/utils/constants.js.map +1 -1
- package/packages/core/dist/cli/utils/settings.d.ts +7 -0
- package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/settings.js +70 -29
- package/packages/core/dist/cli/utils/settings.js.map +1 -1
- package/packages/core/dist/cli/utils/symlinks.js +16 -16
- package/packages/core/dist/cli/utils/symlinks.js.map +1 -1
- package/packages/core/dist/consultation/dialogue-manager.d.ts +1 -1
- package/packages/core/dist/consultation/dialogue-manager.d.ts.map +1 -1
- package/packages/core/dist/consultation/dialogue-manager.js +1 -1
- package/packages/core/dist/consultation/dialogue-manager.js.map +1 -1
- package/packages/core/dist/consultation/dialogue-manager.test.js.map +1 -1
- package/packages/core/dist/consultation/tandem-metrics.d.ts +91 -0
- package/packages/core/dist/consultation/tandem-metrics.d.ts.map +1 -0
- package/packages/core/dist/consultation/tandem-metrics.js +131 -0
- package/packages/core/dist/consultation/tandem-metrics.js.map +1 -0
- package/packages/core/dist/consultation/tandem-metrics.test.d.ts +18 -0
- package/packages/core/dist/consultation/tandem-metrics.test.d.ts.map +1 -0
- package/packages/core/dist/consultation/tandem-metrics.test.js +457 -0
- package/packages/core/dist/consultation/tandem-metrics.test.js.map +1 -0
- package/packages/core/dist/public/css/react.css +1 -1
- package/packages/core/dist/public/js/react/react.js +14 -14
- package/packages/core/dist/server/api/agent-load.js +1 -1
- package/packages/core/dist/server/api/agent-load.js.map +1 -1
- package/packages/core/dist/server/api/git.d.ts.map +1 -1
- package/packages/core/dist/server/api/git.js +0 -1
- package/packages/core/dist/server/api/git.js.map +1 -1
- package/packages/core/dist/server/api/index.d.ts +2 -0
- package/packages/core/dist/server/api/index.d.ts.map +1 -1
- package/packages/core/dist/server/api/index.js +2 -0
- package/packages/core/dist/server/api/index.js.map +1 -1
- package/packages/core/dist/server/api/project-info.d.ts +11 -0
- package/packages/core/dist/server/api/project-info.d.ts.map +1 -0
- package/packages/core/dist/server/api/project-info.js +18 -0
- package/packages/core/dist/server/api/project-info.js.map +1 -0
- package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
- package/packages/core/dist/server/otlp-receiver.js +18 -1
- package/packages/core/dist/server/otlp-receiver.js.map +1 -1
- package/packages/core/dist/server/otlp-receiver.test.js +1 -1
- package/packages/core/dist/server/otlp-receiver.test.js.map +1 -1
- package/packages/core/dist/server/server.d.ts +0 -3
- package/packages/core/dist/server/server.d.ts.map +1 -1
- package/packages/core/dist/server/server.js +5 -38
- package/packages/core/dist/server/server.js.map +1 -1
- package/packages/core/dist/server/server.test.d.ts +1 -1
- package/packages/core/dist/server/server.test.js +12 -23
- package/packages/core/dist/server/server.test.js.map +1 -1
- package/packages/core/dist/server/settings.d.ts +1 -0
- package/packages/core/dist/server/settings.d.ts.map +1 -1
- package/packages/core/dist/server/settings.js +13 -0
- package/packages/core/dist/server/settings.js.map +1 -1
- package/packages/core/dist/shared/capabilities.d.ts +88 -0
- package/packages/core/dist/shared/capabilities.d.ts.map +1 -0
- package/packages/core/dist/shared/capabilities.js +133 -0
- package/packages/core/dist/shared/capabilities.js.map +1 -0
- package/packages/core/dist/shared/capabilities.test.d.ts +2 -0
- package/packages/core/dist/shared/capabilities.test.d.ts.map +1 -0
- package/packages/core/dist/shared/capabilities.test.js +217 -0
- package/packages/core/dist/shared/capabilities.test.js.map +1 -0
- package/packages/core/dist/shared/spawn-prompt.d.ts +47 -0
- package/packages/core/dist/shared/spawn-prompt.d.ts.map +1 -0
- package/packages/core/dist/shared/spawn-prompt.js +82 -0
- package/packages/core/dist/shared/spawn-prompt.js.map +1 -0
- package/packages/core/dist/shared/spawn-prompt.test.d.ts +2 -0
- package/packages/core/dist/shared/spawn-prompt.test.d.ts.map +1 -0
- package/packages/core/dist/shared/spawn-prompt.test.js +251 -0
- package/packages/core/dist/shared/spawn-prompt.test.js.map +1 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts +18 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.js +434 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.js.map +1 -0
- package/packages/core/dist/workflow/team-lifecycle.d.ts +169 -0
- package/packages/core/dist/workflow/team-lifecycle.d.ts.map +1 -0
- package/packages/core/dist/workflow/team-lifecycle.js +217 -0
- package/packages/core/dist/workflow/team-lifecycle.js.map +1 -0
- package/packages/core/dist/workflow/team-lifecycle.test.d.ts +20 -0
- package/packages/core/dist/workflow/team-lifecycle.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/team-lifecycle.test.js +966 -0
- package/packages/core/dist/workflow/team-lifecycle.test.js.map +1 -0
- package/packages/core/dist/workflow/workflow-schema.d.ts +32 -0
- package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.js +120 -0
- package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.test.js +570 -1
- package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
- package/packages/core/dist/workflow/workflow-team-templates.test.d.ts +17 -0
- package/packages/core/dist/workflow/workflow-team-templates.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/workflow-team-templates.test.js +275 -0
- package/packages/core/dist/workflow/workflow-team-templates.test.js.map +1 -0
- package/pennyfarthing-dist/agents/dev.md +21 -12
- package/pennyfarthing-dist/agents/reviewer.md +23 -4
- package/pennyfarthing-dist/agents/sm-finish.md +19 -2
- package/pennyfarthing-dist/agents/sm-setup.md +7 -7
- package/pennyfarthing-dist/agents/sm.md +12 -12
- package/pennyfarthing-dist/agents/tea.md +2 -2
- package/pennyfarthing-dist/agents/testing-runner.md +1 -1
- package/pennyfarthing-dist/commands/pf-architect.md +1 -1
- package/pennyfarthing-dist/commands/pf-ba.md +1 -1
- package/pennyfarthing-dist/commands/pf-chore.md +2 -2
- package/pennyfarthing-dist/commands/pf-dev.md +1 -1
- package/pennyfarthing-dist/commands/pf-devops.md +1 -1
- package/pennyfarthing-dist/commands/pf-epic.md +6 -6
- package/pennyfarthing-dist/commands/pf-git.md +12 -10
- package/pennyfarthing-dist/commands/pf-health-check.md +1 -1
- package/pennyfarthing-dist/commands/pf-help.md +12 -12
- package/pennyfarthing-dist/commands/pf-orchestrator.md +1 -1
- package/pennyfarthing-dist/commands/pf-pm.md +1 -1
- package/pennyfarthing-dist/commands/pf-prime.md +8 -8
- package/pennyfarthing-dist/commands/pf-reviewer.md +1 -1
- package/pennyfarthing-dist/commands/pf-session.md +7 -7
- package/pennyfarthing-dist/commands/pf-sm.md +1 -1
- package/pennyfarthing-dist/commands/pf-sprint.md +7 -7
- package/pennyfarthing-dist/commands/pf-tea.md +1 -1
- package/pennyfarthing-dist/commands/pf-tech-writer.md +1 -1
- package/pennyfarthing-dist/commands/pf-theme.md +9 -9
- package/pennyfarthing-dist/commands/pf-ux-designer.md +1 -1
- package/pennyfarthing-dist/commands/pf-work.md +1 -1
- package/pennyfarthing-dist/gates/approval.md +63 -0
- package/pennyfarthing-dist/gates/confidence-sm.md +71 -0
- package/pennyfarthing-dist/gates/context-ok.md +56 -0
- package/pennyfarthing-dist/gates/evaluations/confidence-sm.md +54 -0
- package/pennyfarthing-dist/gates/quality-pass.md +67 -0
- package/pennyfarthing-dist/gates/tests-fail.md +84 -0
- package/pennyfarthing-dist/gates/tests-pass.md +79 -0
- package/pennyfarthing-dist/guides/agent-behavior.md +84 -29
- package/pennyfarthing-dist/guides/agent-coordination.md +10 -10
- package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +6 -6
- package/pennyfarthing-dist/guides/agent-template-tactical.md +1 -1
- package/pennyfarthing-dist/guides/bell-mode.md +1 -1
- package/pennyfarthing-dist/guides/bikerack.md +10 -10
- package/pennyfarthing-dist/guides/brownfield-tools.md +24 -24
- package/pennyfarthing-dist/guides/command-tag-taxonomy.md +1 -1
- package/pennyfarthing-dist/guides/gate-schema.md +2 -2
- package/pennyfarthing-dist/guides/gates.md +3 -3
- package/pennyfarthing-dist/guides/handoff-cli.md +8 -8
- package/pennyfarthing-dist/guides/hooks.md +29 -29
- package/pennyfarthing-dist/guides/prime.md +2 -2
- package/pennyfarthing-dist/guides/reflector.md +1 -1
- package/pennyfarthing-dist/guides/skill-schema.md +6 -6
- package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
- package/pennyfarthing-dist/guides/workflow-schema.md +1 -1
- package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
- package/pennyfarthing-dist/guides/xml-tags.md +8 -8
- package/pennyfarthing-dist/scripts/README.md +4 -4
- package/pennyfarthing-dist/scripts/core/agent-session.sh +2 -5
- package/pennyfarthing-dist/scripts/core/check-context.sh +3 -1
- package/pennyfarthing-dist/scripts/core/pf.sh +5 -0
- package/pennyfarthing-dist/scripts/core/phase-check-start.sh +4 -89
- package/pennyfarthing-dist/scripts/core/prime.sh +2 -25
- package/pennyfarthing-dist/scripts/git/README.md +14 -14
- package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +2 -3
- package/pennyfarthing-dist/scripts/git/git-status-all.sh +2 -3
- package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +2 -3
- package/pennyfarthing-dist/scripts/git/worktree-manager.sh +2 -4
- package/pennyfarthing-dist/scripts/hooks/README.md +6 -6
- package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +4 -183
- package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +4 -95
- package/pennyfarthing-dist/scripts/hooks/context-warning.sh +4 -65
- package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +3 -31
- package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +5 -4
- package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +29 -34
- package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +4 -71
- package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +3 -19
- package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +4 -30
- package/pennyfarthing-dist/scripts/hooks/session-start.sh +3 -32
- package/pennyfarthing-dist/scripts/hooks/session-stop.sh +4 -65
- package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +4 -78
- package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +3 -93
- package/pennyfarthing-dist/scripts/lib/env.sh +34 -0
- package/pennyfarthing-dist/scripts/lib/run-pf.sh +39 -0
- package/pennyfarthing-dist/scripts/misc/README.md +1 -1
- package/pennyfarthing-dist/scripts/misc/statusline.sh +4 -301
- package/pennyfarthing-dist/scripts/sprint/README.md +21 -21
- package/pennyfarthing-dist/scripts/workflow/README.md +2 -2
- package/pennyfarthing-dist/scripts/workflow/finish-story.sh +2 -16
- package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +3 -3
- package/pennyfarthing-dist/skills/pf-bc/examples.md +23 -23
- package/pennyfarthing-dist/skills/pf-bc/skill.md +17 -17
- package/pennyfarthing-dist/skills/pf-bc/usage.md +8 -8
- package/pennyfarthing-dist/skills/pf-jira/SKILL.md +15 -15
- package/pennyfarthing-dist/skills/pf-jira/examples.md +48 -48
- package/pennyfarthing-dist/skills/pf-jira/usage.md +15 -15
- package/pennyfarthing-dist/skills/pf-sprint/examples.md +80 -80
- package/pennyfarthing-dist/skills/pf-sprint/skill.md +35 -35
- package/pennyfarthing-dist/skills/pf-sprint/usage.md +30 -30
- package/pennyfarthing-dist/skills/pf-theme/examples.md +15 -15
- package/pennyfarthing-dist/skills/pf-theme/skill.md +6 -6
- package/pennyfarthing-dist/skills/pf-theme/usage.md +5 -5
- package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -27
- package/pennyfarthing-dist/skills/pf-workflow/skill.md +11 -11
- package/pennyfarthing-dist/skills/pf-workflow/usage.md +11 -11
- package/pennyfarthing-dist/skills/skill-registry.yaml +19 -19
- package/pennyfarthing-dist/templates/settings.local.json.template +19 -10
- package/pennyfarthing-dist/workflows/bdd-team.yaml +89 -0
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +1 -1
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +1 -1
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +1 -1
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +1 -1
- package/pennyfarthing-dist/workflows/project-setup/steps/step-01-discover.md +47 -0
- package/pennyfarthing-dist/workflows/tdd-team.yaml +80 -0
- package/pennyfarthing-dist/workflows/tdd.yaml +11 -2
- package/pennyfarthing_scripts/CLAUDE.md +19 -10
- package/pennyfarthing_scripts/__init__.py +1 -1
- package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/context.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/session_start_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/__pycache__/focus.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/__pycache__/split.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/cli.py +2 -2
- package/pennyfarthing_scripts/bellmode_hook.py +9 -296
- package/pennyfarthing_scripts/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/events.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_data.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_screen.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/audit_log_panel.py +161 -0
- package/pennyfarthing_scripts/bikerack/base_panel.py +27 -4
- package/pennyfarthing_scripts/bikerack/changed_panel.py +96 -4
- package/pennyfarthing_scripts/bikerack/context_meter_footer.py +88 -0
- package/pennyfarthing_scripts/bikerack/debug_panel.py +1 -1
- package/pennyfarthing_scripts/bikerack/diffs_panel.py +30 -0
- package/pennyfarthing_scripts/bikerack/events.py +28 -0
- package/pennyfarthing_scripts/bikerack/launcher.py +6 -6
- package/pennyfarthing_scripts/bikerack/portrait_resolver.py +139 -0
- package/pennyfarthing_scripts/bikerack/progress_panel.py +0 -1
- package/pennyfarthing_scripts/bikerack/sprint_panel.py +373 -142
- package/pennyfarthing_scripts/bikerack/story_detail_data.py +247 -0
- package/pennyfarthing_scripts/bikerack/story_detail_screen.py +177 -0
- package/pennyfarthing_scripts/bikerack/tui.py +304 -62
- package/pennyfarthing_scripts/bikerack/ws_client.py +2 -2
- package/pennyfarthing_scripts/cli.py +5 -0
- package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/config.py +29 -2
- package/pennyfarthing_scripts/common/pr_config.py +38 -0
- package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/cli.py +3 -3
- package/pennyfarthing_scripts/context.py +3 -3
- package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/repos.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/hooks_installer.py +2 -3
- package/pennyfarthing_scripts/git/status_all.py +1 -1
- package/pennyfarthing_scripts/git/worktree.py +2 -2
- package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/phase_check.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/cli.py +33 -1
- package/pennyfarthing_scripts/handoff/complete_phase.py +28 -0
- package/pennyfarthing_scripts/handoff/marker.py +15 -15
- package/pennyfarthing_scripts/handoff/phase_check.py +96 -0
- package/pennyfarthing_scripts/handoff/resolve_gate.py +13 -1
- package/pennyfarthing_scripts/hooks/__init__.py +442 -0
- package/pennyfarthing_scripts/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/bell_mode.py +214 -0
- package/pennyfarthing_scripts/hooks/cli.py +96 -0
- package/pennyfarthing_scripts/hooks/context_breaker.py +104 -0
- package/pennyfarthing_scripts/hooks/context_warning.py +66 -0
- package/pennyfarthing_scripts/hooks/cyclist_pretooluse.py +129 -0
- package/pennyfarthing_scripts/hooks/pre_edit_check.py +77 -0
- package/pennyfarthing_scripts/hooks/reflector_check.py +270 -0
- package/pennyfarthing_scripts/hooks/schema_validation.py +202 -0
- package/pennyfarthing_scripts/hooks/session_start.py +294 -0
- package/pennyfarthing_scripts/hooks/session_stop.py +111 -0
- package/pennyfarthing_scripts/hooks/sprint_yaml_validation.py +97 -0
- package/pennyfarthing_scripts/hooks/statusline.py +429 -0
- package/pennyfarthing_scripts/hooks.py +27 -432
- package/pennyfarthing_scripts/pretooluse_hook.py +3 -185
- package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/heatmap.py +3 -15
- package/pennyfarthing_scripts/prime/workflow.py +2 -1
- package/pennyfarthing_scripts/schema_validation_hook.py +3 -298
- package/pennyfarthing_scripts/session_start_hook.py +4 -186
- package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/cli.py +121 -0
- package/pennyfarthing_scripts/sprint/loader.py +154 -3
- package/pennyfarthing_scripts/sprint/story_update.py +26 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_workflow_list_team.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/test_bikerack.py +26 -26
- package/pennyfarthing_scripts/tests/test_dialogue_manager.py +0 -1
- package/pennyfarthing_scripts/tests/test_sprint_panel.py +344 -265
- package/pennyfarthing_scripts/tests/test_workflow_list_team.py +147 -0
- package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/team_mode.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/team_mode.py +323 -0
- package/pennyfarthing_scripts/validate/adapters/workflow.py +19 -0
- package/pennyfarthing_scripts/welcome_hook.py +3 -149
- package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/team_lifecycle.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/cli.py +22 -20
- package/pennyfarthing_scripts/workflow/state.py +0 -1
- package/pennyfarthing_scripts/workflow/team_lifecycle.py +256 -0
- package/packages/core/dist/cli/cyclist-migration.test.d.ts +0 -16
- package/packages/core/dist/cli/cyclist-migration.test.d.ts.map +0 -1
- package/packages/core/dist/cli/cyclist-migration.test.js +0 -229
- package/packages/core/dist/cli/cyclist-migration.test.js.map +0 -1
- package/packages/core/dist/scripts/theme-detail.test.d.ts +0 -10
- package/packages/core/dist/scripts/theme-detail.test.d.ts.map +0 -1
- package/packages/core/dist/scripts/theme-detail.test.js +0 -199
- package/packages/core/dist/scripts/theme-detail.test.js.map +0 -1
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Story 86-6: Tandem Metrics and Token Tracking
|
|
3
|
+
*
|
|
4
|
+
* RED state tests for consultation token usage, frequency, and outcome metrics.
|
|
5
|
+
* These metrics are tracked separately from leader session tokens and written
|
|
6
|
+
* to the dialogue file summary section.
|
|
7
|
+
*
|
|
8
|
+
* ACs covered:
|
|
9
|
+
* AC1: Consultation tokens logged separately from leader session tokens
|
|
10
|
+
* AC2: Metrics captured: count, total tokens, avg response time, outcome distribution
|
|
11
|
+
* AC3: Metrics written to dialogue file summary section
|
|
12
|
+
* AC4: Session summary includes tandem overhead percentage
|
|
13
|
+
* AC5: Target: consultation overhead < 25% of baseline story token cost
|
|
14
|
+
*
|
|
15
|
+
* Run with: npm test
|
|
16
|
+
*/
|
|
17
|
+
import { describe, it } from 'node:test';
|
|
18
|
+
import assert from 'node:assert';
|
|
19
|
+
import { aggregateMetrics, calculateOverheadPercent, isWithinBudget, formatMetricsSummary, parseMetricsFromSummary, } from './tandem-metrics.js';
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// Test Fixtures
|
|
22
|
+
// =============================================================================
|
|
23
|
+
const EXCHANGE_WITH_METRICS = {
|
|
24
|
+
number: 1,
|
|
25
|
+
timestamp: '10:05',
|
|
26
|
+
leader: 'dev',
|
|
27
|
+
partner: 'architect',
|
|
28
|
+
question: 'Should we use a class or functional approach?',
|
|
29
|
+
recommendation: 'Use pure functions',
|
|
30
|
+
confidence: 'high',
|
|
31
|
+
outcome: 'applied',
|
|
32
|
+
outcomeNote: 'Adopted functional approach',
|
|
33
|
+
metrics: {
|
|
34
|
+
inputTokens: 150,
|
|
35
|
+
outputTokens: 85,
|
|
36
|
+
responseTimeMs: 2300,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
const SECOND_EXCHANGE_WITH_METRICS = {
|
|
40
|
+
number: 2,
|
|
41
|
+
timestamp: '10:20',
|
|
42
|
+
leader: 'dev',
|
|
43
|
+
partner: 'architect',
|
|
44
|
+
question: 'Shell wrapper: Node.js or pure bash?',
|
|
45
|
+
recommendation: 'Pure bash for dependency-free scripts',
|
|
46
|
+
confidence: 'medium',
|
|
47
|
+
outcome: 'deferred',
|
|
48
|
+
outcomeNote: 'Revisit after prototype',
|
|
49
|
+
metrics: {
|
|
50
|
+
inputTokens: 200,
|
|
51
|
+
outputTokens: 120,
|
|
52
|
+
responseTimeMs: 3100,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
const THIRD_EXCHANGE_WITH_METRICS = {
|
|
56
|
+
number: 3,
|
|
57
|
+
timestamp: '10:35',
|
|
58
|
+
leader: 'dev',
|
|
59
|
+
partner: 'architect',
|
|
60
|
+
question: 'Error handling: result objects or exceptions?',
|
|
61
|
+
recommendation: 'Result objects per framework convention',
|
|
62
|
+
confidence: 'high',
|
|
63
|
+
outcome: 'applied',
|
|
64
|
+
outcomeNote: 'Used {success, data?, error?} pattern',
|
|
65
|
+
metrics: {
|
|
66
|
+
inputTokens: 180,
|
|
67
|
+
outputTokens: 95,
|
|
68
|
+
responseTimeMs: 1800,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
const EXCHANGE_NO_METRICS = {
|
|
72
|
+
number: 4,
|
|
73
|
+
timestamp: '10:50',
|
|
74
|
+
leader: 'dev',
|
|
75
|
+
partner: 'architect',
|
|
76
|
+
question: 'Legacy exchange without tracking',
|
|
77
|
+
recommendation: 'N/A',
|
|
78
|
+
confidence: 'low',
|
|
79
|
+
};
|
|
80
|
+
const EXCHANGE_REJECTED = {
|
|
81
|
+
number: 5,
|
|
82
|
+
timestamp: '11:00',
|
|
83
|
+
leader: 'dev',
|
|
84
|
+
partner: 'tea',
|
|
85
|
+
question: 'Should we add integration tests here?',
|
|
86
|
+
recommendation: 'Yes, add container-based tests',
|
|
87
|
+
confidence: 'high',
|
|
88
|
+
outcome: 'rejected',
|
|
89
|
+
outcomeNote: 'Unit tests sufficient for this scope',
|
|
90
|
+
metrics: {
|
|
91
|
+
inputTokens: 130,
|
|
92
|
+
outputTokens: 70,
|
|
93
|
+
responseTimeMs: 1500,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
const EXCHANGE_PENDING = {
|
|
97
|
+
number: 6,
|
|
98
|
+
timestamp: '11:10',
|
|
99
|
+
leader: 'dev',
|
|
100
|
+
partner: 'architect',
|
|
101
|
+
question: 'Pending decision',
|
|
102
|
+
recommendation: 'Still thinking',
|
|
103
|
+
confidence: 'low',
|
|
104
|
+
metrics: {
|
|
105
|
+
inputTokens: 100,
|
|
106
|
+
outputTokens: 50,
|
|
107
|
+
responseTimeMs: 900,
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
// =============================================================================
|
|
111
|
+
// AC1: Consultation tokens logged separately from leader session tokens
|
|
112
|
+
// =============================================================================
|
|
113
|
+
describe('86-6: Tandem Metrics and Token Tracking', () => {
|
|
114
|
+
describe('AC1: Consultation tokens tracked per exchange', () => {
|
|
115
|
+
it('should track input and output tokens separately per exchange', () => {
|
|
116
|
+
const exchanges = [EXCHANGE_WITH_METRICS];
|
|
117
|
+
const metrics = aggregateMetrics(exchanges);
|
|
118
|
+
assert.strictEqual(metrics.totalInputTokens, 150, 'Must track input tokens from consultation request');
|
|
119
|
+
assert.strictEqual(metrics.totalOutputTokens, 85, 'Must track output tokens from consultation response');
|
|
120
|
+
});
|
|
121
|
+
it('should sum tokens across multiple exchanges', () => {
|
|
122
|
+
const exchanges = [EXCHANGE_WITH_METRICS, SECOND_EXCHANGE_WITH_METRICS];
|
|
123
|
+
const metrics = aggregateMetrics(exchanges);
|
|
124
|
+
assert.strictEqual(metrics.totalInputTokens, 350, 'Must sum input tokens: 150 + 200');
|
|
125
|
+
assert.strictEqual(metrics.totalOutputTokens, 205, 'Must sum output tokens: 85 + 120');
|
|
126
|
+
assert.strictEqual(metrics.totalTokens, 555, 'Must sum total tokens: 350 + 205');
|
|
127
|
+
});
|
|
128
|
+
it('should exclude exchanges without metrics from token totals', () => {
|
|
129
|
+
const exchanges = [EXCHANGE_WITH_METRICS, EXCHANGE_NO_METRICS];
|
|
130
|
+
const metrics = aggregateMetrics(exchanges);
|
|
131
|
+
assert.strictEqual(metrics.totalInputTokens, 150, 'Must only count exchanges with metrics');
|
|
132
|
+
assert.strictEqual(metrics.totalOutputTokens, 85, 'Must only count exchanges with metrics');
|
|
133
|
+
});
|
|
134
|
+
it('should still count exchanges without metrics in consultationCount', () => {
|
|
135
|
+
const exchanges = [EXCHANGE_WITH_METRICS, EXCHANGE_NO_METRICS];
|
|
136
|
+
const metrics = aggregateMetrics(exchanges);
|
|
137
|
+
assert.strictEqual(metrics.consultationCount, 2, 'All exchanges count toward consultation count regardless of metrics');
|
|
138
|
+
});
|
|
139
|
+
it('should handle empty exchange list', () => {
|
|
140
|
+
const metrics = aggregateMetrics([]);
|
|
141
|
+
assert.strictEqual(metrics.consultationCount, 0);
|
|
142
|
+
assert.strictEqual(metrics.totalInputTokens, 0);
|
|
143
|
+
assert.strictEqual(metrics.totalOutputTokens, 0);
|
|
144
|
+
assert.strictEqual(metrics.totalTokens, 0);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
// =============================================================================
|
|
148
|
+
// AC2: Metrics captured: count, total tokens, avg response time, outcome dist
|
|
149
|
+
// =============================================================================
|
|
150
|
+
describe('AC2: Aggregate metrics calculation', () => {
|
|
151
|
+
it('should calculate average response time across exchanges', () => {
|
|
152
|
+
const exchanges = [EXCHANGE_WITH_METRICS, SECOND_EXCHANGE_WITH_METRICS];
|
|
153
|
+
const metrics = aggregateMetrics(exchanges);
|
|
154
|
+
// (2300 + 3100) / 2 = 2700
|
|
155
|
+
assert.strictEqual(metrics.avgResponseTimeMs, 2700, 'Must calculate average response time from exchanges with metrics');
|
|
156
|
+
});
|
|
157
|
+
it('should exclude exchanges without metrics from response time average', () => {
|
|
158
|
+
const exchanges = [EXCHANGE_WITH_METRICS, EXCHANGE_NO_METRICS];
|
|
159
|
+
const metrics = aggregateMetrics(exchanges);
|
|
160
|
+
assert.strictEqual(metrics.avgResponseTimeMs, 2300, 'Average must only consider exchanges with metrics data');
|
|
161
|
+
});
|
|
162
|
+
it('should return 0 avg response time for no metrics', () => {
|
|
163
|
+
const exchanges = [EXCHANGE_NO_METRICS];
|
|
164
|
+
const metrics = aggregateMetrics(exchanges);
|
|
165
|
+
assert.strictEqual(metrics.avgResponseTimeMs, 0, 'No metrics data means 0 average response time');
|
|
166
|
+
});
|
|
167
|
+
it('should calculate outcome distribution', () => {
|
|
168
|
+
const exchanges = [
|
|
169
|
+
EXCHANGE_WITH_METRICS, // applied
|
|
170
|
+
SECOND_EXCHANGE_WITH_METRICS, // deferred
|
|
171
|
+
THIRD_EXCHANGE_WITH_METRICS, // applied
|
|
172
|
+
EXCHANGE_REJECTED, // rejected
|
|
173
|
+
EXCHANGE_PENDING, // pending (no outcome)
|
|
174
|
+
];
|
|
175
|
+
const metrics = aggregateMetrics(exchanges);
|
|
176
|
+
assert.strictEqual(metrics.outcomeDistribution['applied'], 2, 'Must count applied outcomes');
|
|
177
|
+
assert.strictEqual(metrics.outcomeDistribution['deferred'], 1, 'Must count deferred outcomes');
|
|
178
|
+
assert.strictEqual(metrics.outcomeDistribution['rejected'], 1, 'Must count rejected outcomes');
|
|
179
|
+
assert.strictEqual(metrics.outcomeDistribution['pending'], 1, 'Must count exchanges with no outcome as pending');
|
|
180
|
+
});
|
|
181
|
+
it('should include all outcome types even when count is zero', () => {
|
|
182
|
+
const exchanges = [EXCHANGE_WITH_METRICS]; // only applied
|
|
183
|
+
const metrics = aggregateMetrics(exchanges);
|
|
184
|
+
assert.strictEqual(metrics.outcomeDistribution['applied'], 1);
|
|
185
|
+
assert.strictEqual(metrics.outcomeDistribution['deferred'], 0, 'Must include deferred even when zero');
|
|
186
|
+
assert.strictEqual(metrics.outcomeDistribution['rejected'], 0, 'Must include rejected even when zero');
|
|
187
|
+
assert.strictEqual(metrics.outcomeDistribution['pending'], 0, 'Must include pending even when zero');
|
|
188
|
+
});
|
|
189
|
+
it('should handle all-pending exchanges', () => {
|
|
190
|
+
const exchanges = [EXCHANGE_PENDING, EXCHANGE_NO_METRICS];
|
|
191
|
+
const metrics = aggregateMetrics(exchanges);
|
|
192
|
+
assert.strictEqual(metrics.outcomeDistribution['pending'], 2);
|
|
193
|
+
assert.strictEqual(metrics.outcomeDistribution['applied'], 0);
|
|
194
|
+
});
|
|
195
|
+
it('should calculate metrics across three exchanges correctly', () => {
|
|
196
|
+
const exchanges = [
|
|
197
|
+
EXCHANGE_WITH_METRICS,
|
|
198
|
+
SECOND_EXCHANGE_WITH_METRICS,
|
|
199
|
+
THIRD_EXCHANGE_WITH_METRICS,
|
|
200
|
+
];
|
|
201
|
+
const metrics = aggregateMetrics(exchanges);
|
|
202
|
+
assert.strictEqual(metrics.consultationCount, 3);
|
|
203
|
+
assert.strictEqual(metrics.totalInputTokens, 530, 'Must sum: 150 + 200 + 180');
|
|
204
|
+
assert.strictEqual(metrics.totalOutputTokens, 300, 'Must sum: 85 + 120 + 95');
|
|
205
|
+
assert.strictEqual(metrics.totalTokens, 830);
|
|
206
|
+
// (2300 + 3100 + 1800) / 3 = 2400
|
|
207
|
+
assert.strictEqual(metrics.avgResponseTimeMs, 2400);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
// =============================================================================
|
|
211
|
+
// AC3: Metrics written to dialogue file summary section
|
|
212
|
+
// =============================================================================
|
|
213
|
+
describe('AC3: Metrics formatted for dialogue summary', () => {
|
|
214
|
+
it('should format consultation token totals', () => {
|
|
215
|
+
const metrics = {
|
|
216
|
+
consultationCount: 3,
|
|
217
|
+
totalInputTokens: 530,
|
|
218
|
+
totalOutputTokens: 300,
|
|
219
|
+
totalTokens: 830,
|
|
220
|
+
avgResponseTimeMs: 2400,
|
|
221
|
+
outcomeDistribution: { applied: 2, deferred: 1, rejected: 0, pending: 0 },
|
|
222
|
+
overheadPercent: null,
|
|
223
|
+
};
|
|
224
|
+
const lines = formatMetricsSummary(metrics);
|
|
225
|
+
const text = lines.join('\n');
|
|
226
|
+
assert.ok(text.includes('830'), 'Must include total token count');
|
|
227
|
+
assert.ok(text.includes('530') || text.includes('input'), 'Must include input token breakdown');
|
|
228
|
+
assert.ok(text.includes('300') || text.includes('output'), 'Must include output token breakdown');
|
|
229
|
+
});
|
|
230
|
+
it('should format average response time', () => {
|
|
231
|
+
const metrics = {
|
|
232
|
+
consultationCount: 2,
|
|
233
|
+
totalInputTokens: 350,
|
|
234
|
+
totalOutputTokens: 205,
|
|
235
|
+
totalTokens: 555,
|
|
236
|
+
avgResponseTimeMs: 2700,
|
|
237
|
+
outcomeDistribution: { applied: 1, deferred: 1, rejected: 0, pending: 0 },
|
|
238
|
+
overheadPercent: null,
|
|
239
|
+
};
|
|
240
|
+
const lines = formatMetricsSummary(metrics);
|
|
241
|
+
const text = lines.join('\n');
|
|
242
|
+
assert.ok(text.includes('2700') || text.includes('2,700'), 'Must include average response time in ms');
|
|
243
|
+
});
|
|
244
|
+
it('should format outcome distribution', () => {
|
|
245
|
+
const metrics = {
|
|
246
|
+
consultationCount: 5,
|
|
247
|
+
totalInputTokens: 760,
|
|
248
|
+
totalOutputTokens: 420,
|
|
249
|
+
totalTokens: 1180,
|
|
250
|
+
avgResponseTimeMs: 1920,
|
|
251
|
+
outcomeDistribution: { applied: 2, deferred: 1, rejected: 1, pending: 1 },
|
|
252
|
+
overheadPercent: 15.0,
|
|
253
|
+
};
|
|
254
|
+
const lines = formatMetricsSummary(metrics);
|
|
255
|
+
const text = lines.join('\n');
|
|
256
|
+
assert.ok(text.includes('applied'), 'Must include applied in distribution');
|
|
257
|
+
assert.ok(text.includes('deferred'), 'Must include deferred in distribution');
|
|
258
|
+
assert.ok(text.includes('rejected'), 'Must include rejected in distribution');
|
|
259
|
+
});
|
|
260
|
+
it('should format overhead percentage when present', () => {
|
|
261
|
+
const metrics = {
|
|
262
|
+
consultationCount: 3,
|
|
263
|
+
totalInputTokens: 530,
|
|
264
|
+
totalOutputTokens: 300,
|
|
265
|
+
totalTokens: 830,
|
|
266
|
+
avgResponseTimeMs: 2400,
|
|
267
|
+
outcomeDistribution: { applied: 2, deferred: 1, rejected: 0, pending: 0 },
|
|
268
|
+
overheadPercent: 12.5,
|
|
269
|
+
};
|
|
270
|
+
const lines = formatMetricsSummary(metrics);
|
|
271
|
+
const text = lines.join('\n');
|
|
272
|
+
assert.ok(text.includes('12.5%') || text.includes('12.5'), 'Must include overhead percentage');
|
|
273
|
+
});
|
|
274
|
+
it('should handle null overhead percentage gracefully', () => {
|
|
275
|
+
const metrics = {
|
|
276
|
+
consultationCount: 1,
|
|
277
|
+
totalInputTokens: 150,
|
|
278
|
+
totalOutputTokens: 85,
|
|
279
|
+
totalTokens: 235,
|
|
280
|
+
avgResponseTimeMs: 2300,
|
|
281
|
+
outcomeDistribution: { applied: 1, deferred: 0, rejected: 0, pending: 0 },
|
|
282
|
+
overheadPercent: null,
|
|
283
|
+
};
|
|
284
|
+
const lines = formatMetricsSummary(metrics);
|
|
285
|
+
const text = lines.join('\n');
|
|
286
|
+
// Should either show "N/A" or omit the overhead line — not crash
|
|
287
|
+
assert.ok(typeof text === 'string', 'Must format without crashing on null overhead');
|
|
288
|
+
assert.ok(!text.includes('null'), 'Must not display literal "null" in summary');
|
|
289
|
+
});
|
|
290
|
+
it('should return an array of markdown bullet lines', () => {
|
|
291
|
+
const metrics = {
|
|
292
|
+
consultationCount: 2,
|
|
293
|
+
totalInputTokens: 350,
|
|
294
|
+
totalOutputTokens: 205,
|
|
295
|
+
totalTokens: 555,
|
|
296
|
+
avgResponseTimeMs: 2700,
|
|
297
|
+
outcomeDistribution: { applied: 1, deferred: 1, rejected: 0, pending: 0 },
|
|
298
|
+
overheadPercent: 10.0,
|
|
299
|
+
};
|
|
300
|
+
const lines = formatMetricsSummary(metrics);
|
|
301
|
+
assert.ok(Array.isArray(lines), 'Must return an array');
|
|
302
|
+
assert.ok(lines.length > 0, 'Must return at least one line');
|
|
303
|
+
for (const line of lines) {
|
|
304
|
+
assert.ok(line.startsWith('- '), `Each line must be a markdown bullet: "${line}"`);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
it('should include consultation count in summary', () => {
|
|
308
|
+
const metrics = {
|
|
309
|
+
consultationCount: 4,
|
|
310
|
+
totalInputTokens: 600,
|
|
311
|
+
totalOutputTokens: 400,
|
|
312
|
+
totalTokens: 1000,
|
|
313
|
+
avgResponseTimeMs: 2000,
|
|
314
|
+
outcomeDistribution: { applied: 2, deferred: 1, rejected: 0, pending: 1 },
|
|
315
|
+
overheadPercent: null,
|
|
316
|
+
};
|
|
317
|
+
const lines = formatMetricsSummary(metrics);
|
|
318
|
+
const text = lines.join('\n');
|
|
319
|
+
assert.ok(text.includes('4'), 'Must include consultation count');
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
// =============================================================================
|
|
323
|
+
// AC3 (continued): Parse metrics back from summary
|
|
324
|
+
// =============================================================================
|
|
325
|
+
describe('AC3: Parse metrics from summary', () => {
|
|
326
|
+
it('should round-trip metrics through format and parse', () => {
|
|
327
|
+
const original = {
|
|
328
|
+
consultationCount: 3,
|
|
329
|
+
totalInputTokens: 530,
|
|
330
|
+
totalOutputTokens: 300,
|
|
331
|
+
totalTokens: 830,
|
|
332
|
+
avgResponseTimeMs: 2400,
|
|
333
|
+
outcomeDistribution: { applied: 2, deferred: 1, rejected: 0, pending: 0 },
|
|
334
|
+
overheadPercent: 12.5,
|
|
335
|
+
};
|
|
336
|
+
const formatted = formatMetricsSummary(original);
|
|
337
|
+
const parsed = parseMetricsFromSummary(formatted.join('\n'));
|
|
338
|
+
assert.ok(parsed, 'Must parse formatted metrics');
|
|
339
|
+
assert.strictEqual(parsed.consultationCount, 3);
|
|
340
|
+
assert.strictEqual(parsed.totalTokens, 830);
|
|
341
|
+
assert.strictEqual(parsed.avgResponseTimeMs, 2400);
|
|
342
|
+
});
|
|
343
|
+
it('should return null for summary without metrics', () => {
|
|
344
|
+
const plainSummary = `- **Total exchanges:** 2
|
|
345
|
+
- **Key decisions:** None
|
|
346
|
+
- **Time in tandem:** 15m`;
|
|
347
|
+
const parsed = parseMetricsFromSummary(plainSummary);
|
|
348
|
+
assert.strictEqual(parsed, null, 'Must return null when no metrics fields are present');
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
// =============================================================================
|
|
352
|
+
// AC4: Session summary includes tandem overhead percentage
|
|
353
|
+
// =============================================================================
|
|
354
|
+
describe('AC4: Overhead percentage calculation', () => {
|
|
355
|
+
it('should calculate overhead as percentage of baseline', () => {
|
|
356
|
+
// 830 tandem tokens, 10000 baseline = 8.3%
|
|
357
|
+
const result = calculateOverheadPercent(830, 10000);
|
|
358
|
+
assert.strictEqual(result, 8.3, 'Must calculate: (830 / 10000) * 100 = 8.3');
|
|
359
|
+
});
|
|
360
|
+
it('should return null when baseline is zero', () => {
|
|
361
|
+
const result = calculateOverheadPercent(500, 0);
|
|
362
|
+
assert.strictEqual(result, null, 'Must return null for zero baseline (cannot divide by zero)');
|
|
363
|
+
});
|
|
364
|
+
it('should handle zero tandem tokens', () => {
|
|
365
|
+
const result = calculateOverheadPercent(0, 10000);
|
|
366
|
+
assert.strictEqual(result, 0, 'Zero tandem tokens means 0% overhead');
|
|
367
|
+
});
|
|
368
|
+
it('should round to one decimal place', () => {
|
|
369
|
+
// 333 / 10000 = 3.33 → 3.3
|
|
370
|
+
const result = calculateOverheadPercent(333, 10000);
|
|
371
|
+
assert.strictEqual(result, 3.3, 'Must round to one decimal place');
|
|
372
|
+
});
|
|
373
|
+
it('should handle large overhead values', () => {
|
|
374
|
+
// 5000 / 10000 = 50%
|
|
375
|
+
const result = calculateOverheadPercent(5000, 10000);
|
|
376
|
+
assert.strictEqual(result, 50.0, 'Must handle overhead > 25% target');
|
|
377
|
+
});
|
|
378
|
+
it('should handle very small overhead values', () => {
|
|
379
|
+
// 1 / 100000 = 0.001 → 0.0
|
|
380
|
+
const result = calculateOverheadPercent(1, 100000);
|
|
381
|
+
assert.strictEqual(result, 0.0, 'Must handle very small percentages');
|
|
382
|
+
});
|
|
383
|
+
it('should include overhead in aggregated metrics when baseline provided', () => {
|
|
384
|
+
const exchanges = [EXCHANGE_WITH_METRICS, SECOND_EXCHANGE_WITH_METRICS];
|
|
385
|
+
const metrics = aggregateMetrics(exchanges);
|
|
386
|
+
// totalTokens = 555, test with baseline of 5000
|
|
387
|
+
const overhead = calculateOverheadPercent(metrics.totalTokens, 5000);
|
|
388
|
+
assert.strictEqual(overhead, 11.1, 'Must calculate: (555 / 5000) * 100 = 11.1');
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
// =============================================================================
|
|
392
|
+
// AC5: Target: consultation overhead < 25% of baseline story token cost
|
|
393
|
+
// =============================================================================
|
|
394
|
+
describe('AC5: Budget threshold validation', () => {
|
|
395
|
+
it('should pass when overhead is below 25% threshold', () => {
|
|
396
|
+
const result = isWithinBudget(12.5);
|
|
397
|
+
assert.strictEqual(result, true, '12.5% is below 25% threshold');
|
|
398
|
+
});
|
|
399
|
+
it('should fail when overhead exceeds 25% threshold', () => {
|
|
400
|
+
const result = isWithinBudget(30.0);
|
|
401
|
+
assert.strictEqual(result, false, '30% exceeds 25% threshold');
|
|
402
|
+
});
|
|
403
|
+
it('should fail when overhead exactly equals 25%', () => {
|
|
404
|
+
const result = isWithinBudget(25.0);
|
|
405
|
+
assert.strictEqual(result, false, '25% is not strictly less than 25% — must be under');
|
|
406
|
+
});
|
|
407
|
+
it('should pass when overhead is zero', () => {
|
|
408
|
+
const result = isWithinBudget(0);
|
|
409
|
+
assert.strictEqual(result, true, '0% overhead is within any threshold');
|
|
410
|
+
});
|
|
411
|
+
it('should pass when overhead is null (no baseline available)', () => {
|
|
412
|
+
const result = isWithinBudget(null);
|
|
413
|
+
assert.strictEqual(result, true, 'Null overhead (no baseline) should not block — pass by default');
|
|
414
|
+
});
|
|
415
|
+
it('should use custom threshold when provided', () => {
|
|
416
|
+
assert.strictEqual(isWithinBudget(15.0, 10), false, '15% exceeds custom 10% threshold');
|
|
417
|
+
assert.strictEqual(isWithinBudget(8.0, 10), true, '8% is within custom 10% threshold');
|
|
418
|
+
});
|
|
419
|
+
it('should default to 25% when no threshold specified', () => {
|
|
420
|
+
assert.strictEqual(isWithinBudget(24.9), true, '24.9% is just under default 25%');
|
|
421
|
+
assert.strictEqual(isWithinBudget(25.1), false, '25.1% is over default 25%');
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
// =============================================================================
|
|
425
|
+
// Result format compliance (framework pattern)
|
|
426
|
+
// =============================================================================
|
|
427
|
+
describe('Result format compliance', () => {
|
|
428
|
+
it('should return TandemMetricsSummary with all required fields', () => {
|
|
429
|
+
const exchanges = [EXCHANGE_WITH_METRICS];
|
|
430
|
+
const metrics = aggregateMetrics(exchanges);
|
|
431
|
+
assert.ok('consultationCount' in metrics, 'Must have consultationCount');
|
|
432
|
+
assert.ok('totalInputTokens' in metrics, 'Must have totalInputTokens');
|
|
433
|
+
assert.ok('totalOutputTokens' in metrics, 'Must have totalOutputTokens');
|
|
434
|
+
assert.ok('totalTokens' in metrics, 'Must have totalTokens');
|
|
435
|
+
assert.ok('avgResponseTimeMs' in metrics, 'Must have avgResponseTimeMs');
|
|
436
|
+
assert.ok('outcomeDistribution' in metrics, 'Must have outcomeDistribution');
|
|
437
|
+
assert.ok('overheadPercent' in metrics, 'Must have overheadPercent');
|
|
438
|
+
});
|
|
439
|
+
it('should return formatMetricsSummary as string array', () => {
|
|
440
|
+
const metrics = {
|
|
441
|
+
consultationCount: 1,
|
|
442
|
+
totalInputTokens: 150,
|
|
443
|
+
totalOutputTokens: 85,
|
|
444
|
+
totalTokens: 235,
|
|
445
|
+
avgResponseTimeMs: 2300,
|
|
446
|
+
outcomeDistribution: { applied: 1, deferred: 0, rejected: 0, pending: 0 },
|
|
447
|
+
overheadPercent: 5.0,
|
|
448
|
+
};
|
|
449
|
+
const result = formatMetricsSummary(metrics);
|
|
450
|
+
assert.ok(Array.isArray(result), 'Must return array');
|
|
451
|
+
for (const line of result) {
|
|
452
|
+
assert.strictEqual(typeof line, 'string', 'Each element must be a string');
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
//# sourceMappingURL=tandem-metrics.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tandem-metrics.test.js","sourceRoot":"","sources":["../../src/consultation/tandem-metrics.test.ts"],"names":[],"mappings":"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"}
|