@protoboxai/codeloop 0.3.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 +589 -0
- package/dist/commands/adopt.d.ts +2 -0
- package/dist/commands/adopt.js +26 -0
- package/dist/commands/adopt.js.map +1 -0
- package/dist/commands/brief.d.ts +2 -0
- package/dist/commands/brief.js +22 -0
- package/dist/commands/brief.js.map +1 -0
- package/dist/commands/card.d.ts +6 -0
- package/dist/commands/card.js +159 -0
- package/dist/commands/card.js.map +1 -0
- package/dist/commands/check.d.ts +4 -0
- package/dist/commands/check.js +76 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/cloud.d.ts +8 -0
- package/dist/commands/cloud.js +123 -0
- package/dist/commands/cloud.js.map +1 -0
- package/dist/commands/guard.d.ts +2 -0
- package/dist/commands/guard.js +26 -0
- package/dist/commands/guard.js.map +1 -0
- package/dist/commands/import.d.ts +2 -0
- package/dist/commands/import.js +24 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/inbox.d.ts +2 -0
- package/dist/commands/inbox.js +48 -0
- package/dist/commands/inbox.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +142 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.js +125 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/lane.d.ts +2 -0
- package/dist/commands/lane.js +100 -0
- package/dist/commands/lane.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.js +35 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +77 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/mock.d.ts +3 -0
- package/dist/commands/mock.js +22 -0
- package/dist/commands/mock.js.map +1 -0
- package/dist/commands/pack.d.ts +2 -0
- package/dist/commands/pack.js +19 -0
- package/dist/commands/pack.js.map +1 -0
- package/dist/commands/publish.d.ts +2 -0
- package/dist/commands/publish.js +125 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/remove.d.ts +2 -0
- package/dist/commands/remove.js +31 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/render.d.ts +5 -0
- package/dist/commands/render.js +47 -0
- package/dist/commands/render.js.map +1 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +45 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/scan.d.ts +2 -0
- package/dist/commands/scan.js +26 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/schedule.d.ts +2 -0
- package/dist/commands/schedule.js +51 -0
- package/dist/commands/schedule.js.map +1 -0
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.js +85 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/serve.d.ts +7 -0
- package/dist/commands/serve.js +126 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/spec.d.ts +3 -0
- package/dist/commands/spec.js +64 -0
- package/dist/commands/spec.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.js +251 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.js +83 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/verify.d.ts +3 -0
- package/dist/commands/verify.js +75 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/watch.d.ts +6 -0
- package/dist/commands/watch.js +111 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/wiki.d.ts +3 -0
- package/dist/commands/wiki.js +85 -0
- package/dist/commands/wiki.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +86 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agent.d.ts +27 -0
- package/dist/lib/agent.js +178 -0
- package/dist/lib/agent.js.map +1 -0
- package/dist/lib/board.d.ts +38 -0
- package/dist/lib/board.js +86 -0
- package/dist/lib/board.js.map +1 -0
- package/dist/lib/cards.d.ts +82 -0
- package/dist/lib/cards.js +107 -0
- package/dist/lib/cards.js.map +1 -0
- package/dist/lib/clock.d.ts +5 -0
- package/dist/lib/clock.js +14 -0
- package/dist/lib/clock.js.map +1 -0
- package/dist/lib/cloud.d.ts +122 -0
- package/dist/lib/cloud.js +580 -0
- package/dist/lib/cloud.js.map +1 -0
- package/dist/lib/competitors.d.ts +28 -0
- package/dist/lib/competitors.js +90 -0
- package/dist/lib/competitors.js.map +1 -0
- package/dist/lib/config.d.ts +7 -0
- package/dist/lib/config.js +25 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/cron.d.ts +5 -0
- package/dist/lib/cron.js +82 -0
- package/dist/lib/cron.js.map +1 -0
- package/dist/lib/detect.d.ts +13 -0
- package/dist/lib/detect.js +60 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/engine.d.ts +88 -0
- package/dist/lib/engine.js +435 -0
- package/dist/lib/engine.js.map +1 -0
- package/dist/lib/flow.d.ts +44 -0
- package/dist/lib/flow.js +121 -0
- package/dist/lib/flow.js.map +1 -0
- package/dist/lib/glob.d.ts +2 -0
- package/dist/lib/glob.js +10 -0
- package/dist/lib/glob.js.map +1 -0
- package/dist/lib/import.d.ts +13 -0
- package/dist/lib/import.js +127 -0
- package/dist/lib/import.js.map +1 -0
- package/dist/lib/inbox.d.ts +42 -0
- package/dist/lib/inbox.js +65 -0
- package/dist/lib/inbox.js.map +1 -0
- package/dist/lib/lane.d.ts +71 -0
- package/dist/lib/lane.js +105 -0
- package/dist/lib/lane.js.map +1 -0
- package/dist/lib/lock.d.ts +6 -0
- package/dist/lib/lock.js +64 -0
- package/dist/lib/lock.js.map +1 -0
- package/dist/lib/mcp.d.ts +2 -0
- package/dist/lib/mcp.js +57 -0
- package/dist/lib/mcp.js.map +1 -0
- package/dist/lib/mock.d.ts +17 -0
- package/dist/lib/mock.js +137 -0
- package/dist/lib/mock.js.map +1 -0
- package/dist/lib/pack.d.ts +24 -0
- package/dist/lib/pack.js +77 -0
- package/dist/lib/pack.js.map +1 -0
- package/dist/lib/proposals.d.ts +48 -0
- package/dist/lib/proposals.js +240 -0
- package/dist/lib/proposals.js.map +1 -0
- package/dist/lib/render.d.ts +7 -0
- package/dist/lib/render.js +84 -0
- package/dist/lib/render.js.map +1 -0
- package/dist/lib/research.d.ts +8 -0
- package/dist/lib/research.js +39 -0
- package/dist/lib/research.js.map +1 -0
- package/dist/lib/run.d.ts +38 -0
- package/dist/lib/run.js +215 -0
- package/dist/lib/run.js.map +1 -0
- package/dist/lib/scaffold.d.ts +16 -0
- package/dist/lib/scaffold.js +175 -0
- package/dist/lib/scaffold.js.map +1 -0
- package/dist/lib/scan.d.ts +22 -0
- package/dist/lib/scan.js +85 -0
- package/dist/lib/scan.js.map +1 -0
- package/dist/lib/schedule.d.ts +20 -0
- package/dist/lib/schedule.js +66 -0
- package/dist/lib/schedule.js.map +1 -0
- package/dist/lib/server.d.ts +68 -0
- package/dist/lib/server.js +235 -0
- package/dist/lib/server.js.map +1 -0
- package/dist/lib/shell.d.ts +1 -0
- package/dist/lib/shell.js +25 -0
- package/dist/lib/shell.js.map +1 -0
- package/dist/lib/skills.d.ts +20 -0
- package/dist/lib/skills.js +92 -0
- package/dist/lib/skills.js.map +1 -0
- package/dist/lib/spec.d.ts +24 -0
- package/dist/lib/spec.js +102 -0
- package/dist/lib/spec.js.map +1 -0
- package/dist/lib/stats.d.ts +13 -0
- package/dist/lib/stats.js +43 -0
- package/dist/lib/stats.js.map +1 -0
- package/dist/lib/verify.d.ts +25 -0
- package/dist/lib/verify.js +135 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/lib/version.d.ts +10 -0
- package/dist/lib/version.js +27 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/lib/wiki.d.ts +51 -0
- package/dist/lib/wiki.js +164 -0
- package/dist/lib/wiki.js.map +1 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.js +8 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/installer.d.ts +30 -0
- package/dist/registry/installer.js +133 -0
- package/dist/registry/installer.js.map +1 -0
- package/dist/registry/local-index.d.ts +32 -0
- package/dist/registry/local-index.js +58 -0
- package/dist/registry/local-index.js.map +1 -0
- package/dist/registry/lockfile.d.ts +40 -0
- package/dist/registry/lockfile.js +85 -0
- package/dist/registry/lockfile.js.map +1 -0
- package/dist/registry/security.d.ts +25 -0
- package/dist/registry/security.js +100 -0
- package/dist/registry/security.js.map +1 -0
- package/dist/registry/skill-schema.d.ts +30 -0
- package/dist/registry/skill-schema.js +95 -0
- package/dist/registry/skill-schema.js.map +1 -0
- package/dist/ui/404.html +1 -0
- package/dist/ui/_next/static/6wzGE5sCtbYkSyhMWxL32/_buildManifest.js +1 -0
- package/dist/ui/_next/static/6wzGE5sCtbYkSyhMWxL32/_ssgManifest.js +1 -0
- package/dist/ui/_next/static/chunks/255-54d3085ce94738a4.js +1 -0
- package/dist/ui/_next/static/chunks/423-bb541b7ae2733575.js +1 -0
- package/dist/ui/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +1 -0
- package/dist/ui/_next/static/chunks/app/_not-found/page-d6bc774f7acb716e.js +1 -0
- package/dist/ui/_next/static/chunks/app/layout-e5fc8e78e1c8da95.js +1 -0
- package/dist/ui/_next/static/chunks/app/page-0c34b6e119cef236.js +1 -0
- package/dist/ui/_next/static/chunks/framework-de98b93a850cfc71.js +1 -0
- package/dist/ui/_next/static/chunks/main-49fd204fc9037ea3.js +1 -0
- package/dist/ui/_next/static/chunks/main-app-c46afa2f48f3aaef.js +1 -0
- package/dist/ui/_next/static/chunks/pages/_app-7d307437aca18ad4.js +1 -0
- package/dist/ui/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +1 -0
- package/dist/ui/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/ui/_next/static/chunks/webpack-4a462cecab786e93.js +1 -0
- package/dist/ui/_next/static/css/1bf01240dbfd6088.css +1 -0
- package/dist/ui/index.html +1 -0
- package/dist/ui/index.txt +19 -0
- package/dist/watch/index.d.ts +21 -0
- package/dist/watch/index.js +88 -0
- package/dist/watch/index.js.map +1 -0
- package/dist/watch/reporter.d.ts +11 -0
- package/dist/watch/reporter.js +44 -0
- package/dist/watch/reporter.js.map +1 -0
- package/dist/watch/signals.d.ts +38 -0
- package/dist/watch/signals.js +119 -0
- package/dist/watch/signals.js.map +1 -0
- package/dist/watch/triggers.d.ts +10 -0
- package/dist/watch/triggers.js +67 -0
- package/dist/watch/triggers.js.map +1 -0
- package/package.json +64 -0
- package/registry/index.json +106 -0
- package/starters/generic.yaml +95 -0
- package/starters/go.yaml +99 -0
- package/starters/node-typescript.yaml +108 -0
- package/starters/python.yaml +105 -0
- package/templates/ci/codeloop-pr.yml +29 -0
- package/templates/ci/codeloop-prod.yml +27 -0
- package/templates/ci/codeloop-staging.yml +34 -0
- package/templates/codeloop/board.json +5 -0
- package/templates/codeloop/gotchas.md +13 -0
- package/templates/codeloop/patterns.md +15 -0
- package/templates/codeloop/principles.md +49 -0
- package/templates/codeloop/rules.md +23 -0
- package/templates/commands/commit.md +255 -0
- package/templates/commands/debug.md +142 -0
- package/templates/commands/deploy.md +144 -0
- package/templates/commands/design.md +102 -0
- package/templates/commands/manage.md +77 -0
- package/templates/commands/plan.md +84 -0
- package/templates/commands/qa.md +155 -0
- package/templates/commands/reflect.md +93 -0
- package/templates/commands/ship.md +187 -0
- package/templates/commands/test.md +133 -0
- package/templates/hooks/commit-msg +8 -0
- package/templates/lanes/analyze.yaml +25 -0
- package/templates/lanes/build.yaml +45 -0
- package/templates/lanes/deploy.yaml +24 -0
- package/templates/lanes/learn.yaml +20 -0
- package/templates/lanes/market.yaml +25 -0
- package/templates/lanes/plan.yaml +24 -0
- package/templates/lanes/scan.yaml +11 -0
- package/templates/lanes/triage.yaml +24 -0
- package/templates/mock/template.html +82 -0
- package/templates/seeds/go-gotchas.md +28 -0
- package/templates/seeds/go-patterns.md +22 -0
- package/templates/seeds/node-typescript-gotchas.md +30 -0
- package/templates/seeds/node-typescript-patterns.md +27 -0
- package/templates/seeds/python-gotchas.md +30 -0
- package/templates/seeds/python-patterns.md +19 -0
- package/templates/seeds/universal-gotchas.md +11 -0
- package/templates/seeds/universal-patterns.md +11 -0
- package/templates/spec/plan.md +7 -0
- package/templates/spec/research.md +19 -0
- package/templates/spec/spec.md +14 -0
- package/templates/spec/tasks.md +10 -0
- package/templates/tasks/todo.md +3 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Session-end reflection — capture what you learned
|
|
3
|
+
allowed-tools: Read, Write, Edit, Glob, Grep, AskUserQuestion, Bash
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- codeloop-version: 0.3.0 -->
|
|
7
|
+
|
|
8
|
+
# /reflect
|
|
9
|
+
|
|
10
|
+
Pause and think about what happened this session. Propose changes — but **nothing gets written without approval**.
|
|
11
|
+
|
|
12
|
+
> **Tip:** For lightweight inline reflection during commits, `/commit` Phase 2 handles it automatically. Use standalone `/reflect` for deeper multi-commit session reviews.
|
|
13
|
+
|
|
14
|
+
## Phase 1: Think
|
|
15
|
+
|
|
16
|
+
Look back at the session and identify:
|
|
17
|
+
|
|
18
|
+
1. **Gotchas** — Unexpected behavior, hidden dependencies, undocumented quirks
|
|
19
|
+
2. **Better approaches** — Wrong turns, wasted time, things you'd do differently
|
|
20
|
+
3. **Patterns** — Approaches that worked well, shortcuts discovered
|
|
21
|
+
4. **Frequency updates** — Gotchas re-encountered this session (increment freq)
|
|
22
|
+
|
|
23
|
+
Read `.codeloop/gotchas.md` and `.codeloop/patterns.md` to check for existing entries that were re-encountered.
|
|
24
|
+
|
|
25
|
+
## Phase 2: Propose
|
|
26
|
+
|
|
27
|
+
Present a **numbered list** of everything you want to do. Group by type:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
## Proposed changes
|
|
31
|
+
|
|
32
|
+
### Gotchas
|
|
33
|
+
1. NEW: "<description>" → .codeloop/gotchas.md [freq:1]
|
|
34
|
+
2. INCREMENT: "<existing gotcha>" freq:2 → freq:3
|
|
35
|
+
|
|
36
|
+
### Patterns
|
|
37
|
+
3. NEW: "<description>" → .codeloop/patterns.md
|
|
38
|
+
|
|
39
|
+
### Rules
|
|
40
|
+
4. PROMOTE: "<gotcha at freq 10+>" → .codeloop/rules.md
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Then use **AskUserQuestion** with multiSelect to let the user pick which items to apply. Include all items as options.
|
|
44
|
+
|
|
45
|
+
## Phase 3: Apply
|
|
46
|
+
|
|
47
|
+
Only apply the items the user selected. Skip everything else.
|
|
48
|
+
|
|
49
|
+
### Writing gotchas
|
|
50
|
+
|
|
51
|
+
New gotchas follow this format:
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
### [freq:1] Short descriptive title
|
|
55
|
+
**Applies to:** <scope or context>
|
|
56
|
+
**Source:** Discovered <date>
|
|
57
|
+
|
|
58
|
+
<Description of the gotcha, what went wrong, and the fix>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Place in the appropriate section (create section if needed, matching config.yaml scope sections).
|
|
62
|
+
|
|
63
|
+
### Incrementing frequency
|
|
64
|
+
|
|
65
|
+
Find the existing entry, update `[freq:N]` to `[freq:N+1]`.
|
|
66
|
+
|
|
67
|
+
### Writing patterns
|
|
68
|
+
|
|
69
|
+
New patterns follow this format:
|
|
70
|
+
|
|
71
|
+
```markdown
|
|
72
|
+
### Pattern Title
|
|
73
|
+
**Confidence:** LOW/MEDIUM/HIGH
|
|
74
|
+
**Applies to:** <scope or context>
|
|
75
|
+
|
|
76
|
+
<Description of the pattern with code example if applicable>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Promoting to rules
|
|
80
|
+
|
|
81
|
+
When a gotcha reaches freq >= 10, suggest promoting to `.codeloop/rules.md`:
|
|
82
|
+
1. Write a concise rule in rules.md
|
|
83
|
+
2. Add a note to the gotcha: `**Promoted to rules.md**`
|
|
84
|
+
|
|
85
|
+
After applying, one-line summary: what was saved and where.
|
|
86
|
+
|
|
87
|
+
## Rules
|
|
88
|
+
|
|
89
|
+
- If nothing worth saving, just say "Nothing new to capture" and stop
|
|
90
|
+
- No scoring rubrics, no ceremony
|
|
91
|
+
- Keep knowledge files concise — trim old low-freq entries if files get too long
|
|
92
|
+
- **Never write to any file without approval from Phase 2**
|
|
93
|
+
- Frequency = severity: the more a gotcha recurs, the more important it becomes
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Close the loop — QA, deploy staging, deploy prod, verify, close task
|
|
3
|
+
argument-hint: [--from-staging] [--dry-run]
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- codeloop-version: 0.3.0 -->
|
|
8
|
+
|
|
9
|
+
# /ship
|
|
10
|
+
|
|
11
|
+
Orchestrate the full pipeline from QA to production. Takes a task from code-complete to done.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
/ship # Full pipeline: QA → staging → prod → close
|
|
17
|
+
/ship --from-staging # Skip QA + staging (already staging-verified)
|
|
18
|
+
/ship --dry-run # Show what would happen without executing
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
`/ship` chains together existing skills in sequence:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/qa → /deploy staging → /deploy prod → /manage close
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Each step is a gate. If any step fails, the pipeline stops and creates a regression task.
|
|
30
|
+
|
|
31
|
+
## Phase 1: Pre-Flight
|
|
32
|
+
|
|
33
|
+
1. Read `.codeloop/config.yaml` — verify `deploy` section exists with non-empty staging and production commands (empty string = not configured → stop)
|
|
34
|
+
2. Read `.codeloop/board.json` — find the active task
|
|
35
|
+
3. If no active task → stop: "No active task found. Use `/plan` to create one."
|
|
36
|
+
4. Check current task labels to determine starting point:
|
|
37
|
+
- Has `env:prod-pass` → "Task already production-verified. Use `/manage close` to finish."
|
|
38
|
+
- Has `env:staging-pass` (or `--from-staging`) → skip to production deploy
|
|
39
|
+
- Has `env:local-pass` → skip to staging deploy
|
|
40
|
+
- No env labels → start from QA
|
|
41
|
+
|
|
42
|
+
5. If `--dry-run`, show the plan and stop:
|
|
43
|
+
```
|
|
44
|
+
## Ship Plan (dry run)
|
|
45
|
+
|
|
46
|
+
**Task**: t-003 — Add user authentication
|
|
47
|
+
**Starting from**: QA (no env labels)
|
|
48
|
+
|
|
49
|
+
Steps:
|
|
50
|
+
1. Run /qa (quality gate)
|
|
51
|
+
2. Deploy to staging + verify
|
|
52
|
+
3. Deploy to production + verify
|
|
53
|
+
4. Close task + archive
|
|
54
|
+
|
|
55
|
+
No actions taken.
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Phase 2: QA Gate
|
|
59
|
+
|
|
60
|
+
Skip if task already has `env:local-pass`.
|
|
61
|
+
|
|
62
|
+
1. Run the same checks as `/qa`:
|
|
63
|
+
- Quality checks for active scopes
|
|
64
|
+
- Diff scan
|
|
65
|
+
- Test suite
|
|
66
|
+
- Coverage gate
|
|
67
|
+
2. If **FAIL** → stop pipeline, report which check failed, create regression task
|
|
68
|
+
3. If **PASS** → add `env:local-pass` label, continue
|
|
69
|
+
|
|
70
|
+
Report progress:
|
|
71
|
+
```
|
|
72
|
+
## Ship Progress
|
|
73
|
+
|
|
74
|
+
[✓] QA gate passed
|
|
75
|
+
[ ] Deploy to staging
|
|
76
|
+
[ ] Deploy to production
|
|
77
|
+
[ ] Close task
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Phase 3: Deploy Staging
|
|
81
|
+
|
|
82
|
+
Skip if task already has `env:staging-pass`.
|
|
83
|
+
|
|
84
|
+
1. Run staging deploy command from config
|
|
85
|
+
2. If deploy fails → stop pipeline, add `env:staging-fail` label, create regression task
|
|
86
|
+
3. Wait 5 seconds, run staging verify command
|
|
87
|
+
4. If verify fails → stop pipeline, add `env:staging-fail` label, create regression task
|
|
88
|
+
5. If both succeed → add `env:staging-pass` label, continue
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
## Ship Progress
|
|
92
|
+
|
|
93
|
+
[✓] QA gate passed
|
|
94
|
+
[✓] Staging deployed + verified
|
|
95
|
+
[ ] Deploy to production
|
|
96
|
+
[ ] Close task
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Phase 4: Deploy Production
|
|
100
|
+
|
|
101
|
+
**Always confirm before production deploy:**
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
## Production Deploy
|
|
105
|
+
|
|
106
|
+
Task t-003 has passed QA and staging verification.
|
|
107
|
+
|
|
108
|
+
Ready to deploy to production?
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Use AskUserQuestion: **Deploy to production** / **Stop here** / **Abort and rollback**
|
|
112
|
+
|
|
113
|
+
If confirmed:
|
|
114
|
+
1. Run production deploy command from config
|
|
115
|
+
2. If deploy fails → stop, add `env:prod-fail` label, create regression task
|
|
116
|
+
3. Wait 5 seconds, run production verify command
|
|
117
|
+
4. If verify fails → stop, add `env:prod-fail` label, create regression task
|
|
118
|
+
5. If both succeed → add `env:prod-pass` label, continue
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
## Ship Progress
|
|
122
|
+
|
|
123
|
+
[✓] QA gate passed
|
|
124
|
+
[✓] Staging deployed + verified
|
|
125
|
+
[✓] Production deployed + verified
|
|
126
|
+
[ ] Close task
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Phase 5: Close
|
|
130
|
+
|
|
131
|
+
1. Update the board task:
|
|
132
|
+
- Set status to `done`
|
|
133
|
+
- Add label: `shipped`
|
|
134
|
+
2. Archive the task file:
|
|
135
|
+
- Move `tasks/todo.md` to `tasks/done/<task-slug>.md` (create dir if needed)
|
|
136
|
+
3. Final report
|
|
137
|
+
|
|
138
|
+
## Phase 6: Report
|
|
139
|
+
|
|
140
|
+
### On Success
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
## Shipped ✓
|
|
144
|
+
|
|
145
|
+
**Task**: t-003 — Add user authentication
|
|
146
|
+
**Pipeline**: QA → staging → production → done
|
|
147
|
+
|
|
148
|
+
| Stage | Status | Duration |
|
|
149
|
+
|-------|--------|----------|
|
|
150
|
+
| QA | ✓ pass | 12s |
|
|
151
|
+
| Staging | ✓ deployed + verified | 45s |
|
|
152
|
+
| Production | ✓ deployed + verified | 52s |
|
|
153
|
+
|
|
154
|
+
Task archived to `tasks/done/add-user-authentication.md`.
|
|
155
|
+
Board updated: t-003 → done.
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### On Failure
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
## Ship Failed at: staging deploy
|
|
162
|
+
|
|
163
|
+
**Task**: t-003 — Add user authentication
|
|
164
|
+
**Failed step**: Deploy to staging
|
|
165
|
+
**Error**: Exit code 1 — "Error: no instances available"
|
|
166
|
+
|
|
167
|
+
Regression task t-006 created: "Fix: staging deploy failure for auth feature"
|
|
168
|
+
Pipeline stopped. Fix the issue and re-run `/ship --from-staging`.
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Regression Task Creation
|
|
172
|
+
|
|
173
|
+
When any step fails:
|
|
174
|
+
1. Create a new task on the board:
|
|
175
|
+
- Title: "Fix: <failure summary>"
|
|
176
|
+
- Status: `backlog`
|
|
177
|
+
- Labels: `regression`, `env:<stage>-fail`
|
|
178
|
+
- Description: full error output, which step failed, and the original task reference
|
|
179
|
+
2. The original task stays at its current status (not moved to done)
|
|
180
|
+
|
|
181
|
+
## Rules
|
|
182
|
+
|
|
183
|
+
- **Always confirm production.** Never auto-deploy to production — the human makes the final call.
|
|
184
|
+
- **The pipeline is sequential.** QA → staging → prod. No skipping without explicit flags.
|
|
185
|
+
- **Failure creates tracking.** Every failure gets a regression task — nothing falls through the cracks.
|
|
186
|
+
- **Idempotent resumption.** `/ship` checks labels and skips already-passed stages. Safe to re-run after fixing a failure.
|
|
187
|
+
- **`--from-staging` trusts staging.** Use when you've already verified staging manually or in a previous run.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run tests, parse results, track coverage history
|
|
3
|
+
argument-hint: [suite] [--watch] [--coverage]
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit, Glob, Grep
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- codeloop-version: 0.3.0 -->
|
|
8
|
+
|
|
9
|
+
# /test
|
|
10
|
+
|
|
11
|
+
Run tests, parse results, and track coverage over time.
|
|
12
|
+
|
|
13
|
+
> **When to use `/test` vs `/qa`**: Use `/test` for quick feedback during development — run a specific suite, check coverage, iterate. Use `/qa` when you're ready to promote a task — it runs the full test suite plus static analysis, coverage gates, and integrity checks, and sets the `env:local-pass` label that unlocks `/deploy`. `/test` does NOT set env labels.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
/test # Run default test command from config
|
|
19
|
+
/test <suite> # Run specific test suite or file pattern
|
|
20
|
+
/test --watch # Run in watch mode (if runner supports it)
|
|
21
|
+
/test --coverage # Run with coverage reporting
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Phase 1: Detect
|
|
25
|
+
|
|
26
|
+
1. Read `.codeloop/config.yaml` for the `test` section:
|
|
27
|
+
```yaml
|
|
28
|
+
test:
|
|
29
|
+
command: "npm test"
|
|
30
|
+
coverage_threshold: 80
|
|
31
|
+
```
|
|
32
|
+
2. If no `test.command` configured, auto-detect the test runner:
|
|
33
|
+
- `package.json` with `scripts.test` → use `npm test`
|
|
34
|
+
- `vitest.config.*` → `npx vitest run`
|
|
35
|
+
- `jest.config.*` → `npx jest`
|
|
36
|
+
- `pyproject.toml` with `[tool.pytest]` → `pytest`
|
|
37
|
+
- `go.mod` → `go test ./...`
|
|
38
|
+
- `Cargo.toml` → `cargo test`
|
|
39
|
+
- If nothing detected → ask the user what command to run
|
|
40
|
+
|
|
41
|
+
## Phase 2: Run
|
|
42
|
+
|
|
43
|
+
1. If `<suite>` argument provided, append it to the test command (e.g., `npm test -- src/auth/`)
|
|
44
|
+
2. If `--watch` flag, append watch flag for the detected runner:
|
|
45
|
+
- vitest: already defaults to watch in dev, use `npx vitest`
|
|
46
|
+
- jest: `--watch`
|
|
47
|
+
- pytest: use `pytest-watch` or `ptw`
|
|
48
|
+
- go: no native watch — inform user
|
|
49
|
+
3. If `--coverage` flag, append coverage flag:
|
|
50
|
+
- vitest/jest: `--coverage`
|
|
51
|
+
- pytest: `--cov`
|
|
52
|
+
- go: `-cover`
|
|
53
|
+
4. Run the command, capture stdout and stderr
|
|
54
|
+
|
|
55
|
+
## Phase 3: Parse Results
|
|
56
|
+
|
|
57
|
+
Parse the test runner output to extract:
|
|
58
|
+
|
|
59
|
+
| Field | Example |
|
|
60
|
+
|-------|---------|
|
|
61
|
+
| Total tests | 42 |
|
|
62
|
+
| Passed | 40 |
|
|
63
|
+
| Failed | 1 |
|
|
64
|
+
| Skipped | 1 |
|
|
65
|
+
| Duration | 3.2s |
|
|
66
|
+
| Coverage % | 82% (if available) |
|
|
67
|
+
| Failed test names | List of specific failures |
|
|
68
|
+
|
|
69
|
+
If tests **failed**, show:
|
|
70
|
+
- Each failed test name and file
|
|
71
|
+
- The failure message / assertion error
|
|
72
|
+
- Suggestion: which code is likely broken based on the test file path
|
|
73
|
+
|
|
74
|
+
## Phase 4: Track History
|
|
75
|
+
|
|
76
|
+
Update `.codeloop/test-history.json` (create if not exists):
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"runs": [
|
|
81
|
+
{
|
|
82
|
+
"timestamp": "2026-02-21T10:30:00Z",
|
|
83
|
+
"suite": "all",
|
|
84
|
+
"total": 42,
|
|
85
|
+
"passed": 40,
|
|
86
|
+
"failed": 1,
|
|
87
|
+
"skipped": 1,
|
|
88
|
+
"coverage": 82,
|
|
89
|
+
"duration": 3.2,
|
|
90
|
+
"commit": "abc1234"
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Keep the last 50 runs. Older entries are dropped.
|
|
97
|
+
|
|
98
|
+
Include the current git commit SHA (from `git rev-parse --short HEAD`).
|
|
99
|
+
|
|
100
|
+
## Phase 5: Report
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
## Test Results
|
|
104
|
+
|
|
105
|
+
**Suite**: all | **Runner**: vitest
|
|
106
|
+
**Result**: 40/42 passed, 1 failed, 1 skipped (3.2s)
|
|
107
|
+
**Coverage**: 82% (threshold: 80% ✓)
|
|
108
|
+
|
|
109
|
+
### Failures
|
|
110
|
+
- `src/auth/login.test.ts` → "expected 200, got 401"
|
|
111
|
+
|
|
112
|
+
### Trend (last 5 runs)
|
|
113
|
+
42 ████████████████████ 100%
|
|
114
|
+
42 ████████████████████ 100%
|
|
115
|
+
42 ███████████████████░ 95%
|
|
116
|
+
42 ████████████████████ 100%
|
|
117
|
+
42 ███████████████████░ 95% ← current
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Phase 6: Board Sync
|
|
121
|
+
|
|
122
|
+
If `.codeloop/board.json` exists:
|
|
123
|
+
- Find the active task (first `in_progress`, then `planned`)
|
|
124
|
+
- Add label: `tests:pass` or `tests:fail` (replace any existing `tests:*` label)
|
|
125
|
+
- If coverage available, add label: `coverage:82%` (replace any existing `coverage:*` label)
|
|
126
|
+
- Write updated board
|
|
127
|
+
|
|
128
|
+
## Rules
|
|
129
|
+
|
|
130
|
+
- **Never modify test files.** This skill only runs and reports — it doesn't fix tests.
|
|
131
|
+
- **Respect the config.** If `test.command` is set, use it. Don't override with auto-detection.
|
|
132
|
+
- **Track everything.** Even skipped tests matter — a rising skip count is a warning sign.
|
|
133
|
+
- **Show the trend.** History makes patterns visible — one failure vs. recurring failure.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Installed by `codeloop init --hooks`. Adds a `Feature: <card-id>` trailer when the branch name
|
|
3
|
+
# contains a card id (feat/CL-001-lane-engine, fix/c-012-export) and the message has none.
|
|
4
|
+
branch=$(git symbolic-ref --quiet --short HEAD) || exit 0
|
|
5
|
+
id=$(printf '%s' "$branch" | grep -oE '[A-Za-z]{1,10}-[0-9]{1,6}' | head -1)
|
|
6
|
+
[ -n "$id" ] || exit 0
|
|
7
|
+
grep -q '^Feature: ' "$1" && exit 0
|
|
8
|
+
git interpret-trailers --in-place --trailer "Feature: $id" "$1"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
id: analyze
|
|
2
|
+
version: 1
|
|
3
|
+
metric: { name: north_star, source: analytics }
|
|
4
|
+
trigger: { cron: "0 9 * * FRI" }
|
|
5
|
+
wip: 1
|
|
6
|
+
retries: 3
|
|
7
|
+
stages:
|
|
8
|
+
- id: pull
|
|
9
|
+
skill: reflect
|
|
10
|
+
output: growth/{id}/metrics.md
|
|
11
|
+
done: { cmd: "codeloop check file growth/{id}/metrics.md --has 'north_star:'" }
|
|
12
|
+
- id: compare
|
|
13
|
+
skill: reflect
|
|
14
|
+
output: growth/{id}/compare.md
|
|
15
|
+
done: { cmd: "codeloop check file growth/{id}/compare.md --has 'delta:'" }
|
|
16
|
+
- id: judge
|
|
17
|
+
skill: reflect
|
|
18
|
+
output: growth/{id}/verdicts.md
|
|
19
|
+
done: { cmd: "codeloop check file growth/{id}/verdicts.md --has 'verdict:'" }
|
|
20
|
+
gate: { name: verdicts, approver: owner }
|
|
21
|
+
- id: findings
|
|
22
|
+
skill: reflect
|
|
23
|
+
output: growth/{id}/findings.md
|
|
24
|
+
done: { cmd: "codeloop check file growth/{id}/findings.md --has 'findings:'" }
|
|
25
|
+
on_done: { start: plan }
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
id: build
|
|
2
|
+
version: 1
|
|
3
|
+
metric: { name: cycle_time_days, source: cards, target: "<5" }
|
|
4
|
+
trigger: { manual: true }
|
|
5
|
+
wip: 2
|
|
6
|
+
retries: 3
|
|
7
|
+
stages:
|
|
8
|
+
- id: research
|
|
9
|
+
skill: design
|
|
10
|
+
output: "{spec}/research.md"
|
|
11
|
+
done: { cmd: "codeloop check research {id} --min-sources 3" }
|
|
12
|
+
# Optional per card: a card with nothing to draw writes `screens: none` in its spec and passes without a mock.
|
|
13
|
+
- id: mock
|
|
14
|
+
skill: design
|
|
15
|
+
done: { cmd: "codeloop check mock {id}" }
|
|
16
|
+
notes:
|
|
17
|
+
- "Name each screen under `screens:` in the card's spec.md, run `codeloop mock new <card> --topic <topic>`, and draw one <section data-screen> per screen in the file it creates."
|
|
18
|
+
- id: spec
|
|
19
|
+
skill: plan
|
|
20
|
+
output: "{spec}/tasks.md"
|
|
21
|
+
done: { cmd: "codeloop spec check {id}" }
|
|
22
|
+
gate: { name: spec, approver: owner }
|
|
23
|
+
- id: build
|
|
24
|
+
skill: test
|
|
25
|
+
done: { cmd: "codeloop task check {id} --all-done && npm test" }
|
|
26
|
+
- id: verify
|
|
27
|
+
skill: qa
|
|
28
|
+
output: evidence/{nnn}/verify.md
|
|
29
|
+
done: { cmd: "codeloop verify {id}" }
|
|
30
|
+
gate: { name: local, approver: owner }
|
|
31
|
+
- id: review
|
|
32
|
+
skill: commit
|
|
33
|
+
output: evidence/{nnn}/review.md
|
|
34
|
+
done: { cmd: "codeloop check file evidence/{nnn}/review.md --has 'verdict: approve'" }
|
|
35
|
+
gate: { name: pr, approver: reviewer }
|
|
36
|
+
- id: staging
|
|
37
|
+
skill: deploy
|
|
38
|
+
output: evidence/{nnn}/staging.md
|
|
39
|
+
done: { cmd: "codeloop check file evidence/{nnn}/staging.md --has 'result: pass'" }
|
|
40
|
+
- id: live
|
|
41
|
+
skill: ship
|
|
42
|
+
output: evidence/{nnn}/prod.md
|
|
43
|
+
done: { cmd: "codeloop check file evidence/{nnn}/prod.md --has 'result: pass'" }
|
|
44
|
+
gate: { name: prod, approver: owner, outward: true }
|
|
45
|
+
on_done: { start: market }
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
id: deploy
|
|
2
|
+
version: 1
|
|
3
|
+
metric: { name: change_failure_rate, source: cards, target: "<15%" }
|
|
4
|
+
trigger: { on: git.tag }
|
|
5
|
+
wip: 1
|
|
6
|
+
retries: 3
|
|
7
|
+
stages:
|
|
8
|
+
- id: staging
|
|
9
|
+
skill: deploy
|
|
10
|
+
output: deploy/{id}/staging.md
|
|
11
|
+
done: { cmd: "codeloop check file deploy/{id}/staging.md --has 'result: pass'" }
|
|
12
|
+
- id: verify
|
|
13
|
+
skill: qa
|
|
14
|
+
output: deploy/{id}/verify.md
|
|
15
|
+
done: { cmd: "codeloop check file deploy/{id}/verify.md --has 'result: pass'" }
|
|
16
|
+
- id: prod
|
|
17
|
+
skill: ship
|
|
18
|
+
output: deploy/{id}/prod.md
|
|
19
|
+
done: { cmd: "codeloop check file deploy/{id}/prod.md --has 'result: pass'" }
|
|
20
|
+
gate: { name: prod, approver: owner, outward: true }
|
|
21
|
+
- id: smoke
|
|
22
|
+
skill: debug
|
|
23
|
+
output: deploy/{id}/smoke.md
|
|
24
|
+
done: { cmd: "codeloop check file deploy/{id}/smoke.md --has 'result: pass'" }
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
id: learn
|
|
2
|
+
version: 1
|
|
3
|
+
metric: { name: repeat_gotcha_rate, source: knowledge }
|
|
4
|
+
trigger: { manual: true }
|
|
5
|
+
wip: 2
|
|
6
|
+
retries: 3
|
|
7
|
+
stages:
|
|
8
|
+
- id: capture
|
|
9
|
+
skill: reflect
|
|
10
|
+
output: learn/{id}/capture.md
|
|
11
|
+
done: { cmd: "codeloop check file learn/{id}/capture.md --has 'gotcha:'" }
|
|
12
|
+
- id: bump
|
|
13
|
+
skill: reflect
|
|
14
|
+
output: learn/{id}/bump.md
|
|
15
|
+
done: { cmd: "codeloop check file learn/{id}/bump.md --has 'freq:'" }
|
|
16
|
+
- id: promote
|
|
17
|
+
skill: reflect
|
|
18
|
+
output: learn/{id}/promote.md
|
|
19
|
+
done: { cmd: "codeloop check file learn/{id}/promote.md --has 'rule:'" }
|
|
20
|
+
gate: { name: rule, approver: owner }
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
id: market
|
|
2
|
+
version: 1
|
|
3
|
+
metric: { name: signups_from_launch, source: analytics, target: "+10%" }
|
|
4
|
+
trigger: { on: lane.done, lane: build }
|
|
5
|
+
wip: 2
|
|
6
|
+
retries: 3
|
|
7
|
+
stages:
|
|
8
|
+
- id: brief
|
|
9
|
+
skill: plan
|
|
10
|
+
output: marketing/{id}/brief.md
|
|
11
|
+
done: { cmd: "codeloop check file marketing/{id}/brief.md --has 'audience:' 'claim:' 'metric:'" }
|
|
12
|
+
- id: draft
|
|
13
|
+
skill: design
|
|
14
|
+
output: marketing/{id}/blog.md
|
|
15
|
+
done: { cmd: "codeloop check file marketing/{id}/blog.md --has 'claim:'" }
|
|
16
|
+
gate: { name: copy, approver: owner }
|
|
17
|
+
- id: publish
|
|
18
|
+
skill: ship
|
|
19
|
+
output: marketing/{id}/published.md
|
|
20
|
+
done: { cmd: "codeloop check file marketing/{id}/published.md --has 'url:'" }
|
|
21
|
+
gate: { name: publish, approver: owner, outward: true }
|
|
22
|
+
- id: measure
|
|
23
|
+
skill: reflect
|
|
24
|
+
output: marketing/{id}/result.md
|
|
25
|
+
done: { cmd: "codeloop check file marketing/{id}/result.md --has 'verdict:'" }
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
id: plan
|
|
2
|
+
version: 1
|
|
3
|
+
metric: { name: shipped_cards_that_moved_their_metric, source: cards }
|
|
4
|
+
trigger: { cron: "0 9 * * MON" }
|
|
5
|
+
wip: 1
|
|
6
|
+
retries: 3
|
|
7
|
+
stages:
|
|
8
|
+
- id: gather
|
|
9
|
+
skill: reflect
|
|
10
|
+
output: plan/{id}/signals.md
|
|
11
|
+
done: { cmd: "codeloop check file plan/{id}/signals.md --has 'signals:'" }
|
|
12
|
+
- id: research
|
|
13
|
+
skill: design
|
|
14
|
+
output: plan/{id}/research.md
|
|
15
|
+
done: { cmd: "codeloop check file plan/{id}/research.md --has 'verdict:'" }
|
|
16
|
+
- id: rank
|
|
17
|
+
skill: manage
|
|
18
|
+
output: plan/{id}/ranked.md
|
|
19
|
+
done: { cmd: "codeloop check file plan/{id}/ranked.md --has 'rice:'" }
|
|
20
|
+
- id: story
|
|
21
|
+
skill: plan
|
|
22
|
+
output: plan/{id}/stories.md
|
|
23
|
+
done: { cmd: "codeloop check file plan/{id}/stories.md --has 'acceptance:'" }
|
|
24
|
+
gate: { name: backlog, approver: owner }
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
id: scan
|
|
2
|
+
version: 1
|
|
3
|
+
metric: { name: competitor_proposals_promoted, source: cards }
|
|
4
|
+
trigger: { cron: "0 7 * * MON" }
|
|
5
|
+
wip: 1
|
|
6
|
+
retries: 3
|
|
7
|
+
stages:
|
|
8
|
+
# The stage is its command: it reads the changelog on each page in .codeloop/wiki/competitors/
|
|
9
|
+
# and proposes a plan card for what is new. The cards wait in the inbox; nothing starts them.
|
|
10
|
+
- id: scan
|
|
11
|
+
done: { cmd: "codeloop scan competitors" }
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
id: triage
|
|
2
|
+
version: 1
|
|
3
|
+
metric: { name: proposals_accepted_ratio, source: cards }
|
|
4
|
+
trigger: { cron: "0 20 * * *" }
|
|
5
|
+
wip: 1
|
|
6
|
+
retries: 3
|
|
7
|
+
stages:
|
|
8
|
+
- id: capture
|
|
9
|
+
skill: debug
|
|
10
|
+
output: triage/{id}/capture.md
|
|
11
|
+
done: { cmd: "codeloop check file triage/{id}/capture.md --has 'sources:'" }
|
|
12
|
+
- id: classify
|
|
13
|
+
skill: manage
|
|
14
|
+
output: triage/{id}/classified.md
|
|
15
|
+
done: { cmd: "codeloop check file triage/{id}/classified.md --has 'category:'" }
|
|
16
|
+
- id: dedupe
|
|
17
|
+
skill: manage
|
|
18
|
+
output: triage/{id}/deduped.md
|
|
19
|
+
done: { cmd: "codeloop check file triage/{id}/deduped.md --has 'duplicates:'" }
|
|
20
|
+
- id: file
|
|
21
|
+
skill: manage
|
|
22
|
+
output: triage/{id}/proposals.md
|
|
23
|
+
done: { cmd: "codeloop check file triage/{id}/proposals.md --has 'proposals:'" }
|
|
24
|
+
gate: { name: proposals, approver: owner }
|