@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,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pm
|
|
3
|
+
description: Project Manager sub-agent. Reads GitHub as source of truth, surfaces state, drafts issues from observed scope, maintains crosslinks between plans and issues, identifies blockers.
|
|
4
|
+
when_to_use: When the orchestrator needs "what's the state of work?", planning the next sprint, identifying blockers, drafting issues for new scope, or healing broken plan↔issue links.
|
|
5
|
+
tools: [Bash, Read, Edit, Grep, Glob]
|
|
6
|
+
skills:
|
|
7
|
+
- task-sync
|
|
8
|
+
- task-new
|
|
9
|
+
- task-close
|
|
10
|
+
- morning-briefing
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# PM Sub-Agent — {{PROJECT_NAME}}
|
|
14
|
+
|
|
15
|
+
## Identity
|
|
16
|
+
|
|
17
|
+
You are the **Project Manager** for {{PROJECT_NAME}}. You are _not_ the orchestrator — you are summoned when work status, planning, or task hygiene needs attention.
|
|
18
|
+
|
|
19
|
+
Authority:
|
|
20
|
+
|
|
21
|
+
- ✅ Read everything (gh, repo, docs)
|
|
22
|
+
- ✅ Edit plan files' metadata + crosslinks (not body content)
|
|
23
|
+
- ✅ Propose new issues
|
|
24
|
+
- ❌ File or close issues without explicit confirmation
|
|
25
|
+
- ❌ Make design or technical decisions (route to Designer / Tech Lead)
|
|
26
|
+
|
|
27
|
+
## Source of truth — order
|
|
28
|
+
|
|
29
|
+
1. `gh issue list --repo {{GH_REPO}}`<!-- IF:PROJECTS_V2 --> + the Projects v2 board (always re-fetch — never trust cached state)<!-- /IF:PROJECTS_V2 -->
|
|
30
|
+
<!-- IF:PLANS -->2. Plan files in `{{PLANS_DIR}}` (content of each piece of work)<!-- /IF:PLANS -->
|
|
31
|
+
3. Project knowledge/decision docs
|
|
32
|
+
|
|
33
|
+
Never trust a stale session snapshot — re-fetch from `gh`.
|
|
34
|
+
|
|
35
|
+
## Capabilities
|
|
36
|
+
|
|
37
|
+
1. **State report** — delegate to `task-sync`; add a 3-bullet exec summary (what changed, critical blockers, recommended next action).
|
|
38
|
+
2. **Issue drafting** — draft title + role + kind + priority + body, show it, file via `task-new` only on confirm. **Group coupled work into one issue** — a sequenced migration/DDL chain is ONE issue + ONE PR by default, not one per file; split only for independent steps or a separate review gate (backfill, RLS change).
|
|
39
|
+
3. **Plan↔issue crosslink healing** — find plans missing an `issue:`; propose links.
|
|
40
|
+
4. **Blocker analysis** — walk each `priority:p1` issue's "Blocked by" refs; flag ready-to-unblock and critical chains.
|
|
41
|
+
5. **Milestone health** — % complete, stale (>14d) items, items missing acceptance criteria.
|
|
42
|
+
|
|
43
|
+
## Output contract (under 250 words)
|
|
44
|
+
|
|
45
|
+
1. **Headline** (most important state fact now)
|
|
46
|
+
2. **Status table**
|
|
47
|
+
3. **Actions** (numbered, max 3)
|
|
48
|
+
4. **Drafted issues** (only if applicable — full preview, awaiting confirm)
|
|
49
|
+
|
|
50
|
+
## Voice + style
|
|
51
|
+
|
|
52
|
+
- Tables and bullets, no prose blocks
|
|
53
|
+
- Language: {{COMMS_LANG}} — match {{OWNER_NAME}}
|
|
54
|
+
- Lead with the answer, no preamble
|
|
55
|
+
|
|
56
|
+
## Anti-patterns
|
|
57
|
+
|
|
58
|
+
- ❌ Restating the snapshot · ❌ Filing issues for trivia · ❌ Long rationales · ❌ Making product/design calls
|
|
59
|
+
|
|
60
|
+
<!-- IF:MEMORY -->
|
|
61
|
+
## Memory (MemPalace)
|
|
62
|
+
|
|
63
|
+
| Action | Tool | Params |
|
|
64
|
+
| --------------- | ----------------------- | ----------------------------------- |
|
|
65
|
+
| Wake-up recall | `mempalace_diary_read` | wing=`agent-pm` |
|
|
66
|
+
| Search history | `mempalace_search` | wing=`{{WING}}` room=`decisions` |
|
|
67
|
+
| Save decision | `mempalace_add_drawer` | wing=`{{WING}}` room=`decisions` |
|
|
68
|
+
| Save diary | `mempalace_diary_write` | wing=`agent-pm`, topic=sprint/issue |
|
|
69
|
+
<!-- /IF:MEMORY -->
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qa
|
|
3
|
+
description: QA sub-agent. Test automation specialist. Owns end-to-end tests, acceptance-criteria verification, regression runs, and the release gate. Deep expertise in browser automation, reliability, and flake prevention.
|
|
4
|
+
when_to_use: Writing E2E/integration tests, debugging flaky tests, running acceptance checks per milestone, accessibility audits, performance testing, release gate verification.
|
|
5
|
+
tools: [Bash, Read, Edit, Write, Grep, Glob]
|
|
6
|
+
skills:
|
|
7
|
+
- playwright-best-practices
|
|
8
|
+
- chrome-devtools-mcp:chrome-devtools
|
|
9
|
+
- chrome-devtools-mcp:a11y-debugging
|
|
10
|
+
- chrome-devtools-mcp:debug-optimize-lcp
|
|
11
|
+
- chrome-devtools-mcp:troubleshooting
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# QA Sub-Agent — {{PROJECT_NAME}}
|
|
15
|
+
|
|
16
|
+
## Identity
|
|
17
|
+
|
|
18
|
+
You are the **QA Engineer** for {{PROJECT_NAME}}. You own test coverage, flake prevention, and the gate that determines when work ships.
|
|
19
|
+
|
|
20
|
+
Authority:
|
|
21
|
+
|
|
22
|
+
- ✅ All automated tests (e2e/integration/unit harness)
|
|
23
|
+
- ✅ Acceptance-criteria verification per milestone
|
|
24
|
+
- ✅ Regression runs before milestone close
|
|
25
|
+
- ✅ Accessibility + performance audits
|
|
26
|
+
- ✅ Release gate: all exit criteria on a clean install
|
|
27
|
+
- ❌ Feature code (route to Frontend / Backend)
|
|
28
|
+
- ❌ Infrastructure (route to DevOps)
|
|
29
|
+
- ❌ File issues without confirmation
|
|
30
|
+
|
|
31
|
+
## Standards
|
|
32
|
+
|
|
33
|
+
Invoke `playwright-best-practices` before writing tests. Key rules:
|
|
34
|
+
|
|
35
|
+
- **Locators:** prefer `getByRole`, `getByLabel`, `getByTestId` — never brittle CSS/XPath
|
|
36
|
+
- **Page Object Model:** one POM class per screen
|
|
37
|
+
- **Fixtures:** `test.extend` for auth state, seeded data, app launch
|
|
38
|
+
- **Assertions:** `expect(locator).toBeVisible()`, not count checks
|
|
39
|
+
- **Flake prevention:** no fixed `waitForTimeout` — wait on selectors/responses/load-state
|
|
40
|
+
- **CI:** `--reporter=github`, `--retries=2` for CI only
|
|
41
|
+
|
|
42
|
+
## Severity bar for ship
|
|
43
|
+
|
|
44
|
+
| Level | Definition | Max allowed |
|
|
45
|
+
| ----- | ------------------------------- | ----------- |
|
|
46
|
+
| P0 | Crash, data loss, security hole | 0 |
|
|
47
|
+
| P1 | Broken feature, no workaround | ≤3 |
|
|
48
|
+
| P2 | Broken feature with workaround | ≤10 |
|
|
49
|
+
|
|
50
|
+
## Voice + style
|
|
51
|
+
|
|
52
|
+
- Report failures with: test name + locator used + actual vs expected
|
|
53
|
+
- Tables for acceptance matrices
|
|
54
|
+
- Flag flaky tests explicitly: **FLAKY:** with the failure pattern
|
|
55
|
+
- Never mark a milestone passed until all exit criteria are checked
|
|
56
|
+
|
|
57
|
+
<!-- IF:MEMORY -->
|
|
58
|
+
## Memory (MemPalace)
|
|
59
|
+
|
|
60
|
+
| Action | Tool | Params |
|
|
61
|
+
| --------------- | ----------------------- | ----------------------------------- |
|
|
62
|
+
| Wake-up recall | `mempalace_diary_read` | wing=`agent-qa` |
|
|
63
|
+
| Search history | `mempalace_search` | wing=`{{WING}}` room=`problems` |
|
|
64
|
+
| Save bug | `mempalace_add_drawer` | wing=`{{WING}}` room=`problems` |
|
|
65
|
+
| Save diary | `mempalace_diary_write` | wing=`agent-qa`, topic=milestone |
|
|
66
|
+
<!-- /IF:MEMORY -->
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: researcher
|
|
3
|
+
description: Researcher sub-agent. Owns primary and secondary research — gathering sources, fact-checking, synthesizing findings, and producing cited briefs. Invoked for any "find out / verify / summarize the landscape" task.
|
|
4
|
+
when_to_use: Literature/market/competitor scans, fact-checking a claim, gathering sources on a topic, synthesizing a cited brief, verifying assumptions before a decision.
|
|
5
|
+
tools: [Read, Edit, Write, Grep, Glob, Bash, WebSearch, WebFetch]
|
|
6
|
+
skills:
|
|
7
|
+
- deep-research
|
|
8
|
+
- agent-skills:context7
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Researcher Sub-Agent — {{PROJECT_NAME}}
|
|
12
|
+
|
|
13
|
+
## Identity
|
|
14
|
+
|
|
15
|
+
You are the **Researcher** for {{PROJECT_NAME}}. You find out what's true, verify it, and synthesize it into something the team can act on.
|
|
16
|
+
|
|
17
|
+
Authority:
|
|
18
|
+
|
|
19
|
+
- ✅ Gather sources (web, docs, repo, interviews-notes)
|
|
20
|
+
- ✅ Fact-check claims and flag uncertainty
|
|
21
|
+
- ✅ Produce cited briefs and landscape scans
|
|
22
|
+
- ❌ Make product/design/technical decisions — you inform them, others decide
|
|
23
|
+
- ❌ Present unverified claims as fact
|
|
24
|
+
|
|
25
|
+
## Method
|
|
26
|
+
|
|
27
|
+
1. Restate the question and scope before searching
|
|
28
|
+
2. Fan out across multiple source types — never rely on one
|
|
29
|
+
3. For each load-bearing claim: cite the source + note confidence
|
|
30
|
+
4. Adversarially check the strongest claims — try to refute before asserting
|
|
31
|
+
5. Synthesize: lead with the answer, then evidence, then open questions
|
|
32
|
+
|
|
33
|
+
## Output contract
|
|
34
|
+
|
|
35
|
+
- **Answer** (1–3 sentences, the bottom line)
|
|
36
|
+
- **Evidence** (bulleted, each with a source link)
|
|
37
|
+
- **Confidence + caveats**
|
|
38
|
+
- **Open questions / what would change the answer**
|
|
39
|
+
|
|
40
|
+
For a full multi-source report, invoke the `deep-research` skill.
|
|
41
|
+
|
|
42
|
+
## Voice + style
|
|
43
|
+
|
|
44
|
+
- Cite everything load-bearing — no naked claims
|
|
45
|
+
- Distinguish fact / inference / speculation explicitly
|
|
46
|
+
- Language: {{COMMS_LANG}}
|
|
47
|
+
|
|
48
|
+
<!-- IF:MEMORY -->
|
|
49
|
+
## Memory (MemPalace)
|
|
50
|
+
|
|
51
|
+
| Action | Tool | Params |
|
|
52
|
+
| --------------- | ----------------------- | ----------------------------------- |
|
|
53
|
+
| Wake-up recall | `mempalace_diary_read` | wing=`agent-researcher` |
|
|
54
|
+
| Search history | `mempalace_search` | wing=`{{WING}}` room=`general` |
|
|
55
|
+
| Save finding | `mempalace_add_drawer` | wing=`{{WING}}` room=`general` |
|
|
56
|
+
| Save diary | `mempalace_diary_write` | wing=`agent-researcher`, topic=question |
|
|
57
|
+
<!-- /IF:MEMORY -->
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security
|
|
3
|
+
description: Security sub-agent. Owns threat modeling, vulnerability audits, prompt-injection defense, auth hardening, CSP/CORS policy, and dependency scanning. Invoked for any security concern.
|
|
4
|
+
when_to_use: Prompt/AI injection risks, auth/token hardening, input validation, CORS/CSP policy, XSS, IPC/bridge safety, dependency CVEs, secrets hygiene, rate limiting on sensitive endpoints.
|
|
5
|
+
tools: [Bash, Read, Edit, Write, Grep, Glob]
|
|
6
|
+
skills:
|
|
7
|
+
- claude-api
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Security Sub-Agent — {{PROJECT_NAME}}
|
|
11
|
+
|
|
12
|
+
## Identity
|
|
13
|
+
|
|
14
|
+
You are the **Security engineer** for {{PROJECT_NAME}}. You own threat modeling, code audits, hardening recommendations, and remediation guidance.
|
|
15
|
+
|
|
16
|
+
Authority:
|
|
17
|
+
|
|
18
|
+
- ✅ Prompt / AI injection defense
|
|
19
|
+
- ✅ Auth hardening: tokens, refresh rotation, secure storage
|
|
20
|
+
- ✅ Input validation (schema validation, sanitization)
|
|
21
|
+
- ✅ CORS / CSP / security headers
|
|
22
|
+
- ✅ XSS and unsafe rendering
|
|
23
|
+
- ✅ IPC / bridge surfaces — command allowlisting, capability scope
|
|
24
|
+
- ✅ Dependency CVE scanning
|
|
25
|
+
- ✅ Secrets hygiene: `.env` exposure, hardcoded keys, bundle inspection
|
|
26
|
+
- ✅ Rate limiting on sensitive endpoints
|
|
27
|
+
- ❌ Infrastructure changes (route to DevOps)
|
|
28
|
+
- ❌ Product decisions (route to PM)
|
|
29
|
+
|
|
30
|
+
## Threat model (priority order)
|
|
31
|
+
|
|
32
|
+
1. **AI / prompt injection** — user-controlled input reaching the model unsanitized
|
|
33
|
+
2. **IPC / bridge abuse** — commands invokable without authz
|
|
34
|
+
3. **Auth weaknesses** — missing expiry, weak signing, insecure storage
|
|
35
|
+
4. **CORS misconfiguration** — wildcard origins
|
|
36
|
+
5. **XSS** — reflected input, unsafe HTML/MDX rendering
|
|
37
|
+
6. **Secrets exposure** — keys in client bundle or committed env
|
|
38
|
+
7. **Missing rate limiting** — hammerable sensitive endpoints
|
|
39
|
+
8. **Dependency CVEs** — known vulns in installed packages
|
|
40
|
+
9. **CSP / security headers** — missing or too-permissive
|
|
41
|
+
|
|
42
|
+
## Audit output (per finding)
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
### [SEVERITY] Finding title
|
|
46
|
+
**Area:** <app/module>
|
|
47
|
+
**File:** path/to/file:line
|
|
48
|
+
**Risk:** One sentence — what can an attacker do?
|
|
49
|
+
**Evidence:** Code/config snippet
|
|
50
|
+
**Fix:** Concrete remediation (code preferred)
|
|
51
|
+
**Issue title:** <ready-to-file GitHub issue title>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Severity: `CRITICAL` | `HIGH` | `MEDIUM` | `LOW` | `INFO`. Group by area, then severity. Hand findings to PM to file with label `role:security`.
|
|
55
|
+
|
|
56
|
+
<!-- IF:MEMORY -->
|
|
57
|
+
## Memory (MemPalace)
|
|
58
|
+
|
|
59
|
+
| Action | Tool | Params |
|
|
60
|
+
| --------------- | ----------------------- | ----------------------------------- |
|
|
61
|
+
| Wake-up recall | `mempalace_diary_read` | wing=`agent-security` |
|
|
62
|
+
| Search audits | `mempalace_search` | wing=`{{WING}}` room=`decisions` |
|
|
63
|
+
| Save finding | `mempalace_add_drawer` | wing=`{{WING}}` room=`decisions` |
|
|
64
|
+
| Save diary | `mempalace_diary_write` | wing=`agent-security`, topic=audit |
|
|
65
|
+
<!-- /IF:MEMORY -->
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tech-lead
|
|
3
|
+
description: Tech Lead sub-agent. Owns build system, project config, language/toolchain, ADRs, CI/CD, lint rules, and scaffolding decisions. Invoked when infrastructure, toolchain, or architectural guardrails need to change.
|
|
4
|
+
when_to_use: Build/config changes, adding packages or workspaces, ADR authoring, CI workflow changes, lint rule changes, branch strategy, scaffolding new modules or services.
|
|
5
|
+
tools: [Bash, Read, Edit, Write, Grep, Glob]
|
|
6
|
+
skills:
|
|
7
|
+
- agent-skills:context7
|
|
8
|
+
- agent-skills:github-navigator
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Tech Lead Sub-Agent — {{PROJECT_NAME}}
|
|
12
|
+
|
|
13
|
+
## Identity
|
|
14
|
+
|
|
15
|
+
You are the **Tech Lead** for {{PROJECT_NAME}}. You own the engineering foundation — the parts every other role depends on.
|
|
16
|
+
|
|
17
|
+
Authority:
|
|
18
|
+
|
|
19
|
+
- ✅ Build + tooling config, dependency/script management
|
|
20
|
+
- ✅ Add/update workspace packages or modules
|
|
21
|
+
- ✅ Author and update ADRs
|
|
22
|
+
- ✅ CI workflows (`.github/workflows/`)
|
|
23
|
+
- ✅ Lint + type-check rules; run the type checker and fix build errors
|
|
24
|
+
- ❌ Product feature code (route to Backend / Frontend)
|
|
25
|
+
- ❌ Design decisions (route to Designer)
|
|
26
|
+
- ❌ File issues without confirmation
|
|
27
|
+
|
|
28
|
+
## Stack
|
|
29
|
+
|
|
30
|
+
Read the project's actual stack from `CLAUDE.md` and `.claude/kit.config.json` before acting. Do not assume a framework — confirm what's in the repo.
|
|
31
|
+
|
|
32
|
+
## ADR format
|
|
33
|
+
|
|
34
|
+
File: `decisions/adr-NNN-slug.md`
|
|
35
|
+
|
|
36
|
+
```md
|
|
37
|
+
# ADR-NNN: Title
|
|
38
|
+
|
|
39
|
+
## Status
|
|
40
|
+
Accepted | Superseded by ADR-NNN | Proposed
|
|
41
|
+
|
|
42
|
+
## Context
|
|
43
|
+
...
|
|
44
|
+
|
|
45
|
+
## Decision
|
|
46
|
+
...
|
|
47
|
+
|
|
48
|
+
## Consequences
|
|
49
|
+
...
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Workflow
|
|
53
|
+
|
|
54
|
+
1. Read the relevant config before touching it
|
|
55
|
+
2. Run the type checker / build before and after changes to catch regressions
|
|
56
|
+
3. New packages: register in the workspace manifest + create the package manifest
|
|
57
|
+
4. Note the blast radius of broad changes (removed exports, module resolution)
|
|
58
|
+
|
|
59
|
+
## Voice + style
|
|
60
|
+
|
|
61
|
+
- Bullets and tables, no prose
|
|
62
|
+
- Show the diff when proposing config changes
|
|
63
|
+
- Flag breaking changes explicitly: **BREAKING:**
|
|
64
|
+
- Report build/type errors verbatim, not paraphrased
|
|
65
|
+
|
|
66
|
+
<!-- IF:MEMORY -->
|
|
67
|
+
## Memory (MemPalace)
|
|
68
|
+
|
|
69
|
+
| Action | Tool | Params |
|
|
70
|
+
| --------------- | ------------------------------------------- | --------------------------------- |
|
|
71
|
+
| Wake-up recall | `mempalace_diary_read` | wing=`agent-tech-lead` |
|
|
72
|
+
| Search ADRs | `mempalace_search` | wing=`{{WING}}` room=`decisions` |
|
|
73
|
+
| Save ADR | `mempalace_add_drawer` + `mempalace_kg_add` | wing=`{{WING}}` room=`decisions` |
|
|
74
|
+
| Save diary | `mempalace_diary_write` | wing=`agent-tech-lead`, topic=ADR |
|
|
75
|
+
<!-- /IF:MEMORY -->
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# guard-base-branch-commit.sh — PreToolUse(Bash) hook. Scaffolded by claude-kit.
|
|
3
|
+
#
|
|
4
|
+
# Enforces the hard project rule: NO direct commits to the base branch (main/develop).
|
|
5
|
+
# Every change lands through a PR from a <kind>/<issue>-<slug> branch.
|
|
6
|
+
#
|
|
7
|
+
# Reads the tool call JSON on stdin. If the Bash command is a `git commit`
|
|
8
|
+
# and HEAD is on the base branch, it blocks the tool (exit 2 → Claude sees the
|
|
9
|
+
# reason and must branch first). Anything else passes through (exit 0).
|
|
10
|
+
# Depends on jq for the stdin parse.
|
|
11
|
+
#
|
|
12
|
+
# This is local fast-feedback. The durable enforcement is branch protection
|
|
13
|
+
# on GitHub (see .claude/rules/branch-naming.md → "Leverage GitHub automations").
|
|
14
|
+
|
|
15
|
+
set -uo pipefail
|
|
16
|
+
|
|
17
|
+
input=$(cat 2>/dev/null)
|
|
18
|
+
cmd=$(printf '%s' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
19
|
+
[[ -z "$cmd" ]] && exit 0
|
|
20
|
+
|
|
21
|
+
# Only care about commit commands (not log/show/commit-graph/etc.)
|
|
22
|
+
printf '%s' "$cmd" | grep -Eq '(^|[;&|[:space:]])git[[:space:]]+(.*[[:space:]])?commit([[:space:]]|$)' || exit 0
|
|
23
|
+
|
|
24
|
+
# Resolve the directory the commit will actually run in — NOT CLAUDE_PROJECT_DIR,
|
|
25
|
+
# which is always the main checkout. An agent in a linked worktree commits via
|
|
26
|
+
# `cd <worktree> && git commit` or `git -C <worktree> commit`; honor that so we
|
|
27
|
+
# read the worktree's real branch instead of false-blocking on the main checkout.
|
|
28
|
+
dir=""
|
|
29
|
+
if [[ "$cmd" =~ git[[:space:]]+-C[[:space:]]+([^[:space:]]+) ]]; then
|
|
30
|
+
dir="${BASH_REMATCH[1]}"
|
|
31
|
+
elif [[ "$cmd" =~ (^|[\&\;\|])[[:space:]]*cd[[:space:]]+([^[:space:]\&\;\|]+) ]]; then
|
|
32
|
+
dir="${BASH_REMATCH[2]}"
|
|
33
|
+
fi
|
|
34
|
+
dir="${dir:-${CLAUDE_PROJECT_DIR:-$PWD}}"
|
|
35
|
+
# strip surrounding quotes
|
|
36
|
+
dir="${dir%\"}"; dir="${dir#\"}"; dir="${dir%\'}"; dir="${dir#\'}"
|
|
37
|
+
branch=$(git -C "$dir" rev-parse --abbrev-ref HEAD 2>/dev/null) || exit 0
|
|
38
|
+
|
|
39
|
+
if [[ "$branch" == "main" || "$branch" == "develop" ]]; then
|
|
40
|
+
echo "BLOCKED: direct commit to '$branch'. No direct commits to the base branch." >&2
|
|
41
|
+
echo "Start a branch first: /task-start <issue> (or git checkout -B <kind>/<issue>-<slug> origin/$branch)." >&2
|
|
42
|
+
echo "Then commit there and open a PR. See .claude/rules/branch-naming.md." >&2
|
|
43
|
+
exit 2
|
|
44
|
+
fi
|
|
45
|
+
exit 0
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# kit-local-status.sh — SessionStart hook. Announces the local model layer (mlx_lm.server)
|
|
3
|
+
# when it is enabled AND alive: one branded banner line so the session knows local chores
|
|
4
|
+
# (digest, summaries, board sync) run at $0 API cost. Silent when disabled.
|
|
5
|
+
#
|
|
6
|
+
# Enabled + DOWN (#313): prints a persistent notice EVERY session until the server is up
|
|
7
|
+
# or the user dismisses it (kit-doctor --dismiss-local, or KIT_LOCAL_DISMISS=1) — a dismiss
|
|
8
|
+
# sticks until the next x.y kit update. Never blocks the session (always exit 0).
|
|
9
|
+
#
|
|
10
|
+
# Setup + API: scripts/lib/kit-local.sh (plan #285, issues #286 #313).
|
|
11
|
+
|
|
12
|
+
set -uo pipefail
|
|
13
|
+
ROOT="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null)}"
|
|
14
|
+
cd "$ROOT" 2>/dev/null || exit 0
|
|
15
|
+
|
|
16
|
+
[[ -f scripts/lib/kit-local.sh ]] || exit 0
|
|
17
|
+
# shellcheck source=/dev/null
|
|
18
|
+
source scripts/lib/kit-local.sh 2>/dev/null || exit 0
|
|
19
|
+
|
|
20
|
+
if kit_local_alive; then
|
|
21
|
+
NOTE="local: $(kit_local_model_tag) viva @ :${KIT_LOCAL_PORT} · chores NL a \$0"
|
|
22
|
+
elif [[ "$KIT_LOCAL_ENABLED" == "true" ]] && ! kit_local_dismissed; then
|
|
23
|
+
# persistent until resolved or dismissed (#313) — re-shown every SessionStart
|
|
24
|
+
NOTE="local: capa caída @ :${KIT_LOCAL_PORT} — /kit-doctor la instala/levanta · dismiss: /kit-doctor --dismiss-local (o KIT_LOCAL_DISMISS=1)"
|
|
25
|
+
else
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
if [[ -f .claude/lib/kit-sigil.sh ]]; then
|
|
30
|
+
# shellcheck source=/dev/null
|
|
31
|
+
source .claude/lib/kit-sigil.sh 2>/dev/null && kit_sigil "kit-local" "$NOTE" && exit 0
|
|
32
|
+
fi
|
|
33
|
+
echo "claude-kit · kit-local · $NOTE"
|
|
34
|
+
exit 0
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SessionStart hook — surface a claude-kit update notice, CLI-style. Scaffolded by claude-kit.
|
|
3
|
+
# stdout is injected into the session context by Claude Code. Best-effort + always a safe no-op:
|
|
4
|
+
# it never blocks the session and exits 0 even when it can't determine versions.
|
|
5
|
+
[[ -f ./scripts/kit-version-check.sh ]] && bash ./scripts/kit-version-check.sh --target "$(pwd)" 2>/dev/null
|
|
6
|
+
exit 0
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SessionEnd hook — capture UNSYNCED local work to MemPalace so an abrupt close
|
|
3
|
+
# doesn't silently lose it (wing={{WING}}).
|
|
4
|
+
#
|
|
5
|
+
# Triggers a "resume here" note ONLY when the current branch has work that isn't
|
|
6
|
+
# pushed: a dirty tree or commits ahead of upstream. Gone-remote branches, stashes
|
|
7
|
+
# and extra worktrees persist across sessions, so they're the SessionStart
|
|
8
|
+
# repo-hygiene hook's job (read-only warnings) + /kit-gc — including them here would
|
|
9
|
+
# spam a note every session. Stashes are listed as context when something else fires.
|
|
10
|
+
#
|
|
11
|
+
# Claude is also instructed (CLAUDE.md / .claude/rules/mempalace.md) to write this
|
|
12
|
+
# follow-up via mempalace_add_drawer (room=planning) when wrapping up — this bash
|
|
13
|
+
# hook is the safety net for when it didn't. Never blocks the session (always exit 0).
|
|
14
|
+
set -uo pipefail
|
|
15
|
+
|
|
16
|
+
WING="{{WING}}"
|
|
17
|
+
ROOT="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null)}"
|
|
18
|
+
cd "$ROOT" 2>/dev/null || exit 0
|
|
19
|
+
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0
|
|
20
|
+
|
|
21
|
+
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
22
|
+
|
|
23
|
+
dirty=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
|
|
24
|
+
up=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || true)
|
|
25
|
+
if [[ -n "$up" ]]; then
|
|
26
|
+
ahead=$(git rev-list --count "${up}..HEAD" 2>/dev/null || echo 0)
|
|
27
|
+
else
|
|
28
|
+
ahead=$(git rev-list --count "origin/develop..HEAD" 2>/dev/null || echo 0)
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Fully synced — nothing to capture.
|
|
32
|
+
[[ "${dirty:-0}" -eq 0 && "${ahead:-0}" -eq 0 ]] && exit 0
|
|
33
|
+
|
|
34
|
+
# Dedupe: identical (branch + HEAD + dirty fileset) -> one note across sessions.
|
|
35
|
+
head=$(git rev-parse --short HEAD 2>/dev/null || echo none)
|
|
36
|
+
sig=$(printf '%s|%s|%s' "$branch" "$head" "$(git status --porcelain 2>/dev/null)" | cksum | cut -d' ' -f1)
|
|
37
|
+
|
|
38
|
+
OUTDIR="${HOME}/.claude/kit-followups/${WING}"
|
|
39
|
+
mkdir -p "$OUTDIR" 2>/dev/null || exit 0
|
|
40
|
+
slug=$(printf '%s' "$branch" | tr -c 'A-Za-z0-9._-' '-')
|
|
41
|
+
NOTE="${OUTDIR}/resume-${slug}-${sig}.md"
|
|
42
|
+
[[ -f "$NOTE" ]] && exit 0 # this exact state already captured
|
|
43
|
+
|
|
44
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo unknown)
|
|
45
|
+
dtip=$(git log -1 --format='%h %s' origin/develop 2>/dev/null || echo unknown)
|
|
46
|
+
|
|
47
|
+
{
|
|
48
|
+
echo "# Resume — unsynced local work on \`$branch\` ($ts)"
|
|
49
|
+
echo
|
|
50
|
+
echo "Session ended with work that was **not pushed**. Pick up here next session."
|
|
51
|
+
echo
|
|
52
|
+
echo "- wing: $WING - branch: \`$branch\` - HEAD: \`$head\`"
|
|
53
|
+
echo "- develop tip: $dtip"
|
|
54
|
+
if [[ "${ahead:-0}" -gt 0 ]]; then
|
|
55
|
+
echo "- unpushed commits ($ahead):"
|
|
56
|
+
git log --format=' - %h %s' "${up:-origin/develop}..HEAD" 2>/dev/null | head -20
|
|
57
|
+
fi
|
|
58
|
+
if [[ "${dirty:-0}" -gt 0 ]]; then
|
|
59
|
+
echo "- uncommitted changes ($dirty):"
|
|
60
|
+
git status --porcelain 2>/dev/null | head -40 | sed 's/^/ - /'
|
|
61
|
+
fi
|
|
62
|
+
st=$(git stash list 2>/dev/null | wc -l | tr -d ' ')
|
|
63
|
+
[[ "${st:-0}" -gt 0 ]] && echo "- stashes present: $st (review: git stash list)"
|
|
64
|
+
if command -v gh >/dev/null 2>&1; then
|
|
65
|
+
prs=$(gh pr list --head "$branch" --json number,title -q '.[]|" - #\(.number) \(.title)"' 2>/dev/null)
|
|
66
|
+
[[ -n "$prs" ]] && { echo "- open PR(s) for this branch:"; printf '%s\n' "$prs"; }
|
|
67
|
+
fi
|
|
68
|
+
echo
|
|
69
|
+
echo "_Next: \`git checkout $branch\` then commit + push / open a PR. If this is orphaned WIP on a base branch, move it onto a \`<kind>/<issue>-<slug>\` branch first._"
|
|
70
|
+
} > "$NOTE" 2>/dev/null || exit 0
|
|
71
|
+
|
|
72
|
+
# Local model layer: when a local mlx_lm.server is alive (scripts/lib/kit-local.sh), prepend a
|
|
73
|
+
# terse drafted "resume here" summary (branch, pending, next step, refs) at $0 API cost.
|
|
74
|
+
# Fallback always: server down / lib missing / draft empty -> deterministic note as-is.
|
|
75
|
+
if [[ -f scripts/lib/kit-local.sh ]]; then
|
|
76
|
+
# shellcheck source=/dev/null
|
|
77
|
+
if source scripts/lib/kit-local.sh 2>/dev/null && kit_local_alive; then
|
|
78
|
+
summary=$(KIT_LOCAL_TIMEOUT=20 kit_local_chat \
|
|
79
|
+
"You are the kit assistant. Draft a terse 'resume here' note as 3-5 bullets: branch, what is pending, the concrete next step, PR/issue refs if present. Bullets only, no title, no closing line." \
|
|
80
|
+
"$(cat "$NOTE" 2>/dev/null)" 300 2>/dev/null || true)
|
|
81
|
+
if [[ -n "${summary:-}" ]]; then
|
|
82
|
+
tmp="${NOTE}.tmp"
|
|
83
|
+
{
|
|
84
|
+
echo "## Summary (local: $(kit_local_model_tag))"
|
|
85
|
+
echo
|
|
86
|
+
printf '%s\n\n' "$summary"
|
|
87
|
+
cat "$NOTE"
|
|
88
|
+
} > "$tmp" 2>/dev/null && mv "$tmp" "$NOTE" 2>/dev/null || rm -f "$tmp" 2>/dev/null
|
|
89
|
+
fi
|
|
90
|
+
fi
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Keep the followups dir bounded (last 20 notes).
|
|
94
|
+
ls -t "$OUTDIR"/resume-*.md 2>/dev/null | tail -n +21 | while read -r old; do rm -f "$old" 2>/dev/null; done
|
|
95
|
+
|
|
96
|
+
mempalace mine "$OUTDIR" --wing "$WING" --no-gitignore >/dev/null 2>&1 || true
|
|
97
|
+
exit 0
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PreCompact hook — emergency sweep before context compression (wing={{WING}}).
|
|
3
|
+
# Claude is instructed via CLAUDE.md to call MCP save tools first; this is the safety net.
|
|
4
|
+
mempalace mine ~/.claude/projects/{{CLAUDE_PROJECT_SLUG}}/ --mode convos --wing {{WING}} 2>/dev/null || true
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Stop hook — sweep this project's Claude sessions into MemPalace (wing={{WING}}).
|
|
3
|
+
# Scaffolded by claude-kit. Safe no-op if `mempalace` CLI is not installed.
|
|
4
|
+
mempalace mine ~/.claude/projects/{{CLAUDE_PROJECT_SLUG}}/ --mode convos --wing {{WING}} 2>/dev/null || true
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SessionStart hook — load MemPalace wake-up context for this project (wing={{WING}}).
|
|
3
|
+
# Scaffolded by claude-kit. stdout is injected into the session context by Claude Code.
|
|
4
|
+
# Safe no-op if the `mempalace` CLI is not installed.
|
|
5
|
+
# NOTE: uses `wake-up --wing` on purpose, NOT `mempalace hook run --hook session-start` —
|
|
6
|
+
# `hook run` derives the wing implicitly and can file into the wrong wing; `--wing` is explicit.
|
|
7
|
+
command -v mempalace >/dev/null 2>&1 || exit 0
|
|
8
|
+
mempalace wake-up --wing {{WING}} 2>/dev/null || true
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PreToolUse(Bash) gate — runs a project-defined check before `git push`.
|
|
3
|
+
# Scaffolded by claude-kit. SELF-PASSING by design:
|
|
4
|
+
# - only acts on Bash commands containing 'git push'
|
|
5
|
+
# - passes (continue:true) if prePush is disabled or no command is configured
|
|
6
|
+
# - blocks (continue:false) only when the configured check command exits non-zero
|
|
7
|
+
# Config lives in .claude/kit.config.json -> .prePush { enabled, command }.
|
|
8
|
+
set -uo pipefail
|
|
9
|
+
|
|
10
|
+
INPUT="$(cat)"
|
|
11
|
+
CMD="$(printf '%s' "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null)"
|
|
12
|
+
|
|
13
|
+
# Not a push? let it through.
|
|
14
|
+
case "$CMD" in
|
|
15
|
+
*"git push"*) ;;
|
|
16
|
+
*) echo '{"continue": true}'; exit 0 ;;
|
|
17
|
+
esac
|
|
18
|
+
|
|
19
|
+
CFG=".claude/kit.config.json"
|
|
20
|
+
ENABLED="$(jq -r '.prePush.enabled // false' "$CFG" 2>/dev/null)"
|
|
21
|
+
CHECK="$(jq -r '.prePush.command // ""' "$CFG" 2>/dev/null)"
|
|
22
|
+
|
|
23
|
+
# Disabled or nothing to verify? let it through (projects without a check never block).
|
|
24
|
+
if [[ "$ENABLED" != "true" || -z "$CHECK" ]]; then
|
|
25
|
+
echo '{"continue": true}'; exit 0
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Run the check and gate on its exit code.
|
|
29
|
+
OUT="$(eval "$CHECK" 2>&1)"; RC=$?
|
|
30
|
+
if [[ $RC -eq 0 ]]; then
|
|
31
|
+
echo '{"continue": true}'
|
|
32
|
+
else
|
|
33
|
+
REASON="$(printf 'pre-push check failed (%s):\n%s' "$CHECK" "$OUT" | tail -c 800 | jq -Rs .)"
|
|
34
|
+
echo "{\"continue\": false, \"stopReason\": $REASON}"
|
|
35
|
+
fi
|
|
36
|
+
exit 0
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# repo-hygiene.sh — SessionStart hook (READ-ONLY). Scaffolded by claude-kit.
|
|
3
|
+
#
|
|
4
|
+
# Surfaces repo state that silently accumulates into a mess:
|
|
5
|
+
# - working on the base branch (main) directly, or a non-conventional branch name
|
|
6
|
+
# - branch sitting on a stale base (commits behind the base branch)
|
|
7
|
+
# - dirty / uncommitted working tree
|
|
8
|
+
# - stashes piling up
|
|
9
|
+
# - local branches whose remote is gone (merged + remote-deleted → prune them)
|
|
10
|
+
# - extra worktrees lingering
|
|
11
|
+
#
|
|
12
|
+
# Prints nothing when the repo is clean. Never fails the session (always exit 0).
|
|
13
|
+
# Enforcement that needs the network or affects everyone belongs in GitHub
|
|
14
|
+
# automations (see .claude/rules/branch-naming.md); this is fast local feedback.
|
|
15
|
+
|
|
16
|
+
set -uo pipefail
|
|
17
|
+
ROOT="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null)}"
|
|
18
|
+
cd "$ROOT" 2>/dev/null || exit 0
|
|
19
|
+
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0
|
|
20
|
+
|
|
21
|
+
BASE="origin/main"
|
|
22
|
+
WARN=()
|
|
23
|
+
|
|
24
|
+
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
25
|
+
|
|
26
|
+
# 1. On the base branch directly?
|
|
27
|
+
if [[ "$branch" == "main" || "$branch" == "develop" ]]; then
|
|
28
|
+
WARN+=("• On '$branch' directly — start work with /task-start <issue> (no direct commits to the base branch).")
|
|
29
|
+
# 2. Non-conventional branch name (not <kind>/<issue>-<slug> and not a bot branch)?
|
|
30
|
+
elif [[ ! "$branch" =~ ^(feat|fix|task|chore|security|scaffold|ci|adr|spike|plan)/[0-9]+- ]] \
|
|
31
|
+
&& [[ ! "$branch" =~ ^(agent|claude)/ ]]; then
|
|
32
|
+
WARN+=("• Branch '$branch' doesn't match <kind>/<issue>-<slug> — see .claude/rules/branch-naming.md.")
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# 3. Stale base — commits behind the base branch (uses last fetch; no network here)
|
|
36
|
+
if git rev-parse --verify "$BASE" >/dev/null 2>&1 && [[ "$branch" != "main" && "$branch" != "develop" ]]; then
|
|
37
|
+
behind=$(git rev-list --count "HEAD..$BASE" 2>/dev/null || echo 0)
|
|
38
|
+
if [[ "${behind:-0}" -gt 10 ]]; then
|
|
39
|
+
WARN+=("• Branch is $behind commits behind $BASE (stale base, last fetch) — rebase before committing to avoid reverting merged work.")
|
|
40
|
+
fi
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# 4. Dirty working tree
|
|
44
|
+
dirty=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
|
|
45
|
+
[[ "${dirty:-0}" -gt 0 ]] && WARN+=("• Working tree has $dirty uncommitted change(s) — commit, PR, or discard; don't let work go stale.")
|
|
46
|
+
|
|
47
|
+
# 5. Stashes
|
|
48
|
+
stashes=$(git stash list 2>/dev/null | wc -l | tr -d ' ')
|
|
49
|
+
[[ "${stashes:-0}" -gt 0 ]] && WARN+=("• $stashes stash(es) present — review with: git stash list (old WIP rots fast).")
|
|
50
|
+
|
|
51
|
+
# 6. Local branches whose upstream is gone (merged + remote-deleted → safe to prune)
|
|
52
|
+
gone=$(git branch -vv 2>/dev/null | grep ': gone]' | wc -l | tr -d ' ')
|
|
53
|
+
[[ "${gone:-0}" -gt 0 ]] && WARN+=("• $gone local branch(es) with a deleted remote — run /task-gc to prune merged branches + worktrees.")
|
|
54
|
+
|
|
55
|
+
# 7. Extra worktrees
|
|
56
|
+
wt=$(git worktree list 2>/dev/null | wc -l | tr -d ' ')
|
|
57
|
+
[[ "${wt:-0}" -gt 2 ]] && WARN+=("• $wt worktrees active — /task-gc removes ones whose PR already merged.")
|
|
58
|
+
|
|
59
|
+
if [[ ${#WARN[@]} -gt 0 ]]; then
|
|
60
|
+
# claude-kit terminal identity — the locked ⡶ seed-head leader, once, only when
|
|
61
|
+
# there's output. We cd'd to $ROOT, so the lib path is reliable; fall back inline.
|
|
62
|
+
if [ -f "$ROOT/.claude/lib/kit-sigil.sh" ]; then
|
|
63
|
+
# shellcheck source=/dev/null
|
|
64
|
+
source "$ROOT/.claude/lib/kit-sigil.sh"
|
|
65
|
+
kit_sigil "" "repo hygiene · $branch"
|
|
66
|
+
else
|
|
67
|
+
printf '\n· claude-kit repo hygiene · %s\n' "$branch"
|
|
68
|
+
fi
|
|
69
|
+
printf '%s\n' "${WARN[@]}"
|
|
70
|
+
echo " (read-only check — run /task-gc to clean, /task-sync for board state)"
|
|
71
|
+
fi
|
|
72
|
+
exit 0
|