@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 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/prompts/<first name>/<yyyy-mm>/<yyyy-mm-dd>_<repo>_<session>.md`.
55
- The first name comes from `doc/team/people.md` there, found by the git
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 `doc/prompts/_unknown/`. No
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
@@ -39,7 +39,7 @@
39
39
  "ecosystem": null,
40
40
  "resolvedVersion": null,
41
41
  "via": null,
42
- "hash": "0xcda6ccaeb5d52dd1"
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": "0xf4266eea17b3b9c1"
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": "0xcdef2684fcaaac5a"
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": "0x55b2f0deb18d70d4"
86
+ "hash": "0x3a4506ccd5c8e1be"
87
87
  },
88
88
  {
89
89
  "path": ".claude/skills/gg-ticket/SKILL.md",
90
- "hash": "0x0532d8ac37060521"
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": "0xed4328d138fe76ef"
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": "0xb6eecdb4c7a1ebe8"
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 `doc/prompts/<your first name>/` on the
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
- `doc/team/people.md` in the project management repo: the person whose
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/prompts/_unknown/`. Your e-mail address never goes there.
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 for the ticket infos
11
+ ## Ask the developer what the ticket should do
12
12
 
13
- Ask for these one after the other and give the developer a single input
14
- field per answer — one question per field, never all of them in one
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
- - Ask for the ticket ID
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
- - Replace `~/dev/` by the workspace directory from the memory
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
- ## Create a ticket
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 DnaJiraPrefix-145 -m"Fix issue abc"
33
- cd tickets/DnaJiraPrefix-145
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 two
66
- options: automatically or manually.
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
- If the ticket is only planned (see below), the project management repo may
84
- be the only repo of the ticket.
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/requirements`) and none of its accepted requirements
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, and open each
325
- pull request without auto-merge in the browser.
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
- const promptsDir = 'doc/prompts';
21
- const peopleFile = 'doc/team/people.md';
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
- return `${promptsDir}/${folder}/${date.slice(0, 7)}/${date}_${slug(meta.folder) || 'session'}_${id}.md`;
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
- return git(['-C', dir, 'show', `FETCH_HEAD:${peopleFile}`]).out;
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>`. If one is missing, go back to `/gg-review`.
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
- - Open every pull request without auto-merge in the browser. Ask the
61
- provider whether auto-merge is set:
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 and open its pull request URLs as in step 3. Update the blog
74
- post of the repo when the fix changes what it describes.
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 for the ticket data
11
+ ## 1. Ask what the ticket should do
12
12
 
13
- Ask for these three, one after the other, and give the user a single input
14
- field per answer — one question per field, never all three in one question
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 DnaJiraPrefix-145 -m"Fix issue abc"
26
- cd tickets/DnaJiraPrefix-145
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 two
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 (`doc/requirements`)
91
- and no accepted requirement covers the ticket, engineer them with the user
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ggdna/dna-gg",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "DNA layer: gg CLI workflow guides, repo setup scripts and CI check",
5
5
  "keywords": [
6
6
  "dna",