@ggdna/dna-gg 1.4.1 → 1.5.1
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 +5 -3
- package/dna/_generated.json +7 -7
- package/dna/doc/guides/develop-guide.md +6 -4
- package/dna/doc/guides/develop-without-ai-guide.md +4 -1
- package/dna/doc/guides/for-ai/ai-dev-guide.md +10 -2
- 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-ticket/SKILL.md +11 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -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": "0x47e288578bf3e862"
|
|
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",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
89
|
"path": ".claude/skills/gg-ticket/SKILL.md",
|
|
90
|
-
"hash": "
|
|
90
|
+
"hash": "0xa44f6e5ad54a6d0b"
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
93
|
"path": ".claude/skills/gg/SKILL.md",
|
|
@@ -107,15 +107,15 @@
|
|
|
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",
|
|
114
|
-
"hash": "
|
|
114
|
+
"hash": "0xc0d6546a678cb8cc"
|
|
115
115
|
},
|
|
116
116
|
{
|
|
117
117
|
"path": "doc/guides/for-ai/ai-dev-guide.md",
|
|
118
|
-
"hash": "
|
|
118
|
+
"hash": "0x3f2e79da5752c5fe"
|
|
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.
|
|
@@ -22,12 +22,15 @@ If you have not done that yet:
|
|
|
22
22
|
cd ~/dev/
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
## Add
|
|
25
|
+
## Add repos to the ticket
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
gg do add repo1 repo2
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
Name all repos in one call: every call refreshes the ocean and builds
|
|
32
|
+
the dependency graph again.
|
|
33
|
+
|
|
31
34
|
## Open the workspace in Vscode
|
|
32
35
|
|
|
33
36
|
```bash
|
|
@@ -104,6 +104,12 @@ After the user's confirmation, add the repos to the ticket:
|
|
|
104
104
|
gg do add repo1 repo2
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
+
Name all code repos in this one call, never one `gg do add` per repo —
|
|
108
|
+
not even for repos you find one after the other. Every call refreshes
|
|
109
|
+
the ocean and builds the dependency graph again, and a ticket repo that
|
|
110
|
+
depends on several new repos is resolved again for each call. The same
|
|
111
|
+
goes for repos you find later, while implementing: add them together.
|
|
112
|
+
|
|
107
113
|
## Keep every repo in its scope
|
|
108
114
|
|
|
109
115
|
Every repo covers one fixed scope: the `summary` and `domain` of its
|
|
@@ -121,7 +127,8 @@ as code does not fit the repo it is in or is about to land in:
|
|
|
121
127
|
covers: propose creating one with `gg do create repo`, which adds it to
|
|
122
128
|
the ticket
|
|
123
129
|
- **Add an existing repo** — the code belongs to a repo in .ocean that is
|
|
124
|
-
not part of the ticket yet: propose adding it with `gg do add
|
|
130
|
+
not part of the ticket yet: propose adding it with `gg do add`,
|
|
131
|
+
several repos in one call
|
|
125
132
|
- **Move code** — existing code, or code you just wrote, belongs to another
|
|
126
133
|
repo: propose moving it there
|
|
127
134
|
|
|
@@ -158,7 +165,8 @@ gg do code
|
|
|
158
165
|
## Plan (optional)
|
|
159
166
|
|
|
160
167
|
Requirements come before the plan. If the project management repo keeps
|
|
161
|
-
requirements (`doc
|
|
168
|
+
requirements (`doc/<yyyy>-Q<n>/requirements`, in the newest quarter
|
|
169
|
+
folder) and none of its accepted requirements
|
|
162
170
|
covers the ticket, engineer them with the user first — with
|
|
163
171
|
`/gg-plan-requirements` if the repo has it — and plan the ticket only after
|
|
164
172
|
that. Bug tickets are the exception, they name their bug file.
|
|
@@ -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
|
|
|
@@ -90,6 +90,12 @@ After the confirmation:
|
|
|
90
90
|
gg do add repo1 repo2
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
Name all code repos in this one call, never one `gg do add` per repo —
|
|
94
|
+
not even for repos you find one after the other. Every call refreshes
|
|
95
|
+
the ocean and builds the dependency graph again, and a ticket repo that
|
|
96
|
+
depends on several new repos is resolved again for each call. The same
|
|
97
|
+
goes for repos you find later, while implementing: add them together.
|
|
98
|
+
|
|
93
99
|
## 5. Open the workspace only on request
|
|
94
100
|
|
|
95
101
|
Do not open VS Code on your own — many tickets need no editor. Tell the
|
|
@@ -103,8 +109,9 @@ Run it only when the user asks for it.
|
|
|
103
109
|
|
|
104
110
|
## 6. Plan or implement
|
|
105
111
|
|
|
106
|
-
If the project management repo keeps requirements
|
|
107
|
-
|
|
112
|
+
If the project management repo keeps requirements
|
|
113
|
+
(`doc/<yyyy>-Q<n>/requirements`, in the newest quarter folder) and no
|
|
114
|
+
accepted requirement covers the ticket, engineer them with the user
|
|
108
115
|
first — with `/gg-plan-requirements` if the repo has it — before any plan or
|
|
109
116
|
code. Bug tickets are the exception, they name their bug file.
|
|
110
117
|
|
|
@@ -135,7 +142,8 @@ not fit the repo it is in or is about to land in:
|
|
|
135
142
|
|
|
136
143
|
- **Split a repo** that has grown a second scope into two repos
|
|
137
144
|
- **Add a new repo** with `gg do create repo` for a domain no repo covers
|
|
138
|
-
- **Add an existing repo** with `gg do add` when the code belongs there
|
|
145
|
+
- **Add an existing repo** with `gg do add` when the code belongs there;
|
|
146
|
+
several repos in one call
|
|
139
147
|
- **Move code**, existing or just written, into the repo whose scope it fits
|
|
140
148
|
|
|
141
149
|
Name the code, the repo it is in, the repo it should go to and why. Let the
|