@jeiemgi/cckit 0.1.6
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-plugin/plugin.json +22 -0
- package/AGENTS.md +101 -0
- package/LICENSE-APACHE +202 -0
- package/LICENSE-MIT +21 -0
- package/README.md +143 -0
- package/SECURITY.md +22 -0
- package/bin/cckit +215 -0
- package/cckit.config.json +34 -0
- package/commands/kit-add.md +42 -0
- package/commands/kit-docs.md +45 -0
- package/commands/kit-doctor.md +52 -0
- package/commands/kit-export-project.md +58 -0
- package/commands/kit-export-training.md +49 -0
- package/commands/kit-init.md +126 -0
- package/commands/kit-routines.md +59 -0
- package/commands/kit-update.md +132 -0
- package/docs/kit-annotate/01-explainer.html +225 -0
- package/docs/kit-annotate/02-implementation-plan.html +196 -0
- package/docs/media/.onboarding-capture.cast +5 -0
- package/docs/media/README.md +43 -0
- package/docs/media/build-demo.sh +63 -0
- package/docs/media/build-kit-init.sh +51 -0
- package/docs/media/build-onboarding.sh +51 -0
- package/docs/media/kit-dry-run.cast +107 -0
- package/docs/media/kit-dry-run.gif +0 -0
- package/docs/media/kit-init.cast +56 -0
- package/docs/media/kit-init.gif +0 -0
- package/docs/media/kit-onboarding.cast +148 -0
- package/docs/media/kit-onboarding.gif +0 -0
- package/githooks/pre-commit +18 -0
- package/kit.config.schema.json +105 -0
- package/package.json +54 -0
- package/privacy-denylist.example +8 -0
- package/profiles/automation.json +36 -0
- package/profiles/content.json +41 -0
- package/profiles/minimal.json +31 -0
- package/profiles/research.json +37 -0
- package/profiles/software.json +32 -0
- package/scripts/annotate-setup.sh +149 -0
- package/scripts/autopilot.sh +50 -0
- package/scripts/capture-project-ids.sh +53 -0
- package/scripts/check.sh +66 -0
- package/scripts/contribute.sh +48 -0
- package/scripts/debug.sh +54 -0
- package/scripts/init-upgrade-test.sh +99 -0
- package/scripts/init.sh +827 -0
- package/scripts/install.sh +24 -0
- package/scripts/kit-add-test.sh +62 -0
- package/scripts/kit-add.sh +115 -0
- package/scripts/kit-adopt-test.sh +61 -0
- package/scripts/kit-adopt.sh +122 -0
- package/scripts/kit-bump-version.sh +79 -0
- package/scripts/kit-digest.sh +126 -0
- package/scripts/kit-doctor.sh +663 -0
- package/scripts/kit-export-project-test.sh +82 -0
- package/scripts/kit-export-project.sh +245 -0
- package/scripts/kit-export-training-test.sh +51 -0
- package/scripts/kit-export-training.sh +175 -0
- package/scripts/kit-migrate-test.sh +80 -0
- package/scripts/kit-migrate.sh +190 -0
- package/scripts/kit-onboard-test.sh +63 -0
- package/scripts/kit-onboard.sh +69 -0
- package/scripts/kit-promote-test.sh +54 -0
- package/scripts/kit-promote.sh +102 -0
- package/scripts/kit-remove-test.sh +61 -0
- package/scripts/kit-remove.sh +84 -0
- package/scripts/kit-routines.sh +322 -0
- package/scripts/kit-version-check.sh +91 -0
- package/scripts/kit-wire-test.sh +54 -0
- package/scripts/kit-wire.sh +132 -0
- package/scripts/knowledge-lint.sh +96 -0
- package/scripts/lib/cckit-output.sh +36 -0
- package/scripts/lib/effort-metrics.sh +452 -0
- package/scripts/lib/effort-ops-test.sh +83 -0
- package/scripts/lib/effort-ops.sh +132 -0
- package/scripts/lib/effort-plan.sh +104 -0
- package/scripts/lib/effort.sh +191 -0
- package/scripts/lib/engine-adapter.sh +92 -0
- package/scripts/lib/gh-log.sh +58 -0
- package/scripts/lib/gh-project.sh +212 -0
- package/scripts/lib/handoff.sh +35 -0
- package/scripts/lib/kit-cli-test.sh +42 -0
- package/scripts/lib/kit-cli.sh +32 -0
- package/scripts/lib/kit-config-resolve.sh +145 -0
- package/scripts/lib/kit-config.sh +88 -0
- package/scripts/lib/kit-engine-test.sh +107 -0
- package/scripts/lib/kit-events.sh +62 -0
- package/scripts/lib/kit-gc.sh +117 -0
- package/scripts/lib/kit-interview-test.sh +77 -0
- package/scripts/lib/kit-interview.sh +203 -0
- package/scripts/lib/kit-local.sh +79 -0
- package/scripts/lib/kit-manifest.sh +127 -0
- package/scripts/lib/kit-mode-test.sh +49 -0
- package/scripts/lib/kit-mode.sh +67 -0
- package/scripts/lib/kit-operate.sh +105 -0
- package/scripts/lib/kit-profile-test.sh +62 -0
- package/scripts/lib/kit-profile.sh +115 -0
- package/scripts/lib/kit-task-ops-test.sh +63 -0
- package/scripts/lib/kit-task-ops.sh +341 -0
- package/scripts/lib/pr-evidence.sh +173 -0
- package/scripts/lib/project-scan.sh +16 -0
- package/scripts/lib/react-detect.sh +78 -0
- package/scripts/lib/role-identity.sh +47 -0
- package/scripts/lib/secret-guard.sh +96 -0
- package/scripts/lib/toon.sh +35 -0
- package/scripts/lib/ui.sh +42 -0
- package/scripts/lib/version-bump.sh +59 -0
- package/scripts/lib/worktree-issue-test.sh +45 -0
- package/scripts/lib/worktree-issue.sh +73 -0
- package/scripts/lib/worktree-start.sh +280 -0
- package/scripts/orchestrate.sh +160 -0
- package/scripts/portable-test.sh +53 -0
- package/scripts/publish.sh +94 -0
- package/scripts/setup-labels.sh +25 -0
- package/scripts/setup-milestones.sh +17 -0
- package/scripts/showcase.sh +64 -0
- package/scripts/status.sh +44 -0
- package/scripts/task-sync.sh +59 -0
- package/scripts/test.sh +48 -0
- package/scripts/web-install.sh +22 -0
- package/skills/kit-annotate/SKILL.md +107 -0
- package/skills/kit-autopilot/SKILL.md +108 -0
- package/skills/kit-contribute/SKILL.md +134 -0
- package/skills/kit-customize/SKILL.md +134 -0
- package/skills/kit-dev/SKILL.md +67 -0
- package/skills/kit-digest/SKILL.md +41 -0
- package/skills/kit-effort-close/SKILL.md +156 -0
- package/skills/kit-effort-new/SKILL.md +173 -0
- package/skills/kit-effort-pr/SKILL.md +139 -0
- package/skills/kit-effort-start/SKILL.md +85 -0
- package/skills/kit-gc/SKILL.md +80 -0
- package/skills/kit-onboard/SKILL.md +50 -0
- package/skills/kit-security-sweep/SKILL.md +57 -0
- package/skills/kit-ship/SKILL.md +43 -0
- package/skills/kit-task-close/SKILL.md +66 -0
- package/skills/kit-task-new/SKILL.md +51 -0
- package/skills/kit-task-pr/SKILL.md +43 -0
- package/skills/kit-task-pr-auto/SKILL.md +27 -0
- package/skills/kit-task-pr-merge/SKILL.md +53 -0
- package/skills/kit-task-start/SKILL.md +76 -0
- package/skills/kit-task-sync/SKILL.md +37 -0
- package/templates/CLAUDE.md.tmpl +106 -0
- package/templates/agents/analyst.md +55 -0
- package/templates/agents/auto-dev.md +93 -0
- package/templates/agents/backend.md +59 -0
- package/templates/agents/designer.md +73 -0
- package/templates/agents/devops.md +57 -0
- package/templates/agents/editor.md +48 -0
- package/templates/agents/frontend.md +81 -0
- package/templates/agents/generalist.md +46 -0
- package/templates/agents/local-delegate.md +70 -0
- package/templates/agents/n8n.md +65 -0
- package/templates/agents/pm.md +69 -0
- package/templates/agents/qa.md +66 -0
- package/templates/agents/researcher.md +57 -0
- package/templates/agents/security.md +65 -0
- package/templates/agents/tech-lead.md +75 -0
- package/templates/hooks/guard-base-branch-commit.sh.tmpl +45 -0
- package/templates/hooks/kit-local-status.sh.tmpl +34 -0
- package/templates/hooks/kit_version_check.sh.tmpl +6 -0
- package/templates/hooks/mempal_followup.sh.tmpl +97 -0
- package/templates/hooks/mempal_precompact.sh.tmpl +4 -0
- package/templates/hooks/mempal_save.sh.tmpl +4 -0
- package/templates/hooks/mempal_session_start.sh.tmpl +8 -0
- package/templates/hooks/prepush_gate.sh.tmpl +36 -0
- package/templates/hooks/repo-hygiene.sh.tmpl +72 -0
- package/templates/kit.config.json.tmpl +32 -0
- package/templates/knowledge-INDEX.md.tmpl +12 -0
- package/templates/lib/kit-sigil.sh.tmpl +124 -0
- package/templates/rules/branch-naming.md +104 -0
- package/templates/rules/communication-style.md +22 -0
- package/templates/rules/delegation-brief.md +40 -0
- package/templates/rules/design-routing.md +35 -0
- package/templates/rules/effort-model.md +122 -0
- package/templates/rules/knowledge-base.md +41 -0
- package/templates/rules/mempalace.md +110 -0
- package/templates/rules/plan-output-format.md +58 -0
- package/templates/rules/react-annotate.md +69 -0
- package/templates/rules/risk-tiered-review.md +62 -0
- package/templates/rules/skill-gaps.md +48 -0
- package/templates/rules/task-management.md +42 -0
- package/templates/settings/settings.local.json.tmpl +27 -0
- package/templates/skills/NAMESPACED +13 -0
- package/templates/skills/copywriting/SKILL.md +252 -0
- package/templates/skills/copywriting/references/copy-frameworks.md +344 -0
- package/templates/skills/copywriting/references/natural-transitions.md +272 -0
- package/templates/skills/feature-build-refine/SKILL.md +367 -0
- package/templates/skills/karpathy-guidelines/SKILL.md +69 -0
- package/templates/skills/morning-briefing/SKILL.md +46 -0
- package/templates/skills/speckit/SKILL.md +239 -0
- package/templates/skills/supabase-patterns/SKILL.md +88 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# autopilot.sh - unattended multi-flow driver. A THIN wrapper over orchestrate.sh: pick the issues
|
|
3
|
+
# to run (explicit args, or auto-select the unblocked open issues from the board), then orchestrate
|
|
4
|
+
# them under a concurrency cap, detached, with no human present.
|
|
5
|
+
#
|
|
6
|
+
# This is the SCRIPT half of autopilot - it launches the flows. The "captain" half (decide, review,
|
|
7
|
+
# merge each PR, continue to the next wave) is the driving agent's job, not this script's.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# cckit autopilot # auto-select unblocked open issues from the board
|
|
11
|
+
# cckit autopilot 6 7 8 # drive exactly these issues
|
|
12
|
+
# cckit autopilot --cap 3 # cap concurrent flows (passed through to orchestrate)
|
|
13
|
+
# cckit autopilot --agent codex # drive a different agent CLI
|
|
14
|
+
# cckit autopilot --dry-run # print the plan, launch nothing
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
PASS=() # flags forwarded to orchestrate
|
|
18
|
+
ISSUES=()
|
|
19
|
+
while [ "$#" -gt 0 ]; do
|
|
20
|
+
case "$1" in
|
|
21
|
+
--cap|--agent) PASS+=("$1" "$2"); shift 2 ;;
|
|
22
|
+
--cap=*|--agent=*|--dry-run|--no-seed|--force|--session=*) PASS+=("$1"); shift ;;
|
|
23
|
+
-h|--help) sed -n '2,17p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
|
24
|
+
[0-9]*) ISSUES+=("$1"); shift ;;
|
|
25
|
+
*) echo "autopilot: unknown arg '$1'" >&2; exit 2 ;;
|
|
26
|
+
esac
|
|
27
|
+
done
|
|
28
|
+
|
|
29
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
30
|
+
ROOT="$(git -C "$SCRIPT_DIR" worktree list --porcelain | awk '/^worktree /{print $2; exit}')"
|
|
31
|
+
[ -n "$ROOT" ] || { echo "autopilot: not in a git repo" >&2; exit 1; }
|
|
32
|
+
|
|
33
|
+
# No explicit issues -> auto-select from the board: open issues, minus effort PARENTS (the
|
|
34
|
+
# "[Effort] N ..." umbrella issues that decompose into subs, identified by label:effort OR the
|
|
35
|
+
# title convention) and minus anything blocked_by an open issue. orchestrate re-checks the
|
|
36
|
+
# blocked_by gate at launch; this is the coarse pre-filter so the board drives the wave.
|
|
37
|
+
if [ "${#ISSUES[@]}" -eq 0 ]; then
|
|
38
|
+
echo "autopilot: no issues passed - auto-selecting unblocked open issues from the board"
|
|
39
|
+
board="$(bash "$ROOT/scripts/task-sync.sh" --llm)"
|
|
40
|
+
while IFS= read -r n; do
|
|
41
|
+
[ -n "$n" ] && ISSUES+=("$n")
|
|
42
|
+
done < <(printf '%s' "$board" | jq -r '
|
|
43
|
+
.[]
|
|
44
|
+
| select((any(.labels[]; . == "effort")) or (.title | test("^\\[Effort\\] ")) | not)
|
|
45
|
+
| .number')
|
|
46
|
+
[ "${#ISSUES[@]}" -ge 1 ] || { echo "autopilot: nothing open to drive" >&2; exit 0; }
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
echo "autopilot: driving ${#ISSUES[@]} issue(s) -> orchestrate (detached): ${ISSUES[*]}"
|
|
50
|
+
exec bash "$ROOT/scripts/orchestrate.sh" --detach "${PASS[@]+"${PASS[@]}"}" "${ISSUES[@]}"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Capture Projects v2 field + option IDs into scripts/.project-ids.env.
|
|
3
|
+
# Reads owner + project number from .claude/kit.config.json. Run from project root.
|
|
4
|
+
# Handles "Status", "Role", and "Plan Link" fields by name (case-insensitive).
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
source "$(dirname "$0")/lib/kit-config.sh" && load_kit_config
|
|
7
|
+
|
|
8
|
+
[[ "$KIT_PROJECTS_V2" != "true" ]] && { echo "Projects v2 not enabled for this project — nothing to capture."; exit 0; }
|
|
9
|
+
|
|
10
|
+
OUT="$(dirname "$0")/.project-ids.env"
|
|
11
|
+
|
|
12
|
+
DATA=$(gh api graphql -f query='
|
|
13
|
+
query($login:String!, $number:Int!){
|
|
14
|
+
user(login:$login){
|
|
15
|
+
projectV2(number:$number){
|
|
16
|
+
id
|
|
17
|
+
fields(first:50){ nodes{
|
|
18
|
+
__typename
|
|
19
|
+
... on ProjectV2FieldCommon { id name }
|
|
20
|
+
... on ProjectV2SingleSelectField { id name options { id name } }
|
|
21
|
+
}}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}' -f login="$KIT_OWNER" -F number="$KIT_PROJECT_NUMBER")
|
|
25
|
+
|
|
26
|
+
PROJECT_ID=$(echo "$DATA" | jq -r '.data.user.projectV2.id')
|
|
27
|
+
[[ -z "$PROJECT_ID" || "$PROJECT_ID" == "null" ]] && { echo "✗ Could not resolve project #$KIT_PROJECT_NUMBER for $KIT_OWNER"; exit 1; }
|
|
28
|
+
|
|
29
|
+
# jq filter: normalize an option/field label -> UPPER_SNAKE
|
|
30
|
+
norm='def n: ascii_upcase | gsub("[ -]";"_");'
|
|
31
|
+
|
|
32
|
+
{
|
|
33
|
+
echo "# Generated by capture-project-ids.sh — do not edit by hand."
|
|
34
|
+
echo "PROJECT_ID=$PROJECT_ID"
|
|
35
|
+
|
|
36
|
+
# Single-select fields -> <FIELD>_FIELD_ID + <FIELD>_OPT_<OPTION>
|
|
37
|
+
echo "$DATA" | jq -r "$norm"'
|
|
38
|
+
.data.user.projectV2.fields.nodes[]
|
|
39
|
+
| select(.options != null)
|
|
40
|
+
| (.name | n) as $f
|
|
41
|
+
| ([ "\($f)_FIELD_ID=\(.id)" ]
|
|
42
|
+
+ (.options[] | "\($f)_OPT_\(.name | n)=\(.id)" | [.])) []'
|
|
43
|
+
|
|
44
|
+
# Text/other fields -> <FIELD>_FIELD_ID
|
|
45
|
+
echo "$DATA" | jq -r "$norm"'
|
|
46
|
+
.data.user.projectV2.fields.nodes[]
|
|
47
|
+
| select(.options == null) | select(.name != null)
|
|
48
|
+
| "\(.name | n)_FIELD_ID=\(.id)"'
|
|
49
|
+
} > "$OUT"
|
|
50
|
+
|
|
51
|
+
echo "✓ Wrote $OUT"
|
|
52
|
+
echo " Fields captured:"
|
|
53
|
+
grep -E '_FIELD_ID=' "$OUT" | sed 's/^/ /'
|
package/scripts/check.sh
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# check.sh - cckit local gate. Runs the fast, dependency-light checks that must pass before a PR.
|
|
3
|
+
# No CI required; this is the bar. Exit non-zero on the first failure.
|
|
4
|
+
set -uo pipefail
|
|
5
|
+
cd "$(cd "$(dirname "$0")/.." && pwd)"
|
|
6
|
+
|
|
7
|
+
fail=0
|
|
8
|
+
note() { printf '%s\n' "$*" >&2; }
|
|
9
|
+
|
|
10
|
+
# 1. Every shell script parses (bash -n).
|
|
11
|
+
note "==> shell syntax (bash -n)"
|
|
12
|
+
while IFS= read -r f; do
|
|
13
|
+
bash -n "$f" || { note "x syntax: $f"; fail=1; }
|
|
14
|
+
done < <(find bin scripts -type f \( -name '*.sh' -o -perm -u+x \) 2>/dev/null | sort -u)
|
|
15
|
+
|
|
16
|
+
# 1b. shellcheck at error severity — static analysis when available, skipped if not installed
|
|
17
|
+
# (like jq below) so the gate stays dependency-light. CI installs shellcheck so this always runs there.
|
|
18
|
+
note "==> shellcheck (errors)"
|
|
19
|
+
if command -v shellcheck >/dev/null 2>&1; then
|
|
20
|
+
find bin scripts -type f \( -name '*.sh' -o -name 'cckit' \) -print0 \
|
|
21
|
+
| xargs -0 shellcheck --severity=error || fail=1
|
|
22
|
+
else
|
|
23
|
+
note " (shellcheck absent - skipping)"
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# 2. The plugin manifest is valid JSON.
|
|
27
|
+
note "==> plugin manifest JSON"
|
|
28
|
+
if command -v jq >/dev/null 2>&1; then
|
|
29
|
+
jq -e . .claude-plugin/plugin.json >/dev/null || { note "x invalid plugin.json"; fail=1; }
|
|
30
|
+
jq -e . cckit.config.json >/dev/null || { note "x invalid cckit.config.json"; fail=1; }
|
|
31
|
+
else
|
|
32
|
+
note " (jq absent - skipping JSON validation)"
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# 3. No tedos branding leaked into what SHIPS (the de-tedos-ification gate). Scans TRACKED files
|
|
36
|
+
# only (git grep) so gitignored runtime state (.cckit/), build output (dist/), and deps never trip
|
|
37
|
+
# a false positive - only committed content must be tedos-free. Falls back to a filtered recursive
|
|
38
|
+
# grep outside a git work tree.
|
|
39
|
+
note "==> no tedos branding (tracked files)"
|
|
40
|
+
_tedos_scan() {
|
|
41
|
+
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
42
|
+
git grep -inI tedos -- . ':!scripts/check.sh'
|
|
43
|
+
else
|
|
44
|
+
grep -rniI --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=.cckit \
|
|
45
|
+
--exclude-dir=dist --exclude=check.sh tedos .
|
|
46
|
+
fi
|
|
47
|
+
}
|
|
48
|
+
if _tedos_scan >/dev/null 2>&1; then
|
|
49
|
+
note "x found 'tedos' references - cckit must be tedos-free:"
|
|
50
|
+
_tedos_scan | head -20 >&2
|
|
51
|
+
fail=1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# 4. Secret + privacy guard - no secrets, keys, env, or private data in anything publishable.
|
|
55
|
+
note "==> secret + privacy guard"
|
|
56
|
+
if [ -f scripts/lib/secret-guard.sh ]; then
|
|
57
|
+
. scripts/lib/secret-guard.sh
|
|
58
|
+
secret_guard_scan || fail=1
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# 5. Behavioral tests - run every *-test.sh through the test runner.
|
|
62
|
+
note "==> behavioral tests"
|
|
63
|
+
bash scripts/test.sh || fail=1
|
|
64
|
+
|
|
65
|
+
[ "$fail" -eq 0 ] && note "PASS cckit check passed" || note "FAIL cckit check FAILED"
|
|
66
|
+
exit "$fail"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# contribute.sh - open a contribution PR to cckit, GATED on the local checks. The checks gate
|
|
3
|
+
# (scripts/check.sh: shell syntax, valid manifests, no stray branding, secret/privacy guard) MUST
|
|
4
|
+
# pass before anything is pushed - a red gate stops here. This is the agent-agnostic CLI half of
|
|
5
|
+
# the kit-contribute skill.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# cckit contribute "<one-line summary>" # gate -> push branch -> open PR to the upstream base
|
|
9
|
+
# cckit contribute --dry-run "<summary>" # run the gate + preconditions, push/PR nothing
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
12
|
+
# shellcheck source=/dev/null
|
|
13
|
+
source "$ROOT/scripts/lib/kit-config.sh" && load_kit_config
|
|
14
|
+
repo="$KIT_REPO"; base="${KIT_BASE_BRANCH:-main}"
|
|
15
|
+
|
|
16
|
+
dry=0; summary=""
|
|
17
|
+
for a in "$@"; do
|
|
18
|
+
case "$a" in --dry-run) dry=1 ;; *) summary="${summary:+$summary }$a" ;; esac
|
|
19
|
+
done
|
|
20
|
+
|
|
21
|
+
branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
|
|
22
|
+
case "$branch" in
|
|
23
|
+
""|main|develop|"$base") echo "contribute: start a feature branch first (cckit start <issue>)." >&2; exit 2 ;;
|
|
24
|
+
esac
|
|
25
|
+
|
|
26
|
+
echo "==> contribute: checks gate (scripts/check.sh)"
|
|
27
|
+
if ! bash "$ROOT/scripts/check.sh"; then
|
|
28
|
+
echo "contribute: checks gate FAILED - fix it before contributing (a green gate is the bar)." >&2
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
git fetch origin "$base" --quiet 2>/dev/null || true
|
|
33
|
+
if [ -z "$(git log --oneline "origin/$base..$branch" 2>/dev/null)" ]; then
|
|
34
|
+
echo "contribute: no commits ahead of $base on '$branch' - commit your change first." >&2; exit 2
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
[ -n "$summary" ] || { echo "contribute: pass a one-line summary: cckit contribute \"<what + why>\"" >&2; exit 2; }
|
|
38
|
+
|
|
39
|
+
if [ "$dry" -eq 1 ]; then
|
|
40
|
+
echo "contribute: DRY RUN - gate green, '$branch' has commits ahead of $base."
|
|
41
|
+
echo " would: push '$branch' + open a PR to $repo ($base) titled: $summary"
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
git push -u origin "$branch" 2>&1 | tail -1
|
|
46
|
+
gh pr create --repo "$repo" --base "$base" --head "$branch" \
|
|
47
|
+
--title "$summary" \
|
|
48
|
+
--body "$(printf '## Contribution\n\n%s\n\nChecks gate (scripts/check.sh): green.\nDual-licensed MIT OR Apache-2.0 per CONTRIBUTING.md.\n' "$summary")"
|
package/scripts/debug.sh
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# debug.sh - OPTIONAL, auto-detected browser-debug capability via chrome-devtools-axi (Kun Chen,
|
|
3
|
+
# https://github.com/kunchenguid/chrome-devtools-axi). Token-efficient (TOON output), self-contained
|
|
4
|
+
# Chrome bridge. NOT a hard dependency: cckit is pure bash; axi needs Node + Chrome. When present,
|
|
5
|
+
# this drives axi; when absent, it prints how to enable it and exits 0 (degrade, never hard-fail an
|
|
6
|
+
# unattended run).
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# cckit debug <axi-args...> drive axi (screenshot / a11y / console / network / lighthouse)
|
|
10
|
+
# cckit debug --check report whether the capability is available, then exit
|
|
11
|
+
#
|
|
12
|
+
# Resolution order for the axi command:
|
|
13
|
+
# 1. $CCKIT_AXI explicit command/path override
|
|
14
|
+
# 2. chrome-devtools-axi on PATH (npm i -g chrome-devtools-axi)
|
|
15
|
+
# 3. npx -y chrome-devtools-axi when node + npx are present
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
have() { command -v "$1" >/dev/null 2>&1; }
|
|
19
|
+
|
|
20
|
+
chrome_present() {
|
|
21
|
+
have google-chrome || have chromium || have chromium-browser \
|
|
22
|
+
|| [ -x "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" ] \
|
|
23
|
+
|| [ -x "/Applications/Chromium.app/Contents/MacOS/Chromium" ]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# Echo how to invoke axi, or return non-zero if unavailable.
|
|
27
|
+
axi_cmd() {
|
|
28
|
+
if [ -n "${CCKIT_AXI:-}" ]; then printf '%s' "$CCKIT_AXI"; return 0; fi
|
|
29
|
+
if have chrome-devtools-axi; then printf 'chrome-devtools-axi'; return 0; fi
|
|
30
|
+
if have npx && have node; then printf 'npx -y chrome-devtools-axi'; return 0; fi
|
|
31
|
+
return 1
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
cmd="$(axi_cmd || true)"
|
|
35
|
+
|
|
36
|
+
if [ "${1:-}" = "--check" ]; then
|
|
37
|
+
if [ -n "$cmd" ] && chrome_present; then
|
|
38
|
+
echo "cckit debug: AVAILABLE via '$cmd' (Chrome detected)"
|
|
39
|
+
else
|
|
40
|
+
echo "cckit debug: optional capability NOT available."
|
|
41
|
+
[ -n "$cmd" ] || echo " - axi: install with 'npm i -g chrome-devtools-axi' (or have node+npx)"
|
|
42
|
+
chrome_present || echo " - Chrome: not detected (install Google Chrome or Chromium)"
|
|
43
|
+
fi
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
if [ -z "$cmd" ] || ! chrome_present; then
|
|
48
|
+
echo "cckit debug: browser-debug capability unavailable - skipping (optional)." >&2
|
|
49
|
+
[ -n "$cmd" ] || echo " enable: npm i -g chrome-devtools-axi (needs Node + Chrome)" >&2
|
|
50
|
+
exit 0 # degrade, do not hard-fail an unattended run
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# shellcheck disable=SC2086
|
|
54
|
+
exec $cmd "$@"
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# init-upgrade-test.sh — self-test for the `init.sh --upgrade` clobber contract (#334).
|
|
3
|
+
#
|
|
4
|
+
# Reproduces the 2026-06-11 incident in a throwaway project and asserts the fix:
|
|
5
|
+
# 1. existing kit-owned files (scripts/) are PRESERVED, never downgraded to older templates;
|
|
6
|
+
# 2. paths the project removed/renamed (kit.config.json `upgrade.removed/renamed`) are
|
|
7
|
+
# NEVER re-added by "add missing files";
|
|
8
|
+
# 3. the net effect of an upgrade on a converged project is ONLY the kitVersion bump.
|
|
9
|
+
#
|
|
10
|
+
# Network-free: drives init.sh through the --upgrade path only (skips kit-doctor + gh).
|
|
11
|
+
# Run: bash scripts/init-upgrade-test.sh
|
|
12
|
+
|
|
13
|
+
set -uo pipefail
|
|
14
|
+
PLUGIN_DIR=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
|
|
15
|
+
INIT="$PLUGIN_DIR/scripts/init.sh"
|
|
16
|
+
|
|
17
|
+
fail=0
|
|
18
|
+
t() { # t <label> <got> <want>
|
|
19
|
+
if [ "$2" != "$3" ]; then echo "FAIL: $1 -> got '[$2]' want '[$3]'"; fail=1; else echo "ok: $1"; fi
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
command -v jq >/dev/null 2>&1 || { echo "SKIP: jq not available"; exit 0; }
|
|
23
|
+
command -v git >/dev/null 2>&1 || { echo "SKIP: git not available"; exit 0; }
|
|
24
|
+
|
|
25
|
+
PLUGIN_VERSION="$(jq -r '.version // "0.0.0"' "$PLUGIN_DIR/.claude-plugin/plugin.json" 2>/dev/null || echo 0.0.0)"
|
|
26
|
+
|
|
27
|
+
proj="$(mktemp -d)"; trap 'rm -rf "$proj"' EXIT
|
|
28
|
+
cd "$proj"
|
|
29
|
+
git init -q
|
|
30
|
+
git config user.email kit-test@example.com
|
|
31
|
+
git config user.name kit-test
|
|
32
|
+
|
|
33
|
+
# --- seed a minimal initialized project so the --upgrade path engages (no doctor/gh) ----
|
|
34
|
+
mkdir -p .claude
|
|
35
|
+
cat > .claude/kit.config.json <<JSON
|
|
36
|
+
{
|
|
37
|
+
"kitVersion": "0.0.1",
|
|
38
|
+
"profile": "software",
|
|
39
|
+
"project": { "name": "UpgradeTest", "slug": "upgrade-test" },
|
|
40
|
+
"github": { "repo": "example/upgrade-test", "owner": "example", "projectsV2": false }
|
|
41
|
+
}
|
|
42
|
+
JSON
|
|
43
|
+
|
|
44
|
+
# First upgrade = full scaffold via the upgrade path. --force skips the dirty-tree guard
|
|
45
|
+
# (the seed config is still untracked at this point).
|
|
46
|
+
CLAUDE_PLUGIN_ROOT="$PLUGIN_DIR" bash "$INIT" --upgrade --target "$proj" --force >/dev/null 2>&1 \
|
|
47
|
+
|| { echo "FAIL: initial scaffold (--upgrade) exited non-zero"; exit 1; }
|
|
48
|
+
|
|
49
|
+
t "scaffold added morning-briefing skill" "$([ -f .claude/skills/morning-briefing/SKILL.md ] && echo yes || echo no)" "yes"
|
|
50
|
+
t "scaffold added speckit skill" "$([ -d .claude/skills/speckit ] && echo yes || echo no)" "yes"
|
|
51
|
+
t "scaffold added task-management rule" "$([ -f .claude/rules/task-management.md ] && echo yes || echo no)" "yes"
|
|
52
|
+
t "scaffold copied task-sync.sh" "$([ -f scripts/task-sync.sh ] && echo yes || echo no)" "yes"
|
|
53
|
+
|
|
54
|
+
git add -A && git commit -q -m "scaffold"
|
|
55
|
+
|
|
56
|
+
# --- simulate the project's deliberate divergence (the cckit state) --------------------
|
|
57
|
+
# rename a scaffolded skill, delete two scaffolded paths, register them in the upgrade block,
|
|
58
|
+
# and mark a kit-owned script so a downgrade would be detectable.
|
|
59
|
+
git mv .claude/skills/morning-briefing .claude/skills/kit-morning-briefing
|
|
60
|
+
git rm -q -r .claude/skills/speckit
|
|
61
|
+
git rm -q .claude/rules/task-management.md
|
|
62
|
+
MARKER="# LOCAL-FIX-MARKER-#334 (must survive upgrade)"
|
|
63
|
+
printf '\n%s\n' "$MARKER" >> scripts/task-sync.sh
|
|
64
|
+
|
|
65
|
+
jq --arg k "0.0.1" '
|
|
66
|
+
.kitVersion = $k
|
|
67
|
+
| .upgrade = {
|
|
68
|
+
removed: [ ".claude/skills/speckit", ".claude/rules/task-management.md" ],
|
|
69
|
+
renamed: { ".claude/skills/morning-briefing": ".claude/skills/kit-morning-briefing" }
|
|
70
|
+
}' .claude/kit.config.json > .claude/kit.config.json.tmp && mv .claude/kit.config.json.tmp .claude/kit.config.json
|
|
71
|
+
|
|
72
|
+
git add -A && git commit -q -m "diverge: rename + delete + register exclusions"
|
|
73
|
+
|
|
74
|
+
# --- the upgrade under test (clean tree, real un-forced path) --------------------------
|
|
75
|
+
CLAUDE_PLUGIN_ROOT="$PLUGIN_DIR" bash "$INIT" --upgrade --target "$proj" >/dev/null 2>&1 \
|
|
76
|
+
|| { echo "FAIL: upgrade under test exited non-zero"; exit 1; }
|
|
77
|
+
|
|
78
|
+
# 1. removed/renamed are NOT resurrected
|
|
79
|
+
t "renamed morning-briefing NOT re-added" "$([ -e .claude/skills/morning-briefing ] && echo present || echo absent)" "absent"
|
|
80
|
+
t "removed speckit NOT re-added" "$([ -e .claude/skills/speckit ] && echo present || echo absent)" "absent"
|
|
81
|
+
t "removed rule NOT re-added" "$([ -e .claude/rules/task-management.md ] && echo present || echo absent)" "absent"
|
|
82
|
+
t "renamed target still present" "$([ -d .claude/skills/kit-morning-briefing ] && echo yes || echo no)" "yes"
|
|
83
|
+
|
|
84
|
+
# 2. kit-owned script PRESERVED (not downgraded — marker survives)
|
|
85
|
+
t "script not downgraded (marker kept)" "$(grep -cF "$MARKER" scripts/task-sync.sh)" "1"
|
|
86
|
+
|
|
87
|
+
# 3. net effect = ONLY the kitVersion bump
|
|
88
|
+
changed="$(git status --porcelain | awk '{print $2}' | sort | tr '\n' ' ' | sed 's/ $//')"
|
|
89
|
+
t "only kit.config.json changed" "$changed" ".claude/kit.config.json"
|
|
90
|
+
|
|
91
|
+
diff_body="$(git diff -- .claude/kit.config.json | grep -E '^[+-]' | grep -vE '^(\+\+\+|---)')"
|
|
92
|
+
only_kitver="$(printf '%s\n' "$diff_body" | grep -vqE '"kitVersion"' && echo no || echo yes)"
|
|
93
|
+
t "diff is only the kitVersion line" "$only_kitver" "yes"
|
|
94
|
+
t "kitVersion bumped to plugin version" "$(jq -r '.kitVersion' .claude/kit.config.json)" "$PLUGIN_VERSION"
|
|
95
|
+
t "upgrade block preserved through merge" "$(jq -r '.upgrade.removed | length' .claude/kit.config.json)" "2"
|
|
96
|
+
|
|
97
|
+
echo ""
|
|
98
|
+
[ "$fail" -eq 0 ] && echo "PASS: init.sh --upgrade honors the preserve/exclude contract (#334)" || echo "FAILED"
|
|
99
|
+
exit "$fail"
|