ai-core-framework 0.1.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/.claude-plugin/plugin.json +21 -0
- package/.codex-plugin/plugin.json +35 -0
- package/.cursor-plugin/plugin.json +22 -0
- package/README.md +173 -0
- package/bin/ai-core-framework.js +110 -0
- package/core/README.md +162 -0
- package/core/agents/README.md +32 -0
- package/core/agents/business-analyst.md +269 -0
- package/core/agents/developer.md +375 -0
- package/core/agents/qa-tester.md +477 -0
- package/core/agents/scrum-master.md +136 -0
- package/core/agents/tech-lead.md +345 -0
- package/core/config/backlog.schema.json +38 -0
- package/core/config/docs-policy.default.json +37 -0
- package/core/config/release.schema.json +120 -0
- package/core/config/ticket.schema.json +253 -0
- package/core/rules/00-global-rules.md +373 -0
- package/core/rules/01-git-workflow.md +388 -0
- package/core/rules/02-code-quality.md +77 -0
- package/core/rules/03-security.md +78 -0
- package/core/rules/04-documentation.md +72 -0
- package/core/rules/05-testing-mandatory.md +374 -0
- package/core/rules/06-approval-gates.md +388 -0
- package/core/rules/07-definition-of-ready.md +112 -0
- package/core/rules/08-definition-of-done.md +149 -0
- package/core/scripts/ai-core.sh +456 -0
- package/core/scripts/generate-views.sh +210 -0
- package/core/scripts/install-codex-prompts.sh +127 -0
- package/core/scripts/log-user-request.sh +113 -0
- package/core/scripts/setup-project.sh +183 -0
- package/core/scripts/sync-platforms.sh +322 -0
- package/core/scripts/validate-audit-log.sh +73 -0
- package/core/scripts/validate-docs.sh +365 -0
- package/core/scripts/validate-permissions.sh +132 -0
- package/core/scripts/validate-state.sh +611 -0
- package/core/scripts/workflow.sh +513 -0
- package/core/skills/README.md +21 -0
- package/core/skills/ai-core-commands/SKILL.md +86 -0
- package/core/skills/brainstorming/SKILL.md +40 -0
- package/core/skills/development-implement-task/SKILL.md +308 -0
- package/core/skills/executing-ticket/SKILL.md +28 -0
- package/core/skills/git-branch-status/SKILL.md +56 -0
- package/core/skills/git-cleanup-branches/SKILL.md +57 -0
- package/core/skills/git-scan-untracked/SKILL.md +50 -0
- package/core/skills/meta-generate-views/SKILL.md +54 -0
- package/core/skills/meta-request-log/SKILL.md +61 -0
- package/core/skills/meta-sprint-report/SKILL.md +59 -0
- package/core/skills/meta-sync-platforms/SKILL.md +53 -0
- package/core/skills/meta-ticket-health/SKILL.md +61 -0
- package/core/skills/meta-validate-audit-log/SKILL.md +42 -0
- package/core/skills/meta-validate-docs/SKILL.md +58 -0
- package/core/skills/meta-validate-permissions/SKILL.md +53 -0
- package/core/skills/meta-validate-state/SKILL.md +58 -0
- package/core/skills/planning-analyze-requirements/SKILL.md +471 -0
- package/core/skills/planning-backlog-status/SKILL.md +57 -0
- package/core/skills/planning-document-existing-requirements/SKILL.md +246 -0
- package/core/skills/planning-estimate-task/SKILL.md +60 -0
- package/core/skills/planning-groom-ticket/SKILL.md +442 -0
- package/core/skills/planning-mark-ready/SKILL.md +111 -0
- package/core/skills/planning-plan-refactor/SKILL.md +66 -0
- package/core/skills/planning-plan-sprint/SKILL.md +112 -0
- package/core/skills/planning-prioritize-backlog/SKILL.md +62 -0
- package/core/skills/planning-write-plan/SKILL.md +68 -0
- package/core/skills/project-detect-stack/SKILL.md +71 -0
- package/core/skills/project-discover-codebase/SKILL.md +74 -0
- package/core/skills/project-setup-project/SKILL.md +113 -0
- package/core/skills/qa-bug-status/SKILL.md +52 -0
- package/core/skills/qa-report-bug/SKILL.md +518 -0
- package/core/skills/qa-smoke-test/SKILL.md +387 -0
- package/core/skills/qa-triage-bug/SKILL.md +62 -0
- package/core/skills/qa-verify-fix/SKILL.md +446 -0
- package/core/skills/release-hotfix/SKILL.md +117 -0
- package/core/skills/release-release/SKILL.md +123 -0
- package/core/skills/release-rollback/SKILL.md +62 -0
- package/core/skills/review-create-pr/SKILL.md +418 -0
- package/core/skills/review-merge-pr/SKILL.md +425 -0
- package/core/skills/review-techlead-review/SKILL.md +547 -0
- package/core/skills/using-ai-core/SKILL.md +72 -0
- package/core/skills/verification-before-done/SKILL.md +35 -0
- package/core/skills/writing-implementation-plan/SKILL.md +45 -0
- package/core/templates/ci/ai-core-governance.yml +112 -0
- package/core/templates/ci/node-pnpm.yml +35 -0
- package/core/templates/pm/retrospective-template.md +47 -0
- package/core/templates/pm/sprint-plan-template.md +45 -0
- package/core/templates/pr/pull-request-template.md +247 -0
- package/core/templates/project/CODEOWNERS +11 -0
- package/core/templates/project/docs-policy.json +3 -0
- package/core/templates/project/project-config.yaml +137 -0
- package/core/templates/project/project-structure.yaml +76 -0
- package/core/templates/qa/bug-report-template.md +371 -0
- package/core/templates/qa/test-plan-template.md +57 -0
- package/core/templates/release/release-record-template.json +67 -0
- package/core/templates/requirements/PRD-template.md +58 -0
- package/core/templates/requirements/user-story-template.md +381 -0
- package/core/templates/technical/ADR-template.md +46 -0
- package/core/templates/technical/refactor-plan-template.md +84 -0
- package/core/templates/technical/tech-design-template.md +71 -0
- package/core/workflows/bug-lifecycle.md +56 -0
- package/core/workflows/feature-lifecycle.md +347 -0
- package/core/workflows/hotfix-lifecycle.md +65 -0
- package/core/workflows/sprint-lifecycle.md +56 -0
- package/lib/install-codex.js +85 -0
- package/package.json +36 -0
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# core/scripts/workflow.sh
|
|
3
|
+
#
|
|
4
|
+
# Executable handlers for AI Core state workflow commands.
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
COMMAND="${1:-}"
|
|
9
|
+
shift || true
|
|
10
|
+
|
|
11
|
+
RED='\033[0;31m'
|
|
12
|
+
GREEN='\033[0;32m'
|
|
13
|
+
BLUE='\033[0;34m'
|
|
14
|
+
NC='\033[0m'
|
|
15
|
+
|
|
16
|
+
log_info() { echo -e "${BLUE}i${NC} $1"; }
|
|
17
|
+
log_pass() { echo -e "${GREEN}+${NC} $1"; }
|
|
18
|
+
log_fail() { echo -e "${RED}x${NC} $1"; }
|
|
19
|
+
|
|
20
|
+
require_jq() {
|
|
21
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
22
|
+
log_fail "jq not installed. Install with: brew install jq"
|
|
23
|
+
exit 2
|
|
24
|
+
fi
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
now_utc() {
|
|
28
|
+
date -u +%Y-%m-%dT%H:%M:%SZ
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
agent_name() {
|
|
32
|
+
local agent="${AI_AGENT:-unknown-agent}"
|
|
33
|
+
if [[ "$agent" == *-agent ]]; then
|
|
34
|
+
printf '%s' "$agent"
|
|
35
|
+
else
|
|
36
|
+
printf '%s-agent' "$agent"
|
|
37
|
+
fi
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
ticket_file() {
|
|
41
|
+
printf 'project/tickets/%s.json' "$1"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
slugify() {
|
|
45
|
+
printf '%s' "$1" |
|
|
46
|
+
tr '[:upper:]' '[:lower:]' |
|
|
47
|
+
sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-+/-/g' |
|
|
48
|
+
cut -c1-60
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
next_ticket_id() {
|
|
52
|
+
local max_id
|
|
53
|
+
max_id=$(find project/tickets -name 'TICKET-*.json' -type f 2>/dev/null |
|
|
54
|
+
sed -E 's/.*TICKET-([0-9]+)\.json/\1/' |
|
|
55
|
+
sort -n |
|
|
56
|
+
tail -1)
|
|
57
|
+
if [ -z "$max_id" ]; then
|
|
58
|
+
printf 'TICKET-001'
|
|
59
|
+
else
|
|
60
|
+
printf 'TICKET-%03d' "$((10#$max_id + 1))"
|
|
61
|
+
fi
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
write_json() {
|
|
65
|
+
local file="$1"
|
|
66
|
+
local tmp
|
|
67
|
+
tmp=$(mktemp)
|
|
68
|
+
cat > "$tmp"
|
|
69
|
+
mv "$tmp" "$file"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
hash_value() {
|
|
73
|
+
local value="$1"
|
|
74
|
+
if command -v sha256sum >/dev/null 2>&1; then
|
|
75
|
+
printf '%s' "$value" | sha256sum | awk '{print $1}'
|
|
76
|
+
else
|
|
77
|
+
printf '%s' "$value" | shasum -a 256 | awk '{print $1}'
|
|
78
|
+
fi
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
last_audit_hash() {
|
|
82
|
+
local audit_file="project/audit-log.jsonl"
|
|
83
|
+
if [ ! -s "$audit_file" ]; then
|
|
84
|
+
printf ''
|
|
85
|
+
return 0
|
|
86
|
+
fi
|
|
87
|
+
tail -1 "$audit_file" | jq -r '.hash // empty'
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
append_audit() {
|
|
91
|
+
local command="$1"
|
|
92
|
+
local ticket_id="$2"
|
|
93
|
+
local from_state="$3"
|
|
94
|
+
local to_state="$4"
|
|
95
|
+
local reason="$5"
|
|
96
|
+
|
|
97
|
+
mkdir -p project
|
|
98
|
+
local audit_file="project/audit-log.jsonl"
|
|
99
|
+
local at by prev payload hash
|
|
100
|
+
at=$(now_utc)
|
|
101
|
+
by=$(agent_name)
|
|
102
|
+
prev=$(last_audit_hash)
|
|
103
|
+
payload=$(jq -cn \
|
|
104
|
+
--arg at "$at" \
|
|
105
|
+
--arg by "$by" \
|
|
106
|
+
--arg command "$command" \
|
|
107
|
+
--arg ticket_id "$ticket_id" \
|
|
108
|
+
--arg from_state "$from_state" \
|
|
109
|
+
--arg to_state "$to_state" \
|
|
110
|
+
--arg reason "$reason" \
|
|
111
|
+
--arg prev_hash "$prev" \
|
|
112
|
+
'{at:$at, by_agent:$by, command:$command, ticket_id:$ticket_id, from_state:$from_state, to_state:$to_state, reason:$reason, prev_hash:$prev_hash}')
|
|
113
|
+
hash=$(hash_value "$payload")
|
|
114
|
+
jq -cn --argjson payload "$payload" --arg hash "$hash" '$payload + {hash:$hash}' >> "$audit_file"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
transition_ticket() {
|
|
118
|
+
local ticket_id="$1"
|
|
119
|
+
local from_state="$2"
|
|
120
|
+
local to_state="$3"
|
|
121
|
+
local command="$4"
|
|
122
|
+
local reason="$5"
|
|
123
|
+
local file
|
|
124
|
+
file=$(ticket_file "$ticket_id")
|
|
125
|
+
|
|
126
|
+
if [ ! -f "$file" ]; then
|
|
127
|
+
log_fail "Ticket not found: $ticket_id"
|
|
128
|
+
exit 1
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
local status
|
|
132
|
+
status=$(jq -r '.status' "$file")
|
|
133
|
+
if [ "$status" != "$from_state" ]; then
|
|
134
|
+
log_fail "$ticket_id status must be $from_state, got $status"
|
|
135
|
+
exit 1
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
local at by
|
|
139
|
+
at=$(now_utc)
|
|
140
|
+
by=$(agent_name)
|
|
141
|
+
|
|
142
|
+
jq \
|
|
143
|
+
--arg status "$to_state" \
|
|
144
|
+
--arg at "$at" \
|
|
145
|
+
--arg by "$by" \
|
|
146
|
+
--arg command "$command" \
|
|
147
|
+
--arg from_state "$from_state" \
|
|
148
|
+
--arg to_state "$to_state" \
|
|
149
|
+
--arg reason "$reason" \
|
|
150
|
+
'.status = $status
|
|
151
|
+
| .updated_at = $at
|
|
152
|
+
| .state_history += [{
|
|
153
|
+
from_state: $from_state,
|
|
154
|
+
to_state: $to_state,
|
|
155
|
+
at: $at,
|
|
156
|
+
by_agent: $by,
|
|
157
|
+
by_command: $command,
|
|
158
|
+
reason: $reason
|
|
159
|
+
}]' "$file" | write_json "$file"
|
|
160
|
+
|
|
161
|
+
append_audit "$command" "$ticket_id" "$from_state" "$to_state" "$reason"
|
|
162
|
+
bash core/scripts/validate-state.sh "$ticket_id"
|
|
163
|
+
bash core/scripts/validate-permissions.sh
|
|
164
|
+
log_pass "$ticket_id transitioned $from_state -> $to_state"
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
require_ticket_field() {
|
|
168
|
+
local ticket_id="$1"
|
|
169
|
+
local query="$2"
|
|
170
|
+
local message="$3"
|
|
171
|
+
if ! jq -e "$query" "$(ticket_file "$ticket_id")" >/dev/null 2>&1; then
|
|
172
|
+
log_fail "$ticket_id: $message"
|
|
173
|
+
exit 1
|
|
174
|
+
fi
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
cmd_analyze_requirements() {
|
|
178
|
+
local requirement="${*:-}"
|
|
179
|
+
if [ ${#requirement} -lt 10 ]; then
|
|
180
|
+
log_fail "Requirement text must be at least 10 characters"
|
|
181
|
+
exit 1
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
mkdir -p project/tickets docs/project/specs
|
|
185
|
+
local ticket_id file at by slug spec_path
|
|
186
|
+
ticket_id=$(next_ticket_id)
|
|
187
|
+
file=$(ticket_file "$ticket_id")
|
|
188
|
+
at=$(now_utc)
|
|
189
|
+
by=$(agent_name)
|
|
190
|
+
slug=$(slugify "$requirement")
|
|
191
|
+
[ -n "$slug" ] || slug="requirement"
|
|
192
|
+
spec_path="docs/project/specs/${ticket_id}-${slug}.md"
|
|
193
|
+
|
|
194
|
+
cat > "$spec_path" <<EOF
|
|
195
|
+
# ${ticket_id}: ${requirement:0:120}
|
|
196
|
+
|
|
197
|
+
## Goal
|
|
198
|
+
|
|
199
|
+
${requirement}
|
|
200
|
+
|
|
201
|
+
## Background
|
|
202
|
+
|
|
203
|
+
Created by /analyze-requirements from stakeholder input.
|
|
204
|
+
|
|
205
|
+
## Users And Stakeholders
|
|
206
|
+
|
|
207
|
+
- Primary user: stakeholder
|
|
208
|
+
- Owner agent: $by
|
|
209
|
+
|
|
210
|
+
## In Scope
|
|
211
|
+
|
|
212
|
+
- Convert the requirement into a groomable ticket.
|
|
213
|
+
- Validate expected behavior through acceptance criteria.
|
|
214
|
+
|
|
215
|
+
## Out Of Scope
|
|
216
|
+
|
|
217
|
+
- Technical implementation details.
|
|
218
|
+
- Story point estimation.
|
|
219
|
+
|
|
220
|
+
## Acceptance Criteria
|
|
221
|
+
|
|
222
|
+
1. Happy path: valid preconditions produce the expected outcome.
|
|
223
|
+
2. Edge case: boundary input or uncommon state is handled predictably.
|
|
224
|
+
3. Error case: invalid input or unavailable dependency produces a safe error and no data corruption.
|
|
225
|
+
|
|
226
|
+
## Risks And Assumptions
|
|
227
|
+
|
|
228
|
+
- Requirement may need refinement during grooming.
|
|
229
|
+
- Technical risks are owned by /groom-ticket and /write-plan.
|
|
230
|
+
|
|
231
|
+
## Next Command
|
|
232
|
+
|
|
233
|
+
\`/groom-ticket ${ticket_id} <story_points>\`
|
|
234
|
+
EOF
|
|
235
|
+
|
|
236
|
+
jq -n \
|
|
237
|
+
--arg id "$ticket_id" \
|
|
238
|
+
--arg title "${requirement:0:120}" \
|
|
239
|
+
--arg req "$requirement" \
|
|
240
|
+
--arg at "$at" \
|
|
241
|
+
--arg by "$by" \
|
|
242
|
+
--arg spec_path "$spec_path" \
|
|
243
|
+
'{
|
|
244
|
+
id: $id,
|
|
245
|
+
title: $title,
|
|
246
|
+
type: "feature",
|
|
247
|
+
status: "DRAFT",
|
|
248
|
+
priority: "SHOULD",
|
|
249
|
+
user_story: {
|
|
250
|
+
as_a: "stakeholder",
|
|
251
|
+
i_want: $req,
|
|
252
|
+
so_that: "business value can be validated"
|
|
253
|
+
},
|
|
254
|
+
acceptance_criteria: [
|
|
255
|
+
{scenario:"Happy path", given:"valid preconditions", when:"the user performs the requested action", then:"the expected outcome is achieved"},
|
|
256
|
+
{scenario:"Edge case", given:"boundary input or uncommon state", when:"the action is attempted", then:"the system handles it predictably"},
|
|
257
|
+
{scenario:"Error case", given:"invalid input or unavailable dependency", when:"the action is attempted", then:"the user receives a safe error and no data is corrupted"}
|
|
258
|
+
],
|
|
259
|
+
created_at: $at,
|
|
260
|
+
created_by: $by,
|
|
261
|
+
updated_at: $at,
|
|
262
|
+
spec_path: $spec_path,
|
|
263
|
+
state_history: [{
|
|
264
|
+
from_state: null,
|
|
265
|
+
to_state: "DRAFT",
|
|
266
|
+
at: $at,
|
|
267
|
+
by_agent: $by,
|
|
268
|
+
by_command: "/analyze-requirements",
|
|
269
|
+
reason: "Created from executable requirement intake"
|
|
270
|
+
}],
|
|
271
|
+
comments: [{
|
|
272
|
+
author: $by,
|
|
273
|
+
at: $at,
|
|
274
|
+
text: ("Source requirement: " + $req)
|
|
275
|
+
}],
|
|
276
|
+
labels: ["needs-grooming"]
|
|
277
|
+
}' > "$file"
|
|
278
|
+
|
|
279
|
+
append_audit "/analyze-requirements" "$ticket_id" "null" "DRAFT" "Created from executable requirement intake"
|
|
280
|
+
bash core/scripts/validate-state.sh "$ticket_id"
|
|
281
|
+
log_pass "Created $ticket_id"
|
|
282
|
+
log_pass "Created $spec_path"
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
cmd_groom_ticket() {
|
|
286
|
+
local ticket_id="${1:-}"
|
|
287
|
+
local points="${2:-}"
|
|
288
|
+
[ -n "$ticket_id" ] || { log_fail "Usage: /groom-ticket TICKET-XXX [points]"; exit 2; }
|
|
289
|
+
|
|
290
|
+
if [ -n "$points" ]; then
|
|
291
|
+
local file at by
|
|
292
|
+
file=$(ticket_file "$ticket_id")
|
|
293
|
+
at=$(now_utc)
|
|
294
|
+
by=$(agent_name)
|
|
295
|
+
jq --argjson points "$points" --arg by "$by" --arg at "$at" \
|
|
296
|
+
'.estimate = {story_points:$points, estimated_by:$by, estimated_at:$at}
|
|
297
|
+
| .technical_approach = (.technical_approach // "Executable grooming recorded. Add detailed approach before implementation.")
|
|
298
|
+
| .risks = (.risks // [{description:"Implementation risk requires Tech Lead review", probability:"MEDIUM", impact:"MEDIUM", mitigation:"Review before sprint planning"}])' "$file" | write_json "$file"
|
|
299
|
+
fi
|
|
300
|
+
|
|
301
|
+
require_ticket_field "$ticket_id" '.user_story' "missing user_story"
|
|
302
|
+
require_ticket_field "$ticket_id" '.acceptance_criteria | length >= 3' "requires at least 3 acceptance criteria"
|
|
303
|
+
require_ticket_field "$ticket_id" '.estimate.story_points' "missing estimate.story_points; pass points or add estimate"
|
|
304
|
+
transition_ticket "$ticket_id" "DRAFT" "GROOMED" "/groom-ticket" "Executable grooming gate passed"
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
cmd_mark_ready() {
|
|
308
|
+
local ticket_id="${1:-}"
|
|
309
|
+
[ -n "$ticket_id" ] || { log_fail "Usage: /mark-ready TICKET-XXX"; exit 2; }
|
|
310
|
+
require_ticket_field "$ticket_id" '.estimate.story_points' "missing estimate"
|
|
311
|
+
require_ticket_field "$ticket_id" '.acceptance_criteria | length >= 3' "requires at least 3 acceptance criteria"
|
|
312
|
+
transition_ticket "$ticket_id" "GROOMED" "READY" "/mark-ready" "Definition of Ready gate passed"
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
cmd_write_plan() {
|
|
316
|
+
local ticket_id="${1:-}"
|
|
317
|
+
[ -n "$ticket_id" ] || { log_fail "Usage: /write-plan TICKET-XXX"; exit 2; }
|
|
318
|
+
|
|
319
|
+
local file status title slug plan_path spec_path at by
|
|
320
|
+
file=$(ticket_file "$ticket_id")
|
|
321
|
+
[ -f "$file" ] || { log_fail "Ticket not found: $ticket_id"; exit 1; }
|
|
322
|
+
status=$(jq -r '.status // empty' "$file")
|
|
323
|
+
case "$status" in
|
|
324
|
+
GROOMED|READY) ;;
|
|
325
|
+
*) log_fail "$ticket_id status must be GROOMED or READY before /write-plan, got $status"; exit 1 ;;
|
|
326
|
+
esac
|
|
327
|
+
|
|
328
|
+
mkdir -p docs/project/plans
|
|
329
|
+
title=$(jq -r '.title // .id' "$file")
|
|
330
|
+
slug=$(slugify "$title")
|
|
331
|
+
[ -n "$slug" ] || slug="implementation"
|
|
332
|
+
plan_path="docs/project/plans/${ticket_id}-${slug}-plan.md"
|
|
333
|
+
spec_path=$(jq -r '.spec_path // empty' "$file")
|
|
334
|
+
at=$(now_utc)
|
|
335
|
+
by=$(agent_name)
|
|
336
|
+
|
|
337
|
+
cat > "$plan_path" <<EOF
|
|
338
|
+
# ${ticket_id}: ${title} Implementation Plan
|
|
339
|
+
|
|
340
|
+
**Ticket:** \`${ticket_id}\`
|
|
341
|
+
**Status at planning:** \`${status}\`
|
|
342
|
+
**Spec:** ${spec_path:-Not linked}
|
|
343
|
+
**Created by:** ${by}
|
|
344
|
+
**Created at:** ${at}
|
|
345
|
+
|
|
346
|
+
## Goal
|
|
347
|
+
|
|
348
|
+
Implement the ticket scope while preserving the approved acceptance criteria and documentation obligations.
|
|
349
|
+
|
|
350
|
+
## Current Context
|
|
351
|
+
|
|
352
|
+
- Read \`project/tickets/${ticket_id}.json\`.
|
|
353
|
+
- Read the linked spec if present.
|
|
354
|
+
- Inspect affected code before editing.
|
|
355
|
+
|
|
356
|
+
## Affected Files
|
|
357
|
+
|
|
358
|
+
- To be confirmed by the developer before implementation.
|
|
359
|
+
- Add exact paths here if codebase discovery identifies them.
|
|
360
|
+
|
|
361
|
+
## Tasks
|
|
362
|
+
|
|
363
|
+
- [ ] Confirm ticket scope and acceptance criteria.
|
|
364
|
+
- [ ] Identify exact production files and test files.
|
|
365
|
+
- [ ] Write or update failing tests for the happy path.
|
|
366
|
+
- [ ] Write or update failing tests for edge/error cases.
|
|
367
|
+
- [ ] Implement the smallest code change that satisfies the tests.
|
|
368
|
+
- [ ] Run targeted tests and record output.
|
|
369
|
+
- [ ] Update docs required by the ticket metadata.
|
|
370
|
+
- [ ] Run validation gates: state, permissions, docs, audit log.
|
|
371
|
+
|
|
372
|
+
## Test Strategy
|
|
373
|
+
|
|
374
|
+
- Unit tests for deterministic logic.
|
|
375
|
+
- Integration tests for changed boundaries.
|
|
376
|
+
- Manual or smoke-test evidence before DONE.
|
|
377
|
+
|
|
378
|
+
## Documentation Updates
|
|
379
|
+
|
|
380
|
+
- Update \`documentation.paths\` in the ticket when docs are required.
|
|
381
|
+
- Add ADR or runbook links if architecture, migration, or operations behavior changes.
|
|
382
|
+
|
|
383
|
+
## Verification Commands
|
|
384
|
+
|
|
385
|
+
\`\`\`text
|
|
386
|
+
/validate-state
|
|
387
|
+
/validate-permissions
|
|
388
|
+
/validate-docs
|
|
389
|
+
\`\`\`
|
|
390
|
+
|
|
391
|
+
## Rollback Notes
|
|
392
|
+
|
|
393
|
+
Rollback should revert the implementation commit or disable the changed behavior behind the safest available control. Add a more specific rollback path before release if this touches data, auth, billing, deployment, or migrations.
|
|
394
|
+
|
|
395
|
+
## Next Command
|
|
396
|
+
|
|
397
|
+
\`/implement-task ${ticket_id}\`
|
|
398
|
+
EOF
|
|
399
|
+
|
|
400
|
+
jq --arg path "$plan_path" --arg at "$at" --arg by "$by" \
|
|
401
|
+
'.implementation_plan_path = $path
|
|
402
|
+
| .updated_at = $at
|
|
403
|
+
| .comments = ((.comments // []) + [{
|
|
404
|
+
author: $by,
|
|
405
|
+
at: $at,
|
|
406
|
+
text: ("Implementation plan created: " + $path)
|
|
407
|
+
}])' "$file" | write_json "$file"
|
|
408
|
+
|
|
409
|
+
append_audit "/write-plan" "$ticket_id" "$status" "$status" "Implementation plan created"
|
|
410
|
+
bash core/scripts/validate-state.sh "$ticket_id"
|
|
411
|
+
bash core/scripts/validate-permissions.sh
|
|
412
|
+
log_pass "Created $plan_path"
|
|
413
|
+
log_pass "Linked plan from $file"
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
cmd_implement_task() {
|
|
417
|
+
local ticket_id="${1:-}"
|
|
418
|
+
[ -n "$ticket_id" ] || { log_fail "Usage: /implement-task TICKET-XXX"; exit 2; }
|
|
419
|
+
if ! jq -e '.implementation_plan_path // empty' "$(ticket_file "$ticket_id")" >/dev/null 2>&1; then
|
|
420
|
+
log_info "$ticket_id has no implementation_plan_path. Recommended first: /write-plan $ticket_id"
|
|
421
|
+
fi
|
|
422
|
+
transition_ticket "$ticket_id" "READY" "IN_PROGRESS" "/implement-task" "Implementation started"
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
cmd_create_pr() {
|
|
426
|
+
local ticket_id="${1:-}"
|
|
427
|
+
local pr_url="${2:-}"
|
|
428
|
+
[ -n "$ticket_id" ] || { log_fail "Usage: /create-pr TICKET-XXX [pr_url]"; exit 2; }
|
|
429
|
+
if [ "$(jq -r '.status' "$(ticket_file "$ticket_id")")" != "IN_PROGRESS" ]; then
|
|
430
|
+
log_fail "$ticket_id status must be IN_PROGRESS before PR metadata is written"
|
|
431
|
+
exit 1
|
|
432
|
+
fi
|
|
433
|
+
if [ -n "$pr_url" ]; then
|
|
434
|
+
jq --arg pr_url "$pr_url" '.pr_url = $pr_url' "$(ticket_file "$ticket_id")" | write_json "$(ticket_file "$ticket_id")"
|
|
435
|
+
fi
|
|
436
|
+
require_ticket_field "$ticket_id" '.pr_url // empty' "missing pr_url; pass PR URL"
|
|
437
|
+
transition_ticket "$ticket_id" "IN_PROGRESS" "IN_REVIEW" "/create-pr" "PR created and linked"
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
cmd_merge_pr() {
|
|
441
|
+
local ticket_id="${1:-}"
|
|
442
|
+
[ -n "$ticket_id" ] || { log_fail "Usage: /merge-pr TICKET-XXX"; exit 2; }
|
|
443
|
+
require_ticket_field "$ticket_id" '.pr_url // empty' "missing pr_url"
|
|
444
|
+
transition_ticket "$ticket_id" "IN_REVIEW" "QA" "/merge-pr" "PR merged and ready for QA"
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
cmd_smoke_test() {
|
|
448
|
+
local ticket_id="${1:-}"
|
|
449
|
+
local evidence_path="${2:-}"
|
|
450
|
+
[ -n "$ticket_id" ] || { log_fail "Usage: /smoke-test TICKET-XXX [evidence_path]"; exit 2; }
|
|
451
|
+
if [ "$(jq -r '.status' "$(ticket_file "$ticket_id")")" != "QA" ]; then
|
|
452
|
+
log_fail "$ticket_id status must be QA before QA evidence is written"
|
|
453
|
+
exit 1
|
|
454
|
+
fi
|
|
455
|
+
[ -n "$evidence_path" ] || evidence_path="project/test-runs/${ticket_id}-$(date -u +%Y%m%d%H%M%S).md"
|
|
456
|
+
mkdir -p "$(dirname "$evidence_path")"
|
|
457
|
+
if [ ! -f "$evidence_path" ]; then
|
|
458
|
+
printf '# Smoke Test Evidence: %s\n\nGenerated by executable smoke-test gate at %s.\n' "$ticket_id" "$(now_utc)" > "$evidence_path"
|
|
459
|
+
fi
|
|
460
|
+
local at by
|
|
461
|
+
at=$(now_utc)
|
|
462
|
+
by=$(agent_name)
|
|
463
|
+
jq --arg path "$evidence_path" --arg by "$by" --arg at "$at" \
|
|
464
|
+
'.qa_evidence = {required:true, path:$path, verified_by:$by, verified_at:$at}
|
|
465
|
+
| .dod_checklist = ((.dod_checklist // {}) + {
|
|
466
|
+
code_complete:true,
|
|
467
|
+
tests_passed:true,
|
|
468
|
+
docs_updated:true,
|
|
469
|
+
review_approved:true,
|
|
470
|
+
qa_verified:true,
|
|
471
|
+
release_notes_updated:true,
|
|
472
|
+
security_checked:true
|
|
473
|
+
})
|
|
474
|
+
| .completed_at = $at' "$(ticket_file "$ticket_id")" | write_json "$(ticket_file "$ticket_id")"
|
|
475
|
+
transition_ticket "$ticket_id" "QA" "DONE" "/smoke-test" "Smoke test passed with evidence"
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
cmd_release() {
|
|
479
|
+
local version="${1:-}"
|
|
480
|
+
[ -n "$version" ] || { log_fail "Usage: /release vMAJOR.MINOR.PATCH"; exit 2; }
|
|
481
|
+
mkdir -p project/releases
|
|
482
|
+
local file="project/releases/${version}.json"
|
|
483
|
+
if [ -f "$file" ]; then
|
|
484
|
+
log_fail "Release record already exists: $file"
|
|
485
|
+
exit 1
|
|
486
|
+
fi
|
|
487
|
+
local at by
|
|
488
|
+
at=$(now_utc)
|
|
489
|
+
by=$(agent_name)
|
|
490
|
+
jq --arg version "$version" --arg at "$at" --arg by "$by" \
|
|
491
|
+
'.version = $version
|
|
492
|
+
| .created_at = $at
|
|
493
|
+
| .created_by = $by' core/templates/release/release-record-template.json > "$file"
|
|
494
|
+
log_pass "Created release record $file"
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
main() {
|
|
498
|
+
require_jq
|
|
499
|
+
case "$COMMAND" in
|
|
500
|
+
analyze-requirements) cmd_analyze_requirements "$@" ;;
|
|
501
|
+
groom-ticket) cmd_groom_ticket "$@" ;;
|
|
502
|
+
write-plan) cmd_write_plan "$@" ;;
|
|
503
|
+
mark-ready) cmd_mark_ready "$@" ;;
|
|
504
|
+
implement-task) cmd_implement_task "$@" ;;
|
|
505
|
+
create-pr) cmd_create_pr "$@" ;;
|
|
506
|
+
merge-pr) cmd_merge_pr "$@" ;;
|
|
507
|
+
smoke-test) cmd_smoke_test "$@" ;;
|
|
508
|
+
release) cmd_release "$@" ;;
|
|
509
|
+
*) log_fail "No workflow handler for $COMMAND"; exit 2 ;;
|
|
510
|
+
esac
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
main "$@"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# AI Core Skills
|
|
2
|
+
|
|
3
|
+
Skills define chat-first agent behavior. Commands define workflow actions. Scripts implement deterministic checks and state updates.
|
|
4
|
+
|
|
5
|
+
Use skills when the user intent is broader than one command:
|
|
6
|
+
|
|
7
|
+
- `using-ai-core`: session bootstrap and command interpretation
|
|
8
|
+
- `ai-core-commands`: interpret AI Core slash-command text in Codex chat
|
|
9
|
+
- `brainstorming`: requirement discovery before ticket work
|
|
10
|
+
- `writing-implementation-plan`: detailed plan creation before coding
|
|
11
|
+
- `executing-ticket`: implementation discipline for active tickets
|
|
12
|
+
- `verification-before-done`: evidence gate before completion claims
|
|
13
|
+
|
|
14
|
+
Normal user interaction should stay in chat:
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
/analyze-requirements "User can reset password"
|
|
18
|
+
/groom-ticket TICKET-001 5
|
|
19
|
+
/write-plan TICKET-001
|
|
20
|
+
next TICKET-001
|
|
21
|
+
```
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ai-core-commands
|
|
3
|
+
description: Interpret AI Core slash-command text in Codex. Use when the user types AI Core commands such as /setup-project, /analyze-requirements, /document-existing-requirements, /groom-ticket, /write-plan, /implement-task, /request-log, or asks to run an AI Core workflow command.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AI Core Commands
|
|
7
|
+
|
|
8
|
+
Codex plugins do not expose `core/commands/*.md` as native slash-command autocomplete. This skill makes AI Core command text executable through normal chat.
|
|
9
|
+
|
|
10
|
+
## Mandatory Trigger
|
|
11
|
+
|
|
12
|
+
Use this skill when the user message starts with, mentions, or asks to run any AI Core command:
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
/setup-project
|
|
16
|
+
/analyze-requirements
|
|
17
|
+
/document-existing-requirements
|
|
18
|
+
/groom-ticket
|
|
19
|
+
/mark-ready
|
|
20
|
+
/write-plan
|
|
21
|
+
/implement-task
|
|
22
|
+
/create-pr
|
|
23
|
+
/techlead-review
|
|
24
|
+
/merge-pr
|
|
25
|
+
/smoke-test
|
|
26
|
+
/verify-fix
|
|
27
|
+
/release
|
|
28
|
+
/request-log
|
|
29
|
+
guide /...
|
|
30
|
+
next TICKET-XXX
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Required Behavior
|
|
34
|
+
|
|
35
|
+
1. Log the user request first:
|
|
36
|
+
```bash
|
|
37
|
+
AI_AGENT=codex bash core/scripts/log-user-request.sh "<user request text>"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
2. Resolve command metadata:
|
|
41
|
+
- Search `core/commands/**/<command-name>.md`.
|
|
42
|
+
- Read the command file.
|
|
43
|
+
- Infer `owner_agent`, `requires_agents`, args, preconditions, postconditions, hard rules, and output format.
|
|
44
|
+
|
|
45
|
+
3. Load the matching agent file when present:
|
|
46
|
+
- `core/agents/<owner_agent>.md`
|
|
47
|
+
|
|
48
|
+
4. Execute the command in chat-first mode:
|
|
49
|
+
- Use deterministic scripts only when the command file or workflow requires them.
|
|
50
|
+
- Do not ask the user to run shell wrappers during normal use.
|
|
51
|
+
- Preserve all hard rules from `core/rules/00-global-rules.md`.
|
|
52
|
+
|
|
53
|
+
5. Report:
|
|
54
|
+
- Command executed
|
|
55
|
+
- Inferred agent
|
|
56
|
+
- Files created or changed
|
|
57
|
+
- Validation result
|
|
58
|
+
- Suggested next AI Core command
|
|
59
|
+
|
|
60
|
+
## Command Discovery
|
|
61
|
+
|
|
62
|
+
Command files are stored under:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
core/commands/
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The command name maps to a Markdown file by removing the leading slash:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
/analyze-requirements -> core/commands/**/analyze-requirements.md
|
|
72
|
+
/request-log -> core/commands/**/request-log.md
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
If multiple files match the same command name, stop and ask for clarification.
|
|
76
|
+
|
|
77
|
+
If no file matches, say the command is not defined and suggest `/request-log`, `/setup-project`, or checking `core/commands/README.md`.
|
|
78
|
+
|
|
79
|
+
## Strict Rules
|
|
80
|
+
|
|
81
|
+
- MUST NOT invent command behavior not present in command files.
|
|
82
|
+
- MUST NOT skip required preconditions.
|
|
83
|
+
- MUST NOT silently skip request logging.
|
|
84
|
+
- MUST NOT modify production code unless AI Core ticket rules allow it.
|
|
85
|
+
- MUST distinguish native Codex slash commands from AI Core chat commands. AI Core commands may not appear in `/` autocomplete, but they still MUST be interpreted when typed in chat.
|
|
86
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brainstorming
|
|
3
|
+
description: Use before creating or changing product behavior. Converts a rough idea into an approved spec before ticket grooming or implementation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Brainstorming
|
|
7
|
+
|
|
8
|
+
Use this before implementation work, feature creation, behavior changes, or large refactors.
|
|
9
|
+
|
|
10
|
+
## Process
|
|
11
|
+
|
|
12
|
+
1. Inspect current project context briefly.
|
|
13
|
+
2. Ask clarifying questions one at a time when the requirement is ambiguous.
|
|
14
|
+
3. Propose 2-3 approaches with tradeoffs and a recommendation.
|
|
15
|
+
4. Present a concise design for user approval.
|
|
16
|
+
5. Save the approved spec to `docs/project/specs/TICKET-XXX-<slug>.md`.
|
|
17
|
+
6. Link the spec from `project/tickets/TICKET-XXX.json` as `spec_path`.
|
|
18
|
+
7. Suggest `/groom-ticket TICKET-XXX`.
|
|
19
|
+
|
|
20
|
+
## Hard Gates
|
|
21
|
+
|
|
22
|
+
- Do not write production code during brainstorming.
|
|
23
|
+
- Do not invent missing business requirements silently.
|
|
24
|
+
- Do not estimate story points. Estimation belongs to `/groom-ticket`.
|
|
25
|
+
- Do not create implementation plans here. Use `/write-plan` after the ticket is groomed or ready.
|
|
26
|
+
|
|
27
|
+
## Spec Contents
|
|
28
|
+
|
|
29
|
+
Each spec should include:
|
|
30
|
+
|
|
31
|
+
- goal
|
|
32
|
+
- background
|
|
33
|
+
- users and stakeholders
|
|
34
|
+
- in-scope behavior
|
|
35
|
+
- out-of-scope items
|
|
36
|
+
- acceptance criteria
|
|
37
|
+
- risks and assumptions
|
|
38
|
+
- open questions
|
|
39
|
+
- next command
|
|
40
|
+
|