@erclx/canon 5.25.0 → 5.27.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 +4 -3
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/api-design/SKILL.md +2 -0
- package/claude/skills/auto-ship/SKILL.md +3 -11
- package/claude/skills/auto-ship/references/review-findings.md +20 -0
- package/claude/skills/backlog-triage/SKILL.md +2 -0
- package/claude/skills/bash-cli-script/SKILL.md +2 -0
- package/claude/skills/build-in-slices/SKILL.md +2 -0
- package/claude/skills/canon-cli/SKILL.md +2 -0
- package/claude/skills/canon-feedback/SKILL.md +2 -0
- package/claude/skills/canon-feedback-triage/SKILL.md +2 -0
- package/claude/skills/canon-operator/SKILL.md +2 -0
- package/claude/skills/canon-rollout/SKILL.md +3 -11
- package/claude/skills/canon-rollout/references/failure-recovery.md +20 -0
- package/claude/skills/canvas/SKILL.md +14 -1
- package/claude/skills/ci-workflow/SKILL.md +2 -0
- package/claude/skills/code-craft/SKILL.md +2 -0
- package/claude/skills/codebase-layout/SKILL.md +2 -0
- package/claude/skills/context-fold/REQUIREMENT.md +6 -2
- package/claude/skills/context-fold/SKILL.md +9 -21
- package/claude/skills/context-fold/references/anchor-sweep.md +2 -2
- package/claude/skills/context-fold/references/completion-report.md +26 -0
- package/claude/skills/create-rule/SKILL.md +2 -0
- package/claude/skills/create-skill/SKILL.md +2 -0
- package/claude/skills/create-standard/SKILL.md +2 -0
- package/claude/skills/decision-escalate/SKILL.md +2 -0
- package/claude/skills/deploy-app/SKILL.md +2 -0
- package/claude/skills/deprecation-migration/SKILL.md +2 -0
- package/claude/skills/design-extract/SKILL.md +2 -0
- package/claude/skills/design-taste/REQUIREMENT.md +1 -1
- package/claude/skills/design-taste/SKILL.md +6 -2
- package/claude/skills/design-taste/references/adopted.md +40 -0
- package/claude/skills/design-taste/references/kinds.md +1 -1
- package/claude/skills/design-taste/references/systems.md +1 -7
- package/claude/skills/design-taste/references/tells.md +2 -24
- package/claude/skills/docs-sync/REQUIREMENT.md +2 -1
- package/claude/skills/docs-sync/SKILL.md +2 -0
- package/claude/skills/document-health/REQUIREMENT.md +2 -0
- package/claude/skills/document-health/SKILL.md +23 -0
- package/claude/skills/document-health/references/axes.md +12 -0
- package/claude/skills/draft-and-pick/SKILL.md +3 -1
- package/claude/skills/draft-doc/SKILL.md +2 -0
- package/claude/skills/draft-doc/references/wiki.md +1 -1
- package/claude/skills/draft-figure/SKILL.md +2 -0
- package/claude/skills/draft-identity/SKILL.md +3 -1
- package/claude/skills/draft-ready/SKILL.md +2 -0
- package/claude/skills/draft-screencast/SKILL.md +11 -7
- package/claude/skills/draft-slides/REQUIREMENT.md +17 -12
- package/claude/skills/draft-slides/SKILL.md +33 -20
- package/claude/skills/git-branch/SKILL.md +2 -0
- package/claude/skills/git-commit/SKILL.md +2 -0
- package/claude/skills/git-followup/SKILL.md +2 -0
- package/claude/skills/git-issue/SKILL.md +2 -0
- package/claude/skills/git-issue/references/issue.md +10 -0
- package/claude/skills/git-pr/SKILL.md +2 -0
- package/claude/skills/git-pr/references/evidence.md +14 -6
- package/claude/skills/git-pr/references/labels.md +12 -0
- package/claude/skills/git-ship/SKILL.md +2 -0
- package/claude/skills/git-split/SKILL.md +21 -8
- package/claude/skills/git-stage/SKILL.md +2 -0
- package/claude/skills/git-worktree/SKILL.md +2 -0
- package/claude/skills/index-lookup/SKILL.md +2 -0
- package/claude/skills/markdown-propose/SKILL.md +2 -0
- package/claude/skills/markdown-propose/references/format.md +9 -0
- package/claude/skills/memory-capture/SKILL.md +2 -0
- package/claude/skills/memory-review/SKILL.md +2 -0
- package/claude/skills/memory-review/references/later-phases.md +7 -0
- package/claude/skills/plan-feature/SKILL.md +2 -0
- package/claude/skills/plan-groundwork/SKILL.md +2 -0
- package/claude/skills/plan-intake/SKILL.md +2 -0
- package/claude/skills/plan-intake-answer/SKILL.md +2 -0
- package/claude/skills/project-commands/SKILL.md +2 -0
- package/claude/skills/read-frames/SKILL.md +2 -0
- package/claude/skills/record-screencast/SKILL.md +2 -0
- package/claude/skills/repo-metadata/SKILL.md +2 -0
- package/claude/skills/restate-plainly/SKILL.md +2 -0
- package/claude/skills/review-address/SKILL.md +3 -7
- package/claude/skills/review-address/references/post-review-findings.md +16 -0
- package/claude/skills/review-branch/SKILL.md +2 -0
- package/claude/skills/review-craft/SKILL.md +2 -0
- package/claude/skills/review-craft/references/ui.md +2 -2
- package/claude/skills/review-pr/SKILL.md +4 -8
- package/claude/skills/review-pr/references/body-variants.md +52 -0
- package/claude/skills/review-pr/references/key-changes.md +16 -0
- package/claude/skills/review-pr/references/post.md +15 -43
- package/claude/skills/review-ui/SKILL.md +3 -1
- package/claude/skills/review-ui/references/post.md +4 -2
- package/claude/skills/role-orchestrator/SKILL.md +5 -14
- package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +8 -0
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +13 -0
- package/claude/skills/role-orchestrator/references/orchestrator-handback.md +1 -1
- package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +23 -0
- package/claude/skills/role-orchestrator/references/orchestrator-launch.md +5 -33
- package/claude/skills/role-orchestrator/references/orchestrator-poll.md +1 -21
- package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +1 -1
- package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +38 -0
- package/claude/skills/role-orchestrator/references/orchestrator-watch.md +26 -0
- package/claude/skills/role-planner/SKILL.md +2 -0
- package/claude/skills/role-reviewer/REQUIREMENT.md +1 -1
- package/claude/skills/role-reviewer/SKILL.md +2 -0
- package/claude/skills/role-worker/SKILL.md +2 -0
- package/claude/skills/search-craft/REQUIREMENT.md +1 -1
- package/claude/skills/search-craft/SKILL.md +5 -1
- package/claude/skills/search-craft/references/adopted.md +30 -0
- package/claude/skills/seed-sync/SKILL.md +2 -0
- package/claude/skills/session-compact/SKILL.md +2 -0
- package/claude/skills/session-map/SKILL.md +2 -0
- package/claude/skills/session-relay/SKILL.md +2 -0
- package/claude/skills/session-resume/SKILL.md +2 -0
- package/claude/skills/session-worktree/SKILL.md +3 -11
- package/claude/skills/session-worktree/references/install-command.md +20 -0
- package/claude/skills/sketch-design/SKILL.md +2 -0
- package/claude/skills/systematic-debugging/SKILL.md +2 -0
- package/claude/skills/target-check/SKILL.md +2 -0
- package/claude/skills/target-setup/SKILL.md +2 -0
- package/claude/skills/target-setup/references/detect.md +8 -0
- package/claude/skills/target-setup/references/indexes.md +13 -0
- package/claude/skills/target-setup/references/verify.md +8 -0
- package/claude/skills/task-board/SKILL.md +2 -0
- package/claude/skills/teach-workspace/SKILL.md +5 -15
- package/claude/skills/teach-workspace/references/lesson-build.md +75 -0
- package/claude/skills/teach-workspace/references/lesson-craft.md +13 -69
- package/claude/skills/teach-workspace/references/revisit.md +22 -0
- package/claude/skills/test-craft/SKILL.md +2 -0
- package/claude/skills/test-first/SKILL.md +4 -0
- package/claude/skills/test-first/references/adopted.md +36 -0
- package/claude/skills/ui-checklist/SKILL.md +2 -0
- package/claude/skills/ux-audit/SKILL.md +2 -0
- package/claude/skills/ux-measure/SKILL.md +2 -0
- package/claude/skills/ux-walkthrough/SKILL.md +2 -0
- package/claude/skills/video-craft/SKILL.md +2 -0
- package/claude/skills/write-human/SKILL.md +3 -1
- package/claude/skills/write-human/references/machine-tells.md +13 -0
- package/claude/skills/youtube-transcripts/SKILL.md +2 -0
- package/docs/agents/canvas.md +24 -6
- package/docs/agents/capture.md +6 -6
- package/docs/agents/commands.md +5 -5
- package/docs/agents/index.md +5 -5
- package/docs/agents/install-and-sync.md +7 -0
- package/docs/agents/key-changes.md +1 -1
- package/docs/agents/pr-evidence.md +38 -15
- package/docs/agents/pr-local.md +19 -13
- package/docs/agents/pr-preview.md +44 -21
- package/docs/agents/records-stale.md +22 -9
- package/docs/agents/records.md +1 -1
- package/docs/agents/sandbox.md +29 -5
- package/docs/agents/scripting.md +8 -1
- package/docs/agents/skills-audit.md +11 -3
- package/docs/agents/slides.md +15 -3
- package/docs/workflow/ai-workflow.md +1 -1
- package/docs/workflow/index.md +1 -0
- package/docs/workflow/operating-model.md +5 -6
- package/docs/workflow/parallel-features.md +23 -2
- package/docs/workflow/skill-map-on-request.md +42 -0
- package/docs/workflow/skill-map.md +3 -34
- package/docs/workflow/zshrc-aliases.md +1 -1
- package/package.json +1 -1
- package/scripts/core/regen-hero.ts +1 -1
- package/scripts/lib/sandbox-git.sh +1 -9
- package/scripts/lib/sandbox-path.sh +6 -162
- package/scripts/sandbox-hook.sh +99 -0
- package/src/audits/run.ts +1 -1
- package/src/canvas/address.ts +12 -3
- package/src/canvas/capture.ts +1 -9
- package/src/canvas/client/inspector/align-grid.tsx +162 -0
- package/src/canvas/client/inspector/color-field.tsx +398 -0
- package/src/canvas/client/inspector/color-inputs.tsx +139 -0
- package/src/canvas/client/inspector/color-picker.tsx +668 -0
- package/src/canvas/client/inspector/color-space.ts +240 -0
- package/src/canvas/client/inspector/field.tsx +5 -1
- package/src/canvas/client/inspector/fields.css +547 -17
- package/src/canvas/client/inspector/size-field.tsx +69 -0
- package/src/canvas/client/inspector/values.ts +166 -1
- package/src/canvas/client/inspector.tsx +236 -73
- package/src/canvas/client/selection.tsx +197 -0
- package/src/canvas/client/shell.css +104 -12
- package/src/canvas/client/state.ts +69 -9
- package/src/canvas/client/surface.tsx +147 -22
- package/src/canvas/content.ts +50 -1
- package/src/canvas/edit.ts +37 -4
- package/src/canvas/editing.ts +203 -0
- package/src/canvas/global.d.ts +15 -0
- package/src/canvas/server.ts +149 -12
- package/src/canvas/tokens.ts +59 -17
- package/src/capture/render.ts +45 -7
- package/src/capture/sources.ts +43 -0
- package/src/census/count.ts +2 -2
- package/src/claude/cases/workflow.ts +5 -0
- package/src/claude/seeds.ts +2 -2
- package/src/claude/skills-audit.ts +96 -14
- package/src/claude/skills-drift.ts +1 -1
- package/src/claude/skills-families.ts +36 -0
- package/src/claude/skills-list.ts +76 -15
- package/src/commands/audits.ts +2 -2
- package/src/commands/canvas.ts +179 -2
- package/src/commands/claude.ts +94 -11
- package/src/commands/design.ts +142 -2
- package/src/commands/feedback.ts +3 -3
- package/src/commands/gov.ts +1 -1
- package/src/commands/hooks.ts +1 -1
- package/src/commands/indexes.ts +1 -1
- package/src/commands/init.ts +1 -1
- package/src/commands/intake.ts +1 -1
- package/src/commands/migrate.ts +1 -1
- package/src/commands/pr.ts +105 -58
- package/src/commands/records.ts +89 -7
- package/src/commands/repo.ts +1 -1
- package/src/commands/sandbox.ts +103 -11
- package/src/commands/sessions.ts +1 -1
- package/src/commands/slides.ts +31 -77
- package/src/commands/sync.ts +1 -1
- package/src/commands/tasks.ts +2 -2
- package/src/commands/teach.ts +1 -1
- package/src/commands/transcripts.ts +1 -1
- package/src/commands/worktrees.ts +1 -1
- package/src/comments/scan.ts +1 -1
- package/src/comments/trend.ts +1 -1
- package/src/context/audit.ts +1 -1
- package/src/context/citations.ts +1 -1
- package/src/context/classify/extract.ts +2 -2
- package/src/design/project-fonts.ts +392 -0
- package/src/design/tokens.ts +2 -18
- package/src/docs/read.ts +1 -1
- package/src/{github.ts → feedback/github.ts} +2 -2
- package/src/{client-commands.ts → gate/client-commands.ts} +1 -1
- package/src/gate/measures.ts +53 -13
- package/src/gate/sequencer.ts +1 -1
- package/src/gate/stages.ts +9 -0
- package/src/{git-files.ts → git/files.ts} +2 -2
- package/src/{git-ignore.ts → git/ignore.ts} +1 -1
- package/src/{worktree.ts → git/worktree.ts} +1 -1
- package/src/gov/citations.ts +2 -2
- package/src/gov/install.ts +1 -1
- package/src/gov/payload.ts +1 -1
- package/src/gov/superseded.ts +3 -3
- package/src/gov/test-order.ts +2 -2
- package/src/help.ts +1 -1
- package/src/hooks/post-merge.ts +1 -1
- package/src/indexes/walk.ts +1 -1
- package/src/labels/audit.ts +1 -1
- package/src/markdown/ceiling.ts +1 -1
- package/src/markdown/files.ts +1 -1
- package/src/migrate/apply.ts +1 -1
- package/src/pr/bijection.ts +1 -1
- package/src/pr/evidence.ts +96 -43
- package/src/pr/local.ts +16 -10
- package/src/pr/preview.ts +78 -2
- package/src/record-root.ts +1 -0
- package/src/records/backup.ts +2 -1
- package/src/records/push-guard.ts +1 -1
- package/src/records/stale-canonical.ts +146 -0
- package/src/records/stale.ts +1 -1
- package/src/sandbox/headless/dispatch.ts +264 -0
- package/src/sandbox/headless/run.ts +653 -0
- package/src/sandbox/headless/watch.ts +145 -0
- package/src/sandbox/hooks.ts +128 -0
- package/src/sandbox/provision.ts +607 -0
- package/src/sandbox/tree.ts +99 -4
- package/src/secrets/marker.ts +2 -2
- package/src/secrets/scan.ts +2 -2
- package/src/sessions/claim.ts +1 -1
- package/src/sessions/resolve.ts +1 -1
- package/src/sessions/transfer/bundle.ts +1 -1
- package/src/shipped/references.ts +2 -2
- package/src/slides/convert/export.ts +2 -16
- package/src/slides/decks.ts +110 -0
- package/src/slides/package/fonts.ts +6 -2
- package/src/standards/audit.ts +2 -2
- package/src/standards/read.ts +1 -1
- package/src/sync/check.ts +2 -2
- package/src/sync/engine.ts +2 -2
- package/src/sync/git.ts +1 -1
- package/src/sync/history.ts +1 -1
- package/src/sync/reverse.ts +1 -1
- package/src/sync/seeds-report.ts +1 -1
- package/src/sync/target.ts +1 -1
- package/src/sync/workflow.ts +1 -1
- package/src/targets/pulls.ts +2 -2
- package/src/targets/sweep.ts +2 -2
- package/src/tasks/answers.ts +1 -1
- package/src/tasks/archive.ts +1 -1
- package/src/tasks/reach.ts +1 -1
- package/src/tasks/trunk.ts +1 -1
- package/src/teach/nav.ts +1 -1
- package/src/tooling/inject.ts +2 -2
- package/src/tooling/subfolder.ts +1 -1
- package/src/web/readme-citations.ts +2 -2
- package/src/worktrees/bare-flag.ts +1 -1
- package/src/worktrees/reclaim.ts +2 -2
- package/src/worktrees/remove.ts +1 -1
- package/standards/architecture.md +1 -0
- package/standards/canvas.md +3 -2
- package/standards/requirements.md +2 -0
- package/standards/skill-practice.md +2 -1
- package/standards/skill.md +2 -0
- package/standards/wiki.md +12 -3
- package/tooling/base/configs/.github/workflows/pr-local-preview.yml +2 -2
- package/scripts/lib/sandbox-dispatch.sh +0 -190
- package/scripts/manage-sandbox.sh +0 -472
- package/src/slides/layouts.ts +0 -478
- package/src/slides/parse.ts +0 -84
- package/src/slides/render.ts +0 -110
- package/src/slides/styles.ts +0 -96
- /package/claude/skills/write-human/references/{source-material.md → adopted.md} +0 -0
- /package/src/{commands/feedback-format.ts → feedback/body.ts} +0 -0
- /package/src/{github-format.ts → feedback/github-format.ts} +0 -0
- /package/src/{git-base.ts → git/base.ts} +0 -0
- /package/src/{git-env.ts → git/env.ts} +0 -0
- /package/src/{frontmatter.ts → markdown/frontmatter.ts} +0 -0
- /package/src/{binary.ts → sweep/binary.ts} +0 -0
- /package/src/{exempt-marker.ts → sweep/exempt-marker.ts} +0 -0
- /package/src/{copy.ts → sync/copy.ts} +0 -0
- /package/src/{target.ts → targets/validate.ts} +0 -0
- /package/src/{paths.ts → tasks/paths.ts} +0 -0
- /package/src/{seed-marker.ts → tooling/seed-marker.ts} +0 -0
|
@@ -1,472 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -e
|
|
3
|
-
set -o pipefail
|
|
4
|
-
|
|
5
|
-
SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
|
|
6
|
-
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
7
|
-
export PROJECT_ROOT
|
|
8
|
-
|
|
9
|
-
source "$PROJECT_ROOT/scripts/config.sh"
|
|
10
|
-
source "$PROJECT_ROOT/scripts/lib/ui.sh"
|
|
11
|
-
source "$PROJECT_ROOT/scripts/lib/sandbox-path.sh"
|
|
12
|
-
source "$PROJECT_ROOT/scripts/lib/sandbox-git.sh"
|
|
13
|
-
source "$PROJECT_ROOT/scripts/lib/sandbox-fixtures.sh"
|
|
14
|
-
|
|
15
|
-
# Without this, git falls back to a terminal prompt when no helper supplies a
|
|
16
|
-
# credential, and an unauthenticated run blocks on /dev/tty instead of failing.
|
|
17
|
-
# The harness must never require a TTY.
|
|
18
|
-
export GIT_TERMINAL_PROMPT=0
|
|
19
|
-
|
|
20
|
-
show_help() {
|
|
21
|
-
echo -e "${GREY}┌${NC}"
|
|
22
|
-
echo -e "${GREY}├${NC} ${WHITE}Usage:${NC} canon sandbox [cat:cmd]"
|
|
23
|
-
echo -e "${GREY}│${NC}"
|
|
24
|
-
echo -e "${GREY}│${NC} ${WHITE}Arguments:${NC}"
|
|
25
|
-
echo -e "${GREY}│${NC} cat:cmd ${GREY}# Scenario to provision (e.g. git:commit)${NC}"
|
|
26
|
-
echo -e "${GREY}│${NC}"
|
|
27
|
-
echo -e "${GREY}│${NC} ${WHITE}Commands:${NC}"
|
|
28
|
-
echo -e "${GREY}│${NC} reset ${GREY}# Reset sandbox to baseline${NC}"
|
|
29
|
-
echo -e "${GREY}│${NC} clean ${GREY}# Wipe the sandbox${NC}"
|
|
30
|
-
echo -e "${GREY}│${NC}"
|
|
31
|
-
echo -e "${GREY}│${NC} ${WHITE}Options:${NC}"
|
|
32
|
-
echo -e "${GREY}│${NC} -h, --help ${GREY}# Show this help message${NC}"
|
|
33
|
-
echo -e "${GREY}│${NC}"
|
|
34
|
-
echo -e "${GREY}│${NC} ${WHITE}Examples:${NC}"
|
|
35
|
-
echo -e "${GREY}│${NC} canon sandbox"
|
|
36
|
-
echo -e "${GREY}│${NC} canon sandbox git:commit"
|
|
37
|
-
echo -e "${GREY}│${NC} canon sandbox reset"
|
|
38
|
-
echo -e "${GREY}│${NC} canon sandbox clean"
|
|
39
|
-
echo -e "${GREY}└${NC}"
|
|
40
|
-
exit 0
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
ANCHOR_FIXTURE_DIR="$PROJECT_ROOT/sandbox/fixtures/anchor/create"
|
|
44
|
-
|
|
45
|
-
# Where an anchor scenario's tree comes from and where its remote points are two
|
|
46
|
-
# concerns, and only the remote needs a network. Taking the tree from a fixture
|
|
47
|
-
# stops an arm provisioning from whatever the previous arm force-pushed, which is
|
|
48
|
-
# what made two identical sweeps of the sixteen arms disagree on eleven.
|
|
49
|
-
stage_anchor_tree() {
|
|
50
|
-
# The nine anchor scenarios configure a real remote from their own stage_setup,
|
|
51
|
-
# and sandbox_anchor_url runs inside a command substitution there, where
|
|
52
|
-
# log_error would exit only the subshell and leave an empty remote behind. The
|
|
53
|
-
# guard has to fire here, in the main shell, before any of them run.
|
|
54
|
-
require_sandbox_anchor_config
|
|
55
|
-
|
|
56
|
-
log_step "Staging anchor tree from fixture"
|
|
57
|
-
|
|
58
|
-
assert_fixtures_suffixed "$ANCHOR_FIXTURE_DIR"
|
|
59
|
-
if [ "$(count_fixture_files "$ANCHOR_FIXTURE_DIR")" -eq 0 ]; then
|
|
60
|
-
log_error "Anchor fixture provisions nothing: $ANCHOR_FIXTURE_DIR"
|
|
61
|
-
fi
|
|
62
|
-
|
|
63
|
-
if [ -d "$SANDBOX" ]; then
|
|
64
|
-
rm -rf "$SANDBOX"
|
|
65
|
-
fi
|
|
66
|
-
mkdir -p "$SANDBOX"
|
|
67
|
-
|
|
68
|
-
(
|
|
69
|
-
cd "$SANDBOX"
|
|
70
|
-
create_from_fixtures "$ANCHOR_FIXTURE_DIR"
|
|
71
|
-
git init >/dev/null
|
|
72
|
-
git add .
|
|
73
|
-
git commit -m "feat(sandbox): initial sandbox setup from anchor" --no-verify >/dev/null
|
|
74
|
-
)
|
|
75
|
-
log_info "Anchor tree staged from fixture, remote stays $ANCHOR_REPO"
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
select_sandbox_category() {
|
|
79
|
-
local categories=()
|
|
80
|
-
if ls -d "$SANDBOX_DIR"/*/ >/dev/null 2>&1; then
|
|
81
|
-
# Twin of FIXTURES_DIR in src/commands/sandbox.ts. The exec boundary rules out
|
|
82
|
-
# a shared constant, so a new exclusion has to land on both sides.
|
|
83
|
-
mapfile -t categories < <(find "$SANDBOX_DIR" -mindepth 1 -maxdepth 1 -type d -not -name fixtures -exec basename {} \; | sort)
|
|
84
|
-
fi
|
|
85
|
-
|
|
86
|
-
if [ ${#categories[@]} -eq 0 ]; then
|
|
87
|
-
log_error "No sandbox categories found in $SANDBOX_DIR"
|
|
88
|
-
fi
|
|
89
|
-
|
|
90
|
-
select_option "Select category:" "${categories[@]}"
|
|
91
|
-
_CATEGORY=$SELECTED_OPTION
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
select_sandbox_command() {
|
|
95
|
-
local commands=()
|
|
96
|
-
if ls "$SANDBOX_DIR/$_CATEGORY/"*.sh >/dev/null 2>&1; then
|
|
97
|
-
mapfile -t commands < <(find "$SANDBOX_DIR/$_CATEGORY" -maxdepth 1 -name '*.sh' -exec basename {} .sh \; | sort)
|
|
98
|
-
fi
|
|
99
|
-
|
|
100
|
-
if [ ${#commands[@]} -eq 0 ]; then
|
|
101
|
-
log_error "No sandbox scripts found in $_CATEGORY"
|
|
102
|
-
fi
|
|
103
|
-
|
|
104
|
-
select_option "Select command:" "${commands[@]}"
|
|
105
|
-
_COMMAND=$SELECTED_OPTION
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
prompt_for_category_and_command() {
|
|
109
|
-
select_sandbox_category
|
|
110
|
-
select_sandbox_command
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
parse_command_argument() {
|
|
114
|
-
local input_arg="$1"
|
|
115
|
-
|
|
116
|
-
if [[ "$input_arg" != *":"* ]]; then
|
|
117
|
-
log_error "Invalid format. Use <category>:<command>, 'reset', 'clean', or --help"
|
|
118
|
-
fi
|
|
119
|
-
IFS=':' read -r _CATEGORY _COMMAND <<<"$input_arg"
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
resolve_command_and_category() {
|
|
123
|
-
local input_arg="$1"
|
|
124
|
-
if [ -z "$input_arg" ]; then
|
|
125
|
-
prompt_for_category_and_command
|
|
126
|
-
else
|
|
127
|
-
parse_command_argument "$input_arg"
|
|
128
|
-
fi
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
validate_environment() {
|
|
132
|
-
local current_category="$1"
|
|
133
|
-
local current_command="$2"
|
|
134
|
-
|
|
135
|
-
if [ ! -d "$SANDBOX_DIR" ]; then
|
|
136
|
-
log_error "Sandbox directory not found at: $SANDBOX_DIR"
|
|
137
|
-
fi
|
|
138
|
-
|
|
139
|
-
if [[ "$PWD" == "$SANDBOX" || "$PWD" == "$SANDBOX"/* ]]; then
|
|
140
|
-
log_warn "Detected execution inside the sandbox. Switching to project root..."
|
|
141
|
-
cd "$PROJECT_ROOT" || log_error "Failed to switch to project root."
|
|
142
|
-
fi
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
load_sandbox_script() {
|
|
146
|
-
local current_category="$1"
|
|
147
|
-
local current_command="$2"
|
|
148
|
-
|
|
149
|
-
local sandbox_file="$SANDBOX_DIR/$current_category/$current_command.sh"
|
|
150
|
-
|
|
151
|
-
if [ ! -f "$sandbox_file" ]; then
|
|
152
|
-
log_error "Sandbox script not found: $current_category/$current_command"
|
|
153
|
-
fi
|
|
154
|
-
|
|
155
|
-
# shellcheck source=/dev/null
|
|
156
|
-
source "$sandbox_file"
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
init_empty_sandbox() {
|
|
160
|
-
if [ -d "$SANDBOX" ]; then
|
|
161
|
-
rm -rf "$SANDBOX"
|
|
162
|
-
fi
|
|
163
|
-
mkdir -p "$SANDBOX"
|
|
164
|
-
|
|
165
|
-
cat <<EOF >"$SANDBOX/.gitignore"
|
|
166
|
-
.canon/tmp/
|
|
167
|
-
node_modules
|
|
168
|
-
EOF
|
|
169
|
-
(
|
|
170
|
-
cd "$SANDBOX"
|
|
171
|
-
git init >/dev/null
|
|
172
|
-
git add .gitignore >/dev/null 2>/dev/null
|
|
173
|
-
git commit -m "feat(sandbox): initial empty sandbox setup" --no-verify >/dev/null
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
provision_sandbox() {
|
|
178
|
-
log_step "Provisioning $1:$2"
|
|
179
|
-
|
|
180
|
-
if [[ "$(type -t use_anchor)" == "function" ]]; then
|
|
181
|
-
use_anchor
|
|
182
|
-
stage_anchor_tree
|
|
183
|
-
else
|
|
184
|
-
init_empty_sandbox
|
|
185
|
-
fi
|
|
186
|
-
|
|
187
|
-
# Scoped to the throwaway sandbox repo so the operator's global git config is
|
|
188
|
-
# never written. Covers both the scenario pushes and the ones the agent makes
|
|
189
|
-
# itself once it is running inside the sandbox.
|
|
190
|
-
(cd "$SANDBOX" && configure_sandbox_git_credentials)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
# Runs the real installer rather than copying the source tree. The copies these
|
|
194
|
-
# replaced, for gov rules and for seeds, each reimplemented an installer's
|
|
195
|
-
# selection rules, so a change to what install produces left the sandbox
|
|
196
|
-
# provisioning the old shape and no scenario could observe the difference.
|
|
197
|
-
run_sandbox_install() {
|
|
198
|
-
local label="$1"
|
|
199
|
-
shift
|
|
200
|
-
|
|
201
|
-
local install_log
|
|
202
|
-
install_log="$(mktemp)"
|
|
203
|
-
|
|
204
|
-
# The installer's own frame would bury the provisioning timeline, so it stays
|
|
205
|
-
# captured unless it fails, where it is the only thing naming the cause.
|
|
206
|
-
if ! CANON_NON_INTERACTIVE=1 bun "$PROJECT_ROOT/src/cli.ts" "$@" \
|
|
207
|
-
>/dev/null 2>"$install_log"; then
|
|
208
|
-
cat "$install_log" >&2
|
|
209
|
-
rm -f "$install_log"
|
|
210
|
-
log_error "Could not install $label into the sandbox."
|
|
211
|
-
fi
|
|
212
|
-
|
|
213
|
-
rm -f "$install_log"
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
# The stack decides which rules land. `base` carries the language-agnostic core,
|
|
217
|
-
# which is what a scenario asserting on rule behavior reads. A scenario needing a
|
|
218
|
-
# framework's rules overrides the variable in `use_config`.
|
|
219
|
-
inject_gov_rules() {
|
|
220
|
-
[ ! -d "$PROJECT_ROOT/governance/rules" ] && return
|
|
221
|
-
|
|
222
|
-
run_sandbox_install "gov rules" gov install "${SANDBOX_GOV_STACK:-base}" "$SANDBOX"
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
inject_seeds() {
|
|
226
|
-
[ ! -d "$PROJECT_ROOT/tooling/claude/seeds" ] && return
|
|
227
|
-
|
|
228
|
-
run_sandbox_install "seeds" claude init "$SANDBOX"
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
commit_environment_setup() {
|
|
232
|
-
(
|
|
233
|
-
cd "$SANDBOX"
|
|
234
|
-
git add .
|
|
235
|
-
if ! git diff --cached --quiet; then
|
|
236
|
-
git commit -m "chore(sandbox): initial environment setup" --no-verify >/dev/null
|
|
237
|
-
fi
|
|
238
|
-
)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
# No standards injection. The corpus installs into no target, so a sandbox
|
|
242
|
-
# without one is the shape a scaffolded project has, and a scenario driving a
|
|
243
|
-
# skill that reads a standard exercises the `canon standards <name>` path a real
|
|
244
|
-
# project takes.
|
|
245
|
-
setup_sandbox_assets() {
|
|
246
|
-
[ -n "$SANDBOX_INJECT_SEEDS" ] && inject_seeds
|
|
247
|
-
[ -n "$SANDBOX_INJECT_GOV" ] && inject_gov_rules
|
|
248
|
-
commit_environment_setup
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
initialize_sandbox_environment() {
|
|
252
|
-
local current_category="$1"
|
|
253
|
-
local current_command="$2"
|
|
254
|
-
|
|
255
|
-
load_sandbox_script "$current_category" "$current_command"
|
|
256
|
-
[[ "$(type -t use_config)" == "function" ]] && use_config
|
|
257
|
-
validate_environment "$current_category" "$current_command"
|
|
258
|
-
provision_sandbox "$current_category" "$current_command"
|
|
259
|
-
setup_sandbox_assets
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
commit_sandbox_changes() {
|
|
263
|
-
if [ -z "$SANDBOX_SKIP_AUTO_COMMIT" ]; then
|
|
264
|
-
log_step "Staging environment changes"
|
|
265
|
-
(
|
|
266
|
-
cd "$SANDBOX"
|
|
267
|
-
git add . >/dev/null 2>/dev/null
|
|
268
|
-
git commit -m 'chore(sandbox): apply scenario specific setup' --no-verify >/dev/null
|
|
269
|
-
)
|
|
270
|
-
log_info "Git state clean after setup"
|
|
271
|
-
else
|
|
272
|
-
log_info "Skipping auto-commit"
|
|
273
|
-
fi
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
tag_sandbox_baseline() {
|
|
277
|
-
(
|
|
278
|
-
cd "$SANDBOX"
|
|
279
|
-
git update-ref refs/sandbox/baseline HEAD >/dev/null 2>&1
|
|
280
|
-
git write-tree | xargs -I {} git update-ref refs/sandbox/baseline-index {} >/dev/null 2>&1
|
|
281
|
-
)
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
inject_changed_skills() {
|
|
285
|
-
local base
|
|
286
|
-
base=$(resolve_sandbox_skill_diff_base)
|
|
287
|
-
base="${base:-main}"
|
|
288
|
-
|
|
289
|
-
local changed untracked
|
|
290
|
-
changed=$(git -C "$PROJECT_ROOT" diff "$base" --name-only -- 'claude/skills/**/SKILL.md' 2>/dev/null)
|
|
291
|
-
untracked=$(git -C "$PROJECT_ROOT" ls-files --others --exclude-standard -- 'claude/skills/**/SKILL.md' 2>/dev/null)
|
|
292
|
-
|
|
293
|
-
local combined
|
|
294
|
-
combined=$(printf '%s\n%s\n' "$changed" "$untracked" | awk 'NF && !seen[$0]++')
|
|
295
|
-
|
|
296
|
-
[ -z "$combined" ] && return
|
|
297
|
-
|
|
298
|
-
while IFS= read -r skill_path; do
|
|
299
|
-
# The diff against the base lists a deleted skill alongside a changed one,
|
|
300
|
-
# and there is nothing left to inject for a name this branch removed.
|
|
301
|
-
[ -f "$PROJECT_ROOT/$skill_path" ] || continue
|
|
302
|
-
|
|
303
|
-
local skill_name
|
|
304
|
-
skill_name=$(basename "$(dirname "$skill_path")")
|
|
305
|
-
local target_dir="$SANDBOX/.claude/skills/$skill_name"
|
|
306
|
-
mkdir -p "$target_dir"
|
|
307
|
-
cp "$PROJECT_ROOT/$skill_path" "$target_dir/SKILL.md"
|
|
308
|
-
if [ -n "$SANDBOX_SKIP_AUTO_COMMIT" ]; then
|
|
309
|
-
echo ".claude/skills/$skill_name/SKILL.md" >>"$SANDBOX/.git/info/exclude"
|
|
310
|
-
fi
|
|
311
|
-
log_info "Injected dev skill: $skill_name"
|
|
312
|
-
done <<<"$combined"
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
execute_sandbox_and_commit() {
|
|
316
|
-
pushd "$SANDBOX" >/dev/null
|
|
317
|
-
stage_setup
|
|
318
|
-
popd >/dev/null
|
|
319
|
-
|
|
320
|
-
inject_changed_skills
|
|
321
|
-
commit_sandbox_changes
|
|
322
|
-
tag_sandbox_baseline
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
finalize_sandbox_run() {
|
|
326
|
-
local GREEN RED YELLOW WHITE GREY NC
|
|
327
|
-
set_palette 2
|
|
328
|
-
trap - EXIT
|
|
329
|
-
close_timeline
|
|
330
|
-
echo "" >&2
|
|
331
|
-
echo -e "${GREEN}✓ Sandbox Ready${NC}" >&2
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
cmd_clean() {
|
|
335
|
-
local GREEN RED YELLOW WHITE GREY NC
|
|
336
|
-
set_palette 2
|
|
337
|
-
log_step "Removing sandbox"
|
|
338
|
-
rm -rf "$SANDBOX"
|
|
339
|
-
log_rem "$SANDBOX"
|
|
340
|
-
trap - EXIT
|
|
341
|
-
close_timeline
|
|
342
|
-
echo "" >&2
|
|
343
|
-
echo -e "${GREEN}✓ Sandbox clean${NC}" >&2
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
reset_sandbox() {
|
|
347
|
-
local GREEN RED YELLOW WHITE GREY NC
|
|
348
|
-
set_palette 2
|
|
349
|
-
if [ ! -d "$SANDBOX/.git" ]; then
|
|
350
|
-
log_error "No sandbox found. Run \`canon sandbox\` first."
|
|
351
|
-
fi
|
|
352
|
-
|
|
353
|
-
log_step "Sandbox state"
|
|
354
|
-
|
|
355
|
-
local has_baseline=0
|
|
356
|
-
(cd "$SANDBOX" && git rev-parse refs/sandbox/baseline >/dev/null 2>&1) && has_baseline=1
|
|
357
|
-
|
|
358
|
-
if [ "$has_baseline" -eq 0 ]; then
|
|
359
|
-
log_error "No baseline found. Re-provision with \`canon sandbox <cat>:<cmd>\`."
|
|
360
|
-
fi
|
|
361
|
-
|
|
362
|
-
local is_dirty=0
|
|
363
|
-
(
|
|
364
|
-
cd "$SANDBOX"
|
|
365
|
-
if [ "$(git rev-parse HEAD)" != "$(git rev-parse refs/sandbox/baseline)" ]; then
|
|
366
|
-
exit 1
|
|
367
|
-
fi
|
|
368
|
-
local current_index baseline_index
|
|
369
|
-
current_index=$(git write-tree)
|
|
370
|
-
baseline_index=$(git rev-parse refs/sandbox/baseline-index 2>/dev/null || echo "")
|
|
371
|
-
if [ -n "$baseline_index" ] && [ "$current_index" != "$baseline_index" ]; then
|
|
372
|
-
exit 1
|
|
373
|
-
fi
|
|
374
|
-
if ! git diff --quiet 2>/dev/null; then
|
|
375
|
-
exit 1
|
|
376
|
-
fi
|
|
377
|
-
if [ -n "$(git ls-files --others --exclude-standard 2>/dev/null)" ]; then
|
|
378
|
-
exit 1
|
|
379
|
-
fi
|
|
380
|
-
) || is_dirty=1
|
|
381
|
-
|
|
382
|
-
if [ "$is_dirty" -eq 0 ]; then
|
|
383
|
-
log_info "At baseline"
|
|
384
|
-
trap - EXIT
|
|
385
|
-
close_timeline
|
|
386
|
-
echo "" >&2
|
|
387
|
-
echo -e "${GREEN}✓ Sandbox at baseline${NC}" >&2
|
|
388
|
-
exit 0
|
|
389
|
-
fi
|
|
390
|
-
|
|
391
|
-
log_warn "Uncommitted changes detected"
|
|
392
|
-
|
|
393
|
-
select_option "Reset sandbox to initial state?" "Yes" "No"
|
|
394
|
-
if [ "$SELECTED_OPTION" == "No" ]; then
|
|
395
|
-
log_warn "Reset cancelled"
|
|
396
|
-
exit 0
|
|
397
|
-
fi
|
|
398
|
-
|
|
399
|
-
log_step "Resetting sandbox"
|
|
400
|
-
(
|
|
401
|
-
cd "$SANDBOX"
|
|
402
|
-
git reset --hard refs/sandbox/baseline --quiet
|
|
403
|
-
git clean -fd --quiet
|
|
404
|
-
local baseline_index
|
|
405
|
-
baseline_index=$(git rev-parse refs/sandbox/baseline-index 2>/dev/null || echo "")
|
|
406
|
-
if [ -n "$baseline_index" ] && [ "$baseline_index" != "$(git write-tree)" ]; then
|
|
407
|
-
git read-tree "$baseline_index"
|
|
408
|
-
git checkout-index -a -f
|
|
409
|
-
fi
|
|
410
|
-
)
|
|
411
|
-
log_info "Sandbox reset to baseline"
|
|
412
|
-
|
|
413
|
-
trap - EXIT
|
|
414
|
-
close_timeline
|
|
415
|
-
echo "" >&2
|
|
416
|
-
echo -e "${GREEN}✓ Sandbox reset complete${NC}" >&2
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
main() {
|
|
420
|
-
local no_header=0
|
|
421
|
-
if [[ "$1" == "--no-header" ]]; then
|
|
422
|
-
no_header=1
|
|
423
|
-
shift
|
|
424
|
-
fi
|
|
425
|
-
|
|
426
|
-
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
|
|
427
|
-
show_help
|
|
428
|
-
fi
|
|
429
|
-
|
|
430
|
-
if [[ "$no_header" -eq 0 ]]; then
|
|
431
|
-
open_timeline "canon sandbox"
|
|
432
|
-
fi
|
|
433
|
-
trap close_timeline EXIT
|
|
434
|
-
|
|
435
|
-
if [[ "$PWD" != "$PROJECT_ROOT"* ]]; then
|
|
436
|
-
log_error "Context error: you must run this command from inside the toolkit repository."
|
|
437
|
-
fi
|
|
438
|
-
|
|
439
|
-
SANDBOX="$(resolve_sandbox_dir)"
|
|
440
|
-
SANDBOX_DIR="$PROJECT_ROOT/sandbox"
|
|
441
|
-
|
|
442
|
-
local unsafe
|
|
443
|
-
if ! unsafe="$(assert_sandbox_dir_safe "$SANDBOX" "$PROJECT_ROOT")"; then
|
|
444
|
-
log_error "$unsafe"
|
|
445
|
-
fi
|
|
446
|
-
|
|
447
|
-
if [[ "$1" == "reset" ]]; then
|
|
448
|
-
reset_sandbox
|
|
449
|
-
exit 0
|
|
450
|
-
fi
|
|
451
|
-
|
|
452
|
-
if [[ "$1" == "clean" ]]; then
|
|
453
|
-
cmd_clean
|
|
454
|
-
exit 0
|
|
455
|
-
fi
|
|
456
|
-
|
|
457
|
-
resolve_command_and_category "$1"
|
|
458
|
-
local category="$_CATEGORY"
|
|
459
|
-
local command="$_COMMAND"
|
|
460
|
-
|
|
461
|
-
if [ -n "${2:-}" ]; then
|
|
462
|
-
export SANDBOX_SCENARIO="$2"
|
|
463
|
-
export CANON_NON_INTERACTIVE="1"
|
|
464
|
-
fi
|
|
465
|
-
|
|
466
|
-
initialize_sandbox_environment "$category" "$command"
|
|
467
|
-
execute_sandbox_and_commit
|
|
468
|
-
|
|
469
|
-
finalize_sandbox_run
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
main "$@"
|