@erclx/aitk 0.8.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/LICENSE +21 -0
- package/README.md +99 -0
- package/claude/.claude-plugin/plugin.json +19 -0
- package/claude/skills/bash-script/SKILL.md +96 -0
- package/claude/skills/bash-script/references/patterns.md +349 -0
- package/claude/skills/ci-workflow/SKILL.md +52 -0
- package/claude/skills/ci-workflow/references/workflows.md +74 -0
- package/claude/skills/claude-address-review/SKILL.md +107 -0
- package/claude/skills/claude-autoship/SKILL.md +137 -0
- package/claude/skills/claude-design-extract/SKILL.md +69 -0
- package/claude/skills/claude-design-propose/SKILL.md +75 -0
- package/claude/skills/claude-diagram/SKILL.md +126 -0
- package/claude/skills/claude-docs/SKILL.md +204 -0
- package/claude/skills/claude-feature/REQUIREMENT.md +35 -0
- package/claude/skills/claude-feature/SKILL.md +148 -0
- package/claude/skills/claude-groundwork/SKILL.md +148 -0
- package/claude/skills/claude-groundwork/references/folder-format.md +107 -0
- package/claude/skills/claude-memory-capture/SKILL.md +80 -0
- package/claude/skills/claude-memory-review/REQUIREMENT.md +37 -0
- package/claude/skills/claude-memory-review/SKILL.md +206 -0
- package/claude/skills/claude-orchestrate/SKILL.md +125 -0
- package/claude/skills/claude-pr-review/SKILL.md +150 -0
- package/claude/skills/claude-review/SKILL.md +136 -0
- package/claude/skills/claude-roadmap/SKILL.md +61 -0
- package/claude/skills/claude-roadmap/references/roadmap.md +52 -0
- package/claude/skills/claude-screencast/SKILL.md +160 -0
- package/claude/skills/claude-seed-sync/SKILL.md +141 -0
- package/claude/skills/claude-slides-draft/SKILL.md +62 -0
- package/claude/skills/claude-standards-audit/REQUIREMENT.md +33 -0
- package/claude/skills/claude-standards-audit/SKILL.md +79 -0
- package/claude/skills/claude-standards-audit/references/branch.md +49 -0
- package/claude/skills/claude-standards-audit/references/pr.md +124 -0
- package/claude/skills/claude-tasks/SKILL.md +123 -0
- package/claude/skills/claude-ui-test/SKILL.md +75 -0
- package/claude/skills/claude-ux-audit/SKILL.md +78 -0
- package/claude/skills/claude-worktree/SKILL.md +79 -0
- package/claude/skills/cli-script/SKILL.md +47 -0
- package/claude/skills/cli-script/references/template.md +43 -0
- package/claude/skills/create-rule/SKILL.md +68 -0
- package/claude/skills/create-skill/REQUIREMENT.md +30 -0
- package/claude/skills/create-skill/SKILL.md +24 -0
- package/claude/skills/create-snippet/SKILL.md +28 -0
- package/claude/skills/create-snippet/references/snippets.md +57 -0
- package/claude/skills/create-standard/SKILL.md +31 -0
- package/claude/skills/create-standard/references/standard.md +52 -0
- package/claude/skills/docs-sync/SKILL.md +87 -0
- package/claude/skills/git-branch/REQUIREMENT.md +38 -0
- package/claude/skills/git-branch/SKILL.md +60 -0
- package/claude/skills/git-branch/references/branch.md +49 -0
- package/claude/skills/git-commit/REQUIREMENT.md +33 -0
- package/claude/skills/git-commit/SKILL.md +51 -0
- package/claude/skills/git-commit/references/commit.md +63 -0
- package/claude/skills/git-followup/REQUIREMENT.md +38 -0
- package/claude/skills/git-followup/SKILL.md +35 -0
- package/claude/skills/git-issue/REQUIREMENT.md +38 -0
- package/claude/skills/git-issue/SKILL.md +69 -0
- package/claude/skills/git-issue/references/issue.md +84 -0
- package/claude/skills/git-pr/REQUIREMENT.md +37 -0
- package/claude/skills/git-pr/SKILL.md +119 -0
- package/claude/skills/git-pr/references/branch.md +49 -0
- package/claude/skills/git-pr/references/pr.md +124 -0
- package/claude/skills/git-ship/REQUIREMENT.md +34 -0
- package/claude/skills/git-ship/SKILL.md +39 -0
- package/claude/skills/git-split/REQUIREMENT.md +38 -0
- package/claude/skills/git-split/SKILL.md +160 -0
- package/claude/skills/git-split/references/branch.md +49 -0
- package/claude/skills/git-split/references/pr.md +124 -0
- package/claude/skills/git-stage/REQUIREMENT.md +36 -0
- package/claude/skills/git-stage/SKILL.md +74 -0
- package/claude/skills/git-stage/references/commit.md +63 -0
- package/claude/skills/git-worktree/REQUIREMENT.md +37 -0
- package/claude/skills/git-worktree/SKILL.md +120 -0
- package/claude/skills/migration-claude-md/SKILL.md +74 -0
- package/claude/skills/migration-context/SKILL.md +93 -0
- package/claude/skills/migration-standards/SKILL.md +75 -0
- package/claude/skills/project-commands/SKILL.md +73 -0
- package/claude/skills/session-resume/SKILL.md +36 -0
- package/claude/skills/setup-gov/SKILL.md +71 -0
- package/claude/skills/setup-indexes/SKILL.md +148 -0
- package/claude/skills/setup-init/SKILL.md +114 -0
- package/claude/skills/setup-plugins/SKILL.md +81 -0
- package/claude/skills/setup-plugins/references/plugin-catalog.md +53 -0
- package/claude/skills/setup-verify/SKILL.md +51 -0
- package/claude/skills/systematic-debugging/SKILL.md +70 -0
- package/claude/skills/toolkit-cli/SKILL.md +38 -0
- package/claude/skills/toolkit-feedback/SKILL.md +80 -0
- package/claude/skills/toolkit-operator/SKILL.md +45 -0
- package/claude/skills/toolkit-triage/SKILL.md +63 -0
- package/claude/skills/youtube-transcripts/SKILL.md +34 -0
- package/docs/agents.md +371 -0
- package/docs/ai-workflow.md +157 -0
- package/docs/index.md +20 -0
- package/docs/operating-model.md +106 -0
- package/docs/target-projects.md +183 -0
- package/docs/visual-design-workflow.md +136 -0
- package/docs/zshrc-aliases.md +65 -0
- package/governance/rules/claude/500-prose.md +12 -0
- package/governance/rules/claude/510-context.md +16 -0
- package/governance/rules/claude/520-wireframes.md +12 -0
- package/governance/rules/claude/530-requirements.md +11 -0
- package/governance/rules/claude/540-architecture.md +11 -0
- package/governance/rules/claude/550-design.md +11 -0
- package/governance/rules/claude/555-tasks.md +12 -0
- package/governance/rules/claude/560-diagrams.md +11 -0
- package/governance/rules/claude/570-skill.md +18 -0
- package/governance/rules/claude/580-readme.md +11 -0
- package/governance/rules/claude/590-rule-authoring.md +12 -0
- package/governance/rules/core/000-constitution.md +30 -0
- package/governance/rules/core/010-testing.md +35 -0
- package/governance/rules/core/020-concurrency.md +22 -0
- package/governance/rules/core/030-error-handling.md +31 -0
- package/governance/rules/core/040-performance.md +20 -0
- package/governance/rules/core/050-logging.md +20 -0
- package/governance/rules/core/060-naming.md +19 -0
- package/governance/rules/core/070-planning.md +13 -0
- package/governance/rules/core/080-config-comments.md +22 -0
- package/governance/rules/framework/200-react.md +51 -0
- package/governance/rules/framework/210-astro.md +41 -0
- package/governance/rules/framework/220-fastapi.md +43 -0
- package/governance/rules/framework/230-nextjs.md +48 -0
- package/governance/rules/framework/250-tailwind.md +32 -0
- package/governance/rules/framework/260-shadcn.md +34 -0
- package/governance/rules/lang/100-typescript.md +40 -0
- package/governance/rules/lang/110-python.md +42 -0
- package/governance/rules/lib/300-testing-ts.md +38 -0
- package/governance/rules/lib/310-zod.md +25 -0
- package/governance/rules/lib/320-tanstack-query.md +32 -0
- package/governance/rules/lib/330-testing-py.md +44 -0
- package/governance/rules/lib/340-pydantic.md +38 -0
- package/governance/rules/lib/350-security-web.md +31 -0
- package/governance/rules/ui/400-ui.md +34 -0
- package/governance/rules/ui/410-a11y.md +44 -0
- package/governance/rules/ui/420-forms.md +34 -0
- package/governance/rules/ui/430-ux-completeness.md +62 -0
- package/governance/stacks/astro.toml +2 -0
- package/governance/stacks/base.toml +2 -0
- package/governance/stacks/node.toml +2 -0
- package/governance/stacks/python-fastapi.toml +2 -0
- package/governance/stacks/python.toml +2 -0
- package/governance/stacks/react.toml +2 -0
- package/package.json +67 -0
- package/scripts/config.sh +11 -0
- package/scripts/core/bootstrap.sh +81 -0
- package/scripts/core/check-plugin-boundary.sh +45 -0
- package/scripts/core/check-skill-paths.sh +25 -0
- package/scripts/core/clean.sh +36 -0
- package/scripts/core/install-check.sh +93 -0
- package/scripts/core/regen-claude-copies.sh +26 -0
- package/scripts/core/regen-indexes.sh +10 -0
- package/scripts/core/regen-skill-references.sh +27 -0
- package/scripts/core/snapshot.sh +132 -0
- package/scripts/core/update.sh +35 -0
- package/scripts/core/verify.sh +201 -0
- package/scripts/docs/list.sh +129 -0
- package/scripts/gov/list.sh +234 -0
- package/scripts/lib/frontmatter.sh +30 -0
- package/scripts/lib/gov.sh +14 -0
- package/scripts/lib/sandbox-fixtures.sh +109 -0
- package/scripts/lib/sandbox-git.sh +73 -0
- package/scripts/lib/tooling.sh +24 -0
- package/scripts/lib/ui.sh +173 -0
- package/scripts/lib/worktree.sh +20 -0
- package/scripts/manage-sandbox.sh +453 -0
- package/scripts/snippets/create.sh +156 -0
- package/scripts/standards/list.sh +91 -0
- package/scripts/tooling/create.sh +109 -0
- package/scripts/tooling/ref.sh +141 -0
- package/scripts/tooling/verify.sh +179 -0
- package/snippets/claude/decision-memo.md +39 -0
- package/snippets/claude/feature-recap.md +19 -0
- package/snippets/claude/figma-steps.md +18 -0
- package/snippets/claude/orchestrator-resume.md +23 -0
- package/snippets/claude/orchestrator-sweep.md +10 -0
- package/snippets/compact-summary.md +5 -0
- package/snippets/create-snippet.md +7 -0
- package/snippets/decision-help.md +6 -0
- package/snippets/meta-prompt.md +14 -0
- package/snippets/research-prompt.md +7 -0
- package/snippets/session-notes.md +11 -0
- package/snippets/snippets.toml +6 -0
- package/snippets/step-by-step.md +10 -0
- package/snippets/web-research.md +21 -0
- package/src/claude/gitignore.ts +51 -0
- package/src/claude/seeds-list.ts +47 -0
- package/src/claude/seeds.ts +124 -0
- package/src/claude/settings.ts +151 -0
- package/src/cli-run.ts +43 -0
- package/src/cli.ts +111 -0
- package/src/commands/claude.ts +349 -0
- package/src/commands/design.ts +39 -0
- package/src/commands/docs.ts +59 -0
- package/src/commands/feedback-format.ts +23 -0
- package/src/commands/feedback.ts +103 -0
- package/src/commands/gov.ts +268 -0
- package/src/commands/indexes.ts +182 -0
- package/src/commands/init.ts +117 -0
- package/src/commands/pass-through.ts +39 -0
- package/src/commands/sandbox.ts +315 -0
- package/src/commands/slides.ts +106 -0
- package/src/commands/snippets.ts +236 -0
- package/src/commands/standards.ts +89 -0
- package/src/commands/sync.ts +211 -0
- package/src/commands/tasks.ts +185 -0
- package/src/commands/tooling.ts +432 -0
- package/src/commands/transcripts.ts +48 -0
- package/src/commands/wiki.ts +101 -0
- package/src/copy.ts +30 -0
- package/src/design/parse.ts +79 -0
- package/src/design/render.ts +170 -0
- package/src/docs/read.ts +59 -0
- package/src/exec.ts +17 -0
- package/src/frontmatter.ts +13 -0
- package/src/github-format.ts +13 -0
- package/src/github.ts +20 -0
- package/src/gov/adapter.ts +73 -0
- package/src/gov/install.ts +103 -0
- package/src/gov/payload.ts +39 -0
- package/src/gov/stacks.ts +124 -0
- package/src/indexes/frontmatter.ts +46 -0
- package/src/indexes/regen.ts +84 -0
- package/src/indexes/render.ts +181 -0
- package/src/indexes/walk.ts +111 -0
- package/src/init/flags.ts +66 -0
- package/src/init/plan.ts +128 -0
- package/src/init/run.ts +46 -0
- package/src/init/steps.ts +91 -0
- package/src/sandbox/coverage.ts +115 -0
- package/src/sandbox/expect.ts +412 -0
- package/src/slides/layouts.ts +391 -0
- package/src/slides/open.ts +18 -0
- package/src/slides/parse.ts +84 -0
- package/src/slides/render.ts +88 -0
- package/src/slides/styles.ts +44 -0
- package/src/snippets/adapter.ts +34 -0
- package/src/snippets/categories.ts +59 -0
- package/src/snippets/install.ts +125 -0
- package/src/snippets/list.ts +32 -0
- package/src/snippets/presets.ts +50 -0
- package/src/standards/adapter.ts +51 -0
- package/src/standards/index-refresh.ts +44 -0
- package/src/standards/install.ts +52 -0
- package/src/sync/check.ts +269 -0
- package/src/sync/engine.ts +416 -0
- package/src/sync/git.ts +204 -0
- package/src/sync/stamp.ts +202 -0
- package/src/sync/target.ts +79 -0
- package/src/sync/workflow.ts +201 -0
- package/src/target.ts +43 -0
- package/src/tasks/archive.ts +304 -0
- package/src/tooling/gitignore.ts +122 -0
- package/src/tooling/inject.ts +214 -0
- package/src/tooling/list.ts +39 -0
- package/src/tooling/manifest.ts +178 -0
- package/src/tooling/package.ts +166 -0
- package/src/tooling/scan.ts +186 -0
- package/src/transcripts/fetch.ts +156 -0
- package/src/transcripts/metadata.ts +54 -0
- package/src/transcripts/vtt.ts +114 -0
- package/src/ui.ts +187 -0
- package/src/wiki/init.ts +85 -0
- package/standards/architecture.md +41 -0
- package/standards/bundled/branch.md +49 -0
- package/standards/bundled/commit.md +63 -0
- package/standards/bundled/issue.md +84 -0
- package/standards/bundled/pr.md +124 -0
- package/standards/bundled/roadmap.md +52 -0
- package/standards/bundled/snippets.md +57 -0
- package/standards/bundled/standard.md +52 -0
- package/standards/context.md +132 -0
- package/standards/design.md +31 -0
- package/standards/diagrams.md +55 -0
- package/standards/index.md +21 -0
- package/standards/prose.md +122 -0
- package/standards/readme.md +163 -0
- package/standards/requirements.md +61 -0
- package/standards/rule.md +79 -0
- package/standards/skill.md +257 -0
- package/standards/tasks.md +140 -0
- package/standards/versioning.md +47 -0
- package/standards/wireframes.md +67 -0
- package/tooling/astro/configs/astro.config.mjs +17 -0
- package/tooling/astro/configs/eslint.config.js +79 -0
- package/tooling/astro/configs/playwright.config.ts +25 -0
- package/tooling/astro/configs/tsconfig.json +12 -0
- package/tooling/astro/configs/vitest.config.ts +22 -0
- package/tooling/astro/manifest.toml +32 -0
- package/tooling/astro/reference.md +60 -0
- package/tooling/base/configs/.editorconfig +5 -0
- package/tooling/base/configs/.github/pull_request_template.md +18 -0
- package/tooling/base/configs/.github/workflows/verify.yml +35 -0
- package/tooling/base/configs/.husky/commit-msg +1 -0
- package/tooling/base/configs/.husky/post-merge +61 -0
- package/tooling/base/configs/.husky/post-rewrite +21 -0
- package/tooling/base/configs/.husky/pre-commit +1 -0
- package/tooling/base/configs/.husky/pre-push +1 -0
- package/tooling/base/configs/.prettierrc +12 -0
- package/tooling/base/configs/.shellcheckrc +1 -0
- package/tooling/base/configs/.vscode/extensions.json +9 -0
- package/tooling/base/configs/.vscode/settings.json +3 -0
- package/tooling/base/configs/commitlint.config.js +11 -0
- package/tooling/base/configs/scripts/clean.sh +45 -0
- package/tooling/base/configs/scripts/update.sh +49 -0
- package/tooling/base/configs/scripts/verify.sh +64 -0
- package/tooling/base/manifest.toml +32 -0
- package/tooling/base/reference.md +114 -0
- package/tooling/base/seeds/.claude/context/ci.md +27 -0
- package/tooling/base/seeds/.claude/context/development.md +32 -0
- package/tooling/base/seeds/.cspell/project-terms.txt +0 -0
- package/tooling/base/seeds/.cspell/tech-stack.txt +19 -0
- package/tooling/base/seeds/.lintstagedrc +8 -0
- package/tooling/base/seeds/.prettierignore +0 -0
- package/tooling/base/seeds/cspell.json +20 -0
- package/tooling/claude/manifest.toml +11 -0
- package/tooling/claude/reference.md +62 -0
- package/tooling/claude/seeds/.claude/ARCHITECTURE.md +13 -0
- package/tooling/claude/seeds/.claude/DESIGN.md +62 -0
- package/tooling/claude/seeds/.claude/REQUIREMENTS.md +18 -0
- package/tooling/claude/seeds/.claude/context/index.md +8 -0
- package/tooling/claude/seeds/.claude/hooks/index-reminder.sh +43 -0
- package/tooling/claude/seeds/.claude/hooks/scratch-guard.sh +45 -0
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +61 -0
- package/tooling/claude/seeds/.claude/hooks/tasks-index.sh +60 -0
- package/tooling/claude/seeds/.claude/settings.json +39 -0
- package/tooling/claude/seeds/.claude/tasks/index.md +8 -0
- package/tooling/claude/seeds/.claude/wireframes/index.md +8 -0
- package/tooling/claude/seeds/CLAUDE.md +87 -0
- package/tooling/claude/user/settings.template.json +10 -0
- package/tooling/claude/user/statusline-command.sh +53 -0
- package/tooling/python/configs/.coveragerc +14 -0
- package/tooling/python/configs/.python-version +1 -0
- package/tooling/python/configs/mypy.ini +6 -0
- package/tooling/python/configs/pytest.ini +4 -0
- package/tooling/python/configs/ruff.toml +15 -0
- package/tooling/python/configs/scripts/verify.sh +77 -0
- package/tooling/python/manifest.toml +16 -0
- package/tooling/python/reference.md +66 -0
- package/tooling/python/seeds/.cspell/tech-stack.txt +19 -0
- package/tooling/python/seeds/tests/test_smoke.py +2 -0
- package/tooling/vite-react/configs/playwright.config.ts +25 -0
- package/tooling/vite-react/configs/tsconfig.json +35 -0
- package/tooling/vite-react/configs/vite.config.ts +14 -0
- package/tooling/vite-react/configs/vitest.config.ts +26 -0
- package/tooling/vite-react/manifest.toml +21 -0
- package/tooling/vite-react/reference.md +55 -0
- package/tooling/vite-react/seeds/.cspell/project-terms.txt +1 -0
- package/tooling/vite-react/seeds/.cspell/tech-stack.txt +1 -0
- package/tooling/web/configs/.github/workflows/verify.yml +134 -0
- package/tooling/web/configs/.vscode/extensions.json +13 -0
- package/tooling/web/configs/.vscode/settings.json +10 -0
- package/tooling/web/configs/e2e/home.spec.ts +6 -0
- package/tooling/web/configs/e2e/screenshot.ts +41 -0
- package/tooling/web/configs/eslint.config.js +82 -0
- package/tooling/web/configs/scripts/screenshot.sh +28 -0
- package/tooling/web/configs/scripts/verify.sh +80 -0
- package/tooling/web/configs/src/test/setup.ts +8 -0
- package/tooling/web/manifest.toml +57 -0
- package/tooling/web/reference.md +95 -0
- package/tooling/web/seeds/.cspell/tech-stack.txt +18 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Fixture files carry this suffix so the repository's own checks ignore them.
|
|
4
|
+
# A stored `index.md.fixture` is not an `index.md`, so the index walker, prettier,
|
|
5
|
+
# shfmt, and shellcheck all skip it and the bytes reach the sandbox unmodified.
|
|
6
|
+
FIXTURE_SUFFIX=".fixture"
|
|
7
|
+
|
|
8
|
+
# The tree mirrors the scenario path, so `category` and `scenario` together match
|
|
9
|
+
# `scripts/sandbox/<category>/<scenario>.sh`. Both segments are load-bearing:
|
|
10
|
+
# four scenario basenames repeat across categories (`claude`, `docs`, `review`,
|
|
11
|
+
# `sync`), and `docs` is also a category of its own.
|
|
12
|
+
fixture_stage_dir() {
|
|
13
|
+
local category="$1"
|
|
14
|
+
local scenario="$2"
|
|
15
|
+
local arm="$3"
|
|
16
|
+
local stage="$4"
|
|
17
|
+
echo "$PROJECT_ROOT/scripts/sandbox/fixtures/$category/$scenario/$arm/$stage"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
list_fixture_files() {
|
|
21
|
+
local source_dir="$1"
|
|
22
|
+
find "$source_dir" -type f -name "*$FIXTURE_SUFFIX" -print0 | sort -z
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
count_fixture_files() {
|
|
26
|
+
local source_dir="$1"
|
|
27
|
+
if [ ! -d "$source_dir" ]; then
|
|
28
|
+
echo 0
|
|
29
|
+
return 0
|
|
30
|
+
fi
|
|
31
|
+
find "$source_dir" -type f -name "*$FIXTURE_SUFFIX" | wc -l
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# The copy loops match on the suffix, so a file without one would be skipped in
|
|
35
|
+
# silence and the scenario would provision a tree it was never meant to have.
|
|
36
|
+
assert_fixtures_suffixed() {
|
|
37
|
+
local source_dir="$1"
|
|
38
|
+
[ -d "$source_dir" ] || return 0
|
|
39
|
+
|
|
40
|
+
local stray
|
|
41
|
+
stray="$(find "$source_dir" -type f -not -name "*$FIXTURE_SUFFIX" | sort | tr '\n' ' ')"
|
|
42
|
+
[ -z "$stray" ] || log_error "Fixture missing the $FIXTURE_SUFFIX suffix: $stray"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
fixture_target_path() {
|
|
46
|
+
local source_dir="$1"
|
|
47
|
+
local source_file="$2"
|
|
48
|
+
local relative="${source_file#"$source_dir"/}"
|
|
49
|
+
echo "${relative%"$FIXTURE_SUFFIX"}"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
create_from_fixtures() {
|
|
53
|
+
local source_dir="$1"
|
|
54
|
+
[ -d "$source_dir" ] || return 0
|
|
55
|
+
|
|
56
|
+
local source_file target
|
|
57
|
+
while IFS= read -r -d '' source_file; do
|
|
58
|
+
target="$(fixture_target_path "$source_dir" "$source_file")"
|
|
59
|
+
mkdir -p "$(dirname "$target")"
|
|
60
|
+
cp "$source_file" "$target"
|
|
61
|
+
done < <(list_fixture_files "$source_dir")
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# An append fixture extends a file the anchor or the injected seeds already
|
|
65
|
+
# provide. A missing target means that upstream shape changed, so fail rather
|
|
66
|
+
# than create the file and silently alter what the scenario provisions.
|
|
67
|
+
append_from_fixtures() {
|
|
68
|
+
local source_dir="$1"
|
|
69
|
+
[ -d "$source_dir" ] || return 0
|
|
70
|
+
|
|
71
|
+
local source_file target
|
|
72
|
+
while IFS= read -r -d '' source_file; do
|
|
73
|
+
target="$(fixture_target_path "$source_dir" "$source_file")"
|
|
74
|
+
if [ ! -f "$target" ]; then
|
|
75
|
+
log_error "Append fixture has no target: $target"
|
|
76
|
+
fi
|
|
77
|
+
cat "$source_file" >>"$target"
|
|
78
|
+
done < <(list_fixture_files "$source_dir")
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# Stages one step of a scenario arm into the sandbox working directory.
|
|
82
|
+
# Scenarios call this once per step so their own git operations stay between
|
|
83
|
+
# the steps, where they are visible.
|
|
84
|
+
stage_fixtures() {
|
|
85
|
+
local category="$1"
|
|
86
|
+
local scenario="$2"
|
|
87
|
+
local arm="$3"
|
|
88
|
+
local stage="$4"
|
|
89
|
+
|
|
90
|
+
local stage_dir
|
|
91
|
+
stage_dir="$(fixture_stage_dir "$category" "$scenario" "$arm" "$stage")"
|
|
92
|
+
|
|
93
|
+
if [ ! -d "$stage_dir" ]; then
|
|
94
|
+
log_error "Fixture stage not found: $category/$scenario/$arm/$stage"
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
assert_fixtures_suffixed "$stage_dir/create"
|
|
98
|
+
assert_fixtures_suffixed "$stage_dir/append"
|
|
99
|
+
|
|
100
|
+
local staged
|
|
101
|
+
staged=$(($(count_fixture_files "$stage_dir/create") + \
|
|
102
|
+
$(count_fixture_files "$stage_dir/append")))
|
|
103
|
+
if [ "$staged" -eq 0 ]; then
|
|
104
|
+
log_error "Fixture stage provisions nothing: $category/$scenario/$arm/$stage"
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
create_from_fixtures "$stage_dir/create"
|
|
108
|
+
append_from_fixtures "$stage_dir/append"
|
|
109
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# The sandbox reaches GitHub over HTTPS with the gh token so a headless run needs
|
|
4
|
+
# no SSH key and no agent. `gh auth login` authenticates the CLI but leaves git
|
|
5
|
+
# itself without a credential, so the harness supplies the helper rather than
|
|
6
|
+
# assuming the machine carries one.
|
|
7
|
+
SANDBOX_GIT_CREDENTIAL_HELPER='!gh auth git-credential'
|
|
8
|
+
|
|
9
|
+
# Call from the main shell before any scenario runs. sandbox_anchor_url is used
|
|
10
|
+
# inside command substitutions, where log_error would exit only the subshell and
|
|
11
|
+
# leave the caller building an empty remote, so the run has to stop here instead.
|
|
12
|
+
require_sandbox_anchor_config() {
|
|
13
|
+
if [ -z "${GITHUB_ORG:-}" ]; then
|
|
14
|
+
log_error "GITHUB_ORG is empty. Export GITHUB_ORG=<org>, or run from a clone whose remote.origin.url points at GitHub."
|
|
15
|
+
fi
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
sandbox_anchor_url() {
|
|
19
|
+
local repo_name="${1:-${ANCHOR_REPO:-}}"
|
|
20
|
+
|
|
21
|
+
if [ -z "$repo_name" ] || [ -z "${GITHUB_ORG:-}" ]; then
|
|
22
|
+
log_error "sandbox_anchor_url needs GITHUB_ORG and a repository name. Call require_sandbox_anchor_config first."
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
printf 'https://github.com/%s/%s.git\n' "$GITHUB_ORG" "$repo_name"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# credential.helper is multi-valued and git concatenates it across system, global,
|
|
29
|
+
# and local, trying each in order until one returns a credential. A plain set
|
|
30
|
+
# leaves an operator's existing helper ahead of this one, so a stale token wins
|
|
31
|
+
# and gh never runs. The empty value resets the inherited list first.
|
|
32
|
+
configure_sandbox_git_credentials() {
|
|
33
|
+
git config credential.helper ""
|
|
34
|
+
git config --add credential.helper "$SANDBOX_GIT_CREDENTIAL_HELPER"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
resolve_sandbox_git_identity() {
|
|
38
|
+
SANDBOX_GIT_NAME="${SANDBOX_GIT_NAME:-$(git config --global user.name 2>/dev/null || true)}"
|
|
39
|
+
SANDBOX_GIT_EMAIL="${SANDBOX_GIT_EMAIL:-$(git config --global user.email 2>/dev/null || true)}"
|
|
40
|
+
|
|
41
|
+
: "${SANDBOX_GIT_NAME:=aitk-sandbox}"
|
|
42
|
+
: "${SANDBOX_GIT_EMAIL:=sandbox@example.com}"
|
|
43
|
+
|
|
44
|
+
export SANDBOX_GIT_NAME SANDBOX_GIT_EMAIL
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
configure_sandbox_git_identity() {
|
|
48
|
+
resolve_sandbox_git_identity
|
|
49
|
+
git config user.name "$SANDBOX_GIT_NAME"
|
|
50
|
+
git config user.email "$SANDBOX_GIT_EMAIL"
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Every scenario that needs a remote points at the same throwaway repository, so
|
|
54
|
+
# the name lives here rather than in each one.
|
|
55
|
+
SANDBOX_ANCHOR_REPO="toolkit-sandbox"
|
|
56
|
+
|
|
57
|
+
# A scenario calls this from its own use_anchor hook rather than this file
|
|
58
|
+
# defining the hook. manage-sandbox.sh keys off `type -t use_anchor`, so
|
|
59
|
+
# declaring it here would hand an anchor to the scenarios that source this file
|
|
60
|
+
# for the identity helpers alone.
|
|
61
|
+
use_sandbox_anchor() {
|
|
62
|
+
export ANCHOR_REPO="${1:-$SANDBOX_ANCHOR_REPO}"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# A remote is useless without an author, so the scenarios that reach one always
|
|
66
|
+
# configure both. configure_sandbox_git_identity stays callable on its own for
|
|
67
|
+
# the scenarios that never push. The remove keeps this idempotent against a
|
|
68
|
+
# sandbox tree that already carries an origin.
|
|
69
|
+
configure_sandbox_anchor_remote() {
|
|
70
|
+
configure_sandbox_git_identity
|
|
71
|
+
git remote remove origin 2>/dev/null || true
|
|
72
|
+
git remote add origin "$(sandbox_anchor_url "$@")"
|
|
73
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
TOOLING_STACK_EXCLUDE=("claude")
|
|
4
|
+
|
|
5
|
+
is_tooling_stack_excluded() {
|
|
6
|
+
local name="$1"
|
|
7
|
+
local excluded
|
|
8
|
+
for excluded in "${TOOLING_STACK_EXCLUDE[@]}"; do
|
|
9
|
+
if [ "$name" = "$excluded" ]; then
|
|
10
|
+
return 0
|
|
11
|
+
fi
|
|
12
|
+
done
|
|
13
|
+
return 1
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
list_tooling_stacks() {
|
|
17
|
+
local tooling_dir="${1:-$PROJECT_ROOT/tooling}"
|
|
18
|
+
local name
|
|
19
|
+
while IFS= read -r entry; do
|
|
20
|
+
name=$(basename "$entry")
|
|
21
|
+
is_tooling_stack_excluded "$name" && continue
|
|
22
|
+
echo "$name"
|
|
23
|
+
done < <(find "$tooling_dir" -mindepth 1 -maxdepth 1 -type d | sort)
|
|
24
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
if [ "${BASH_VERSINFO[0]:-0}" -lt 4 ]; then
|
|
4
|
+
echo "aitk requires bash 4 or newer. Current: ${BASH_VERSION:-unknown}." >&2
|
|
5
|
+
echo "Install via Homebrew: brew install bash" >&2
|
|
6
|
+
exit 1
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
GREEN='\033[0;32m'
|
|
10
|
+
RED='\033[0;31m'
|
|
11
|
+
YELLOW='\033[0;33m'
|
|
12
|
+
WHITE='\033[1;37m'
|
|
13
|
+
GREY='\033[0;90m'
|
|
14
|
+
NC='\033[0m'
|
|
15
|
+
|
|
16
|
+
log_info() { echo -e "${GREY}│${NC} ${GREEN}✓${NC} $1" >&2; }
|
|
17
|
+
log_warn() { echo -e "${GREY}│${NC} ${YELLOW}!${NC} $1" >&2; }
|
|
18
|
+
log_error() {
|
|
19
|
+
echo -e "${GREY}│${NC} ${RED}✗${NC} $1" >&2
|
|
20
|
+
exit 1
|
|
21
|
+
}
|
|
22
|
+
log_step() { echo -e "${GREY}│${NC}\n${GREY}├${NC} ${WHITE}$1${NC}" >&2; }
|
|
23
|
+
log_add() { echo -e "${GREY}│${NC} ${GREEN}+${NC} $1" >&2; }
|
|
24
|
+
log_rem() { echo -e "${GREY}│${NC} ${RED}-${NC} $1" >&2; }
|
|
25
|
+
|
|
26
|
+
pipe_output() { while IFS= read -r line; do echo -e "${GREY}│${NC} $line" >&2; done; }
|
|
27
|
+
|
|
28
|
+
open_timeline() {
|
|
29
|
+
echo -e "${GREY}┌${NC}" >&2
|
|
30
|
+
if [ -n "${1:-}" ]; then
|
|
31
|
+
echo -e "${GREY}│${NC} ${WHITE}$1${NC}" >&2
|
|
32
|
+
fi
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
close_timeline() {
|
|
36
|
+
echo -e "${GREY}└${NC}" >&2
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
guard_root() {
|
|
40
|
+
local target="$1"
|
|
41
|
+
local target_abs
|
|
42
|
+
target_abs=$(cd "$target" && pwd)
|
|
43
|
+
if [ "$target_abs" = "$PROJECT_ROOT" ]; then
|
|
44
|
+
log_error "Cannot run against toolkit root. Files here are the source of truth."
|
|
45
|
+
fi
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
require_project_root() {
|
|
49
|
+
if [[ "$PWD" == *".sandbox"* ]]; then
|
|
50
|
+
echo -e "${GREY}┌${NC}" >&2
|
|
51
|
+
log_error "Execution restricted: Command cannot be run from inside the sandbox environment."
|
|
52
|
+
fi
|
|
53
|
+
if [[ "$PWD" != "$PROJECT_ROOT"* ]]; then
|
|
54
|
+
echo -e "${GREY}┌${NC}" >&2
|
|
55
|
+
log_error "Context Error: You must run this command from inside the repository."
|
|
56
|
+
fi
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
ask() {
|
|
60
|
+
local prompt_text=$1
|
|
61
|
+
local var_name=$2
|
|
62
|
+
local default_val=$3
|
|
63
|
+
local input=""
|
|
64
|
+
local char
|
|
65
|
+
local display_default=""
|
|
66
|
+
if [ -n "$default_val" ]; then
|
|
67
|
+
display_default=" (${default_val})"
|
|
68
|
+
fi
|
|
69
|
+
if [[ "${AITK_NON_INTERACTIVE:-}" == "1" ]]; then
|
|
70
|
+
echo -e "${GREY}│${NC}" >&2
|
|
71
|
+
echo -e "${GREY}◇${NC} ${prompt_text} ${WHITE}${default_val}${NC}" >&2
|
|
72
|
+
export "$var_name"="$default_val"
|
|
73
|
+
return
|
|
74
|
+
fi
|
|
75
|
+
echo -e "${GREY}│${NC}" >&2
|
|
76
|
+
echo -ne "${GREEN}◆${NC} ${prompt_text}${display_default} " >&2
|
|
77
|
+
while IFS= read -r -s -n1 char; do
|
|
78
|
+
if [[ $char == $'\x1b' ]]; then
|
|
79
|
+
read -rsn2 -t 0.001 _ || true
|
|
80
|
+
echo -ne "\r\033[K" >&2
|
|
81
|
+
echo -e "${GREY}◇${NC} ${prompt_text} ${RED}Cancelled${NC}" >&2
|
|
82
|
+
exit 1
|
|
83
|
+
elif [[ $char == $'\x7f' || $char == $'\x08' ]]; then
|
|
84
|
+
if [ -n "$input" ]; then
|
|
85
|
+
input="${input%?}"
|
|
86
|
+
echo -ne "\b \b" >&2
|
|
87
|
+
fi
|
|
88
|
+
elif [[ -z "$char" ]]; then
|
|
89
|
+
break
|
|
90
|
+
else
|
|
91
|
+
input+="$char"
|
|
92
|
+
echo -n "$char" >&2
|
|
93
|
+
fi
|
|
94
|
+
done
|
|
95
|
+
[ -z "$input" ] && input="$default_val"
|
|
96
|
+
echo -ne "\r\033[K" >&2
|
|
97
|
+
echo -e "${GREY}◇${NC} ${prompt_text} ${WHITE}${input}${NC}" >&2
|
|
98
|
+
export "$var_name"="$input"
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
select_or_route_scenario() {
|
|
102
|
+
local prompt_text=$1
|
|
103
|
+
shift
|
|
104
|
+
local options=("$@")
|
|
105
|
+
|
|
106
|
+
if [ -n "${SANDBOX_SCENARIO:-}" ]; then
|
|
107
|
+
echo -e "${GREY}│${NC}" >&2
|
|
108
|
+
echo -e "${GREY}◇${NC} ${prompt_text} ${WHITE}${SANDBOX_SCENARIO}${NC}" >&2
|
|
109
|
+
export SELECTED_OPTION="$SANDBOX_SCENARIO"
|
|
110
|
+
return
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
select_option "$prompt_text" "${options[@]}"
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
select_option() {
|
|
117
|
+
local prompt_text=$1
|
|
118
|
+
shift
|
|
119
|
+
local options=("$@")
|
|
120
|
+
local cur=0
|
|
121
|
+
local count=${#options[@]}
|
|
122
|
+
|
|
123
|
+
if [[ "${AITK_NON_INTERACTIVE:-}" == "1" ]]; then
|
|
124
|
+
echo -e "${GREY}│${NC}" >&2
|
|
125
|
+
echo -e "${GREY}◇${NC} ${prompt_text} ${WHITE}${options[0]}${NC}" >&2
|
|
126
|
+
export SELECTED_OPTION="${options[0]}"
|
|
127
|
+
return
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
if [ ! -t 0 ]; then
|
|
131
|
+
log_error "${prompt_text} requires a TTY. Pass an argument or set AITK_NON_INTERACTIVE=1."
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
echo -e "${GREY}│${NC}" >&2
|
|
135
|
+
echo -ne "${GREEN}◆${NC} ${prompt_text}\n" >&2
|
|
136
|
+
|
|
137
|
+
while true; do
|
|
138
|
+
for i in "${!options[@]}"; do
|
|
139
|
+
if [ "$i" -eq "$cur" ]; then
|
|
140
|
+
echo -e "${GREY}│${NC} ${GREEN}❯ ${options[$i]}${NC}" >&2
|
|
141
|
+
else
|
|
142
|
+
echo -e "${GREY}│${NC} ${GREY}${options[$i]}${NC}" >&2
|
|
143
|
+
fi
|
|
144
|
+
done
|
|
145
|
+
|
|
146
|
+
read -rsn1 key
|
|
147
|
+
case "$key" in
|
|
148
|
+
$'\x1b')
|
|
149
|
+
if read -rsn2 -t 0.001 key_seq; then
|
|
150
|
+
if [[ "$key_seq" == "[A" ]]; then cur=$(((cur - 1 + count) % count)); fi
|
|
151
|
+
if [[ "$key_seq" == "[B" ]]; then cur=$(((cur + 1) % count)); fi
|
|
152
|
+
else
|
|
153
|
+
echo -ne "\033[$((count + 1))A\033[J" >&2
|
|
154
|
+
echo -e "${GREY}◇${NC} ${prompt_text} ${RED}Cancelled${NC}" >&2
|
|
155
|
+
exit 1
|
|
156
|
+
fi
|
|
157
|
+
;;
|
|
158
|
+
"k") cur=$(((cur - 1 + count) % count)) ;;
|
|
159
|
+
"j") cur=$(((cur + 1) % count)) ;;
|
|
160
|
+
"q")
|
|
161
|
+
echo -ne "\033[$((count + 1))A\033[J" >&2
|
|
162
|
+
echo -e "${GREY}◇${NC} ${prompt_text} ${RED}Cancelled${NC}" >&2
|
|
163
|
+
exit 1
|
|
164
|
+
;;
|
|
165
|
+
"") break ;;
|
|
166
|
+
esac
|
|
167
|
+
echo -ne "\033[${count}A" >&2
|
|
168
|
+
done
|
|
169
|
+
|
|
170
|
+
echo -ne "\033[$((count + 1))A\033[J" >&2
|
|
171
|
+
echo -e "${GREY}◇${NC} ${prompt_text} ${WHITE}${options[$cur]}${NC}" >&2
|
|
172
|
+
export SELECTED_OPTION="${options[$cur]}"
|
|
173
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Claude Code's worktree entry writes core.bare into the parent repository's
|
|
4
|
+
# shared config and its exit never restores it, stranding every later command in
|
|
5
|
+
# the main worktree. Sourced by verify.sh, which runs the repair before any stage
|
|
6
|
+
# because the flag breaks the git reads that scope the run.
|
|
7
|
+
|
|
8
|
+
repair_bare_flag() {
|
|
9
|
+
local root="${1:-$PROJECT_ROOT}"
|
|
10
|
+
local common_dir
|
|
11
|
+
[ "$(git -C "$root" config --get core.bare 2>/dev/null || echo false)" = true ] || return 0
|
|
12
|
+
|
|
13
|
+
common_dir=$(git -C "$root" rev-parse --path-format=absolute --git-common-dir 2>/dev/null) || return 0
|
|
14
|
+
# A genuinely bare repository keeps its objects at the root and has no .git
|
|
15
|
+
# directory, so it fails this test and keeps its flag.
|
|
16
|
+
[ "$(basename "$common_dir")" = ".git" ] || return 0
|
|
17
|
+
|
|
18
|
+
git -C "$root" config core.bare false
|
|
19
|
+
log_warn "Repaired core.bare, which worktree entry left set. Recovery is 'git config core.bare false'."
|
|
20
|
+
}
|