shipwright-cli 2.1.2 → 2.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/.claude/agents/devops-engineer.md +14 -12
- package/.claude/agents/doc-fleet-agent.md +99 -0
- package/.claude/agents/test-specialist.md +5 -3
- package/README.md +48 -27
- package/claude-code/CLAUDE.md.shipwright +2 -2
- package/config/policy.json +73 -0
- package/config/policy.schema.json +75 -0
- package/docs/AGI-PLATFORM-PLAN.md +122 -0
- package/docs/AGI-WHATS-NEXT.md +69 -0
- package/docs/KNOWN-ISSUES.md +1 -23
- package/docs/PLATFORM-TODO-BACKLOG.md +41 -0
- package/docs/PLATFORM-TODO-TRIAGE.md +56 -0
- package/docs/README.md +83 -0
- package/docs/TIPS.md +39 -2
- package/docs/config-policy.md +40 -0
- package/docs/definition-of-done.example.md +2 -0
- package/docs/patterns/README.md +5 -0
- package/docs/strategy/02-mission-and-brand.md +3 -3
- package/docs/strategy/README.md +4 -3
- package/docs/tmux-research/TMUX-AUDIT.md +2 -0
- package/docs/tmux-research/TMUX-RESEARCH-INDEX.md +17 -0
- package/package.json +3 -2
- package/scripts/lib/daemon-health.sh +32 -0
- package/scripts/lib/pipeline-quality.sh +23 -0
- package/scripts/lib/policy.sh +32 -0
- package/scripts/sw +5 -1
- package/scripts/sw-activity.sh +35 -46
- package/scripts/sw-adaptive.sh +30 -39
- package/scripts/sw-adversarial.sh +30 -36
- package/scripts/sw-architecture-enforcer.sh +30 -33
- package/scripts/sw-auth.sh +30 -42
- package/scripts/sw-autonomous.sh +60 -40
- package/scripts/sw-changelog.sh +29 -30
- package/scripts/sw-checkpoint.sh +30 -18
- package/scripts/sw-ci.sh +30 -42
- package/scripts/sw-cleanup.sh +32 -15
- package/scripts/sw-code-review.sh +26 -32
- package/scripts/sw-connect.sh +30 -19
- package/scripts/sw-context.sh +30 -19
- package/scripts/sw-cost.sh +30 -40
- package/scripts/sw-daemon.sh +66 -36
- package/scripts/sw-dashboard.sh +31 -40
- package/scripts/sw-db.sh +30 -20
- package/scripts/sw-decompose.sh +30 -38
- package/scripts/sw-deps.sh +30 -41
- package/scripts/sw-developer-simulation.sh +30 -36
- package/scripts/sw-discovery.sh +36 -19
- package/scripts/sw-doc-fleet.sh +822 -0
- package/scripts/sw-docs-agent.sh +30 -36
- package/scripts/sw-docs.sh +29 -31
- package/scripts/sw-doctor.sh +52 -20
- package/scripts/sw-dora.sh +29 -34
- package/scripts/sw-durable.sh +30 -20
- package/scripts/sw-e2e-orchestrator.sh +36 -21
- package/scripts/sw-eventbus.sh +30 -17
- package/scripts/sw-feedback.sh +30 -41
- package/scripts/sw-fix.sh +30 -40
- package/scripts/sw-fleet-discover.sh +30 -41
- package/scripts/sw-fleet-viz.sh +30 -20
- package/scripts/sw-fleet.sh +30 -40
- package/scripts/sw-github-app.sh +30 -41
- package/scripts/sw-github-checks.sh +30 -41
- package/scripts/sw-github-deploy.sh +30 -41
- package/scripts/sw-github-graphql.sh +30 -38
- package/scripts/sw-guild.sh +30 -37
- package/scripts/sw-heartbeat.sh +30 -19
- package/scripts/sw-hygiene.sh +134 -42
- package/scripts/sw-incident.sh +30 -39
- package/scripts/sw-init.sh +31 -14
- package/scripts/sw-instrument.sh +30 -41
- package/scripts/sw-intelligence.sh +39 -44
- package/scripts/sw-jira.sh +31 -41
- package/scripts/sw-launchd.sh +30 -17
- package/scripts/sw-linear.sh +31 -41
- package/scripts/sw-logs.sh +32 -17
- package/scripts/sw-loop.sh +32 -19
- package/scripts/sw-memory.sh +32 -43
- package/scripts/sw-mission-control.sh +31 -40
- package/scripts/sw-model-router.sh +30 -20
- package/scripts/sw-otel.sh +30 -20
- package/scripts/sw-oversight.sh +30 -36
- package/scripts/sw-patrol-meta.sh +31 -0
- package/scripts/sw-pipeline-composer.sh +30 -39
- package/scripts/sw-pipeline-vitals.sh +30 -44
- package/scripts/sw-pipeline.sh +275 -6388
- package/scripts/sw-pm.sh +31 -41
- package/scripts/sw-pr-lifecycle.sh +30 -42
- package/scripts/sw-predictive.sh +32 -34
- package/scripts/sw-prep.sh +30 -19
- package/scripts/sw-ps.sh +32 -17
- package/scripts/sw-public-dashboard.sh +30 -40
- package/scripts/sw-quality.sh +42 -40
- package/scripts/sw-reaper.sh +32 -15
- package/scripts/sw-recruit.sh +428 -48
- package/scripts/sw-regression.sh +30 -38
- package/scripts/sw-release-manager.sh +30 -38
- package/scripts/sw-release.sh +29 -31
- package/scripts/sw-remote.sh +31 -40
- package/scripts/sw-replay.sh +30 -18
- package/scripts/sw-retro.sh +33 -42
- package/scripts/sw-scale.sh +41 -24
- package/scripts/sw-security-audit.sh +30 -20
- package/scripts/sw-self-optimize.sh +33 -37
- package/scripts/sw-session.sh +31 -15
- package/scripts/sw-setup.sh +30 -16
- package/scripts/sw-standup.sh +30 -20
- package/scripts/sw-status.sh +33 -13
- package/scripts/sw-strategic.sh +55 -43
- package/scripts/sw-stream.sh +33 -37
- package/scripts/sw-swarm.sh +30 -21
- package/scripts/sw-team-stages.sh +30 -38
- package/scripts/sw-templates.sh +31 -16
- package/scripts/sw-testgen.sh +30 -31
- package/scripts/sw-tmux-pipeline.sh +29 -31
- package/scripts/sw-tmux-role-color.sh +31 -0
- package/scripts/sw-tmux-status.sh +31 -0
- package/scripts/sw-tmux.sh +31 -15
- package/scripts/sw-trace.sh +30 -19
- package/scripts/sw-tracker-github.sh +31 -0
- package/scripts/sw-tracker-jira.sh +31 -0
- package/scripts/sw-tracker-linear.sh +31 -0
- package/scripts/sw-tracker.sh +30 -40
- package/scripts/sw-triage.sh +68 -61
- package/scripts/sw-upgrade.sh +30 -16
- package/scripts/sw-ux.sh +30 -35
- package/scripts/sw-webhook.sh +30 -25
- package/scripts/sw-widgets.sh +30 -19
- package/scripts/sw-worktree.sh +32 -15
- package/tmux/templates/doc-fleet.json +43 -0
|
@@ -6,54 +6,43 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
VERSION="2.
|
|
9
|
+
VERSION="2.2.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
13
|
-
# ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
|
|
14
|
-
CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
|
|
15
|
-
PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
|
|
16
|
-
BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
|
|
17
|
-
GREEN='\033[38;2;74;222;128m' # success
|
|
18
|
-
YELLOW='\033[38;2;250;204;21m' # warning
|
|
19
|
-
RED='\033[38;2;248;113;113m' # error
|
|
20
|
-
DIM='\033[2m'
|
|
21
|
-
BOLD='\033[1m'
|
|
22
|
-
RESET='\033[0m'
|
|
23
|
-
|
|
24
13
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
25
14
|
# shellcheck source=lib/compat.sh
|
|
26
15
|
[[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
|
|
27
16
|
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
emit_event
|
|
41
|
-
|
|
42
|
-
shift
|
|
43
|
-
local
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
17
|
+
# Canonical helpers (colors, output, events)
|
|
18
|
+
# shellcheck source=lib/helpers.sh
|
|
19
|
+
[[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
|
|
20
|
+
# Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
|
|
21
|
+
[[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
|
|
22
|
+
[[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
|
|
23
|
+
[[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
|
|
24
|
+
[[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
|
|
25
|
+
if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
|
|
26
|
+
now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
|
|
27
|
+
now_epoch() { date +%s; }
|
|
28
|
+
fi
|
|
29
|
+
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
30
|
+
emit_event() {
|
|
31
|
+
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
32
|
+
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
33
|
+
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
34
|
+
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
35
|
+
}
|
|
36
|
+
fi
|
|
37
|
+
CYAN="${CYAN:-\033[38;2;0;212;255m}"
|
|
38
|
+
PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
|
|
39
|
+
BLUE="${BLUE:-\033[38;2;0;102;255m}"
|
|
40
|
+
GREEN="${GREEN:-\033[38;2;74;222;128m}"
|
|
41
|
+
YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
|
|
42
|
+
RED="${RED:-\033[38;2;248;113;113m}"
|
|
43
|
+
DIM="${DIM:-\033[2m}"
|
|
44
|
+
BOLD="${BOLD:-\033[1m}"
|
|
45
|
+
RESET="${RESET:-\033[0m}"
|
|
57
46
|
|
|
58
47
|
# ─── Artifacts Directory ─────────────────────────────────────────────────────
|
|
59
48
|
ARTIFACTS_DIR="${REPO_DIR}/.claude/pipeline-artifacts"
|
|
@@ -6,55 +6,47 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
VERSION="2.
|
|
9
|
+
VERSION="2.2.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
13
|
-
# ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
|
|
14
|
-
CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
|
|
15
|
-
PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
|
|
16
|
-
BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
|
|
17
|
-
GREEN='\033[38;2;74;222;128m' # success
|
|
18
|
-
YELLOW='\033[38;2;250;204;21m' # warning
|
|
19
|
-
RED='\033[38;2;248;113;113m' # error
|
|
20
|
-
DIM='\033[2m'
|
|
21
|
-
BOLD='\033[1m'
|
|
22
|
-
RESET='\033[0m'
|
|
23
|
-
|
|
24
13
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
25
14
|
# shellcheck source=lib/compat.sh
|
|
26
15
|
[[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
|
|
27
16
|
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
17
|
+
# Canonical helpers (colors, output, events)
|
|
18
|
+
# shellcheck source=lib/helpers.sh
|
|
19
|
+
[[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
|
|
20
|
+
# Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
|
|
21
|
+
[[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
|
|
22
|
+
[[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
|
|
23
|
+
[[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
|
|
24
|
+
[[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
|
|
25
|
+
if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
|
|
26
|
+
now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
|
|
27
|
+
now_epoch() { date +%s; }
|
|
28
|
+
fi
|
|
29
|
+
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
30
|
+
emit_event() {
|
|
31
|
+
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
32
|
+
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
33
|
+
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
34
|
+
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
35
|
+
}
|
|
36
|
+
fi
|
|
37
|
+
CYAN="${CYAN:-\033[38;2;0;212;255m}"
|
|
38
|
+
PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
|
|
39
|
+
BLUE="${BLUE:-\033[38;2;0;102;255m}"
|
|
40
|
+
GREEN="${GREEN:-\033[38;2;74;222;128m}"
|
|
41
|
+
YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
|
|
42
|
+
RED="${RED:-\033[38;2;248;113;113m}"
|
|
43
|
+
DIM="${DIM:-\033[2m}"
|
|
44
|
+
BOLD="${BOLD:-\033[1m}"
|
|
45
|
+
RESET="${RESET:-\033[0m}"
|
|
36
46
|
|
|
37
47
|
# ─── Structured Event Log ──────────────────────────────────────────────────
|
|
38
48
|
EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
|
|
39
49
|
|
|
40
|
-
emit_event() {
|
|
41
|
-
local event_type="$1"
|
|
42
|
-
shift
|
|
43
|
-
local json_fields=""
|
|
44
|
-
for kv in "$@"; do
|
|
45
|
-
local key="${kv%%=*}"
|
|
46
|
-
local val="${kv#*=}"
|
|
47
|
-
if [[ "$val" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
|
|
48
|
-
json_fields="${json_fields},\"${key}\":${val}"
|
|
49
|
-
else
|
|
50
|
-
val="${val//\"/\\\"}"
|
|
51
|
-
json_fields="${json_fields},\"${key}\":\"${val}\""
|
|
52
|
-
fi
|
|
53
|
-
done
|
|
54
|
-
mkdir -p "${HOME}/.shipwright"
|
|
55
|
-
echo "{\"ts\":\"$(now_iso)\",\"ts_epoch\":$(now_epoch),\"type\":\"${event_type}\"${json_fields}}" >> "$EVENTS_FILE"
|
|
56
|
-
}
|
|
57
|
-
|
|
58
50
|
# ─── Cache Configuration ───────────────────────────────────────────────────
|
|
59
51
|
GH_CACHE_DIR="${HOME}/.shipwright/github-cache"
|
|
60
52
|
|
package/scripts/sw-guild.sh
CHANGED
|
@@ -6,31 +6,42 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
VERSION="2.
|
|
9
|
+
VERSION="2.2.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
|
-
# ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
|
|
13
|
-
CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
|
|
14
|
-
PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
|
|
15
|
-
BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
|
|
16
|
-
GREEN='\033[38;2;74;222;128m' # success
|
|
17
|
-
YELLOW='\033[38;2;250;204;21m' # warning
|
|
18
|
-
RED='\033[38;2;248;113;113m' # error
|
|
19
|
-
DIM='\033[2m'
|
|
20
|
-
BOLD='\033[1m'
|
|
21
|
-
RESET='\033[0m'
|
|
22
|
-
|
|
23
12
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
24
13
|
# shellcheck source=lib/compat.sh
|
|
25
14
|
[[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
|
|
26
15
|
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
16
|
+
# Canonical helpers (colors, output, events)
|
|
17
|
+
# shellcheck source=lib/helpers.sh
|
|
18
|
+
[[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
|
|
19
|
+
# Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
|
|
20
|
+
[[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
|
|
21
|
+
[[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
|
|
22
|
+
[[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
|
|
23
|
+
[[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
|
|
24
|
+
if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
|
|
25
|
+
now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
|
|
26
|
+
now_epoch() { date +%s; }
|
|
27
|
+
fi
|
|
28
|
+
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
29
|
+
emit_event() {
|
|
30
|
+
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
31
|
+
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
32
|
+
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
33
|
+
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
34
|
+
}
|
|
35
|
+
fi
|
|
36
|
+
CYAN="${CYAN:-\033[38;2;0;212;255m}"
|
|
37
|
+
PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
|
|
38
|
+
BLUE="${BLUE:-\033[38;2;0;102;255m}"
|
|
39
|
+
GREEN="${GREEN:-\033[38;2;74;222;128m}"
|
|
40
|
+
YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
|
|
41
|
+
RED="${RED:-\033[38;2;248;113;113m}"
|
|
42
|
+
DIM="${DIM:-\033[2m}"
|
|
43
|
+
BOLD="${BOLD:-\033[1m}"
|
|
44
|
+
RESET="${RESET:-\033[0m}"
|
|
34
45
|
|
|
35
46
|
# ─── Guild Storage Paths ───────────────────────────────────────────────────
|
|
36
47
|
GUILD_ROOT="${HOME}/.shipwright/guilds"
|
|
@@ -40,24 +51,6 @@ GUILD_DATA="${GUILD_ROOT}/guilds.json"
|
|
|
40
51
|
# ─── Event Logging ────────────────────────────────────────────────────────
|
|
41
52
|
EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
|
|
42
53
|
|
|
43
|
-
emit_event() {
|
|
44
|
-
local event_type="$1"
|
|
45
|
-
shift
|
|
46
|
-
local json_fields=""
|
|
47
|
-
for kv in "$@"; do
|
|
48
|
-
local key="${kv%%=*}"
|
|
49
|
-
local val="${kv#*=}"
|
|
50
|
-
if [[ "$val" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
|
|
51
|
-
json_fields="${json_fields},\"${key}\":${val}"
|
|
52
|
-
else
|
|
53
|
-
val="${val//\"/\\\"}"
|
|
54
|
-
json_fields="${json_fields},\"${key}\":\"${val}\""
|
|
55
|
-
fi
|
|
56
|
-
done
|
|
57
|
-
mkdir -p "${HOME}/.shipwright"
|
|
58
|
-
echo "{\"ts\":\"$(now_iso)\",\"type\":\"${event_type}\"${json_fields}}" >> "$EVENTS_FILE"
|
|
59
|
-
}
|
|
60
|
-
|
|
61
54
|
# ─── Initialization ────────────────────────────────────────────────────────
|
|
62
55
|
ensure_guild_dir() {
|
|
63
56
|
mkdir -p "$GUILD_ROOT"
|
package/scripts/sw-heartbeat.sh
CHANGED
|
@@ -6,35 +6,46 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
VERSION="2.
|
|
9
|
+
VERSION="2.2.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
|
-
# ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
|
|
13
|
-
CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
|
|
14
|
-
PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
|
|
15
|
-
BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
|
|
16
|
-
GREEN='\033[38;2;74;222;128m' # success
|
|
17
|
-
YELLOW='\033[38;2;250;204;21m' # warning
|
|
18
|
-
RED='\033[38;2;248;113;113m' # error
|
|
19
|
-
DIM='\033[2m'
|
|
20
|
-
BOLD='\033[1m'
|
|
21
|
-
RESET='\033[0m'
|
|
22
|
-
|
|
23
12
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
24
13
|
# shellcheck source=lib/compat.sh
|
|
25
14
|
[[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
|
|
26
15
|
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
16
|
+
# Canonical helpers (colors, output, events)
|
|
17
|
+
# shellcheck source=lib/helpers.sh
|
|
18
|
+
[[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
|
|
19
|
+
# Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
|
|
20
|
+
[[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
|
|
21
|
+
[[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
|
|
22
|
+
[[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
|
|
23
|
+
[[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
|
|
24
|
+
if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
|
|
25
|
+
now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
|
|
26
|
+
now_epoch() { date +%s; }
|
|
27
|
+
fi
|
|
28
|
+
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
29
|
+
emit_event() {
|
|
30
|
+
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
31
|
+
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
32
|
+
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
33
|
+
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
34
|
+
}
|
|
35
|
+
fi
|
|
36
|
+
CYAN="${CYAN:-\033[38;2;0;212;255m}"
|
|
37
|
+
PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
|
|
38
|
+
BLUE="${BLUE:-\033[38;2;0;102;255m}"
|
|
39
|
+
GREEN="${GREEN:-\033[38;2;74;222;128m}"
|
|
40
|
+
YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
|
|
41
|
+
RED="${RED:-\033[38;2;248;113;113m}"
|
|
42
|
+
DIM="${DIM:-\033[2m}"
|
|
43
|
+
BOLD="${BOLD:-\033[1m}"
|
|
44
|
+
RESET="${RESET:-\033[0m}"
|
|
32
45
|
|
|
33
46
|
# ─── Constants ──────────────────────────────────────────────────────────────
|
|
34
47
|
HEARTBEAT_DIR="$HOME/.shipwright/heartbeats"
|
|
35
48
|
|
|
36
|
-
now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
|
|
37
|
-
|
|
38
49
|
# ─── Ensure heartbeat directory exists ──────────────────────────────────────
|
|
39
50
|
ensure_dir() {
|
|
40
51
|
mkdir -p "$HEARTBEAT_DIR"
|
package/scripts/sw-hygiene.sh
CHANGED
|
@@ -6,50 +6,49 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
VERSION="2.
|
|
9
|
+
VERSION="2.2.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
13
|
-
# ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
|
|
14
|
-
CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
|
|
15
|
-
PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
|
|
16
|
-
BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
|
|
17
|
-
GREEN='\033[38;2;74;222;128m' # success
|
|
18
|
-
YELLOW='\033[38;2;250;204;21m' # warning
|
|
19
|
-
RED='\033[38;2;248;113;113m' # error
|
|
20
|
-
DIM='\033[2m'
|
|
21
|
-
BOLD='\033[1m'
|
|
22
|
-
RESET='\033[0m'
|
|
23
|
-
|
|
24
13
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
25
14
|
# shellcheck source=lib/compat.sh
|
|
26
15
|
[[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
16
|
+
# Policy (config/policy.json) — tunables override defaults when present
|
|
17
|
+
[[ -f "$SCRIPT_DIR/lib/policy.sh" ]] && source "$SCRIPT_DIR/lib/policy.sh"
|
|
18
|
+
# Canonical helpers (colors, output, events)
|
|
19
|
+
[[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
|
|
20
|
+
# Fallback when helpers.sh not loaded
|
|
21
|
+
[[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
|
|
22
|
+
[[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
|
|
23
|
+
[[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
|
|
24
|
+
[[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
|
|
25
|
+
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
26
|
+
emit_event() {
|
|
35
27
|
local event_type="$1"; shift
|
|
36
|
-
|
|
37
|
-
mkdir -p "$(dirname "$events_file")"
|
|
28
|
+
mkdir -p "${HOME}/.shipwright"
|
|
38
29
|
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
39
|
-
while [[ $# -gt 0 ]]; do
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
30
|
+
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
31
|
+
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
32
|
+
}
|
|
33
|
+
fi
|
|
34
|
+
CYAN="${CYAN:-\033[38;2;0;212;255m}"
|
|
35
|
+
PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
|
|
36
|
+
GREEN="${GREEN:-\033[38;2;74;222;128m}"
|
|
37
|
+
YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
|
|
38
|
+
RED="${RED:-\033[38;2;248;113;113m}"
|
|
39
|
+
DIM="${DIM:-\033[2m}"
|
|
40
|
+
BOLD="${BOLD:-\033[1m}"
|
|
41
|
+
RESET="${RESET:-\033[0m}"
|
|
42
|
+
BLUE="${BLUE:-\033[38;2;0;102;255m}"
|
|
43
|
+
|
|
44
|
+
# ─── Default Settings (policy overrides when config/policy.json exists) ──────
|
|
49
45
|
SUBCOMMAND="${1:-help}"
|
|
50
46
|
AUTO_FIX=false
|
|
51
47
|
VERBOSE=false
|
|
52
48
|
ARTIFACT_AGE_DAYS=7
|
|
49
|
+
if type policy_get &>/dev/null 2>&1; then
|
|
50
|
+
ARTIFACT_AGE_DAYS=$(policy_get ".hygiene.artifact_age_days" "7")
|
|
51
|
+
fi
|
|
53
52
|
JSON_OUTPUT=false
|
|
54
53
|
|
|
55
54
|
# ─── Help ───────────────────────────────────────────────────────────────────
|
|
@@ -68,6 +67,7 @@ show_help() {
|
|
|
68
67
|
echo -e " ${CYAN}naming${RESET} Check naming conventions (files, functions, vars)"
|
|
69
68
|
echo -e " ${CYAN}branches${RESET} List stale and merged remote branches"
|
|
70
69
|
echo -e " ${CYAN}size${RESET} Size analysis and bloat detection"
|
|
70
|
+
echo -e " ${CYAN}platform-refactor${RESET} Scan for hardcoded/fallback/TODO/FIXME — for AGI-level self-improvement"
|
|
71
71
|
echo -e " ${CYAN}fix${RESET} Auto-fix safe issues (naming, whitespace)"
|
|
72
72
|
echo -e " ${CYAN}report${RESET} Generate comprehensive hygiene report"
|
|
73
73
|
echo -e " ${CYAN}help${RESET} Show this help message"
|
|
@@ -373,6 +373,84 @@ analyze_size() {
|
|
|
373
373
|
return 0
|
|
374
374
|
}
|
|
375
375
|
|
|
376
|
+
# ─── Platform Refactor / Hardcoded Scan (AGI-Level Self-Improvement) ───
|
|
377
|
+
# Outputs JSON to REPO_DIR/.claude/platform-hygiene.json for strategic agent.
|
|
378
|
+
scan_platform_refactor() {
|
|
379
|
+
info "Scanning for hardcoded/static/platform-refactor signals..."
|
|
380
|
+
|
|
381
|
+
mkdir -p "$REPO_DIR/.claude"
|
|
382
|
+
local out_file="$REPO_DIR/.claude/platform-hygiene.json"
|
|
383
|
+
local scripts_dir="${REPO_DIR}/scripts"
|
|
384
|
+
|
|
385
|
+
local hardcoded_count fallback_count todo_count fixme_count hack_count
|
|
386
|
+
hardcoded_count=$(grep -rE "hardcoded|Hardcoded|HARDCODED" "$scripts_dir" --include="*.sh" 2>/dev/null | wc -l | tr -d ' ')
|
|
387
|
+
fallback_count=$(grep -rE "Fallback:|fallback:" "$scripts_dir" --include="*.sh" 2>/dev/null | wc -l | tr -d ' ')
|
|
388
|
+
todo_count=$(grep -rE "TODO" "$scripts_dir" --include="*.sh" 2>/dev/null | wc -l | tr -d ' ')
|
|
389
|
+
fixme_count=$(grep -rE "FIXME" "$scripts_dir" --include="*.sh" 2>/dev/null | wc -l | tr -d ' ')
|
|
390
|
+
hack_count=$(grep -rE "HACK|KLUDGE" "$scripts_dir" --include="*.sh" 2>/dev/null | wc -l | tr -d ' ')
|
|
391
|
+
hardcoded_count=${hardcoded_count:-0}
|
|
392
|
+
fallback_count=${fallback_count:-0}
|
|
393
|
+
todo_count=${todo_count:-0}
|
|
394
|
+
fixme_count=${fixme_count:-0}
|
|
395
|
+
hack_count=${hack_count:-0}
|
|
396
|
+
|
|
397
|
+
# Sample findings: file:line (first 25) for strategic context (grep -n gives file:line:content)
|
|
398
|
+
local findings_file findings_raw
|
|
399
|
+
findings_file=$(mktemp)
|
|
400
|
+
findings_raw=$(mktemp)
|
|
401
|
+
grep -rnE "hardcoded|Hardcoded|Fallback:|fallback:|TODO|FIXME|HACK|KLUDGE" "$scripts_dir" --include="*.sh" 2>/dev/null | head -25 > "$findings_raw" || true
|
|
402
|
+
while IFS= read -r line; do
|
|
403
|
+
[[ -z "$line" ]] && continue
|
|
404
|
+
local f="${line%%:*}" rest="${line#*:}" ln="${rest%%:*}"
|
|
405
|
+
ln="${ln:-0}"
|
|
406
|
+
printf '{"file":"%s","line":%s}\n' "${f#$REPO_DIR/}" "$ln"
|
|
407
|
+
done < "$findings_raw" > "$findings_file.raw" 2>/dev/null || true
|
|
408
|
+
jq -s '.' "$findings_file.raw" 2>/dev/null > "$findings_file" || echo "[]" > "$findings_file"
|
|
409
|
+
local findings
|
|
410
|
+
findings=$(cat "$findings_file" 2>/dev/null || echo "[]")
|
|
411
|
+
rm -f "$findings_file" "$findings_file.raw" "$findings_raw"
|
|
412
|
+
|
|
413
|
+
# Script sizes (lines) for hotspot detection
|
|
414
|
+
local sizes_file
|
|
415
|
+
sizes_file=$(mktemp)
|
|
416
|
+
find "$scripts_dir" -maxdepth 1 -name "*.sh" -type f 2>/dev/null | while read -r f; do
|
|
417
|
+
local lines
|
|
418
|
+
lines=$(wc -l < "$f" 2>/dev/null || echo 0)
|
|
419
|
+
printf '{"script":"%s","lines":%s}\n' "$(basename "$f")" "$lines"
|
|
420
|
+
done | jq -s 'sort_by(-.lines) | .[0:15]' 2>/dev/null > "$sizes_file"
|
|
421
|
+
local script_sizes
|
|
422
|
+
script_sizes=$(cat "$sizes_file" 2>/dev/null || echo "[]")
|
|
423
|
+
rm -f "$sizes_file"
|
|
424
|
+
|
|
425
|
+
local timestamp
|
|
426
|
+
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
427
|
+
local report
|
|
428
|
+
report=$(jq -n \
|
|
429
|
+
--arg ts "$timestamp" \
|
|
430
|
+
--arg repo "$(basename "$REPO_DIR")" \
|
|
431
|
+
--argjson hc "$hardcoded_count" \
|
|
432
|
+
--argjson fb "$fallback_count" \
|
|
433
|
+
--argjson todo "$todo_count" \
|
|
434
|
+
--argjson fixme "$fixme_count" \
|
|
435
|
+
--argjson hack "$hack_count" \
|
|
436
|
+
--argjson findings "$findings" \
|
|
437
|
+
--argjson script_sizes "$script_sizes" \
|
|
438
|
+
'{timestamp:$ts,repository:$repo,counts:{hardcoded:$hc,fallback:$fb,todo:$todo,fixme:$fixme,hack:$hack},findings_sample:$findings,script_size_hotspots:$script_sizes}' 2>/dev/null)
|
|
439
|
+
if [[ -n "$report" ]]; then
|
|
440
|
+
echo "$report" > "$out_file"
|
|
441
|
+
success "Platform refactor scan saved to: $out_file"
|
|
442
|
+
if [[ "$JSON_OUTPUT" == true ]]; then
|
|
443
|
+
echo "$report" | jq .
|
|
444
|
+
else
|
|
445
|
+
info " hardcoded: $hardcoded_count fallback: $fallback_count TODO: $todo_count FIXME: $fixme_count HACK/KLUDGE: $hack_count"
|
|
446
|
+
fi
|
|
447
|
+
else
|
|
448
|
+
warn "Could not build platform-hygiene JSON (jq missing?)"
|
|
449
|
+
fi
|
|
450
|
+
emit_event "hygiene_platform_refactor" "hardcoded=$hardcoded_count" "fallback=$fallback_count" "todo=$todo_count"
|
|
451
|
+
return 0
|
|
452
|
+
}
|
|
453
|
+
|
|
376
454
|
# ─── Auto-Fix Mode ────────────────────────────────────────────────────────
|
|
377
455
|
|
|
378
456
|
auto_fix_issues() {
|
|
@@ -446,29 +524,39 @@ generate_report() {
|
|
|
446
524
|
info "Generating comprehensive hygiene report..."
|
|
447
525
|
mkdir -p "$REPO_DIR/.claude"
|
|
448
526
|
|
|
527
|
+
# Include platform-hygiene if available (for strategic agent)
|
|
528
|
+
local platform_refactor="{}"
|
|
529
|
+
if [[ -f "$REPO_DIR/.claude/platform-hygiene.json" ]]; then
|
|
530
|
+
platform_refactor=$(jq -c '.' "$REPO_DIR/.claude/platform-hygiene.json" 2>/dev/null || echo "{}")
|
|
531
|
+
fi
|
|
532
|
+
|
|
449
533
|
# Build JSON report
|
|
450
534
|
local report
|
|
451
|
-
report=$(
|
|
535
|
+
report=$(jq -n \
|
|
536
|
+
--arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
537
|
+
--arg repo "$(basename "$REPO_DIR")" \
|
|
538
|
+
--arg ver "$VERSION" \
|
|
539
|
+
--argjson platform "$platform_refactor" \
|
|
540
|
+
'{timestamp:$ts,repository:$repo,version:$ver,sections:{dead_code:{},structure:{},dependencies:{},naming:{},branches:{},size:{}},platform_refactor:$platform}' 2>/dev/null)
|
|
541
|
+
if [[ -z "$report" ]]; then
|
|
542
|
+
report=$(cat <<EOF
|
|
452
543
|
{
|
|
453
|
-
"timestamp": "
|
|
454
|
-
"repository": "
|
|
455
|
-
"version": "VERSION",
|
|
544
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
545
|
+
"repository": "$(basename "$REPO_DIR")",
|
|
546
|
+
"version": "$VERSION",
|
|
456
547
|
"sections": {
|
|
457
548
|
"dead_code": {},
|
|
458
549
|
"structure": {},
|
|
459
550
|
"dependencies": {},
|
|
460
551
|
"naming": {},
|
|
461
552
|
"branches": {},
|
|
462
|
-
"size": {}
|
|
553
|
+
"size": {},
|
|
554
|
+
"platform_refactor": $platform_refactor
|
|
463
555
|
}
|
|
464
556
|
}
|
|
465
557
|
EOF
|
|
466
558
|
)
|
|
467
|
-
|
|
468
|
-
# Replace placeholders
|
|
469
|
-
report="${report//TIMESTAMP/$(date -u +%Y-%m-%dT%H:%M:%SZ)}"
|
|
470
|
-
report="${report//REPO/$(basename "$REPO_DIR")}"
|
|
471
|
-
report="${report//VERSION/$VERSION}"
|
|
559
|
+
fi
|
|
472
560
|
|
|
473
561
|
if [[ $JSON_OUTPUT == true ]]; then
|
|
474
562
|
echo "$report" | jq .
|
|
@@ -489,6 +577,7 @@ run_full_scan() {
|
|
|
489
577
|
check_naming
|
|
490
578
|
list_stale_branches
|
|
491
579
|
analyze_size
|
|
580
|
+
scan_platform_refactor
|
|
492
581
|
|
|
493
582
|
echo -e "${CYAN}${BOLD}╰────────────────────────────────────────────────────────────────╯${RESET}"
|
|
494
583
|
|
|
@@ -532,6 +621,9 @@ main() {
|
|
|
532
621
|
size)
|
|
533
622
|
analyze_size
|
|
534
623
|
;;
|
|
624
|
+
platform-refactor)
|
|
625
|
+
scan_platform_refactor
|
|
626
|
+
;;
|
|
535
627
|
fix)
|
|
536
628
|
if [[ $AUTO_FIX != true ]]; then
|
|
537
629
|
AUTO_FIX=true
|