@pennyfarthing/core 7.8.2 → 7.9.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 +1 -1
- package/package.json +1 -1
- package/packages/core/dist/cli/commands/init.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/init.js +8 -7
- package/packages/core/dist/cli/commands/init.js.map +1 -1
- package/packages/core/dist/cli/cyclist-migration.test.js +16 -13
- package/packages/core/dist/cli/cyclist-migration.test.js.map +1 -1
- package/packages/core/dist/cli/utils/files.d.ts +5 -4
- package/packages/core/dist/cli/utils/files.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/files.js +8 -6
- package/packages/core/dist/cli/utils/files.js.map +1 -1
- package/packages/core/dist/cli/utils/symlinks.d.ts +7 -0
- package/packages/core/dist/cli/utils/symlinks.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/symlinks.js +25 -0
- package/packages/core/dist/cli/utils/symlinks.js.map +1 -1
- package/packages/core/dist/cli/utils/themes.d.ts +1 -1
- package/packages/core/dist/cli/utils/themes.d.ts.map +1 -1
- package/packages/core/dist/scripts/run-ci.test.js +1 -1
- package/packages/core/dist/scripts/run-ci.test.js.map +1 -1
- package/pennyfarthing-dist/agents/README.md +25 -17
- package/pennyfarthing-dist/agents/architect.md +3 -11
- package/pennyfarthing-dist/agents/dev.md +2 -2
- package/pennyfarthing-dist/agents/devops.md +3 -11
- package/pennyfarthing-dist/agents/handoff.md +4 -4
- package/pennyfarthing-dist/agents/orchestrator.md +2 -4
- package/pennyfarthing-dist/agents/pm.md +4 -11
- package/pennyfarthing-dist/agents/reviewer-preflight.md +4 -3
- package/pennyfarthing-dist/agents/reviewer.md +2 -8
- package/pennyfarthing-dist/agents/sm-handoff.md +3 -3
- package/pennyfarthing-dist/agents/sm-setup.md +1 -1
- package/pennyfarthing-dist/agents/sm.md +5 -29
- package/pennyfarthing-dist/agents/tea.md +2 -2
- package/pennyfarthing-dist/agents/tech-writer.md +3 -12
- package/pennyfarthing-dist/agents/testing-runner.md +8 -8
- package/pennyfarthing-dist/agents/ux-designer.md +3 -12
- package/pennyfarthing-dist/commands/git-cleanup.md +29 -53
- package/pennyfarthing-dist/commands/party-mode.md +20 -10
- package/pennyfarthing-dist/commands/work.md +6 -105
- package/pennyfarthing-dist/guides/agent-behavior.md +19 -7
- package/pennyfarthing-dist/personas/themes/1984.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/a-team.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/agatha-christie.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/alice-in-wonderland.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/all-stars.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/ancient-philosophers.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/ancient-strategists.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/arcane.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/arthurian-mythos.yaml +0 -13
- package/pennyfarthing-dist/personas/themes/avatar-the-last-airbender.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/babylon-5.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/battlestar-galactica.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/better-call-saul.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/big-lebowski.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/black-sails.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/blade-runner.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/bobiverse.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/breaking-bad.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/catch-22.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/classical-composers.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/count-of-monte-cristo.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/cowboy-bebop.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/deadwood.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/dickens.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/discworld.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/doctor-who.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/don-quixote.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/dune.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/enlightenment-thinkers.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/expeditionary-force.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/fargo.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/film-auteurs.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/firefly.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/foundation.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/futurama.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/game-of-thrones.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/gilligans-island.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/gothic-literature.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/great-gatsby.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/greek-mythology.yaml +0 -13
- package/pennyfarthing-dist/personas/themes/hannibal.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/harry-potter.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/his-dark-materials.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/historical-figures.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/hitchhikers-guide.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/house-md.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/imperial-radch.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/inspector-morse.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/jane-austen.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/jazz-legends.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/justified.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/legion-of-doom.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/les-miserables.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/lord-of-the-rings.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/lovecraft-mythos.yaml +0 -13
- package/pennyfarthing-dist/personas/themes/mad-max.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/mad-men.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/marvel-mcu.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/mash.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/mass-effect.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/military-commanders.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/moby-dick.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/monty-python.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/neuromancer.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/norse-mythology.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/parks-and-rec.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/peaky-blinders.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/princess-bride.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/renaissance-masters.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/rome.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/russian-masters.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/sandman.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/scientific-revolutionaries.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/shakespeare.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/sherlock-holmes.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/snow-crash.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/software-pioneers.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/star-trek-tng.yaml +0 -11
- package/pennyfarthing-dist/personas/themes/star-trek-tos.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/star-wars.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/succession.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/superfriends.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/ted-lasso.yaml +0 -11
- package/pennyfarthing-dist/personas/themes/the-americans.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/the-crown.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/the-expanse.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/the-good-place.yaml +0 -11
- package/pennyfarthing-dist/personas/themes/the-matrix.yaml +0 -15
- package/pennyfarthing-dist/personas/themes/the-odyssey.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/the-office.yaml +0 -11
- package/pennyfarthing-dist/personas/themes/the-simpsons.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/the-sopranos.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/the-wire.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/the-witcher.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/twin-peaks.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/vorkosigan-saga.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/watchmen.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/west-wing.yaml +0 -10
- package/pennyfarthing-dist/personas/themes/world-explorers.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/wwii-leaders.yaml +0 -12
- package/pennyfarthing-dist/personas/themes/x-files.yaml +0 -10
- package/pennyfarthing-dist/scripts/core/agent-session.sh +13 -14
- package/pennyfarthing-dist/scripts/core/phase-check-start.sh +1 -1
- package/pennyfarthing-dist/scripts/core/prime.sh +17 -2
- package/pennyfarthing-dist/scripts/core/run.sh +5 -5
- package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +2 -2
- package/pennyfarthing-dist/scripts/git/release.sh +2 -2
- package/pennyfarthing-dist/scripts/health/drift-detection.sh +1 -1
- package/pennyfarthing-dist/scripts/hooks/post-merge.sh +2 -2
- package/pennyfarthing-dist/scripts/hooks/pre-push.sh +2 -2
- package/pennyfarthing-dist/scripts/hooks/session-stop.sh +1 -1
- package/pennyfarthing-dist/scripts/jira/create-jira-epic.sh +1 -1
- package/pennyfarthing-dist/scripts/jira/create-jira-story.sh +1 -1
- package/pennyfarthing-dist/scripts/jira/jira-reconcile.sh +1 -1
- package/pennyfarthing-dist/scripts/lib/common.sh +1 -1
- package/pennyfarthing-dist/scripts/lib/find-root.sh +4 -4
- package/pennyfarthing-dist/scripts/maintenance/migrate-theme-schema.mjs +102 -0
- package/pennyfarthing-dist/scripts/maintenance/sidecar-health.sh +1 -1
- package/pennyfarthing-dist/scripts/misc/add_short_names.py +2 -2
- package/pennyfarthing-dist/scripts/misc/backlog.sh +2 -2
- package/pennyfarthing-dist/scripts/misc/deploy.sh +2 -2
- package/pennyfarthing-dist/scripts/misc/generate-skill-docs.sh +4 -4
- package/pennyfarthing-dist/scripts/misc/log-skill-usage.sh +2 -2
- package/pennyfarthing-dist/scripts/misc/run-ci.sh +1 -1
- package/pennyfarthing-dist/scripts/misc/skill-usage-report.sh +2 -2
- package/pennyfarthing-dist/scripts/sprint/archive-story.sh +6 -2
- package/pennyfarthing-dist/scripts/sprint/available-stories.sh +1 -1
- package/pennyfarthing-dist/scripts/sprint/check-story.sh +1 -1
- package/pennyfarthing-dist/scripts/sprint/get-epic-field.sh +1 -1
- package/pennyfarthing-dist/scripts/sprint/get-story-field.sh +1 -1
- package/pennyfarthing-dist/scripts/sprint/import_epic_to_future.py +2 -2
- package/pennyfarthing-dist/scripts/sprint/list-future.sh +1 -1
- package/pennyfarthing-dist/scripts/sprint/new-sprint.sh +1 -1
- package/pennyfarthing-dist/scripts/sprint/promote-epic.sh +1 -1
- package/pennyfarthing-dist/scripts/sprint/sprint-common.sh +3 -3
- package/pennyfarthing-dist/scripts/sprint/sprint-info.sh +1 -1
- package/pennyfarthing-dist/scripts/sprint/sprint-metrics.sh +2 -2
- package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +2 -2
- package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +3 -2
- package/pennyfarthing-dist/scripts/workflow/check.py +2 -2
- package/pennyfarthing-dist/scripts/workflow/finish-story.sh +1 -1
- package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +1 -1
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.py +2 -2
- package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +1 -1
- package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +1 -1
- package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +1 -1
- package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +1 -1
- package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +1 -1
- package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +1 -1
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +18 -0
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-03-execute.md +18 -4
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +13 -5
- package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/client.py +1 -1
- package/pennyfarthing_scripts/prime/__init__.py +98 -11
- 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__/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__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/cli.py +208 -53
- package/pennyfarthing_scripts/prime/models.py +169 -0
- package/pennyfarthing_scripts/prime/persona.py +288 -0
- package/pennyfarthing_scripts/prime/session.py +183 -0
- package/pennyfarthing_scripts/prime/workflow.py +275 -0
- 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_prime.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/test_prime.py +653 -0
|
@@ -20,22 +20,22 @@
|
|
|
20
20
|
# ./scripts/run.sh jira/jira-claim-story.sh MSSCI-12345
|
|
21
21
|
#
|
|
22
22
|
# This solves the absolute path problem by:
|
|
23
|
-
# 1. Finding PROJECT_ROOT by looking for the .
|
|
23
|
+
# 1. Finding PROJECT_ROOT by looking for the .pennyfarthing/ directory
|
|
24
24
|
# 2. Exporting PROJECT_ROOT for the script to use
|
|
25
25
|
# 3. Running the script with full absolute paths
|
|
26
26
|
|
|
27
27
|
set -euo pipefail
|
|
28
28
|
|
|
29
|
-
# Find PROJECT_ROOT by looking for .
|
|
29
|
+
# Find PROJECT_ROOT by looking for .pennyfarthing/ marker
|
|
30
30
|
find_project_root() {
|
|
31
31
|
local dir="$PWD"
|
|
32
|
-
while [[ ! -d "$dir/.
|
|
32
|
+
while [[ ! -d "$dir/.pennyfarthing" ]] && [[ "$dir" != "/" ]]; do
|
|
33
33
|
dir="$(dirname "$dir")"
|
|
34
34
|
done
|
|
35
|
-
if [[ -d "$dir/.
|
|
35
|
+
if [[ -d "$dir/.pennyfarthing" ]]; then
|
|
36
36
|
echo "$dir"
|
|
37
37
|
else
|
|
38
|
-
echo "Error: Could not find project root (no .
|
|
38
|
+
echo "Error: Could not find project root (no .pennyfarthing/ directory found)" >&2
|
|
39
39
|
exit 1
|
|
40
40
|
fi
|
|
41
41
|
}
|
|
@@ -11,10 +11,10 @@ set -euo pipefail
|
|
|
11
11
|
# Find project root
|
|
12
12
|
find_project_root() {
|
|
13
13
|
local dir="$PWD"
|
|
14
|
-
while [[ ! -d "$dir/.
|
|
14
|
+
while [[ ! -d "$dir/.pennyfarthing" ]] && [[ "$dir" != "/" ]]; do
|
|
15
15
|
dir="$(dirname "$dir")"
|
|
16
16
|
done
|
|
17
|
-
if [[ -d "$dir/.
|
|
17
|
+
if [[ -d "$dir/.pennyfarthing" ]]; then
|
|
18
18
|
echo "$dir"
|
|
19
19
|
else
|
|
20
20
|
echo "Error: Not in a Pennyfarthing project" >&2
|
|
@@ -22,10 +22,10 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
22
22
|
# Use exported PROJECT_ROOT from run.sh, or detect it
|
|
23
23
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
24
24
|
_dir="$PWD"
|
|
25
|
-
while [[ ! -d "$_dir/.
|
|
25
|
+
while [[ ! -d "$_dir/.pennyfarthing" ]] && [[ "$_dir" != "/" ]]; do
|
|
26
26
|
_dir="$(dirname "$_dir")"
|
|
27
27
|
done
|
|
28
|
-
if [[ -d "$_dir/.
|
|
28
|
+
if [[ -d "$_dir/.pennyfarthing" ]]; then
|
|
29
29
|
PROJECT_ROOT="$_dir"
|
|
30
30
|
else
|
|
31
31
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
@@ -17,10 +17,10 @@ set -uo pipefail
|
|
|
17
17
|
# Find project root by looking for .claude/ marker
|
|
18
18
|
find_project_root() {
|
|
19
19
|
local dir="$PWD"
|
|
20
|
-
while [[ ! -d "$dir/.
|
|
20
|
+
while [[ ! -d "$dir/.pennyfarthing" ]] && [[ "$dir" != "/" ]]; do
|
|
21
21
|
dir="$(dirname "$dir")"
|
|
22
22
|
done
|
|
23
|
-
if [[ -d "$dir/.
|
|
23
|
+
if [[ -d "$dir/.pennyfarthing" ]]; then
|
|
24
24
|
echo "$dir"
|
|
25
25
|
else
|
|
26
26
|
return 1
|
|
@@ -12,10 +12,10 @@ set -uo pipefail
|
|
|
12
12
|
# Find project root
|
|
13
13
|
find_project_root() {
|
|
14
14
|
local dir="$PWD"
|
|
15
|
-
while [[ ! -d "$dir/.
|
|
15
|
+
while [[ ! -d "$dir/.pennyfarthing" ]] && [[ "$dir" != "/" ]]; do
|
|
16
16
|
dir="$(dirname "$dir")"
|
|
17
17
|
done
|
|
18
|
-
if [[ -d "$dir/.
|
|
18
|
+
if [[ -d "$dir/.pennyfarthing" ]]; then
|
|
19
19
|
echo "$dir"
|
|
20
20
|
else
|
|
21
21
|
return 1
|
|
@@ -18,7 +18,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
18
18
|
|
|
19
19
|
# Determine project root (directory containing .claude)
|
|
20
20
|
PROJECT_ROOT="$SCRIPT_DIR"
|
|
21
|
-
while [[ ! -d "$PROJECT_ROOT/.
|
|
21
|
+
while [[ ! -d "$PROJECT_ROOT/.pennyfarthing" ]] && [[ "$PROJECT_ROOT" != "/" ]]; do
|
|
22
22
|
PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
|
|
23
23
|
done
|
|
24
24
|
|
|
@@ -17,7 +17,7 @@ fi
|
|
|
17
17
|
# PROJECT_ROOT should be set by run.sh, but find it if not
|
|
18
18
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
19
19
|
d="$PWD"
|
|
20
|
-
while [[ ! -d "$d/.
|
|
20
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
21
21
|
d="$(dirname "$d")"
|
|
22
22
|
done
|
|
23
23
|
PROJECT_ROOT="$d"
|
|
@@ -16,7 +16,7 @@ set -euo pipefail
|
|
|
16
16
|
# PROJECT_ROOT should be set by run.sh, but find it if not
|
|
17
17
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
18
18
|
d="$PWD"
|
|
19
|
-
while [[ ! -d "$d/.
|
|
19
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
20
20
|
d="$(dirname "$d")"
|
|
21
21
|
done
|
|
22
22
|
PROJECT_ROOT="$d"
|
|
@@ -177,7 +177,7 @@ get_python() {
|
|
|
177
177
|
# Find project root if not set
|
|
178
178
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
179
179
|
local d="$PWD"
|
|
180
|
-
while [[ ! -d "$d/.
|
|
180
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
181
181
|
d="$(dirname "$d")"
|
|
182
182
|
done
|
|
183
183
|
PROJECT_ROOT="$d"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env zsh
|
|
2
|
-
# Shared utility: Find project root by .
|
|
2
|
+
# Shared utility: Find project root by .pennyfarthing/ marker
|
|
3
3
|
#
|
|
4
4
|
# DEPRECATED: Scripts invoked via run.sh already have PROJECT_ROOT set.
|
|
5
5
|
# This file is kept for backwards compatibility with scripts that may be
|
|
@@ -19,14 +19,14 @@ if [ -z "${PROJECT_ROOT:-}" ]; then
|
|
|
19
19
|
_find_root_dir="$PWD"
|
|
20
20
|
fi
|
|
21
21
|
|
|
22
|
-
while [[ ! -d "$_find_root_dir/.
|
|
22
|
+
while [[ ! -d "$_find_root_dir/.pennyfarthing" ]] && [[ "$_find_root_dir" != "/" ]]; do
|
|
23
23
|
_find_root_dir="$(dirname "$_find_root_dir")"
|
|
24
24
|
done
|
|
25
25
|
|
|
26
|
-
if [[ -d "$_find_root_dir/.
|
|
26
|
+
if [[ -d "$_find_root_dir/.pennyfarthing" ]]; then
|
|
27
27
|
PROJECT_ROOT="$_find_root_dir"
|
|
28
28
|
else
|
|
29
|
-
echo "Error: Could not find project root (no .
|
|
29
|
+
echo "Error: Could not find project root (no .pennyfarthing/ directory found)" >&2
|
|
30
30
|
exit 1
|
|
31
31
|
fi
|
|
32
32
|
unset _find_root_dir
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Migration Script: Consolidate quote into catchphrases (MSSCI-12478)
|
|
4
|
+
*
|
|
5
|
+
* For each theme YAML:
|
|
6
|
+
* 1. For each agent: if quote exists and isn't in catchphrases, add it
|
|
7
|
+
* 2. Remove the quote field from all agents
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { readFileSync, writeFileSync, readdirSync } from 'node:fs';
|
|
11
|
+
import { join, dirname } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
|
|
17
|
+
const THEMES_DIR = join(__dirname, '..', '..', 'personas', 'themes');
|
|
18
|
+
|
|
19
|
+
function migrateThemeFile(filePath) {
|
|
20
|
+
let content = readFileSync(filePath, 'utf-8');
|
|
21
|
+
const lines = content.split('\n');
|
|
22
|
+
const result = [];
|
|
23
|
+
|
|
24
|
+
let i = 0;
|
|
25
|
+
while (i < lines.length) {
|
|
26
|
+
const line = lines[i];
|
|
27
|
+
const trimmed = line.trimEnd();
|
|
28
|
+
|
|
29
|
+
// Check for quote: at 4-space indent (agent level)
|
|
30
|
+
if (/^ quote:/.test(trimmed)) {
|
|
31
|
+
// Extract the quote value
|
|
32
|
+
const quoteMatch = trimmed.match(/^ quote:\s*["']?(.+?)["']?$/);
|
|
33
|
+
if (quoteMatch) {
|
|
34
|
+
const quoteValue = quoteMatch[1];
|
|
35
|
+
|
|
36
|
+
// Look ahead for catchphrases section
|
|
37
|
+
let catchphrasesIndex = -1;
|
|
38
|
+
let catchphrases = [];
|
|
39
|
+
|
|
40
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
41
|
+
const checkLine = lines[j];
|
|
42
|
+
// Stop if we hit the next agent (2-space indent with colon) or end of agents
|
|
43
|
+
if (/^ \w+:/.test(checkLine) && !/^ /.test(checkLine)) break;
|
|
44
|
+
if (/^agents:/.test(checkLine) || /^theme:/.test(checkLine)) break;
|
|
45
|
+
|
|
46
|
+
if (/^ catchphrases:/.test(checkLine)) {
|
|
47
|
+
catchphrasesIndex = j;
|
|
48
|
+
// Collect existing catchphrases
|
|
49
|
+
for (let k = j + 1; k < lines.length; k++) {
|
|
50
|
+
const catchLine = lines[k];
|
|
51
|
+
if (/^ - /.test(catchLine)) {
|
|
52
|
+
const catchValue = catchLine.replace(/^ - ["']?(.+?)["']?$/, '$1');
|
|
53
|
+
catchphrases.push(catchValue);
|
|
54
|
+
} else if (!/^\s*$/.test(catchLine) && !/^ /.test(catchLine)) {
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Check if quote is already in catchphrases
|
|
63
|
+
const quoteInCatchphrases = catchphrases.some(c => c === quoteValue);
|
|
64
|
+
|
|
65
|
+
if (!quoteInCatchphrases && catchphrasesIndex === -1) {
|
|
66
|
+
// No catchphrases section - this shouldn't happen based on exploration
|
|
67
|
+
// but handle it anyway by skipping quote (tests expect catchphrases to exist)
|
|
68
|
+
console.log(` Warning: No catchphrases found for agent with quote in ${filePath}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Skip the quote line (don't add to result)
|
|
72
|
+
i++;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
result.push(line);
|
|
78
|
+
i++;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const newContent = result.join('\n');
|
|
82
|
+
if (newContent !== content) {
|
|
83
|
+
writeFileSync(filePath, newContent);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Main
|
|
90
|
+
const files = readdirSync(THEMES_DIR).filter(f => f.endsWith('.yaml'));
|
|
91
|
+
console.log(`Migrating ${files.length} theme files...`);
|
|
92
|
+
|
|
93
|
+
let modified = 0;
|
|
94
|
+
for (const file of files) {
|
|
95
|
+
const filePath = join(THEMES_DIR, file);
|
|
96
|
+
if (migrateThemeFile(filePath)) {
|
|
97
|
+
modified++;
|
|
98
|
+
console.log(` Migrated: ${file}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log(`\nDone. Modified ${modified}/${files.length} files.`);
|
|
@@ -14,7 +14,7 @@ set -euo pipefail
|
|
|
14
14
|
# Find project root
|
|
15
15
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
16
16
|
d="$PWD"
|
|
17
|
-
while [[ ! -d "$d/.
|
|
17
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
18
18
|
d="$(dirname "$d")"
|
|
19
19
|
done
|
|
20
20
|
PROJECT_ROOT="$d"
|
|
@@ -23,10 +23,10 @@ except ImportError:
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def find_project_root() -> Path:
|
|
26
|
-
"""Find project root by looking for .
|
|
26
|
+
"""Find project root by looking for .pennyfarthing directory."""
|
|
27
27
|
current = Path.cwd()
|
|
28
28
|
while current != current.parent:
|
|
29
|
-
if (current / ".
|
|
29
|
+
if (current / ".pennyfarthing").is_dir():
|
|
30
30
|
return current
|
|
31
31
|
current = current.parent
|
|
32
32
|
return Path.cwd()
|
|
@@ -8,11 +8,11 @@ set -euo pipefail
|
|
|
8
8
|
SCRIPT_DIR="${0:A:h}"
|
|
9
9
|
PROJECT_ROOT="${SCRIPT_DIR}/../.."
|
|
10
10
|
|
|
11
|
-
# Find project root by looking for .
|
|
11
|
+
# Find project root by looking for .pennyfarthing directory
|
|
12
12
|
find_project_root() {
|
|
13
13
|
local dir="$PWD"
|
|
14
14
|
while [[ "$dir" != "/" ]]; do
|
|
15
|
-
if [[ -d "$dir/.
|
|
15
|
+
if [[ -d "$dir/.pennyfarthing" ]]; then
|
|
16
16
|
echo "$dir"
|
|
17
17
|
return 0
|
|
18
18
|
fi
|
|
@@ -24,10 +24,10 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
24
24
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
25
25
|
# Find PROJECT_ROOT by looking for .claude/ marker
|
|
26
26
|
_dir="$PWD"
|
|
27
|
-
while [[ ! -d "$_dir/.
|
|
27
|
+
while [[ ! -d "$_dir/.pennyfarthing" ]] && [[ "$_dir" != "/" ]]; do
|
|
28
28
|
_dir="$(dirname "$_dir")"
|
|
29
29
|
done
|
|
30
|
-
if [[ -d "$_dir/.
|
|
30
|
+
if [[ -d "$_dir/.pennyfarthing" ]]; then
|
|
31
31
|
PROJECT_ROOT="$_dir"
|
|
32
32
|
else
|
|
33
33
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
|
|
18
18
|
set -euo pipefail
|
|
19
19
|
|
|
20
|
-
# Find project root (directory containing .
|
|
20
|
+
# Find project root (directory containing .pennyfarthing/)
|
|
21
21
|
find_project_root() {
|
|
22
22
|
local dir="$PWD"
|
|
23
|
-
while [[ ! -d "$dir/.
|
|
23
|
+
while [[ ! -d "$dir/.pennyfarthing" ]] && [[ "$dir" != "/" ]]; do
|
|
24
24
|
dir="$(dirname "$dir")"
|
|
25
25
|
done
|
|
26
|
-
if [[ -d "$dir/.
|
|
26
|
+
if [[ -d "$dir/.pennyfarthing" ]]; then
|
|
27
27
|
echo "$dir"
|
|
28
28
|
else
|
|
29
29
|
echo ""
|
|
@@ -32,7 +32,7 @@ find_project_root() {
|
|
|
32
32
|
|
|
33
33
|
PROJECT_ROOT="$(find_project_root)"
|
|
34
34
|
if [[ -z "$PROJECT_ROOT" ]]; then
|
|
35
|
-
echo "Error: Cannot find project root (no .
|
|
35
|
+
echo "Error: Cannot find project root (no .pennyfarthing directory found)" >&2
|
|
36
36
|
exit 1
|
|
37
37
|
fi
|
|
38
38
|
|
|
@@ -28,10 +28,10 @@ fi
|
|
|
28
28
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
29
29
|
# Fallback: find project root ourselves
|
|
30
30
|
dir="$PWD"
|
|
31
|
-
while [[ ! -d "$dir/.
|
|
31
|
+
while [[ ! -d "$dir/.pennyfarthing" ]] && [[ "$dir" != "/" ]]; do
|
|
32
32
|
dir="$(dirname "$dir")"
|
|
33
33
|
done
|
|
34
|
-
if [[ -d "$dir/.
|
|
34
|
+
if [[ -d "$dir/.pennyfarthing" ]]; then
|
|
35
35
|
PROJECT_ROOT="$dir"
|
|
36
36
|
else
|
|
37
37
|
echo "Error: Could not find project root" >&2
|
|
@@ -54,10 +54,10 @@ done
|
|
|
54
54
|
# --- Find project root ---
|
|
55
55
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
56
56
|
dir="$PWD"
|
|
57
|
-
while [[ ! -d "$dir/.
|
|
57
|
+
while [[ ! -d "$dir/.pennyfarthing" ]] && [[ "$dir" != "/" ]]; do
|
|
58
58
|
dir="$(dirname "$dir")"
|
|
59
59
|
done
|
|
60
|
-
if [[ -d "$dir/.
|
|
60
|
+
if [[ -d "$dir/.pennyfarthing" ]]; then
|
|
61
61
|
PROJECT_ROOT="$dir"
|
|
62
62
|
else
|
|
63
63
|
echo "Error: Could not find project root" >&2
|
|
@@ -43,7 +43,7 @@ fi
|
|
|
43
43
|
# PROJECT_ROOT should be set by run.sh, but find it if not
|
|
44
44
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
45
45
|
d="$PWD"
|
|
46
|
-
while [[ ! -d "$d/.
|
|
46
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
47
47
|
d="$(dirname "$d")"
|
|
48
48
|
done
|
|
49
49
|
PROJECT_ROOT="$d"
|
|
@@ -57,7 +57,11 @@ if [[ ! -f "$SPRINT_FILE" ]]; then
|
|
|
57
57
|
fi
|
|
58
58
|
|
|
59
59
|
# Extract sprint name to determine archive file
|
|
60
|
-
|
|
60
|
+
# Try jira_sprint_name first (newer format), then fall back to name (older format)
|
|
61
|
+
SPRINT_NAME=$(grep -E "^\s+jira_sprint_name:" "$SPRINT_FILE" | head -1 | sed 's/.*TO Sprint \([0-9]*\).*/\1/')
|
|
62
|
+
if [[ -z "$SPRINT_NAME" ]]; then
|
|
63
|
+
SPRINT_NAME=$(grep -E "^\s+name:" "$SPRINT_FILE" | head -1 | sed 's/.*"TO Sprint \([0-9]*\)".*/\1/')
|
|
64
|
+
fi
|
|
61
65
|
if [[ -z "$SPRINT_NAME" ]]; then
|
|
62
66
|
echo "Error: Could not extract sprint name from $SPRINT_FILE"
|
|
63
67
|
exit 1
|
|
@@ -9,7 +9,7 @@ set -euo pipefail
|
|
|
9
9
|
# PROJECT_ROOT should be set by run.sh, but find it if not
|
|
10
10
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
11
11
|
d="$PWD"
|
|
12
|
-
while [[ ! -d "$d/.
|
|
12
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
13
13
|
d="$(dirname "$d")"
|
|
14
14
|
done
|
|
15
15
|
PROJECT_ROOT="$d"
|
|
@@ -21,7 +21,7 @@ fi
|
|
|
21
21
|
# PROJECT_ROOT should be set by run.sh
|
|
22
22
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
23
23
|
d="$PWD"
|
|
24
|
-
while [[ ! -d "$d/.
|
|
24
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
25
25
|
d="$(dirname "$d")"
|
|
26
26
|
done
|
|
27
27
|
PROJECT_ROOT="$d"
|
|
@@ -35,7 +35,7 @@ fi
|
|
|
35
35
|
# PROJECT_ROOT should be set by run.sh
|
|
36
36
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
37
37
|
d="$PWD"
|
|
38
|
-
while [[ ! -d "$d/.
|
|
38
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
39
39
|
d="$(dirname "$d")"
|
|
40
40
|
done
|
|
41
41
|
PROJECT_ROOT="$d"
|
|
@@ -30,7 +30,7 @@ fi
|
|
|
30
30
|
# PROJECT_ROOT should be set by run.sh
|
|
31
31
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
32
32
|
d="$PWD"
|
|
33
|
-
while [[ ! -d "$d/.
|
|
33
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
34
34
|
d="$(dirname "$d")"
|
|
35
35
|
done
|
|
36
36
|
PROJECT_ROOT="$d"
|
|
@@ -39,10 +39,10 @@ def log_error(msg: str) -> None:
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
def find_project_root() -> Path:
|
|
42
|
-
"""Find project root by looking for .
|
|
42
|
+
"""Find project root by looking for .pennyfarthing directory."""
|
|
43
43
|
current = Path.cwd()
|
|
44
44
|
while current != current.parent:
|
|
45
|
-
if (current / ".
|
|
45
|
+
if (current / ".pennyfarthing").is_dir():
|
|
46
46
|
return current
|
|
47
47
|
current = current.parent
|
|
48
48
|
return Path.cwd()
|
|
@@ -10,7 +10,7 @@ set -euo pipefail
|
|
|
10
10
|
# PROJECT_ROOT should be set by run.sh, but find it if not
|
|
11
11
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
12
12
|
d="$PWD"
|
|
13
|
-
while [[ ! -d "$d/.
|
|
13
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
14
14
|
d="$(dirname "$d")"
|
|
15
15
|
done
|
|
16
16
|
PROJECT_ROOT="$d"
|
|
@@ -30,7 +30,7 @@ fi
|
|
|
30
30
|
# PROJECT_ROOT should be set by run.sh, but find it if not
|
|
31
31
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
32
32
|
d="$PWD"
|
|
33
|
-
while [[ ! -d "$d/.
|
|
33
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
34
34
|
d="$(dirname "$d")"
|
|
35
35
|
done
|
|
36
36
|
PROJECT_ROOT="$d"
|
|
@@ -19,7 +19,7 @@ fi
|
|
|
19
19
|
# PROJECT_ROOT should be set by run.sh, but find it if not
|
|
20
20
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
21
21
|
d="$PWD"
|
|
22
|
-
while [[ ! -d "$d/.
|
|
22
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
23
23
|
d="$(dirname "$d")"
|
|
24
24
|
done
|
|
25
25
|
PROJECT_ROOT="$d"
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
# Jira project identifier
|
|
7
7
|
export JIRA_PROJECT="MSSCI"
|
|
8
8
|
|
|
9
|
-
# Find PROJECT_ROOT by looking for .
|
|
9
|
+
# Find PROJECT_ROOT by looking for .pennyfarthing/ marker
|
|
10
10
|
find_project_root() {
|
|
11
11
|
local dir="$PWD"
|
|
12
|
-
while [[ ! -d "$dir/.
|
|
12
|
+
while [[ ! -d "$dir/.pennyfarthing" ]] && [[ "$dir" != "/" ]]; do
|
|
13
13
|
dir="$(dirname "$dir")"
|
|
14
14
|
done
|
|
15
|
-
if [[ -d "$dir/.
|
|
15
|
+
if [[ -d "$dir/.pennyfarthing" ]]; then
|
|
16
16
|
echo "$dir"
|
|
17
17
|
else
|
|
18
18
|
return 1
|
|
@@ -9,7 +9,7 @@ set -euo pipefail
|
|
|
9
9
|
# PROJECT_ROOT should be set by run.sh
|
|
10
10
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
11
11
|
d="$PWD"
|
|
12
|
-
while [[ ! -d "$d/.
|
|
12
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
13
13
|
d="$(dirname "$d")"
|
|
14
14
|
done
|
|
15
15
|
PROJECT_ROOT="$d"
|
|
@@ -13,10 +13,10 @@ set -e
|
|
|
13
13
|
# Find project root
|
|
14
14
|
find_project_root() {
|
|
15
15
|
local dir="$PWD"
|
|
16
|
-
while [[ ! -d "$dir/.
|
|
16
|
+
while [[ ! -d "$dir/.pennyfarthing" ]] && [[ "$dir" != "/" ]]; do
|
|
17
17
|
dir="$(dirname "$dir")"
|
|
18
18
|
done
|
|
19
|
-
if [[ -d "$dir/.
|
|
19
|
+
if [[ -d "$dir/.pennyfarthing" ]]; then
|
|
20
20
|
echo "$dir"
|
|
21
21
|
else
|
|
22
22
|
echo "$PWD"
|
|
@@ -41,10 +41,10 @@ except ImportError:
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def find_project_root() -> Path:
|
|
44
|
-
"""Find project root by looking for .
|
|
44
|
+
"""Find project root by looking for .pennyfarthing directory."""
|
|
45
45
|
current = Path.cwd()
|
|
46
46
|
while current != current.parent:
|
|
47
|
-
if (current / ".
|
|
47
|
+
if (current / ".pennyfarthing").is_dir():
|
|
48
48
|
return current
|
|
49
49
|
current = current.parent
|
|
50
50
|
return Path.cwd()
|
|
@@ -136,8 +136,9 @@ check_xml_tags_balanced() {
|
|
|
136
136
|
local open_tags=($(grep -oE '<[a-z][-a-z]*>' "$file" 2>/dev/null | sed 's/[<>]//g' | sort -u))
|
|
137
137
|
|
|
138
138
|
for tag in "${open_tags[@]}"; do
|
|
139
|
-
|
|
140
|
-
local
|
|
139
|
+
# grep -c returns 0 count but exit code 1 when no matches; use arithmetic to default to 0
|
|
140
|
+
local open_count=$(($(grep -c "<${tag}>" "$file" 2>/dev/null) + 0))
|
|
141
|
+
local close_count=$(($(grep -c "</${tag}>" "$file" 2>/dev/null) + 0))
|
|
141
142
|
|
|
142
143
|
if [[ $open_count -ne $close_count ]]; then
|
|
143
144
|
errors+=("Tag <$tag> has $open_count opens but $close_count closes")
|
|
@@ -127,10 +127,10 @@ def print_section(title: str) -> None:
|
|
|
127
127
|
|
|
128
128
|
|
|
129
129
|
def find_project_root() -> Path:
|
|
130
|
-
"""Find project root by looking for .
|
|
130
|
+
"""Find project root by looking for .pennyfarthing directory."""
|
|
131
131
|
current = Path.cwd()
|
|
132
132
|
while current != current.parent:
|
|
133
|
-
if (current / ".
|
|
133
|
+
if (current / ".pennyfarthing").is_dir():
|
|
134
134
|
return current
|
|
135
135
|
current = current.parent
|
|
136
136
|
return Path.cwd()
|
|
@@ -43,7 +43,7 @@ fi
|
|
|
43
43
|
# PROJECT_ROOT should be set by run.sh, but find it if not
|
|
44
44
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
45
45
|
d="$PWD"
|
|
46
|
-
while [[ ! -d "$d/.
|
|
46
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
47
47
|
d="$(dirname "$d")"
|
|
48
48
|
done
|
|
49
49
|
PROJECT_ROOT="$d"
|
|
@@ -49,7 +49,7 @@ fi
|
|
|
49
49
|
# PROJECT_ROOT should be set by run.sh, but find it if not
|
|
50
50
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
51
51
|
d="$PWD"
|
|
52
|
-
while [[ ! -d "$d/.
|
|
52
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
53
53
|
d="$(dirname "$d")"
|
|
54
54
|
done
|
|
55
55
|
PROJECT_ROOT="$d"
|
|
@@ -19,10 +19,10 @@ except ImportError:
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
def find_project_root() -> Path:
|
|
22
|
-
"""Find project root by looking for .
|
|
22
|
+
"""Find project root by looking for .pennyfarthing directory."""
|
|
23
23
|
current = Path.cwd()
|
|
24
24
|
while current != current.parent:
|
|
25
|
-
if (current / ".
|
|
25
|
+
if (current / ".pennyfarthing").is_dir():
|
|
26
26
|
return current
|
|
27
27
|
current = current.parent
|
|
28
28
|
return Path.cwd()
|
|
@@ -10,7 +10,7 @@ set -euo pipefail
|
|
|
10
10
|
# PROJECT_ROOT should be set by run.sh, but find it if not
|
|
11
11
|
if [[ -z "${PROJECT_ROOT:-}" ]]; then
|
|
12
12
|
d="$PWD"
|
|
13
|
-
while [[ ! -d "$d/.
|
|
13
|
+
while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
|
|
14
14
|
d="$(dirname "$d")"
|
|
15
15
|
done
|
|
16
16
|
PROJECT_ROOT="$d"
|