@ggdna/dna-gg 1.4.0 → 1.5.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/README.md +6 -4
- package/dna/_generated.json +7 -7
- package/dna/doc/guides/develop-guide.md +6 -4
- package/dna/doc/guides/for-ai/ai-dev-guide.md +39 -23
- package/dna/dot-claude/hooks/pm-prompts.mjs +31 -4
- package/dna/dot-claude/skills/gg-publish/SKILL.md +2 -1
- package/dna/dot-claude/skills/gg-review/SKILL.md +6 -10
- package/dna/dot-claude/skills/gg-ticket/SKILL.md +31 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ All skills of this layer are prefixed with `gg-`:
|
|
|
39
39
|
- `/gg-commit` — proposes a message and commits through `gg do commit`
|
|
40
40
|
- `/gg-push` — pushes the ticket branches
|
|
41
41
|
- `/gg-review` — checks the scope of every repo, writes the blog posts
|
|
42
|
-
and opens the pull requests
|
|
42
|
+
and opens the pull requests, printing their URLs
|
|
43
43
|
- `/gg-publish` — releases the ticket
|
|
44
44
|
- `/gg-cleanup` — removes what the ticket left behind
|
|
45
45
|
|
|
@@ -51,10 +51,12 @@ All skills of this layer are prefixed with `gg-`:
|
|
|
51
51
|
Claude Code in the project management repo `dnaPmRepo` names. The
|
|
52
52
|
prompts wait in `~/.claude/pm-prompts/sessions/` and are committed to the
|
|
53
53
|
branch `prompts` of that repo when a session starts or ends, under
|
|
54
|
-
`doc
|
|
55
|
-
|
|
54
|
+
`doc/<yyyy>-Q<n>/prompts/<first name>/<yyyy-mm-dd>_<repo>_<session>.md`,
|
|
55
|
+
the quarter of the day the session started. The first name comes from
|
|
56
|
+
`team/people.md` of the newest quarter folder there (`doc/team/people.md`
|
|
57
|
+
in a repo without quarter folders), found by the git
|
|
56
58
|
user name: a first name equal to it or to its first word, or a `Git`
|
|
57
|
-
line listing it. An unknown name goes to `
|
|
59
|
+
line listing it. An unknown name goes to `prompts/_unknown/`. No
|
|
58
60
|
e-mail address is read or written; the commits carry the neutral author
|
|
59
61
|
`pm-prompts`. Only the prompts are kept, never the answers; tokens and
|
|
60
62
|
passwords are replaced by `[redacted]`. No working tree is touched: the commit is built in a bare
|
package/dna/_generated.json
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"ecosystem": null,
|
|
40
40
|
"resolvedVersion": null,
|
|
41
41
|
"via": null,
|
|
42
|
-
"hash": "
|
|
42
|
+
"hash": "0xff6654f75712aad8"
|
|
43
43
|
}
|
|
44
44
|
],
|
|
45
45
|
"claude": {
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
},
|
|
60
60
|
{
|
|
61
61
|
"path": ".claude/hooks/pm-prompts.mjs",
|
|
62
|
-
"hash": "
|
|
62
|
+
"hash": "0x6b8fdf7bbbf7c1a5"
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
"path": ".claude/settings.json",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
},
|
|
76
76
|
{
|
|
77
77
|
"path": ".claude/skills/gg-publish/SKILL.md",
|
|
78
|
-
"hash": "
|
|
78
|
+
"hash": "0x806b4c1fd5f6f654"
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
"path": ".claude/skills/gg-push/SKILL.md",
|
|
@@ -83,11 +83,11 @@
|
|
|
83
83
|
},
|
|
84
84
|
{
|
|
85
85
|
"path": ".claude/skills/gg-review/SKILL.md",
|
|
86
|
-
"hash": "
|
|
86
|
+
"hash": "0x3a4506ccd5c8e1be"
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
89
|
"path": ".claude/skills/gg-ticket/SKILL.md",
|
|
90
|
-
"hash": "
|
|
90
|
+
"hash": "0x8f9f5eb3d5567659"
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
93
|
"path": ".claude/skills/gg/SKILL.md",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
},
|
|
108
108
|
{
|
|
109
109
|
"path": "doc/guides/develop-guide.md",
|
|
110
|
-
"hash": "
|
|
110
|
+
"hash": "0x4c378a55b3c4773b"
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
113
|
"path": "doc/guides/develop-without-ai-guide.md",
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
},
|
|
116
116
|
{
|
|
117
117
|
"path": "doc/guides/for-ai/ai-dev-guide.md",
|
|
118
|
-
"hash": "
|
|
118
|
+
"hash": "0xa7bc4ac78f9387d6"
|
|
119
119
|
},
|
|
120
120
|
{
|
|
121
121
|
"path": "doc/guides/index-guide.md",
|
|
@@ -45,10 +45,12 @@ Use the following skills in Claude
|
|
|
45
45
|
## Your prompts
|
|
46
46
|
|
|
47
47
|
When the repo belongs to a project management repo, every prompt you write
|
|
48
|
-
to Claude Code is kept there, under
|
|
49
|
-
branch `prompts`. Only the prompts, not the answers. Tokens and passwords
|
|
48
|
+
to Claude Code is kept there, under
|
|
49
|
+
`doc/<yyyy>-Q<n>/prompts/<your first name>/` on the branch `prompts`. Only the prompts, not the answers. Tokens and passwords
|
|
50
50
|
are replaced by `[redacted]`. Your first name comes from
|
|
51
|
-
`
|
|
51
|
+
`team/people.md` of the newest quarter folder `doc/<yyyy>-Q<n>` in the
|
|
52
|
+
project management repo: the person whose
|
|
52
53
|
first name is your git user name or its first word, or whose `Git` line
|
|
53
54
|
lists your git user name. Otherwise your prompts land in
|
|
54
|
-
`doc
|
|
55
|
+
`doc/<yyyy>-Q<n>/prompts/_unknown/`. Your e-mail address never goes
|
|
56
|
+
there.
|
|
@@ -8,31 +8,43 @@ found in the LICENSE file in the root of this package.
|
|
|
8
8
|
|
|
9
9
|
# Development guide for AIs
|
|
10
10
|
|
|
11
|
-
## Ask the developer
|
|
11
|
+
## Ask the developer what the ticket should do
|
|
12
12
|
|
|
13
|
-
Ask
|
|
14
|
-
|
|
15
|
-
question and never as a plain prose question:
|
|
13
|
+
Ask a single question: what should the ticket do? One free-text answer is
|
|
14
|
+
enough — never ask for a ticket id, a title or a description separately.
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
- Ask for the ticket title
|
|
19
|
-
- Ask for the ticket description
|
|
20
|
-
|
|
21
|
-
## Replace in this document
|
|
16
|
+
## Create a ticket
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
- Ask for the workspace directory if none is known
|
|
25
|
-
- Replace `DnaJiraPrefix-145` by the ticket ID you asked for
|
|
26
|
-
- Replace `Fix issue abc` by the ticket title you asked for
|
|
18
|
+
Derive from the answer, without asking anything else:
|
|
27
19
|
|
|
28
|
-
|
|
20
|
+
- **id** — a short, descriptive slug in `snake_case`, 2-5 plain ASCII words
|
|
21
|
+
(transliterate non-ASCII, drop punctuation and emoji), e.g.
|
|
22
|
+
`fix_login_crash`. Never a sequential number: several tickets are usually
|
|
23
|
+
worked on in parallel, and a counter collides between them. List the
|
|
24
|
+
existing ticket folders of the workspace root and, if the slug is taken,
|
|
25
|
+
append `_2`, `_3`, … until it is free. If `gg do create ticket` still
|
|
26
|
+
rejects it as taken (e.g. another agent just created the same slug),
|
|
27
|
+
bump the suffix and retry.
|
|
28
|
+
- **message** — one imperative line to one short sentence describing the
|
|
29
|
+
change, for `-m`.
|
|
29
30
|
|
|
30
31
|
```bash
|
|
31
32
|
cd ~/dev/ # workspace
|
|
32
|
-
gg do create ticket
|
|
33
|
-
cd
|
|
33
|
+
gg do create ticket fix_login_crash -m"Fix issue abc"
|
|
34
|
+
cd fix_login_crash
|
|
34
35
|
```
|
|
35
36
|
|
|
37
|
+
Tell the developer the id and the message right after creating the ticket —
|
|
38
|
+
both can be changed any time, e.g. by renaming the folder before anything
|
|
39
|
+
else is added to it, or by editing `ticket.json`.
|
|
40
|
+
|
|
41
|
+
## Replace in this document
|
|
42
|
+
|
|
43
|
+
- Replace `~/dev/` by the workspace directory from the memory
|
|
44
|
+
- Ask for the workspace directory if none is known
|
|
45
|
+
- Replace `fix_login_crash` by the ticket id you derived
|
|
46
|
+
- Replace `Fix issue abc` by the ticket message you derived
|
|
47
|
+
|
|
36
48
|
## Choose the project management repo — or work without one
|
|
37
49
|
|
|
38
50
|
A ticket may belong to a project management repo. It holds the plans,
|
|
@@ -62,8 +74,9 @@ repositories. The ticket then carries no plan of its own.
|
|
|
62
74
|
|
|
63
75
|
## Add git repositories
|
|
64
76
|
|
|
65
|
-
Ask the user how the repos are chosen, as a single question with
|
|
66
|
-
options
|
|
77
|
+
Ask the user how the repos are chosen, as a single question with the
|
|
78
|
+
options below. Offer **only the project management repo** only when one was
|
|
79
|
+
added above — without one there is nothing to be "only" about.
|
|
67
80
|
|
|
68
81
|
Manually: ask in a second single input field which repos the ticket needs,
|
|
69
82
|
e.g. `repo1 repo2`. Check each name against the repos in .ocean and ask
|
|
@@ -80,8 +93,10 @@ Also explain to the user what you roughly want to change in which repo to
|
|
|
80
93
|
implement the ticket and let them confirm that the corresponding repos are
|
|
81
94
|
added to the ticket.
|
|
82
95
|
|
|
83
|
-
|
|
84
|
-
|
|
96
|
+
Only the project management repo: no code repo at all; the ticket stays
|
|
97
|
+
pure planning, and the project management repo added above is everything
|
|
98
|
+
it carries. If the ticket is only planned (see below), this is the way to
|
|
99
|
+
go — the project management repo may be the only repo of the ticket.
|
|
85
100
|
|
|
86
101
|
After the user's confirmation, add the repos to the ticket:
|
|
87
102
|
|
|
@@ -143,7 +158,8 @@ gg do code
|
|
|
143
158
|
## Plan (optional)
|
|
144
159
|
|
|
145
160
|
Requirements come before the plan. If the project management repo keeps
|
|
146
|
-
requirements (`doc
|
|
161
|
+
requirements (`doc/<yyyy>-Q<n>/requirements`, in the newest quarter
|
|
162
|
+
folder) and none of its accepted requirements
|
|
147
163
|
covers the ticket, engineer them with the user first — with
|
|
148
164
|
`/gg-plan-requirements` if the repo has it — and plan the ticket only after
|
|
149
165
|
that. Bug tickets are the exception, they name their bug file.
|
|
@@ -321,8 +337,8 @@ gg do review
|
|
|
321
337
|
```
|
|
322
338
|
|
|
323
339
|
gg creates pull requests for each repo and prints the URLs to the
|
|
324
|
-
terminal. Print every URL to the user, one line per repo
|
|
325
|
-
pull
|
|
340
|
+
terminal. Print every URL to the user, one line per repo. Do not open the
|
|
341
|
+
pull requests in the browser — leave that to the user.
|
|
326
342
|
|
|
327
343
|
Afterwards load the review-light skill and execute it.
|
|
328
344
|
|
|
@@ -17,8 +17,10 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
17
17
|
/** The branch of the project management repo holding the prompts. */
|
|
18
18
|
export const promptsBranch = 'prompts';
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
// Everything a project management repo plans lives in quarter folders
|
|
21
|
+
// doc/<yyyy>-Q<n>; repos not moved yet keep doc/team.
|
|
22
|
+
const quarterDir = /^doc\/(\d{4}-Q[1-4])$/;
|
|
23
|
+
const legacyPeopleFile = 'doc/team/people.md';
|
|
22
24
|
const configFile = path.join('.claude', 'hooks', 'pm-prompts.json');
|
|
23
25
|
|
|
24
26
|
// A session that ended without an end event counts as ended after a week.
|
|
@@ -330,12 +332,32 @@ export function personOf(gitName, peopleMd) {
|
|
|
330
332
|
);
|
|
331
333
|
}
|
|
332
334
|
|
|
335
|
+
/** The quarter folder name of a local date: 2026-11-06 → 2026-Q4. */
|
|
336
|
+
export function quarterOf(date) {
|
|
337
|
+
const month = Number(date.slice(5, 7));
|
|
338
|
+
return `${date.slice(0, 4)}-Q${Math.floor((month - 1) / 3) + 1}`;
|
|
339
|
+
}
|
|
340
|
+
|
|
333
341
|
/** Where the prompts of a session go in the project management repo. */
|
|
334
342
|
export function promptsPath(meta, person) {
|
|
335
343
|
const date = localDate(meta.started);
|
|
336
344
|
const folder = person ? slug(person) : '_unknown';
|
|
337
345
|
const id = String(meta.session).slice(0, 8);
|
|
338
|
-
|
|
346
|
+
const name = `${date}_${slug(meta.folder) || 'session'}_${id}.md`;
|
|
347
|
+
return `doc/${quarterOf(date)}/prompts/${folder}/${name}`;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* The files people.md may be in, best first: the team of the newest quarter
|
|
352
|
+
* folder among the [entries] of doc, then the one of a repo not moved yet.
|
|
353
|
+
*/
|
|
354
|
+
export function peopleFiles(entries) {
|
|
355
|
+
const quarters = entries
|
|
356
|
+
.map((e) => quarterDir.exec(e.trim())?.[1])
|
|
357
|
+
.filter(Boolean)
|
|
358
|
+
.sort()
|
|
359
|
+
.reverse();
|
|
360
|
+
return [...quarters.map((q) => `doc/${q}/team/people.md`), legacyPeopleFile];
|
|
339
361
|
}
|
|
340
362
|
|
|
341
363
|
/** The head of the file a session's prompts start. */
|
|
@@ -392,7 +414,12 @@ function ensureCache(url) {
|
|
|
392
414
|
function readPeople(dir) {
|
|
393
415
|
const fetched = git(['-C', dir, 'fetch', '-q', '--depth=1', 'origin', 'HEAD']);
|
|
394
416
|
if (!fetched.ok) throw new Error(`fetch HEAD: ${fetched.err}`);
|
|
395
|
-
|
|
417
|
+
const ls = git(['-C', dir, 'ls-tree', '--name-only', 'FETCH_HEAD', 'doc/']);
|
|
418
|
+
for (const file of peopleFiles(ls.ok ? ls.out.split('\n') : [])) {
|
|
419
|
+
const shown = git(['-C', dir, 'show', `FETCH_HEAD:${file}`]);
|
|
420
|
+
if (shown.ok) return shown.out;
|
|
421
|
+
}
|
|
422
|
+
return '';
|
|
396
423
|
}
|
|
397
424
|
|
|
398
425
|
// The tip of the prompts branch, '' while it does not exist yet.
|
|
@@ -13,7 +13,8 @@ creates and pushes the version tags. It is interactive — the user runs it.
|
|
|
13
13
|
- Every repo of the ticket is committed and pushed.
|
|
14
14
|
- The pull requests created by `gg do review` are green.
|
|
15
15
|
- Every repo with `doc/guides/blog-guide.md` holds the post of this ticket
|
|
16
|
-
in `doc/blog/<yyyy
|
|
16
|
+
in `doc/blog/<yyyy>`, a project management repo in
|
|
17
|
+
`doc/<yyyy>-Q<n>/blog`. If one is missing, go back to `/gg-review`.
|
|
17
18
|
|
|
18
19
|
## 2. Configure the publish
|
|
19
20
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gg-review
|
|
3
|
-
description: Writes the blog posts of the ticket, opens the pull requests with `gg do review` and reviews the changes. Use when the user says "/gg-review" or asks to review the current ticket.
|
|
3
|
+
description: Writes the blog posts of the ticket, opens the pull requests with `gg do review` and prints their URLs, and reviews the changes. Use when the user says "/gg-review" or asks to review the current ticket.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Review
|
|
@@ -57,21 +57,16 @@ output, so pass the URLs on:
|
|
|
57
57
|
- Print every URL to the user, one line per repo: `<repo>: <url>`. Name
|
|
58
58
|
each repo that gg reports as `No pull request for <repo>`, with the
|
|
59
59
|
reason
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
- GitHub: `gh pr view <url> --json autoMergeRequest` — `null` means off
|
|
63
|
-
- Azure DevOps: `az repos pr show --id <id> --query autoCompleteSetBy`
|
|
64
|
-
— empty means off
|
|
65
|
-
- Open the URL with `start "" "<url>"` on Windows, `open "<url>"` on
|
|
66
|
-
macOS and `xdg-open "<url>"` on Linux
|
|
60
|
+
- Do not open the pull requests in the browser — print the URLs and leave
|
|
61
|
+
opening them to the user.
|
|
67
62
|
|
|
68
63
|
## 4. Review the changes
|
|
69
64
|
|
|
70
65
|
Load the `/review-light` skill and execute it.
|
|
71
66
|
|
|
72
67
|
A fix goes through `/gg-commit` and `/gg-push`, then run `gg do review`
|
|
73
|
-
again. Print
|
|
74
|
-
|
|
68
|
+
again. Print its pull request URLs as in step 3. Update the blog post of
|
|
69
|
+
the repo when the fix changes what it describes.
|
|
75
70
|
|
|
76
71
|
## Important
|
|
77
72
|
|
|
@@ -80,3 +75,4 @@ post of the repo when the fix changes what it describes.
|
|
|
80
75
|
the project management repo.
|
|
81
76
|
- Never start `gg do review` without the user's confirmation.
|
|
82
77
|
- Always print the pull request URLs after `gg do review`.
|
|
78
|
+
- Never open a pull request in the browser on your own.
|
|
@@ -8,24 +8,36 @@ description: Creates a gg ticket and adds the repos it needs. Use when the user
|
|
|
8
8
|
All `gg do` commands run inside the workspace. Ask for the workspace
|
|
9
9
|
directory if none is known.
|
|
10
10
|
|
|
11
|
-
## 1. Ask
|
|
11
|
+
## 1. Ask what the ticket should do
|
|
12
12
|
|
|
13
|
-
Ask
|
|
14
|
-
|
|
15
|
-
and never as a plain prose question:
|
|
16
|
-
|
|
17
|
-
- Ticket ID, e.g. `DnaJiraPrefix-145`
|
|
18
|
-
- Title, one imperative line, e.g. `Fix issue abc`
|
|
19
|
-
- Description, one or two sentences on what the ticket changes
|
|
13
|
+
Ask a single question: what should the ticket do? One free-text answer is
|
|
14
|
+
enough — never ask for a ticket id, a title or a description separately.
|
|
20
15
|
|
|
21
16
|
## 2. Create the ticket
|
|
22
17
|
|
|
18
|
+
Derive from the answer, without asking anything else:
|
|
19
|
+
|
|
20
|
+
- **id** — a short, descriptive slug in `snake_case`, 2-5 plain ASCII words
|
|
21
|
+
(transliterate non-ASCII, drop punctuation and emoji), e.g.
|
|
22
|
+
`fix_login_crash`. Never a sequential number: several tickets are usually
|
|
23
|
+
worked on in parallel, and a counter collides between them. List the
|
|
24
|
+
existing ticket folders of the workspace root and, if the slug is taken,
|
|
25
|
+
append `_2`, `_3`, … until it is free. If `gg do create ticket` still
|
|
26
|
+
rejects it as taken (e.g. another agent just created the same slug),
|
|
27
|
+
bump the suffix and retry.
|
|
28
|
+
- **message** — one imperative line to one short sentence describing the
|
|
29
|
+
change, for `-m`.
|
|
30
|
+
|
|
23
31
|
```bash
|
|
24
32
|
cd ~/dev/ # workspace
|
|
25
|
-
gg do create ticket
|
|
26
|
-
cd
|
|
33
|
+
gg do create ticket fix_login_crash -m"Fix issue abc"
|
|
34
|
+
cd fix_login_crash
|
|
27
35
|
```
|
|
28
36
|
|
|
37
|
+
Tell the user the id and the message right after creating the ticket — both
|
|
38
|
+
can be changed any time, e.g. by renaming the folder before anything else is
|
|
39
|
+
added to it, or by editing `ticket.json`.
|
|
40
|
+
|
|
29
41
|
## 3. Choose the project management repo — or work without one
|
|
30
42
|
|
|
31
43
|
A ticket may belong to a project management repo: plans, decisions and blog
|
|
@@ -52,8 +64,9 @@ Call it the "project management repo" whenever you write to the user, never
|
|
|
52
64
|
|
|
53
65
|
## 4. Choose the code repos
|
|
54
66
|
|
|
55
|
-
Ask the user how the code repos are chosen, as a single question with
|
|
56
|
-
options
|
|
67
|
+
Ask the user how the code repos are chosen, as a single question with the
|
|
68
|
+
options below. Offer **only the project management repo** only when one was
|
|
69
|
+
added in step 3 — without one there is nothing to be "only" about.
|
|
57
70
|
|
|
58
71
|
- **automatically** — Claude finds the repos. Read the `index.jsonc` of
|
|
59
72
|
the candidate repos in `.ocean`. Tell the user which repos the ticket
|
|
@@ -65,6 +78,9 @@ options:
|
|
|
65
78
|
field which repos the ticket needs, e.g. `repo1 repo2`. Check each name
|
|
66
79
|
against the repos in `.ocean` and ask again for names that do not exist
|
|
67
80
|
there. The entered list is the confirmation.
|
|
81
|
+
- **only the project management repo** — no code repo at all; the ticket
|
|
82
|
+
stays pure planning, and the project management repo added in step 3 is
|
|
83
|
+
everything it carries.
|
|
68
84
|
|
|
69
85
|
A ticket that is only planned may need no code repo at all.
|
|
70
86
|
|
|
@@ -87,8 +103,9 @@ Run it only when the user asks for it.
|
|
|
87
103
|
|
|
88
104
|
## 6. Plan or implement
|
|
89
105
|
|
|
90
|
-
If the project management repo keeps requirements
|
|
91
|
-
|
|
106
|
+
If the project management repo keeps requirements
|
|
107
|
+
(`doc/<yyyy>-Q<n>/requirements`, in the newest quarter folder) and no
|
|
108
|
+
accepted requirement covers the ticket, engineer them with the user
|
|
92
109
|
first — with `/gg-plan-requirements` if the repo has it — before any plan or
|
|
93
110
|
code. Bug tickets are the exception, they name their bug file.
|
|
94
111
|
|