@handsupmin/gc-tree 0.8.16 → 0.8.18
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/dist/src/markdown.js +47 -23
- package/dist/src/onboarding-protocol.js +6 -3
- package/dist/src/scaffold.js +25 -12
- package/package.json +1 -1
- package/skills/onboard/SKILL.md +5 -3
package/dist/src/markdown.js
CHANGED
|
@@ -123,14 +123,21 @@ export function renderIndexMarkdown(input) {
|
|
|
123
123
|
}
|
|
124
124
|
else {
|
|
125
125
|
const categoryOrder = ['role', 'repos', 'domain', 'workflows', 'conventions', 'infra', 'verification', 'general'];
|
|
126
|
-
|
|
126
|
+
// Group by category, then by path within category
|
|
127
|
+
const byCategory = new Map();
|
|
127
128
|
for (const doc of input.docs) {
|
|
128
129
|
const category = normalizeCategory(doc.category || deriveCategoryFromPath(doc.path));
|
|
129
|
-
if (!
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
if (!byCategory.has(category))
|
|
131
|
+
byCategory.set(category, new Map());
|
|
132
|
+
const byPath = byCategory.get(category);
|
|
133
|
+
if (!byPath.has(doc.path))
|
|
134
|
+
byPath.set(doc.path, []);
|
|
135
|
+
const label = (doc.label || doc.title).trim();
|
|
136
|
+
if (label && !byPath.get(doc.path).includes(label)) {
|
|
137
|
+
byPath.get(doc.path).push(label);
|
|
138
|
+
}
|
|
132
139
|
}
|
|
133
|
-
const categories = [...
|
|
140
|
+
const categories = [...byCategory.keys()].sort((a, b) => {
|
|
134
141
|
const ai = categoryOrder.indexOf(a);
|
|
135
142
|
const bi = categoryOrder.indexOf(b);
|
|
136
143
|
if (ai === -1 && bi === -1)
|
|
@@ -143,9 +150,12 @@ export function renderIndexMarkdown(input) {
|
|
|
143
150
|
});
|
|
144
151
|
for (const category of categories) {
|
|
145
152
|
lines.push(`## ${displayCategory(category)}`, '');
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
lines.push(
|
|
153
|
+
const byPath = byCategory.get(category);
|
|
154
|
+
for (const [path, labels] of [...byPath.entries()].sort(([a], [b]) => a.localeCompare(b))) {
|
|
155
|
+
lines.push(`- ${path}`);
|
|
156
|
+
for (const label of labels) {
|
|
157
|
+
lines.push(` - ${label}`);
|
|
158
|
+
}
|
|
149
159
|
}
|
|
150
160
|
lines.push('');
|
|
151
161
|
}
|
|
@@ -182,41 +192,55 @@ export function displayCategory(category) {
|
|
|
182
192
|
}
|
|
183
193
|
export function parseIndexEntries(indexContent) {
|
|
184
194
|
let currentCategory = 'general';
|
|
185
|
-
let pendingLabel = null;
|
|
195
|
+
let pendingLabel = null; // legacy: label before indented path
|
|
196
|
+
let currentPath = null; // new: path before indented labels
|
|
186
197
|
const entries = [];
|
|
187
198
|
for (const rawLine of String(indexContent || '').split(/\r?\n/)) {
|
|
188
199
|
const line = rawLine.trimEnd();
|
|
189
200
|
const trimmed = line.trim();
|
|
190
201
|
if (!trimmed) {
|
|
191
202
|
pendingLabel = null;
|
|
203
|
+
currentPath = null;
|
|
192
204
|
continue;
|
|
193
205
|
}
|
|
194
206
|
const heading = trimmed.match(/^##\s+(.+)$/);
|
|
195
207
|
if (heading) {
|
|
196
208
|
currentCategory = normalizeCategory(heading[1] || 'general');
|
|
197
209
|
pendingLabel = null;
|
|
210
|
+
currentPath = null;
|
|
198
211
|
continue;
|
|
199
212
|
}
|
|
200
213
|
if (trimmed.startsWith('- gc-branch:') || trimmed.startsWith('- summary:') || trimmed === '- No source docs yet.') {
|
|
201
214
|
pendingLabel = null;
|
|
215
|
+
currentPath = null;
|
|
202
216
|
continue;
|
|
203
217
|
}
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
218
|
+
const isIndented = /^\s{2,}/.test(rawLine);
|
|
219
|
+
const itemText = trimmed.replace(/^-\s*/, '');
|
|
220
|
+
if (!isIndented) {
|
|
221
|
+
// Top-level list item
|
|
222
|
+
if (itemText.startsWith('docs/')) {
|
|
223
|
+
// New format: path is top-level
|
|
224
|
+
currentPath = itemText;
|
|
225
|
+
pendingLabel = null;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
// Legacy format: label is top-level
|
|
229
|
+
pendingLabel = itemText;
|
|
230
|
+
currentPath = null;
|
|
231
|
+
}
|
|
215
232
|
continue;
|
|
216
233
|
}
|
|
217
|
-
|
|
218
|
-
if (
|
|
219
|
-
|
|
234
|
+
// Indented item
|
|
235
|
+
if (currentPath && !itemText.startsWith('docs/')) {
|
|
236
|
+
// New format: keyword under path
|
|
237
|
+
const category = deriveCategoryFromPath(currentPath) || currentCategory;
|
|
238
|
+
entries.push({ id: docIdFromPath(currentPath), title: itemText, label: itemText, category, path: currentPath });
|
|
239
|
+
}
|
|
240
|
+
else if (pendingLabel && itemText.startsWith('docs/')) {
|
|
241
|
+
// Legacy format: path under label
|
|
242
|
+
const category = deriveCategoryFromPath(itemText) || currentCategory;
|
|
243
|
+
entries.push({ id: docIdFromPath(itemText), title: pendingLabel, label: pendingLabel, category, path: itemText });
|
|
220
244
|
}
|
|
221
245
|
}
|
|
222
246
|
return entries;
|
|
@@ -33,11 +33,10 @@ export function onboardingProtocolLines() {
|
|
|
33
33
|
'Synthesize the interview into an encyclopedia-style context set with many small docs instead of a few broad docs.',
|
|
34
34
|
'Prefer category directories such as `docs/role/`, `docs/repos/`, `docs/domain/`, `docs/workflows/`, `docs/conventions/`, and `docs/infra/` whenever that split fits the material.',
|
|
35
35
|
'Prefer one concept, one repository, one workflow, or one convention per file when possible.',
|
|
36
|
-
'
|
|
37
|
-
'
|
|
36
|
+
'Index entries are the search surface — maximize keyword density. For each doc, generate index entries from: primary concept names, aliases, repo nicknames, workflow names, field names, command names, acronyms, related terms a developer might search for, and any term that would make someone want to open this doc. Do NOT be conservative — more keywords means more chances of being found.',
|
|
37
|
+
'The index format groups keywords under their path: top-level `- docs/path.md` with indented ` - keyword` lines under it. This keeps the index compact while allowing many keywords per doc.',
|
|
38
38
|
'Split glossary docs when a concept is likely to be searched directly, needs more than a short definition, or carries workflow/constraint details; keep only low-value leftover terms in a shared glossary.',
|
|
39
39
|
'The `## Summary` section of every doc must be actionable, not descriptive — write the actual patterns, commands, or constraints a developer needs, not a sentence about what the doc covers. Bad: "이 문서는 updateCollection 패턴을 설명합니다." Good: "updateCollection: { ...dto } spread 필수. return plainToInstance(Res, result satisfies Res). 새 필드 추가 = DTO → 서비스 → 컨트롤러 순서." The summary is injected into the AI context before every task — if it reads like a table of contents entry, it is useless.',
|
|
40
|
-
'Treat `index.md` as a human-readable dictionary-style table of contents grouped by category headings and `label -> path` entries.',
|
|
41
40
|
];
|
|
42
41
|
}
|
|
43
42
|
export function onboardingCompletionLines() {
|
|
@@ -45,8 +44,12 @@ export function onboardingCompletionLines() {
|
|
|
45
44
|
'Before you claim onboarding is complete, run `gctree verify-onboarding --branch <current-gc-branch>` and inspect the real gc-tree files.',
|
|
46
45
|
'Do not claim onboarding is complete unless verification returns `status: "complete"` **and** `quality_issues` is an empty array.',
|
|
47
46
|
'If `quality_issues` is non-empty, do **not** tell the user onboarding is done. Self-heal immediately without asking the user: (a) identify which docs have `category: "general"`, (b) assign each a correct category from `role | repos | domain | workflows | conventions | infra | verification` based on content, (c) rebuild the full onboarding JSON with every doc having an explicit `category` field set to one of those values, (d) run `gctree __apply-onboarding --input <temp-file>` again, (e) rerun `gctree verify-onboarding` and repeat until `quality_issues` is empty. Never use `"general"` as a category in the JSON — it is a fallback for missing data, not a valid category.',
|
|
47
|
+
'After quality_issues passes, perform a summary quality check: read the actual `## Summary` section of each written doc file. If any summary reads like a table of contents entry ("이 문서는 X를 설명합니다", "X에 대한 패턴 모음") rather than actionable content (real patterns, commands, constraints), rewrite it in-place before continuing.',
|
|
48
|
+
'After summary check, perform an index coverage check: for every written doc, read its `## Index Entries` section and verify that the entries cover a wide range of terms a developer would search for — not just the exact document title. If a doc has fewer than 5 index entries, it almost certainly needs more. Add aliases, related terms, command names, field names, and workflow names. Re-apply if entries were added.',
|
|
48
49
|
'If verification returns `status: "incomplete"` for reasons other than quality_issues, do not tell the user onboarding is done; inspect the reported failures, heal what can be healed automatically, rerun verification, and repeat until it passes or a real blocker remains.',
|
|
49
50
|
'After applying the onboarding docs, explicitly list which durable docs were saved.',
|
|
51
|
+
'Before the final summary, run a coverage checklist and ask the user to confirm each area: (a) workflows — are the key cross-repo action sequences documented? (b) conventions — are the code patterns for each repo documented? (c) repos — is each relevant repo covered with role, paths, and cross-repo deps? (d) domain terms / glossary — are important acronyms and terms indexed? Present this as a numbered checklist and ask the user: "이 중 빠진 것이 있으면 말씀해주세요. 없으면 완료하겠습니다." Do not skip this step.',
|
|
52
|
+
'If the user identifies missing areas, gather the information and add the docs before continuing.',
|
|
50
53
|
'Then summarize what you now understand from the saved docs instead of stopping at the filenames alone.',
|
|
51
54
|
'For that final summary, do not ask an open-ended validation question first; present the summary and ask the user to choose only one structured confirmation: 1. This matches well enough. 2. Some parts are wrong. I will give the delta. 3. The frame is wrong. I will restate it.',
|
|
52
55
|
'If the user picks 2 or 3 for the final summary, ask only for the correction delta or replacement frame, then update the saved understanding instead of restarting the interview.',
|
package/dist/src/scaffold.js
CHANGED
|
@@ -104,18 +104,36 @@ function renderCodexOnboardSkill() {
|
|
|
104
104
|
'',
|
|
105
105
|
].join('\n');
|
|
106
106
|
}
|
|
107
|
+
function renderUpdateProtocol() {
|
|
108
|
+
return [
|
|
109
|
+
'1. Run `gctree status` and state the active gc-branch.',
|
|
110
|
+
'2. Understand what changed — read the user\'s request, inspect relevant code or docs if needed, and determine the right content to capture.',
|
|
111
|
+
'3. Decide category and path automatically based on content — never ask the user about scope or placement:',
|
|
112
|
+
' - `docs/workflows/<name>.md` — cross-repo action sequences, step-by-step procedures',
|
|
113
|
+
' - `docs/conventions/<repo>.md` — code patterns, naming, validation, DTO/service conventions for a repo',
|
|
114
|
+
' - `docs/repos/<repo>.md` — repo role, key paths, cross-repo dependencies',
|
|
115
|
+
' - `docs/domain/<concept>.md` — domain terms, acronyms, business logic',
|
|
116
|
+
' - `docs/infra/<topic>.md` — infra, deployment, environment config',
|
|
117
|
+
' - `docs/role/<name>.md` — team member roles, responsibilities',
|
|
118
|
+
'4. Write a `## Summary` that is actionable: actual patterns/commands/constraints a developer needs — not a sentence about what the doc covers.',
|
|
119
|
+
'5. Include a `## Index Entries` section in each doc\'s content with many keywords: aliases, related terms, command names, field names, workflow names, acronyms. More entries = more chances of being found by `gctree resolve`. Fewer than 5 entries almost always means more are needed.',
|
|
120
|
+
'6. Create a temporary JSON file with the updated `docs[]` and run `gctree __apply-update --input <temp-file>`.',
|
|
121
|
+
'7. Run `gctree verify-onboarding --branch <gc-branch>` and inspect the output:',
|
|
122
|
+
' - Check that every updated doc appears in the verified doc list.',
|
|
123
|
+
' - Check that index entries for the new content exist and are searchable (not just generic titles).',
|
|
124
|
+
' - Check that no doc has `category: "general"` — reassign to correct category if so.',
|
|
125
|
+
' - Check that important concepts from the update are present as index labels — if missing, re-apply with added index entries.',
|
|
126
|
+
' - Self-heal any issues without asking the user: fix category, add index entries, re-run `gctree __apply-update`, re-verify.',
|
|
127
|
+
'8. Show the user which docs were updated and confirm the index now covers the new content.',
|
|
128
|
+
];
|
|
129
|
+
}
|
|
107
130
|
function renderCodexUpdateSkill() {
|
|
108
131
|
return [
|
|
109
132
|
'---',
|
|
110
133
|
'description: Guided durable update for the active gc-branch in gctree.',
|
|
111
134
|
'---',
|
|
112
135
|
'',
|
|
113
|
-
|
|
114
|
-
'2. Ask what durable context should change, one question at a time.',
|
|
115
|
-
'3. If this repo clearly belongs to the current gc-branch but is not mapped yet, ask the user whether it should be added to the branch-repo map and run `gctree set-repo-scope --branch <current-gc-branch> --include` when they approve.',
|
|
116
|
-
'4. Create a temporary JSON file containing the updated `docs[]` and optional `branchSummary`.',
|
|
117
|
-
'5. Run `gctree __apply-update --input <temp-file>`.',
|
|
118
|
-
'6. Show the updated docs back to the user.',
|
|
136
|
+
...renderUpdateProtocol(),
|
|
119
137
|
'',
|
|
120
138
|
].join('\n');
|
|
121
139
|
}
|
|
@@ -222,12 +240,7 @@ function renderClaudeUpdateCommand() {
|
|
|
222
240
|
'description: Guided durable update for the active gc-branch in gctree.',
|
|
223
241
|
'---',
|
|
224
242
|
'',
|
|
225
|
-
|
|
226
|
-
'2. Ask what durable context should change, one question at a time.',
|
|
227
|
-
'3. If this repo clearly belongs to the current gc-branch but is not mapped yet, ask the user whether it should be added to the branch-repo map and run `gctree set-repo-scope --branch <current-gc-branch> --include` when they approve.',
|
|
228
|
-
'4. Create a temporary JSON file containing the updated `docs[]` and optional `branchSummary`.',
|
|
229
|
-
'5. Run `gctree __apply-update --input <temp-file>`.',
|
|
230
|
-
'6. Show the updated docs back to the user.',
|
|
243
|
+
...renderUpdateProtocol(),
|
|
231
244
|
'',
|
|
232
245
|
].join('\n');
|
|
233
246
|
}
|
package/package.json
CHANGED
package/skills/onboard/SKILL.md
CHANGED
|
@@ -43,10 +43,10 @@ Use this when a user wants to create global context for a product, company, or w
|
|
|
43
43
|
- prefer an encyclopedia-style context set with many small docs instead of a few broad docs
|
|
44
44
|
- prefer category directories like `docs/role/`, `docs/repos/`, `docs/domain/`, `docs/workflows/`, `docs/conventions/`, and `docs/infra/`
|
|
45
45
|
- prefer one concept, one repository, one workflow, or one convention per file when possible
|
|
46
|
-
- treat `index.md` as
|
|
46
|
+
- treat `index.md` as the search surface — maximize keyword density; for each doc generate entries from: primary names, aliases, nicknames, field names, command names, acronyms, related terms a developer might search for; do NOT be conservative — more keywords = more chances of being found; fewer than 5 index entries per doc almost certainly means more are needed
|
|
47
47
|
- generate index entries automatically from primary concept names, aliases, repository nicknames, and workflow labels when those are clear
|
|
48
48
|
- split glossary docs when a concept is likely to be searched directly, needs more than a short definition, or carries workflow/constraint details; keep only low-value leftover terms in a shared glossary
|
|
49
|
-
-
|
|
49
|
+
- index format: top-level `- docs/path.md` with indented ` - keyword` lines under it — groups all keywords per doc, eliminates path duplication
|
|
50
50
|
- every doc in the JSON **must** have an explicit `category` field set to one of: `role`, `repos`, `domain`, `workflows`, `conventions`, `infra`, `verification` — never use `"general"` as a category; it is a fallback for missing data, not a valid category choice
|
|
51
51
|
- use onboarding only for an empty gc-branch
|
|
52
52
|
|
|
@@ -88,12 +88,14 @@ Use this when a user wants to create global context for a product, company, or w
|
|
|
88
88
|
22. Ask for company/domain glossary terms and acronyms that should become durable context.
|
|
89
89
|
23. Ask which verification commands should be treated as defaults for this gc-branch.
|
|
90
90
|
24. Structure the durable docs as a small encyclopedia: split by category directory, keep one concept/repo/workflow/convention per file when possible, and keep a short `## Summary` at the top of each doc.
|
|
91
|
-
25. Render `index.md` as a
|
|
91
|
+
25. Render `index.md` grouped by category; within each category list each doc path as a top-level item with all its keywords as indented children. Maximize keywords per doc — aliases, related terms, command names, field names, workflow names.
|
|
92
92
|
26. Launch the guided onboarding flow with `gctree onboard [--branch <name>]`.
|
|
93
93
|
27. Before you claim onboarding is complete, run `gctree verify-onboarding --branch <current-gc-branch>` and inspect the real gc-tree files.
|
|
94
94
|
28. Do not claim onboarding is complete unless verification returns `status: "complete"` **and** `quality_issues` is an empty array.
|
|
95
95
|
29. If `quality_issues` is non-empty, do **not** tell the user onboarding is done. Self-heal immediately without prompting the user: (a) identify which docs have `category: "general"`, (b) assign each a correct category from `role | repos | domain | workflows | conventions | infra | verification` based on content, (c) rebuild the full onboarding JSON with every doc having an explicit `category` field — never use `"general"` as a category, (d) rerun `gctree __apply-onboarding --input <temp-file>`, (e) rerun `gctree verify-onboarding`, repeat until `quality_issues` is empty. If `status` is `"incomplete"` for other reasons, inspect the failures, heal them autonomously, and repeat.
|
|
96
96
|
30. After the onboarding docs are written, explicitly list which durable docs were saved.
|
|
97
|
+
30a. Run a coverage checklist before the final summary. Ask the user to confirm each area: (a) workflows — are key cross-repo action sequences documented? (b) conventions — are code patterns for each repo documented with a `## Patterns` section? (c) repos — is each relevant repo covered with role, paths, and cross-repo deps? (d) domain/glossary — are important acronyms and terms indexed with enough keywords? Present as a numbered checklist: "이 중 빠진 것이 있으면 말씀해주세요. 없으면 완료하겠습니다." If the user identifies gaps, gather and add before continuing. Do not skip this step.
|
|
98
|
+
30b. Check index keyword density: read the `## Index Entries` section of each written doc. If any doc has fewer than 5 entries, add more — aliases, related terms, command names, field names, workflow names. Re-apply if entries were added.
|
|
97
99
|
31. Summarize what you now understand from the saved docs instead of ending at the filenames alone.
|
|
98
100
|
32. For that final summary, do not ask an open-ended validation question first. Present the summary and ask the user to choose only one:
|
|
99
101
|
- 1. This matches well enough.
|