@pennyfarthing/core 10.1.0 → 10.2.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 +13 -18
- package/package.json +3 -1
- package/packages/core/dist/cli/commands/doctor-file-layout.test.js.map +1 -1
- package/packages/core/dist/cli/commands/doctor-legacy.test.js +24 -0
- package/packages/core/dist/cli/commands/doctor-legacy.test.js.map +1 -1
- package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/doctor.js +101 -15
- package/packages/core/dist/cli/commands/doctor.js.map +1 -1
- package/packages/core/dist/cli/commands/e2e-fresh-install.test.js +1 -1
- package/packages/core/dist/cli/commands/e2e-fresh-install.test.js.map +1 -1
- package/packages/core/dist/cli/commands/e2e-upgrade.test.js +1 -1
- package/packages/core/dist/cli/commands/e2e-upgrade.test.js.map +1 -1
- package/packages/core/dist/cli/commands/hooks-consolidation.test.js +2 -2
- package/packages/core/dist/cli/commands/hooks-consolidation.test.js.map +1 -1
- package/packages/core/dist/cli/commands/init-consolidation.test.js.map +1 -1
- package/packages/core/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/uninstall.js +24 -13
- package/packages/core/dist/cli/commands/uninstall.js.map +1 -1
- package/packages/core/dist/cli/commands/update-consolidation.test.js +0 -10
- package/packages/core/dist/cli/commands/update-consolidation.test.js.map +1 -1
- package/packages/core/dist/cli/commands/update.js.map +1 -1
- package/packages/core/dist/cli/ocean-profiles.test.js.map +1 -1
- package/packages/core/dist/cli/theme-maker.test.js +64 -115
- package/packages/core/dist/cli/theme-maker.test.js.map +1 -1
- package/packages/core/dist/index.d.ts +1 -1
- package/packages/core/dist/index.d.ts.map +1 -1
- package/packages/core/dist/index.js +2 -2
- package/packages/core/dist/index.js.map +1 -1
- package/packages/core/dist/plugins/plugin-discovery.d.ts +116 -0
- package/packages/core/dist/plugins/plugin-discovery.d.ts.map +1 -0
- package/packages/core/dist/plugins/plugin-discovery.js +165 -0
- package/packages/core/dist/plugins/plugin-discovery.js.map +1 -0
- package/packages/core/dist/plugins/plugin-discovery.test.d.ts +22 -0
- package/packages/core/dist/plugins/plugin-discovery.test.d.ts.map +1 -0
- package/packages/core/dist/plugins/plugin-discovery.test.js +498 -0
- package/packages/core/dist/plugins/plugin-discovery.test.js.map +1 -0
- package/packages/core/dist/scripts/generate-spider-report.js.map +1 -1
- package/packages/core/dist/workflow/context-watch.d.ts +80 -0
- package/packages/core/dist/workflow/context-watch.d.ts.map +1 -0
- package/packages/core/dist/workflow/context-watch.js +235 -0
- package/packages/core/dist/workflow/context-watch.js.map +1 -0
- package/packages/core/dist/workflow/context-watch.test.d.ts +1 -0
- package/packages/core/dist/workflow/context-watch.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/context-watch.test.js +746 -0
- package/packages/core/dist/workflow/context-watch.test.js.map +1 -0
- package/packages/core/dist/workflow/file-watch.d.ts +82 -0
- package/packages/core/dist/workflow/file-watch.d.ts.map +1 -0
- package/packages/core/dist/workflow/file-watch.js +198 -0
- package/packages/core/dist/workflow/file-watch.js.map +1 -0
- package/packages/core/dist/workflow/file-watch.test.d.ts +21 -0
- package/packages/core/dist/workflow/file-watch.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/file-watch.test.js +469 -0
- package/packages/core/dist/workflow/file-watch.test.js.map +1 -0
- package/packages/core/dist/workflow/observation-writer.d.ts +79 -0
- package/packages/core/dist/workflow/observation-writer.d.ts.map +1 -0
- package/packages/core/dist/workflow/observation-writer.js +97 -0
- package/packages/core/dist/workflow/observation-writer.js.map +1 -0
- package/packages/core/dist/workflow/observation-writer.test.d.ts +18 -0
- package/packages/core/dist/workflow/observation-writer.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/observation-writer.test.js +424 -0
- package/packages/core/dist/workflow/observation-writer.test.js.map +1 -0
- package/packages/core/dist/workflow/story-workflow-routing.test.js +4 -2
- package/packages/core/dist/workflow/story-workflow-routing.test.js.map +1 -1
- package/packages/core/dist/workflow/tandem-lifecycle.d.ts +117 -0
- package/packages/core/dist/workflow/tandem-lifecycle.d.ts.map +1 -0
- package/packages/core/dist/workflow/tandem-lifecycle.js +186 -0
- package/packages/core/dist/workflow/tandem-lifecycle.js.map +1 -0
- package/packages/core/dist/workflow/tandem-lifecycle.test.d.ts +16 -0
- package/packages/core/dist/workflow/tandem-lifecycle.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/tandem-lifecycle.test.js +531 -0
- package/packages/core/dist/workflow/tandem-lifecycle.test.js.map +1 -0
- package/packages/core/dist/workflow/tool-watch.d.ts +68 -0
- package/packages/core/dist/workflow/tool-watch.d.ts.map +1 -0
- package/packages/core/dist/workflow/tool-watch.js +166 -0
- package/packages/core/dist/workflow/tool-watch.js.map +1 -0
- package/packages/core/dist/workflow/tool-watch.test.d.ts +18 -0
- package/packages/core/dist/workflow/tool-watch.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/tool-watch.test.js +718 -0
- package/packages/core/dist/workflow/tool-watch.test.js.map +1 -0
- package/packages/core/dist/workflow/workflow-migration.test.js +8 -4
- package/packages/core/dist/workflow/workflow-migration.test.js.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.d.ts +7 -0
- package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.js +44 -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 +192 -0
- package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
- package/pennyfarthing-dist/agents/handoff.md +18 -3
- package/pennyfarthing-dist/agents/sm-finish.md +1 -1
- package/pennyfarthing-dist/agents/sm-handoff.md +27 -4
- package/pennyfarthing-dist/agents/sm.md +11 -5
- package/pennyfarthing-dist/agents/tandem-backseat.md +119 -0
- package/pennyfarthing-dist/commands/setup.md +4 -0
- package/pennyfarthing-dist/guides/agent-behavior.md +62 -6
- package/pennyfarthing-dist/guides/bikelane.md +3 -2
- package/pennyfarthing-dist/guides/scale-levels.md +4 -6
- package/pennyfarthing-dist/guides/tandem-protocol.md +158 -0
- package/pennyfarthing-dist/personas/themes/discworld.yaml +1 -1
- package/pennyfarthing-dist/personas/themes/fifth-element.yaml +295 -0
- package/pennyfarthing-dist/scripts/README.md +1 -1
- package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +131 -54
- package/pennyfarthing-dist/scripts/hooks/post-merge.sh +20 -10
- package/pennyfarthing-dist/scripts/misc/statusline.sh +50 -8
- package/pennyfarthing-dist/scripts/workflow/README.md +2 -2
- package/pennyfarthing-dist/scripts/workflow/finish-story.sh +10 -189
- package/pennyfarthing-dist/skills/skill-registry.schema.json +8 -0
- package/pennyfarthing-dist/skills/skill-registry.yaml +1 -1
- package/pennyfarthing-dist/skills/sprint/skill.md +25 -2
- package/pennyfarthing-dist/skills/workflow/skill.md +24 -1
- package/pennyfarthing-dist/workflows/architecture/workflow.yaml +65 -0
- package/pennyfarthing-dist/workflows/bdd-tandem.yaml +70 -0
- package/pennyfarthing-dist/workflows/tdd-tandem.yaml +61 -0
- 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__/config.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bellmode_hook.py +202 -47
- package/pennyfarthing_scripts/brownfield/__init__.py +6 -6
- package/pennyfarthing_scripts/brownfield/__main__.py +1 -0
- package/pennyfarthing_scripts/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/brownfield/cli.py +0 -1
- package/pennyfarthing_scripts/brownfield/discover.py +1 -2
- package/pennyfarthing_scripts/cli.py +11 -6
- package/pennyfarthing_scripts/codemarkers/__init__.py +5 -1
- package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/analyze.py +177 -2
- package/pennyfarthing_scripts/codemarkers/cli.py +50 -0
- package/pennyfarthing_scripts/codemarkers/formatters.py +0 -1
- package/pennyfarthing_scripts/codemarkers/models.py +15 -0
- package/pennyfarthing_scripts/common/__init__.py +8 -9
- package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/output.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/config.py +1 -1
- package/pennyfarthing_scripts/complexity/__init__.py +1 -1
- package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/analyze.py +1 -1
- package/pennyfarthing_scripts/complexity/cli.py +5 -1
- package/pennyfarthing_scripts/complexity/formatters.py +1 -1
- package/pennyfarthing_scripts/context.py +14 -15
- package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/analyze.py +3 -4
- package/pennyfarthing_scripts/deadcode/cli.py +2 -2
- package/pennyfarthing_scripts/dependencies/__init__.py +2 -2
- package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/analyze.py +1 -1
- package/pennyfarthing_scripts/dependencies/cli.py +8 -4
- package/pennyfarthing_scripts/dependencies/formatters.py +1 -1
- package/pennyfarthing_scripts/git/__init__.py +5 -5
- 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__/status_all.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/create_branches.py +3 -2
- package/pennyfarthing_scripts/git/status_all.py +1 -1
- package/pennyfarthing_scripts/healthscore/__init__.py +2 -2
- package/pennyfarthing_scripts/healthscore/__main__.py +8 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/analyze.py +451 -21
- package/pennyfarthing_scripts/healthscore/cli.py +5 -1
- package/pennyfarthing_scripts/healthscore/models.py +0 -1
- package/pennyfarthing_scripts/hooks.py +8 -11
- package/pennyfarthing_scripts/hotspots/__init__.py +6 -6
- package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/analyze.py +128 -14
- package/pennyfarthing_scripts/hotspots/cli.py +2 -2
- package/pennyfarthing_scripts/hotspots/models.py +0 -1
- package/pennyfarthing_scripts/jira/__init__.py +15 -17
- package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/bidirectional.py +2 -3
- package/pennyfarthing_scripts/jira/claim.py +21 -0
- package/pennyfarthing_scripts/jira/cli.py +2 -2
- package/pennyfarthing_scripts/jira/client.py +4 -4
- package/pennyfarthing_scripts/jira/create.py +45 -1
- package/pennyfarthing_scripts/jira/epic.py +3 -2
- package/pennyfarthing_scripts/jira/reconcile.py +0 -1
- package/pennyfarthing_scripts/jira/story.py +2 -0
- package/pennyfarthing_scripts/jira/sync.py +1 -1
- package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/skill.py +0 -1
- package/pennyfarthing_scripts/migration/step.py +0 -1
- package/pennyfarthing_scripts/migration/validate.py +8 -5
- package/pennyfarthing_scripts/patch_mode.py +2 -2
- package/pennyfarthing_scripts/preflight/__init__.py +1 -1
- package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/finish.py +0 -1
- package/pennyfarthing_scripts/pretooluse_hook.py +6 -7
- package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/cli.py +5 -1
- package/pennyfarthing_scripts/prime/loader.py +2 -3
- package/pennyfarthing_scripts/prime/persona.py +2 -1
- package/pennyfarthing_scripts/prime/tiers.py +4 -4
- package/pennyfarthing_scripts/schema_validation_hook.py +2 -3
- package/pennyfarthing_scripts/sprint/__init__.py +10 -12
- package/pennyfarthing_scripts/sprint/__main__.py +2 -2
- package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_add.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/__pycache__/validate_cmd.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/archive.py +0 -1
- package/pennyfarthing_scripts/sprint/archive_epic.py +1 -4
- package/pennyfarthing_scripts/sprint/cli.py +34 -28
- package/pennyfarthing_scripts/sprint/epic_add.py +8 -1
- package/pennyfarthing_scripts/sprint/import_epic.py +42 -18
- package/pennyfarthing_scripts/sprint/loader.py +6 -0
- package/pennyfarthing_scripts/sprint/status.py +1 -2
- package/pennyfarthing_scripts/sprint/story_add.py +2 -2
- package/pennyfarthing_scripts/sprint/story_finish.py +3 -5
- package/pennyfarthing_scripts/sprint/story_update.py +11 -3
- package/pennyfarthing_scripts/sprint/validate_cmd.py +0 -1
- package/pennyfarthing_scripts/sprint/validator.py +120 -6
- package/pennyfarthing_scripts/sprint/work.py +1 -4
- package/pennyfarthing_scripts/sprint/yaml_io.py +10 -2
- package/pennyfarthing_scripts/story/__init__.py +14 -16
- package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/create.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/size.py +0 -1
- package/pennyfarthing_scripts/story/template.py +0 -1
- package/pennyfarthing_scripts/swebench.py +1 -2
- package/pennyfarthing_scripts/tests/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/conftest.py +1 -2
- package/pennyfarthing_scripts/tests/test_brownfield.py +10 -13
- package/pennyfarthing_scripts/tests/test_cli_modules.py +0 -4
- package/pennyfarthing_scripts/tests/test_codemarkers.py +13 -8
- package/pennyfarthing_scripts/tests/test_common.py +9 -4
- package/pennyfarthing_scripts/tests/test_epic_shard_validation.py +699 -0
- package/pennyfarthing_scripts/tests/test_git_utils.py +10 -13
- package/pennyfarthing_scripts/tests/test_healthscore.py +17 -25
- package/pennyfarthing_scripts/tests/test_jira_package.py +0 -3
- package/pennyfarthing_scripts/tests/test_package_structure.py +3 -16
- package/pennyfarthing_scripts/tests/test_patch_mode.py +7 -11
- package/pennyfarthing_scripts/tests/test_prime.py +39 -21
- package/pennyfarthing_scripts/tests/test_sprint_package.py +3 -8
- package/pennyfarthing_scripts/tests/test_sprint_validator.py +53 -5
- package/pennyfarthing_scripts/tests/test_story_add.py +3 -7
- package/pennyfarthing_scripts/tests/test_story_package.py +0 -3
- package/pennyfarthing_scripts/tests/test_story_update.py +5 -10
- package/pennyfarthing_scripts/tests/test_tiers.py +18 -17
- package/pennyfarthing_scripts/tests/test_token_counting.py +19 -13
- package/pennyfarthing_scripts/tests/test_validate_cmd.py +2 -7
- package/pennyfarthing_scripts/tests/test_workflow_check.py +0 -2
- package/pennyfarthing_scripts/tests/test_yaml_io.py +0 -3
- package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/theme/cli.py +3 -2
- package/pennyfarthing_scripts/validate/__init__.py +21 -0
- package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__init__.py +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/agent.py +239 -0
- package/pennyfarthing_scripts/validate/adapters/schema.py +30 -0
- package/pennyfarthing_scripts/validate/adapters/skill_command.py +292 -0
- package/pennyfarthing_scripts/validate/adapters/sprint.py +69 -0
- package/pennyfarthing_scripts/validate/adapters/workflow.py +320 -0
- package/pennyfarthing_scripts/validate/cli.py +141 -0
- package/pennyfarthing_scripts/welcome_hook.py +2 -3
- package/pennyfarthing_scripts/workflow.py +3 -3
- package/scripts/README.md +3 -15
- package/pennyfarthing-dist/commands/benchmark-control.md +0 -69
- package/pennyfarthing-dist/commands/benchmark.md +0 -485
- package/pennyfarthing-dist/commands/job-fair.md +0 -102
- package/pennyfarthing-dist/commands/solo.md +0 -447
- package/pennyfarthing-dist/guides/benchmarks.md +0 -62
- package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/scripts/test/ensure-swebench-data.sh +0 -59
- package/pennyfarthing-dist/scripts/test/ground-truth-judge.py +0 -220
- package/pennyfarthing-dist/scripts/test/swebench-judge.py +0 -374
- package/pennyfarthing-dist/scripts/test/test-cache.sh +0 -165
- package/pennyfarthing-dist/scripts/test/test-setup.sh +0 -337
- package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.sh +0 -13
- package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +0 -402
- package/pennyfarthing-dist/scripts/theme/update-theme-tiers.sh +0 -97
- package/pennyfarthing-dist/skills/finalize-run/SKILL.md +0 -261
- package/pennyfarthing-dist/skills/judge/SKILL.md +0 -644
- package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +0 -187
- package/pennyfarthing-dist/workflows/dev-story/checklist.md +0 -80
- package/pennyfarthing-dist/workflows/dev-story/instructions.xml +0 -410
- package/pennyfarthing-dist/workflows/dev-story/workflow.yaml +0 -50
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-01-understand.md +0 -201
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-02-investigate.md +0 -156
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-03-generate.md +0 -140
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-04-review.md +0 -203
- package/pennyfarthing-dist/workflows/quick-spec/tech-spec-template.md +0 -74
- package/pennyfarthing-dist/workflows/quick-spec/workflow.yaml +0 -27
- package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
|
@@ -11,7 +11,6 @@ import re
|
|
|
11
11
|
from dataclasses import dataclass, field
|
|
12
12
|
from enum import Enum
|
|
13
13
|
from pathlib import Path
|
|
14
|
-
from typing import Literal
|
|
15
14
|
|
|
16
15
|
# Try to import tomllib (Python 3.11+) or fall back to tomli
|
|
17
16
|
try:
|
|
@@ -642,7 +641,7 @@ def generate_ai_guidance_doc(result: DiscoveryResult) -> str:
|
|
|
642
641
|
|
|
643
642
|
if result.tech_stack:
|
|
644
643
|
# Get unique tech names
|
|
645
|
-
tech_names = sorted(
|
|
644
|
+
tech_names = sorted({item.name.lower() for item in result.tech_stack})[:10]
|
|
646
645
|
lines.extend([
|
|
647
646
|
"## Key Technologies",
|
|
648
647
|
"",
|
|
@@ -31,35 +31,40 @@ def cli():
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
# Import and register sprint group (lazy registration preserves startup time)
|
|
34
|
-
from pennyfarthing_scripts.sprint.cli import sprint
|
|
34
|
+
from pennyfarthing_scripts.sprint.cli import sprint # noqa: E402
|
|
35
35
|
|
|
36
36
|
cli.add_command(sprint)
|
|
37
37
|
|
|
38
38
|
# Import and register hotspots group
|
|
39
|
-
from pennyfarthing_scripts.hotspots.cli import hotspots
|
|
39
|
+
from pennyfarthing_scripts.hotspots.cli import hotspots # noqa: E402
|
|
40
40
|
|
|
41
41
|
cli.add_command(hotspots)
|
|
42
42
|
|
|
43
43
|
# Import and register jira group
|
|
44
|
-
from pennyfarthing_scripts.jira.cli import jira
|
|
44
|
+
from pennyfarthing_scripts.jira.cli import jira # noqa: E402
|
|
45
45
|
|
|
46
46
|
cli.add_command(jira)
|
|
47
47
|
|
|
48
48
|
# Import and register deadcode group
|
|
49
|
-
from pennyfarthing_scripts.deadcode.cli import deadcode
|
|
49
|
+
from pennyfarthing_scripts.deadcode.cli import deadcode # noqa: E402
|
|
50
50
|
|
|
51
51
|
cli.add_command(deadcode)
|
|
52
52
|
|
|
53
53
|
# Import and register theme group
|
|
54
|
-
from pennyfarthing_scripts.theme.cli import theme
|
|
54
|
+
from pennyfarthing_scripts.theme.cli import theme # noqa: E402
|
|
55
55
|
|
|
56
56
|
cli.add_command(theme)
|
|
57
57
|
|
|
58
58
|
# Import and register healthscore group
|
|
59
|
-
from pennyfarthing_scripts.healthscore.cli import healthscore
|
|
59
|
+
from pennyfarthing_scripts.healthscore.cli import healthscore # noqa: E402
|
|
60
60
|
|
|
61
61
|
cli.add_command(healthscore)
|
|
62
62
|
|
|
63
|
+
# Import and register validate group
|
|
64
|
+
from pennyfarthing_scripts.validate.cli import validate # noqa: E402
|
|
65
|
+
|
|
66
|
+
cli.add_command(validate)
|
|
67
|
+
|
|
63
68
|
|
|
64
69
|
@cli.group()
|
|
65
70
|
def agent():
|
|
@@ -2,18 +2,22 @@
|
|
|
2
2
|
Code marker analysis — TODO, FIXME, HACK, XXX detection with git blame.
|
|
3
3
|
|
|
4
4
|
Story 80-1: Python codemarkers module.
|
|
5
|
+
Story 80-2: @deprecated detection and caller cross-reference.
|
|
5
6
|
"""
|
|
6
7
|
|
|
8
|
+
from pennyfarthing_scripts.codemarkers.analyze import analyze_deprecations, analyze_repo
|
|
7
9
|
from pennyfarthing_scripts.codemarkers.models import (
|
|
8
10
|
CodeMarker,
|
|
9
11
|
CodeMarkersResult,
|
|
12
|
+
DeprecationMarker,
|
|
10
13
|
MarkerSummary,
|
|
11
14
|
)
|
|
12
|
-
from pennyfarthing_scripts.codemarkers.analyze import analyze_repo
|
|
13
15
|
|
|
14
16
|
__all__ = [
|
|
15
17
|
"CodeMarker",
|
|
16
18
|
"CodeMarkersResult",
|
|
19
|
+
"DeprecationMarker",
|
|
17
20
|
"MarkerSummary",
|
|
21
|
+
"analyze_deprecations",
|
|
18
22
|
"analyze_repo",
|
|
19
23
|
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -12,12 +12,13 @@ import fnmatch
|
|
|
12
12
|
import re
|
|
13
13
|
import time
|
|
14
14
|
from collections import defaultdict
|
|
15
|
-
from datetime import
|
|
15
|
+
from datetime import UTC, datetime
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
|
|
18
18
|
from pennyfarthing_scripts.codemarkers.models import (
|
|
19
19
|
CodeMarker,
|
|
20
20
|
CodeMarkersResult,
|
|
21
|
+
DeprecationMarker,
|
|
21
22
|
MarkerSummary,
|
|
22
23
|
)
|
|
23
24
|
|
|
@@ -286,7 +287,7 @@ async def analyze_repo(
|
|
|
286
287
|
if author_time > 0:
|
|
287
288
|
age_days = (now - author_time) / 86400
|
|
288
289
|
date_str = datetime.fromtimestamp(
|
|
289
|
-
author_time, tz=
|
|
290
|
+
author_time, tz=UTC
|
|
290
291
|
).isoformat()
|
|
291
292
|
else:
|
|
292
293
|
age_days = 0.0
|
|
@@ -324,3 +325,177 @@ async def analyze_repo(
|
|
|
324
325
|
markers=markers,
|
|
325
326
|
summary=summary,
|
|
326
327
|
)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
# =============================================================================
|
|
331
|
+
# @deprecated detection (Story 80-2)
|
|
332
|
+
# =============================================================================
|
|
333
|
+
|
|
334
|
+
# File extensions to scan for @deprecated JSDoc tags
|
|
335
|
+
_DEPRECATION_EXTENSIONS = frozenset({".ts", ".tsx", ".js"})
|
|
336
|
+
|
|
337
|
+
# Pattern to find @deprecated in JSDoc comments
|
|
338
|
+
_DEPRECATED_PATTERN = re.compile(r"@deprecated\b(.*)")
|
|
339
|
+
|
|
340
|
+
# Pattern to extract symbol name from export declarations
|
|
341
|
+
_SYMBOL_PATTERN = re.compile(
|
|
342
|
+
r"export\s+(?:default\s+)?(?:function|class|const|let|var|interface|type|enum)\s+(\w+)"
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def _grep_deprecations(root: Path, excludes: list[str]) -> list[dict]:
|
|
347
|
+
"""Scan TypeScript/JS files for @deprecated JSDoc tags.
|
|
348
|
+
|
|
349
|
+
For each @deprecated tag found, extracts the symbol name from the
|
|
350
|
+
next export declaration line following the JSDoc block.
|
|
351
|
+
|
|
352
|
+
Args:
|
|
353
|
+
root: Directory to scan recursively
|
|
354
|
+
excludes: Glob patterns for files/dirs to skip
|
|
355
|
+
|
|
356
|
+
Returns:
|
|
357
|
+
List of dicts: {path, line, symbol, text}
|
|
358
|
+
"""
|
|
359
|
+
results: list[dict] = []
|
|
360
|
+
|
|
361
|
+
for file_path in sorted(root.rglob("*")):
|
|
362
|
+
if not file_path.is_file():
|
|
363
|
+
continue
|
|
364
|
+
|
|
365
|
+
if file_path.suffix.lower() not in _DEPRECATION_EXTENSIONS:
|
|
366
|
+
continue
|
|
367
|
+
|
|
368
|
+
rel_path = str(file_path.relative_to(root))
|
|
369
|
+
|
|
370
|
+
if _should_exclude(rel_path, excludes):
|
|
371
|
+
continue
|
|
372
|
+
|
|
373
|
+
try:
|
|
374
|
+
content = file_path.read_text(encoding="utf-8", errors="strict")
|
|
375
|
+
except (UnicodeDecodeError, OSError):
|
|
376
|
+
continue
|
|
377
|
+
|
|
378
|
+
lines = content.split("\n")
|
|
379
|
+
for line_num, line_text in enumerate(lines, start=1):
|
|
380
|
+
match = _DEPRECATED_PATTERN.search(line_text)
|
|
381
|
+
if not match:
|
|
382
|
+
continue
|
|
383
|
+
|
|
384
|
+
# Extract the @deprecated text
|
|
385
|
+
deprecated_text = line_text.strip()
|
|
386
|
+
|
|
387
|
+
# Look ahead for the symbol declaration
|
|
388
|
+
symbol = ""
|
|
389
|
+
for ahead in lines[line_num:]: # line_num is already 1-indexed, so lines[line_num:] starts after current
|
|
390
|
+
sym_match = _SYMBOL_PATTERN.search(ahead)
|
|
391
|
+
if sym_match:
|
|
392
|
+
symbol = sym_match.group(1)
|
|
393
|
+
break
|
|
394
|
+
# Stop looking if we hit another JSDoc or a blank line after the block closes
|
|
395
|
+
stripped = ahead.strip()
|
|
396
|
+
if stripped and not stripped.startswith("*") and not stripped.startswith("/") and not stripped == "":
|
|
397
|
+
break
|
|
398
|
+
|
|
399
|
+
if symbol:
|
|
400
|
+
results.append({
|
|
401
|
+
"path": rel_path,
|
|
402
|
+
"line": line_num,
|
|
403
|
+
"symbol": symbol,
|
|
404
|
+
"text": deprecated_text,
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
return results
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def _count_callers(
|
|
411
|
+
symbol: str, root: Path, defining_file: str
|
|
412
|
+
) -> tuple[int, list[str]]:
|
|
413
|
+
"""Count files that import/reference a deprecated symbol.
|
|
414
|
+
|
|
415
|
+
Greps all TypeScript/JS files for the symbol name, excluding
|
|
416
|
+
the file that defines it.
|
|
417
|
+
|
|
418
|
+
Args:
|
|
419
|
+
symbol: The deprecated symbol name to search for
|
|
420
|
+
root: Directory to scan
|
|
421
|
+
defining_file: Relative path of the file defining the symbol (excluded)
|
|
422
|
+
|
|
423
|
+
Returns:
|
|
424
|
+
(caller_count, list_of_caller_paths)
|
|
425
|
+
"""
|
|
426
|
+
callers: list[str] = []
|
|
427
|
+
|
|
428
|
+
for file_path in sorted(root.rglob("*")):
|
|
429
|
+
if not file_path.is_file():
|
|
430
|
+
continue
|
|
431
|
+
|
|
432
|
+
if file_path.suffix.lower() not in _DEPRECATION_EXTENSIONS:
|
|
433
|
+
continue
|
|
434
|
+
|
|
435
|
+
rel_path = str(file_path.relative_to(root))
|
|
436
|
+
|
|
437
|
+
if rel_path == defining_file:
|
|
438
|
+
continue
|
|
439
|
+
|
|
440
|
+
try:
|
|
441
|
+
content = file_path.read_text(encoding="utf-8", errors="strict")
|
|
442
|
+
except (UnicodeDecodeError, OSError):
|
|
443
|
+
continue
|
|
444
|
+
|
|
445
|
+
if symbol in content:
|
|
446
|
+
callers.append(rel_path)
|
|
447
|
+
|
|
448
|
+
return len(callers), callers
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
async def analyze_deprecations(
|
|
452
|
+
path: Path,
|
|
453
|
+
excludes: list[str] | None = None,
|
|
454
|
+
) -> dict:
|
|
455
|
+
"""Analyze a directory for @deprecated symbols and their callers.
|
|
456
|
+
|
|
457
|
+
Args:
|
|
458
|
+
path: Directory to scan
|
|
459
|
+
excludes: Additional file patterns to exclude
|
|
460
|
+
|
|
461
|
+
Returns:
|
|
462
|
+
Dict with success, deprecations (list of DeprecationMarker),
|
|
463
|
+
summary (total_deprecations, deprecations_with_callers), and
|
|
464
|
+
optionally error.
|
|
465
|
+
"""
|
|
466
|
+
resolved = Path(path).resolve()
|
|
467
|
+
|
|
468
|
+
if not resolved.exists():
|
|
469
|
+
return {
|
|
470
|
+
"success": False,
|
|
471
|
+
"error": f"Path not found: {resolved}",
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
all_excludes = DEFAULT_EXCLUDES + (excludes or [])
|
|
475
|
+
|
|
476
|
+
raw = _grep_deprecations(resolved, all_excludes)
|
|
477
|
+
|
|
478
|
+
markers: list[DeprecationMarker] = []
|
|
479
|
+
for item in raw:
|
|
480
|
+
count, caller_list = _count_callers(
|
|
481
|
+
item["symbol"], resolved, item["path"]
|
|
482
|
+
)
|
|
483
|
+
markers.append(DeprecationMarker(
|
|
484
|
+
path=item["path"],
|
|
485
|
+
line=item["line"],
|
|
486
|
+
symbol=item["symbol"],
|
|
487
|
+
text=item["text"],
|
|
488
|
+
caller_count=count,
|
|
489
|
+
callers=caller_list,
|
|
490
|
+
))
|
|
491
|
+
|
|
492
|
+
with_callers = sum(1 for m in markers if m.caller_count > 0)
|
|
493
|
+
|
|
494
|
+
return {
|
|
495
|
+
"success": True,
|
|
496
|
+
"deprecations": markers,
|
|
497
|
+
"summary": {
|
|
498
|
+
"total_deprecations": len(markers),
|
|
499
|
+
"deprecations_with_callers": with_callers,
|
|
500
|
+
},
|
|
501
|
+
}
|
|
@@ -127,3 +127,53 @@ def summary(repo, repo_path, days, top, fmt, output_file, exclude):
|
|
|
127
127
|
else:
|
|
128
128
|
from pennyfarthing_scripts.codemarkers.formatters import format_summary
|
|
129
129
|
format_summary(result, file=click.get_text_stream("stdout"))
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _run_deprecation_analysis(repo_path, exclude):
|
|
133
|
+
"""Run deprecation analysis and return result dict."""
|
|
134
|
+
from pennyfarthing_scripts.codemarkers.analyze import analyze_deprecations
|
|
135
|
+
|
|
136
|
+
excludes = list(exclude) if exclude else None
|
|
137
|
+
if repo_path:
|
|
138
|
+
p = Path(repo_path).resolve()
|
|
139
|
+
else:
|
|
140
|
+
from pennyfarthing_scripts.common.config import get_project_root
|
|
141
|
+
p = get_project_root()
|
|
142
|
+
|
|
143
|
+
return asyncio.run(analyze_deprecations(p, excludes))
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@codemarkers.command()
|
|
147
|
+
@_common_options
|
|
148
|
+
def deprecations(repo, repo_path, days, top, fmt, output_file, exclude):
|
|
149
|
+
"""Scan for @deprecated symbols and cross-reference callers."""
|
|
150
|
+
result = _run_deprecation_analysis(repo_path, exclude)
|
|
151
|
+
|
|
152
|
+
if fmt == "json":
|
|
153
|
+
import json
|
|
154
|
+
from dataclasses import asdict
|
|
155
|
+
|
|
156
|
+
output = {
|
|
157
|
+
"success": result["success"],
|
|
158
|
+
"deprecations": [asdict(m) for m in result.get("deprecations", [])],
|
|
159
|
+
"summary": result.get("summary", {}),
|
|
160
|
+
}
|
|
161
|
+
text = json.dumps(output, indent=2)
|
|
162
|
+
else:
|
|
163
|
+
lines = []
|
|
164
|
+
deps = result.get("deprecations", [])
|
|
165
|
+
summary = result.get("summary", {})
|
|
166
|
+
lines.append(f"Total deprecations: {summary.get('total_deprecations', 0)}")
|
|
167
|
+
lines.append(f"With active callers: {summary.get('deprecations_with_callers', 0)}")
|
|
168
|
+
lines.append("")
|
|
169
|
+
for m in deps[:top]:
|
|
170
|
+
callers_str = f" ({m.caller_count} callers)" if m.caller_count else ""
|
|
171
|
+
lines.append(f" {m.symbol} @ {m.path}:{m.line}{callers_str}")
|
|
172
|
+
lines.append(f" {m.text}")
|
|
173
|
+
text = "\n".join(lines)
|
|
174
|
+
|
|
175
|
+
if output_file:
|
|
176
|
+
Path(output_file).write_text(text)
|
|
177
|
+
click.echo(f"Output written to {output_file}", err=True)
|
|
178
|
+
else:
|
|
179
|
+
click.echo(text)
|
|
@@ -43,3 +43,18 @@ class CodeMarkersResult:
|
|
|
43
43
|
markers: list[CodeMarker] = field(default_factory=list)
|
|
44
44
|
summary: MarkerSummary | None = None
|
|
45
45
|
error: str | None = None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class DeprecationMarker:
|
|
50
|
+
"""A deprecated symbol with caller cross-reference data (Story 80-2).
|
|
51
|
+
|
|
52
|
+
Stub: Dev will implement full functionality.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
path: str
|
|
56
|
+
line: int
|
|
57
|
+
symbol: str
|
|
58
|
+
text: str
|
|
59
|
+
caller_count: int = 0
|
|
60
|
+
callers: list[str] = field(default_factory=list)
|
|
@@ -5,8 +5,16 @@ This package provides shared utilities used across all CLI tools:
|
|
|
5
5
|
- config: Project configuration loading
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from pennyfarthing_scripts.common.config import (
|
|
9
|
+
find_project_root,
|
|
10
|
+
get_project_root,
|
|
11
|
+
load_pennyfarthing_config,
|
|
12
|
+
load_yaml_config,
|
|
13
|
+
)
|
|
8
14
|
from pennyfarthing_scripts.common.output import (
|
|
9
15
|
Colors,
|
|
16
|
+
_colorize,
|
|
17
|
+
_supports_color,
|
|
10
18
|
bold,
|
|
11
19
|
debug,
|
|
12
20
|
dim,
|
|
@@ -16,15 +24,6 @@ from pennyfarthing_scripts.common.output import (
|
|
|
16
24
|
info,
|
|
17
25
|
success,
|
|
18
26
|
warn,
|
|
19
|
-
_colorize,
|
|
20
|
-
_supports_color,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
from pennyfarthing_scripts.common.config import (
|
|
24
|
-
find_project_root,
|
|
25
|
-
get_project_root,
|
|
26
|
-
load_pennyfarthing_config,
|
|
27
|
-
load_yaml_config,
|
|
28
27
|
)
|
|
29
28
|
|
|
30
29
|
__all__ = [
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -5,8 +5,8 @@ Wraps eslint with complexity rules to extract per-file metrics:
|
|
|
5
5
|
cyclomatic complexity, function length, nesting depth, and line counts.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from pennyfarthing_scripts.complexity.models import FileComplexity, ComplexityResult
|
|
9
8
|
from pennyfarthing_scripts.complexity.analyze import analyze_complexity
|
|
9
|
+
from pennyfarthing_scripts.complexity.models import ComplexityResult, FileComplexity
|
|
10
10
|
|
|
11
11
|
__all__ = [
|
|
12
12
|
"FileComplexity",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -13,7 +13,7 @@ import json
|
|
|
13
13
|
import re
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
|
-
from pennyfarthing_scripts.complexity.models import
|
|
16
|
+
from pennyfarthing_scripts.complexity.models import ComplexityResult, FileComplexity
|
|
17
17
|
|
|
18
18
|
# Regex patterns for extracting numeric values from ESLint messages
|
|
19
19
|
COMPLEXITY_RE = re.compile(r"complexity of (\d+)")
|
|
@@ -9,9 +9,13 @@ from __future__ import annotations
|
|
|
9
9
|
|
|
10
10
|
import asyncio
|
|
11
11
|
from pathlib import Path
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
12
13
|
|
|
13
14
|
import click
|
|
14
15
|
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from pennyfarthing_scripts.complexity.models import ComplexityResult
|
|
18
|
+
|
|
15
19
|
|
|
16
20
|
@click.group()
|
|
17
21
|
def complexity():
|
|
@@ -39,7 +43,7 @@ def _common_options(fn):
|
|
|
39
43
|
return fn
|
|
40
44
|
|
|
41
45
|
|
|
42
|
-
def _run_analysis(target_path: str | None, exclude: tuple) ->
|
|
46
|
+
def _run_analysis(target_path: str | None, exclude: tuple) -> ComplexityResult:
|
|
43
47
|
"""Run analysis and return result."""
|
|
44
48
|
from pennyfarthing_scripts.complexity.analyze import analyze_complexity
|
|
45
49
|
|
|
@@ -11,7 +11,7 @@ import io
|
|
|
11
11
|
import json
|
|
12
12
|
from dataclasses import asdict
|
|
13
13
|
|
|
14
|
-
from pennyfarthing_scripts.complexity.models import
|
|
14
|
+
from pennyfarthing_scripts.complexity.models import ComplexityResult, FileComplexity
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def format_file_table(files: list[FileComplexity], top_n: int = 20) -> str:
|
|
@@ -9,7 +9,6 @@ import os
|
|
|
9
9
|
import time
|
|
10
10
|
from dataclasses import dataclass
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Optional
|
|
13
12
|
|
|
14
13
|
try:
|
|
15
14
|
import yaml
|
|
@@ -45,8 +44,8 @@ class ContextResult:
|
|
|
45
44
|
|
|
46
45
|
# Status
|
|
47
46
|
status: str = "OK" # OK, HIGH
|
|
48
|
-
warning:
|
|
49
|
-
recommendation:
|
|
47
|
+
warning: str | None = None # None, High, Critical
|
|
48
|
+
recommendation: str | None = None
|
|
50
49
|
|
|
51
50
|
# Mode settings
|
|
52
51
|
permission_mode: str = "manual"
|
|
@@ -56,7 +55,7 @@ class ContextResult:
|
|
|
56
55
|
is_cyclist: bool = False
|
|
57
56
|
|
|
58
57
|
# Error state
|
|
59
|
-
error:
|
|
58
|
+
error: str | None = None
|
|
60
59
|
|
|
61
60
|
def to_env_vars(self) -> str:
|
|
62
61
|
"""Output as shell environment variables."""
|
|
@@ -111,7 +110,7 @@ class ContextResult:
|
|
|
111
110
|
return "\n".join(lines)
|
|
112
111
|
|
|
113
112
|
|
|
114
|
-
def load_config(project_dir:
|
|
113
|
+
def load_config(project_dir: str | None = None) -> ContextConfig:
|
|
115
114
|
"""Load context configuration from config files.
|
|
116
115
|
|
|
117
116
|
Checks .pennyfarthing/config.local.yaml first, falls back to
|
|
@@ -166,7 +165,7 @@ def _apply_config(config: ContextConfig, data: dict) -> None:
|
|
|
166
165
|
config.relay_mode = wf.get("relay_mode", False) is True
|
|
167
166
|
|
|
168
167
|
|
|
169
|
-
def get_claude_project_path(project_dir:
|
|
168
|
+
def get_claude_project_path(project_dir: str | None = None) -> Path:
|
|
170
169
|
"""Get the Claude Code project path for transcripts.
|
|
171
170
|
|
|
172
171
|
Claude Code stores transcripts at ~/.claude/projects/<path-with-dashes>
|
|
@@ -184,10 +183,10 @@ def get_claude_project_path(project_dir: Optional[str] = None) -> Path:
|
|
|
184
183
|
|
|
185
184
|
def find_transcript(
|
|
186
185
|
project_path: Path,
|
|
187
|
-
explicit_session:
|
|
188
|
-
session_id_env:
|
|
186
|
+
explicit_session: str | None = None,
|
|
187
|
+
session_id_env: str | None = None,
|
|
189
188
|
stale_threshold_seconds: int = 60,
|
|
190
|
-
) ->
|
|
189
|
+
) -> Path | None:
|
|
191
190
|
"""Find the appropriate transcript file.
|
|
192
191
|
|
|
193
192
|
Priority:
|
|
@@ -208,7 +207,7 @@ def find_transcript(
|
|
|
208
207
|
return None
|
|
209
208
|
|
|
210
209
|
# Helper to find most recent transcript
|
|
211
|
-
def most_recent() ->
|
|
210
|
+
def most_recent() -> Path | None:
|
|
212
211
|
transcripts = sorted(
|
|
213
212
|
[f for f in project_path.glob("*.jsonl") if "agent-" not in f.name],
|
|
214
213
|
key=lambda f: f.stat().st_mtime,
|
|
@@ -236,7 +235,7 @@ def find_transcript(
|
|
|
236
235
|
return most_recent()
|
|
237
236
|
|
|
238
237
|
|
|
239
|
-
def parse_transcript(transcript_path: Path) -> tuple[
|
|
238
|
+
def parse_transcript(transcript_path: Path) -> tuple[int | None, int | None]:
|
|
240
239
|
"""Parse transcript for first and last usage totals.
|
|
241
240
|
|
|
242
241
|
Returns:
|
|
@@ -265,7 +264,7 @@ def parse_transcript(transcript_path: Path) -> tuple[Optional[int], Optional[int
|
|
|
265
264
|
return first_total, last_total
|
|
266
265
|
|
|
267
266
|
|
|
268
|
-
def detect_cyclist(project_dir:
|
|
267
|
+
def detect_cyclist(project_dir: str | None = None) -> bool:
|
|
269
268
|
"""Detect if running inside Cyclist.
|
|
270
269
|
|
|
271
270
|
Checks:
|
|
@@ -300,7 +299,7 @@ def detect_cyclist(project_dir: Optional[str] = None) -> bool:
|
|
|
300
299
|
result = s.connect_ex(("127.0.0.1", port))
|
|
301
300
|
if result == 0:
|
|
302
301
|
return True
|
|
303
|
-
except (ValueError, OSError
|
|
302
|
+
except (ValueError, OSError):
|
|
304
303
|
# Port file invalid or port not responding
|
|
305
304
|
continue
|
|
306
305
|
|
|
@@ -308,8 +307,8 @@ def detect_cyclist(project_dir: Optional[str] = None) -> bool:
|
|
|
308
307
|
|
|
309
308
|
|
|
310
309
|
def check_context(
|
|
311
|
-
explicit_session:
|
|
312
|
-
project_dir:
|
|
310
|
+
explicit_session: str | None = None,
|
|
311
|
+
project_dir: str | None = None,
|
|
313
312
|
) -> ContextResult:
|
|
314
313
|
"""Check current context usage.
|
|
315
314
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -9,10 +9,9 @@ from __future__ import annotations
|
|
|
9
9
|
|
|
10
10
|
import asyncio
|
|
11
11
|
import fnmatch
|
|
12
|
-
from datetime import datetime, timezone
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
|
|
15
12
|
import re
|
|
13
|
+
from datetime import UTC, datetime
|
|
14
|
+
from pathlib import Path
|
|
16
15
|
|
|
17
16
|
from pennyfarthing_scripts.deadcode.models import (
|
|
18
17
|
DeadCodeResult,
|
|
@@ -156,7 +155,7 @@ async def find_stale_files(
|
|
|
156
155
|
filtered.append(fpath)
|
|
157
156
|
|
|
158
157
|
# Enrich each stale file
|
|
159
|
-
now = datetime.now(
|
|
158
|
+
now = datetime.now(UTC)
|
|
160
159
|
stale_files = []
|
|
161
160
|
for fpath in sorted(filtered):
|
|
162
161
|
# Get last commit date
|
|
@@ -41,8 +41,8 @@ def _common_options(fn):
|
|
|
41
41
|
|
|
42
42
|
def _run_analysis(repo: str | None, repo_path: str | None, days: int, exclude: tuple, branch: str):
|
|
43
43
|
"""Run analysis and return result."""
|
|
44
|
-
from pennyfarthing_scripts.deadcode.analyze import analyze_repo, find_stale_files
|
|
45
44
|
from pennyfarthing_scripts.common.config import get_project_root
|
|
45
|
+
from pennyfarthing_scripts.deadcode.analyze import analyze_repo
|
|
46
46
|
|
|
47
47
|
excludes = list(exclude) if exclude else None
|
|
48
48
|
|
|
@@ -109,8 +109,8 @@ def _exports_options(fn):
|
|
|
109
109
|
|
|
110
110
|
def _run_exports_analysis(repo: str | None, repo_path: str | None):
|
|
111
111
|
"""Run unused export analysis and return result."""
|
|
112
|
-
from pennyfarthing_scripts.deadcode.analyze import find_unused_exports
|
|
113
112
|
from pennyfarthing_scripts.common.config import get_project_root
|
|
113
|
+
from pennyfarthing_scripts.deadcode.analyze import find_unused_exports
|
|
114
114
|
|
|
115
115
|
if repo_path:
|
|
116
116
|
p = Path(repo_path).resolve()
|