@caddis/cli 0.4.3 → 0.4.4
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/bundles/antigravity-plugin/plugin.json +1 -1
- package/bundles/antigravity-plugin/scripts/caddis_glossary.py +268 -0
- package/bundles/antigravity-plugin/scripts/setup_project_ai.py +43 -0
- package/bundles/antigravity-plugin/skills/_registry.md +1 -0
- package/bundles/antigravity-plugin/skills/glossary/SKILL.md +85 -0
- package/bundles/manifest.json +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""caddis_glossary — propose the words a project INVENTED, so they can be defined once.
|
|
2
|
+
|
|
3
|
+
WHY. Every project coins vocabulary out of ordinary English, and those are the worst words in
|
|
4
|
+
the codebase: a reader who guesses from the plain word gets them wrong and never knows. caddis
|
|
5
|
+
itself coined `pool`, `relay`, `drift`, `parking-lot`, `live-fire` — and its own glossary went
|
|
6
|
+
five and a half months without mentioning any of them, because nothing measured the gap.
|
|
7
|
+
|
|
8
|
+
WHAT THIS DOES AND DOES NOT DO. It PROPOSES candidates by measurement. It never writes a
|
|
9
|
+
definition, because a definition is domain knowledge that only a person or a model reading the
|
|
10
|
+
code can supply. A file of correct words with empty meanings is worse than no file: it looks
|
|
11
|
+
authoritative and teaches nothing. `/caddis:glossary` is the half that writes the meanings.
|
|
12
|
+
|
|
13
|
+
python caddis_glossary.py # propose candidates, ranked
|
|
14
|
+
python caddis_glossary.py --check # exit 1 if a proposed term has no entry
|
|
15
|
+
python caddis_glossary.py --scaffold # create the file if it is missing
|
|
16
|
+
|
|
17
|
+
HOW A CANDIDATE IS CHOSEN. Frequency alone is useless — "the file" beats every real term. A
|
|
18
|
+
word is a candidate when it is COMMON IN THIS REPO but is not ordinary technical English. The
|
|
19
|
+
stop-list below is the load-bearing part, and it is deliberately generous: a false positive
|
|
20
|
+
costs a human three seconds to ignore, while a false negative leaves a coined word undefined
|
|
21
|
+
forever, which is the failure being fixed.
|
|
22
|
+
|
|
23
|
+
ACCURACY, MEASURED. On a normal application repo it is good: run against `docket` it proposed
|
|
24
|
+
`board`, `lane`, `card`, `gate` — that project's actual coined vocabulary, top of the list. On a
|
|
25
|
+
HARNESS repo full of documentation ABOUT agents it is noisier, because words like `protocol` and
|
|
26
|
+
`intent` are both ordinary English and genuinely overloaded here. It is a suggester, not an
|
|
27
|
+
oracle; a human or the model decides what earns an entry.
|
|
28
|
+
|
|
29
|
+
Stdlib only, cross-platform, and it never raises on a bad file — it is run by a command and by
|
|
30
|
+
a gate, and a traceback from either is worse than a missing suggestion.
|
|
31
|
+
"""
|
|
32
|
+
from __future__ import annotations
|
|
33
|
+
|
|
34
|
+
import argparse
|
|
35
|
+
import collections
|
|
36
|
+
import os
|
|
37
|
+
import re
|
|
38
|
+
import sys
|
|
39
|
+
|
|
40
|
+
# ── what a project's own vocabulary lives in ────────────────────────────────────────────
|
|
41
|
+
DOC_GLOBS = (".md",)
|
|
42
|
+
SKIP_DIRS = {
|
|
43
|
+
".git", "node_modules", ".venv", "venv", "dist", "build", "__pycache__",
|
|
44
|
+
".mypy_cache", ".pytest_cache", "vendor", "site-packages", ".next", "target",
|
|
45
|
+
# Vendored and reference material is someone ELSE'S vocabulary. Without these, caddis's
|
|
46
|
+
# own run proposed `aws4` (33 files) and `mxgraph` (11) out of bundled AWS and draw-io
|
|
47
|
+
# reference docs — words no caddis reader will ever meet.
|
|
48
|
+
"references", "assets", "fixtures", ".archive", "archive", "examples", "sample",
|
|
49
|
+
"samples", "third_party", "vendored", "node_modules", "bundles", "runtime-resources",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Ordinary technical English. A word here is never proposed, however often it appears.
|
|
53
|
+
# Longer than it looks necessary on purpose: the cost of a false positive is a human ignoring
|
|
54
|
+
# one line; the cost of a false negative is a coined word nobody ever defines.
|
|
55
|
+
COMMON = {
|
|
56
|
+
# english scaffolding
|
|
57
|
+
"the", "and", "for", "with", "that", "this", "from", "into", "than", "then", "when",
|
|
58
|
+
"where", "which", "what", "who", "why", "how", "not", "but", "all", "any", "each",
|
|
59
|
+
"one", "two", "only", "also", "more", "most", "less", "some", "such", "same", "other",
|
|
60
|
+
"its", "it's", "you", "your", "our", "their", "they", "them", "has", "have", "had",
|
|
61
|
+
"was", "were", "been", "being", "are", "can", "will", "would", "should", "must", "may",
|
|
62
|
+
"does", "did", "done", "doing", "use", "used", "using", "make", "made", "get", "got",
|
|
63
|
+
"see", "read", "write", "run", "runs", "running", "ran", "set", "put", "take", "give",
|
|
64
|
+
"new", "old", "first", "last", "next", "now", "here", "there", "before", "after",
|
|
65
|
+
"over", "under", "out", "off", "own", "per", "via", "yes", "no", "if", "in", "on", "of",
|
|
66
|
+
"to", "at", "by", "as", "is", "be", "or", "so", "up", "do", "an", "a",
|
|
67
|
+
# ordinary software vocabulary — predictable from the word itself
|
|
68
|
+
"file", "files", "path", "paths", "dir", "directory", "folder", "code", "line", "lines",
|
|
69
|
+
"test", "tests", "testing", "error", "errors", "bug", "fix", "fixed", "build", "built",
|
|
70
|
+
"commit", "commits", "branch", "merge", "push", "pull", "repo", "repository", "git",
|
|
71
|
+
"api", "cli", "url", "http", "https", "json", "yaml", "toml", "html", "css", "sql",
|
|
72
|
+
"user", "users", "name", "names", "value", "values", "key", "keys", "type", "types",
|
|
73
|
+
"list", "lists", "table", "tables", "row", "rows", "column", "field", "fields",
|
|
74
|
+
"function", "method", "class", "module", "package", "library", "script", "scripts",
|
|
75
|
+
"server", "client", "request", "response", "data", "input", "output", "config",
|
|
76
|
+
"version", "release", "install", "update", "delete", "create", "add", "remove",
|
|
77
|
+
"return", "returns", "call", "calls", "check", "checks", "log", "logs", "note", "notes",
|
|
78
|
+
"step", "steps", "case", "cases", "example", "default", "option", "options", "flag",
|
|
79
|
+
"flags", "command", "commands", "tool", "tools", "agent", "agents", "model", "models",
|
|
80
|
+
"session", "sessions", "context", "prompt", "prompts", "token", "tokens", "cache",
|
|
81
|
+
"state", "status", "result", "results", "change", "changes", "work", "works", "time",
|
|
82
|
+
"does", "doc", "docs", "document", "section", "page", "text", "content", "format",
|
|
83
|
+
"project", "projects", "team", "user", "system", "service", "process", "task", "tasks",
|
|
84
|
+
"issue", "issues", "problem", "solution", "reason", "cause", "point", "part", "way",
|
|
85
|
+
"thing", "things", "need", "needs", "want", "know", "like", "just", "even", "still",
|
|
86
|
+
"never", "always", "every", "both", "because", "while", "since", "about", "against",
|
|
87
|
+
# added after the first real run proposed all of these — ordinary in any codebase
|
|
88
|
+
"skill", "skills", "plan", "plans", "phase", "phases", "design", "designs", "review",
|
|
89
|
+
"reviews", "mode", "modes", "pattern", "patterns", "implementation", "reference",
|
|
90
|
+
"description", "descriptions", "workflow", "workflows", "feature", "features",
|
|
91
|
+
"component", "components", "interface", "structure", "approach", "detail", "details",
|
|
92
|
+
"requirement", "requirements", "specification", "architecture", "instructions",
|
|
93
|
+
"guidelines", "standard", "standards", "best", "practice", "practices", "overview",
|
|
94
|
+
"summary", "report", "reports", "action", "actions", "level", "levels", "order",
|
|
95
|
+
"number", "count", "size", "start", "stop", "begin", "end", "open", "close", "load",
|
|
96
|
+
"save", "store", "fetch", "send", "receive", "handle", "handles", "support", "supports",
|
|
97
|
+
"references", "security", "scope", "verification", "react", "python", "typescript",
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_WORD = re.compile(r"[a-z][a-z0-9]*(?:-[a-z0-9]+)*", re.I)
|
|
101
|
+
|
|
102
|
+
# A term must appear at least this often, in at least this many files, to be proposed.
|
|
103
|
+
# One mention is a passing usage; a coined term earns its definition by recurring.
|
|
104
|
+
MIN_USES = 12
|
|
105
|
+
MIN_FILES = 3
|
|
106
|
+
MAX_SUGGESTIONS = 25
|
|
107
|
+
# A coined term is specific, so in a LARGE corpus it shows up in a minority of files. Measured:
|
|
108
|
+
# `description` appeared in 2112 of ~2500 caddis docs and outranked every real term.
|
|
109
|
+
#
|
|
110
|
+
# But this rule INVERTS on a small repo. Applied unconditionally it deleted docket's four best
|
|
111
|
+
# candidates — `board`, `lane`, `card`, `docket` — because in a 50-file repo the core vocabulary
|
|
112
|
+
# genuinely is in most files. So it only engages once there are enough files for "share" to
|
|
113
|
+
# mean anything.
|
|
114
|
+
MAX_FILE_SHARE = 0.25
|
|
115
|
+
SHARE_RULE_MIN_CORPUS = 200
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _doc_files(root: str) -> list[str]:
|
|
119
|
+
found = []
|
|
120
|
+
for dirpath, dirnames, filenames in os.walk(root):
|
|
121
|
+
dirnames[:] = [d for d in dirnames if d not in SKIP_DIRS and not d.startswith(".venv")]
|
|
122
|
+
for n in filenames:
|
|
123
|
+
if n.endswith(DOC_GLOBS):
|
|
124
|
+
found.append(os.path.join(dirpath, n))
|
|
125
|
+
return found
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def glossary_path(root: str) -> str:
|
|
129
|
+
"""`.caddis/kb/GLOSSARY.md` — beside the KB, which is where reference docs live."""
|
|
130
|
+
return os.path.join(root, ".caddis", "kb", "GLOSSARY.md")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def defined_terms(path: str) -> set[str]:
|
|
134
|
+
"""Canonical terms are the first cell of each markdown table row."""
|
|
135
|
+
if not os.path.isfile(path):
|
|
136
|
+
return set()
|
|
137
|
+
terms = set()
|
|
138
|
+
try:
|
|
139
|
+
with open(path, encoding="utf-8", errors="replace") as fh:
|
|
140
|
+
for line in fh:
|
|
141
|
+
if not line.startswith("|"):
|
|
142
|
+
continue
|
|
143
|
+
cells = [c.strip() for c in line.strip().strip("|").split("|")]
|
|
144
|
+
if len(cells) < 2 or not cells[0] or set(cells[0]) <= {"-", ":", " "}:
|
|
145
|
+
continue
|
|
146
|
+
head = cells[0].strip("`*").lower()
|
|
147
|
+
if head in {"term", "canonical term", "word"}:
|
|
148
|
+
continue
|
|
149
|
+
terms.add(head)
|
|
150
|
+
except OSError:
|
|
151
|
+
return set()
|
|
152
|
+
return terms
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def propose(root: str) -> list[tuple[str, int, int]]:
|
|
156
|
+
"""Return [(term, uses, files)] — words this repo says often that plain English does not."""
|
|
157
|
+
uses: collections.Counter = collections.Counter()
|
|
158
|
+
files: dict[str, set] = collections.defaultdict(set)
|
|
159
|
+
for f in _doc_files(root):
|
|
160
|
+
try:
|
|
161
|
+
text = open(f, encoding="utf-8", errors="replace").read().lower()
|
|
162
|
+
except OSError:
|
|
163
|
+
continue
|
|
164
|
+
# Strip fenced code and inline code: identifiers are not project vocabulary.
|
|
165
|
+
text = re.sub(r"```.*?```", " ", text, flags=re.S)
|
|
166
|
+
text = re.sub(r"`[^`]*`", " ", text)
|
|
167
|
+
for w in _WORD.findall(text):
|
|
168
|
+
if len(w) < 4 or w in COMMON:
|
|
169
|
+
continue
|
|
170
|
+
uses[w] += 1
|
|
171
|
+
files[w].add(f)
|
|
172
|
+
total = max(1, len(_doc_files(root)))
|
|
173
|
+
out = [
|
|
174
|
+
(w, n, len(files[w]))
|
|
175
|
+
for w, n in uses.items()
|
|
176
|
+
if n >= MIN_USES
|
|
177
|
+
and len(files[w]) >= MIN_FILES
|
|
178
|
+
and (total < SHARE_RULE_MIN_CORPUS or (len(files[w]) / total) <= MAX_FILE_SHARE)
|
|
179
|
+
]
|
|
180
|
+
out.sort(key=lambda r: (-r[1], r[0]))
|
|
181
|
+
return out
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
TEMPLATE = """# Glossary
|
|
185
|
+
|
|
186
|
+
The words this project invented out of ordinary English, defined once.
|
|
187
|
+
|
|
188
|
+
**Admission test:** a term belongs here when its meaning in this project is *distinct enough
|
|
189
|
+
from its ordinary technical sense that a newcomer would misread it*. `commit` does not belong.
|
|
190
|
+
A word this team uses in its own way does.
|
|
191
|
+
|
|
192
|
+
Proposed by `caddis_glossary.py`, which measures which words this repo says often that plain
|
|
193
|
+
English does not. It cannot write the definitions — run `/caddis:glossary` and the model will
|
|
194
|
+
draft them from the actual code, or write them yourself.
|
|
195
|
+
|
|
196
|
+
| Term | Definition | DO NOT USE |
|
|
197
|
+
|---|---|---|
|
|
198
|
+
| _example_ | Replace this row. A definition should say what the word means HERE, and why the ordinary reading is wrong. | the synonyms that cause confusion |
|
|
199
|
+
|
|
200
|
+
## Flagged ambiguities
|
|
201
|
+
|
|
202
|
+
Name the words that are still overloaded rather than pretending the vocabulary is clean. A
|
|
203
|
+
glossary that hides its own dirt starts lying. Delete this section only when there is genuinely
|
|
204
|
+
nothing to flag.
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def main(argv: list[str] | None = None) -> int:
|
|
209
|
+
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
|
210
|
+
ap.add_argument("--root", default=os.getcwd())
|
|
211
|
+
ap.add_argument("--check", action="store_true",
|
|
212
|
+
help="exit 1 if a proposed term has no entry")
|
|
213
|
+
ap.add_argument("--scaffold", action="store_true",
|
|
214
|
+
help="write the glossary template if it does not exist")
|
|
215
|
+
args = ap.parse_args(argv)
|
|
216
|
+
|
|
217
|
+
root = os.path.abspath(args.root)
|
|
218
|
+
path = glossary_path(root)
|
|
219
|
+
|
|
220
|
+
if args.scaffold:
|
|
221
|
+
if os.path.isfile(path):
|
|
222
|
+
print("[glossary] present — kept: %s" % os.path.relpath(path, root))
|
|
223
|
+
else:
|
|
224
|
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
225
|
+
with open(path, "w", encoding="utf-8", newline="\n") as fh:
|
|
226
|
+
fh.write(TEMPLATE)
|
|
227
|
+
print("[glossary] wrote %s" % os.path.relpath(path, root))
|
|
228
|
+
return 0
|
|
229
|
+
|
|
230
|
+
candidates = propose(root)
|
|
231
|
+
defined = defined_terms(path)
|
|
232
|
+
missing = [(w, n, f) for w, n, f in candidates if w not in defined]
|
|
233
|
+
|
|
234
|
+
if args.check:
|
|
235
|
+
# Advisory by design. A project may legitimately decide a frequent word needs no
|
|
236
|
+
# definition, and a gate that cannot be satisfied gets bypassed rather than obeyed.
|
|
237
|
+
if not os.path.isfile(path):
|
|
238
|
+
print("[glossary] no %s — run with --scaffold" % os.path.relpath(path, root))
|
|
239
|
+
return 0
|
|
240
|
+
if missing:
|
|
241
|
+
print("[glossary] %d frequent term(s) with no entry:" % len(missing))
|
|
242
|
+
for w, n, f in missing[:MAX_SUGGESTIONS]:
|
|
243
|
+
print(" %-24s %4d uses in %d files" % (w, n, f))
|
|
244
|
+
print(" Define them, or leave them — this is advisory. `/caddis:glossary` drafts them.")
|
|
245
|
+
return 1
|
|
246
|
+
print("[glossary] every frequent term is defined (%d entries)" % len(defined))
|
|
247
|
+
return 0
|
|
248
|
+
|
|
249
|
+
if not candidates:
|
|
250
|
+
print("[glossary] no candidates — too few docs, or nothing recurs enough.")
|
|
251
|
+
return 0
|
|
252
|
+
print("Candidate vocabulary for %s" % root)
|
|
253
|
+
print(" (>= %d uses across >= %d files, ordinary English excluded)\n" % (MIN_USES, MIN_FILES))
|
|
254
|
+
print(" %-26s %6s %6s %s" % ("TERM", "USES", "FILES", "DEFINED?"))
|
|
255
|
+
for w, n, f in candidates[:MAX_SUGGESTIONS]:
|
|
256
|
+
print(" %-26s %6d %6d %s" % (w, n, f, "yes" if w in defined else "-- no --"))
|
|
257
|
+
if missing:
|
|
258
|
+
print("\n %d undefined. Run `/caddis:glossary` to draft definitions from the code."
|
|
259
|
+
% len(missing))
|
|
260
|
+
return 0
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
if __name__ == "__main__":
|
|
264
|
+
try:
|
|
265
|
+
sys.exit(main())
|
|
266
|
+
except Exception as exc: # pragma: no cover — a suggester must never break a caller
|
|
267
|
+
print("[glossary] skipped: %s" % exc)
|
|
268
|
+
sys.exit(0)
|
|
@@ -902,6 +902,35 @@ memory.jsonl
|
|
|
902
902
|
"""
|
|
903
903
|
|
|
904
904
|
|
|
905
|
+
GLOSSARY_TEMPLATE = """\
|
|
906
|
+
# Glossary
|
|
907
|
+
|
|
908
|
+
The words this project invented out of ordinary English, defined once.
|
|
909
|
+
|
|
910
|
+
**Admission test:** a term belongs here when its meaning in this project is *distinct
|
|
911
|
+
enough from its ordinary technical sense that a newcomer would misread it*. `commit` does
|
|
912
|
+
not belong. A word this team uses in its own way does.
|
|
913
|
+
|
|
914
|
+
To find candidates, run the measurer. It ranks the words this repo says often that plain
|
|
915
|
+
English does not, and marks which already have an entry:
|
|
916
|
+
|
|
917
|
+
python <caddis>/scripts/caddis_glossary.py
|
|
918
|
+
|
|
919
|
+
It cannot write the definitions - only a person or the model reading the code can say what
|
|
920
|
+
a coined word MEANS here. Run `/caddis:glossary` to have them drafted, or write them.
|
|
921
|
+
|
|
922
|
+
| Term | Definition | DO NOT USE |
|
|
923
|
+
|---|---|---|
|
|
924
|
+
| _example_ | Replace this row. Say what the word means HERE, and why the ordinary reading is wrong. | the synonyms that cause confusion |
|
|
925
|
+
|
|
926
|
+
## Flagged ambiguities
|
|
927
|
+
|
|
928
|
+
Name the words that are still overloaded rather than pretending the vocabulary is clean. A
|
|
929
|
+
glossary that hides its own dirt starts lying. Delete this section only when there is
|
|
930
|
+
genuinely nothing to flag.
|
|
931
|
+
"""
|
|
932
|
+
|
|
933
|
+
|
|
905
934
|
ARTIFACT_CONFIG_EXAMPLE = """\
|
|
906
935
|
# caddis per-repo configuration — a documented template.
|
|
907
936
|
#
|
|
@@ -1198,6 +1227,20 @@ def scaffold_artifact_dir(target: Path, dry: bool) -> list[str]:
|
|
|
1198
1227
|
em.parent.mkdir(parents=True, exist_ok=True)
|
|
1199
1228
|
em.write_text(ENVIRONMENT_MAP_TEMPLATE, encoding="utf-8")
|
|
1200
1229
|
notes.append(f"scaffold: wrote {label}/kb/environment-map.md")
|
|
1230
|
+
# A vocabulary stub, seeded but never auto-filled. `caddis_glossary.py` can measure
|
|
1231
|
+
# which words a repo coined, but only a person or the model reading the code can say
|
|
1232
|
+
# what they MEAN - and a file of correct words with empty meanings looks authoritative
|
|
1233
|
+
# while teaching nothing. The stub carries the admission test so whoever fills it in
|
|
1234
|
+
# knows what qualifies.
|
|
1235
|
+
gl = root / "kb" / "GLOSSARY.md"
|
|
1236
|
+
if gl.exists():
|
|
1237
|
+
notes.append(f"scaffold: {label}/kb/GLOSSARY.md present - kept")
|
|
1238
|
+
else:
|
|
1239
|
+
if not dry:
|
|
1240
|
+
gl.parent.mkdir(parents=True, exist_ok=True)
|
|
1241
|
+
gl.write_text(GLOSSARY_TEMPLATE, encoding="utf-8")
|
|
1242
|
+
notes.append(f"scaffold: wrote {label}/kb/GLOSSARY.md (run /caddis:glossary to fill it)")
|
|
1243
|
+
|
|
1201
1244
|
gi = root / ".gitignore"
|
|
1202
1245
|
if gi.exists():
|
|
1203
1246
|
# APPEND what is missing rather than keeping the file frozen. The old behaviour was
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
| Feature Plan | `feature-plan/` | Create a phased, TDD-structured implementation plan that acts as the durable spine for multi-session work |
|
|
77
77
|
| Gate Preflight | `gate-preflight/` | Deterministic headless preflight — validates a plan against the actual codebase, self-contained (never depends on a skill activating) |
|
|
78
78
|
| Gate Review | `gate-review/` | Deterministic headless code review — adversarial diff review, self-contained (never depends on a skill activating) |
|
|
79
|
+
| Glossary | `glossary/` | Define the words this project invented, in one place — .caddis/kb/GLOSSARY.md |
|
|
79
80
|
| Handoff | `handoff/` | End-of-session handoff — capture exact state so the next session resumes with zero re-discovery |
|
|
80
81
|
| Implement | `implement/` | Headless plan executor — implement an approved plan phase-by-phase on the current feature branch, TDD-first, committing per phase |
|
|
81
82
|
| Kb | `kb/` | Rebuild the KB index (.caddis/kb/DOC-MAP.md) — create it if missing, index un-indexed notes, report dangling links |
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: glossary
|
|
3
|
+
description: Define the words this project invented, in one place — .caddis/kb/GLOSSARY.md
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /glossary — define what this project coined
|
|
7
|
+
|
|
8
|
+
Every project invents vocabulary out of ordinary English, and those are the most dangerous words
|
|
9
|
+
in the codebase: a reader who guesses from the plain word gets it wrong and never finds out.
|
|
10
|
+
caddis itself coined `pool`, `relay`, `drift`, `parking-lot` — and its own glossary went five and
|
|
11
|
+
a half months without mentioning any of them, because nothing measured the gap.
|
|
12
|
+
|
|
13
|
+
Your job is the half a script cannot do: **write what the words mean here.**
|
|
14
|
+
|
|
15
|
+
## Step 1 — get the candidates
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
python <caddis-plugin-root>/scripts/caddis_glossary.py
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
It ranks the words this repo says often that plain English does not, and marks which already
|
|
22
|
+
have an entry. `--scaffold` creates `.caddis/kb/GLOSSARY.md` if it is missing.
|
|
23
|
+
|
|
24
|
+
It is a **suggester, not an oracle**. It is good on an application repo — run against a kanban
|
|
25
|
+
tool it proposed `board`, `lane`, `card` at the top — and noisier on a repo whose docs are ABOUT
|
|
26
|
+
software, where words like `protocol` are both ordinary and genuinely overloaded. Expect to
|
|
27
|
+
discard some suggestions. That is the intended cost: a false positive wastes three seconds, a
|
|
28
|
+
missing term stays undefined forever.
|
|
29
|
+
|
|
30
|
+
If the script is not available, read the repo yourself and look for the same thing.
|
|
31
|
+
|
|
32
|
+
## Step 2 — apply the admission test to each candidate
|
|
33
|
+
|
|
34
|
+
A term belongs **only if its meaning here is distinct enough from its ordinary technical sense
|
|
35
|
+
that a newcomer would misread it.**
|
|
36
|
+
|
|
37
|
+
- `commit`, `branch`, `endpoint` — **no**. The ordinary meaning is correct.
|
|
38
|
+
- A word the team bent to its own purpose — **yes**. That is the whole point.
|
|
39
|
+
|
|
40
|
+
Discard the rest without comment. A padded glossary is skimmed and then ignored.
|
|
41
|
+
|
|
42
|
+
## Step 3 — write each definition from the CODE, not from the word
|
|
43
|
+
|
|
44
|
+
Read where the term is actually used before defining it. A definition that restates the word
|
|
45
|
+
teaches nothing, and a wrong one is worse than a gap because it is believed.
|
|
46
|
+
|
|
47
|
+
Each row gets three things:
|
|
48
|
+
|
|
49
|
+
| Column | What goes in it |
|
|
50
|
+
|---|---|
|
|
51
|
+
| **Term** | The canonical spelling. Pick one and stop using the others. |
|
|
52
|
+
| **Definition** | What it means HERE, and — where it helps — why the ordinary reading misleads. Say the thing a newcomer would get wrong. |
|
|
53
|
+
| **DO NOT USE** | The synonyms actually causing confusion in this repo. Leave blank rather than inventing some. |
|
|
54
|
+
|
|
55
|
+
Good: *"pool — the single source of every shipped resource, in `.github/`. Everything installed is EXPORTED from it; nothing is authored in a bundle."*
|
|
56
|
+
|
|
57
|
+
Bad: *"pool — a pool of resources."*
|
|
58
|
+
|
|
59
|
+
## Step 4 — flag what is still dirty
|
|
60
|
+
|
|
61
|
+
Fill the **Flagged ambiguities** section with the words that remain overloaded. This is the part
|
|
62
|
+
people skip and it is the most valuable part, because a glossary that hides its own dirt starts
|
|
63
|
+
lying.
|
|
64
|
+
|
|
65
|
+
Look for a term used in several incompatible senses. In caddis, `gate` is defined as one thing
|
|
66
|
+
and used as at least twelve — exit gate, quality gate, evidence gate, privacy gate. The honest
|
|
67
|
+
move is to name the overload and recommend the two-word form, not to pick a winner by fiat.
|
|
68
|
+
|
|
69
|
+
Also flag a term whose canonical spelling the code itself contradicts. Do not "fix" either side
|
|
70
|
+
when both are load-bearing; document the split and where each applies.
|
|
71
|
+
|
|
72
|
+
## Step 5 — report
|
|
73
|
+
|
|
74
|
+
Say how many terms you added, how many candidates you rejected and roughly why, and what you
|
|
75
|
+
flagged as ambiguous. If you found nothing worth adding, say that — it is a real answer, and
|
|
76
|
+
better than padding the file to look productive.
|
|
77
|
+
|
|
78
|
+
## Keeping it honest
|
|
79
|
+
|
|
80
|
+
Re-run `caddis_glossary.py --check` later. It exits 1 when a frequent term has no entry. It is
|
|
81
|
+
**advisory**: a project may reasonably decide a common word needs no definition, and a gate that
|
|
82
|
+
cannot be satisfied gets bypassed rather than obeyed.
|
|
83
|
+
|
|
84
|
+
Do not enforce the DO-NOT-USE column by grepping. Most banned synonyms are ordinary English —
|
|
85
|
+
"step", "block", "refuse" — and a check that cries wolf gets deleted, leaving no check at all.
|
package/bundles/manifest.json
CHANGED
package/package.json
CHANGED