@tekyzinc/gsd-t 4.20.11 → 5.0.11
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/CHANGELOG.md +21 -0
- package/README.md +2 -1
- package/bin/gsd-t.js +92 -10
- package/commands/gsd-t-architect.md +135 -0
- package/commands/gsd-t-help.md +7 -0
- package/package.json +1 -1
- package/scripts/gsd-t-architect-oversight-guard.js +116 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to GSD-T are documented here. Updated with each release.
|
|
4
4
|
|
|
5
|
+
## [5.0.11] - 2026-07-12
|
|
6
|
+
|
|
7
|
+
### Fixed — architect hook now ships + installs; de-flaked its test
|
|
8
|
+
|
|
9
|
+
The M101/v5.0.10 architect-oversight hook existed only in `~/.claude/scripts/` — it was never copied into the repo, so `install`/`update-all` would not propagate it to other machines (the "propagate a tool without shipping it = silent no-op" class). This release ships it properly and hardens it.
|
|
10
|
+
|
|
11
|
+
- `scripts/gsd-t-architect-oversight-guard.js`: the hook now lives in the repo (ships with the package). Added an unref'd 1500ms watchdog + a stdin `error` handler so the hook can NEVER hang and block a Write/Edit (fail-open guaranteed even if stdin never EOFs).
|
|
12
|
+
- `bin/gsd-t.js`: `configureArchitectHook()` registers the PreToolUse `Write|Edit` hook via the global-package command pattern (same as the graph/read-intercept hooks); wired into `install`; removed on `uninstall`. Exported for tests.
|
|
13
|
+
- `test/m101-architect-oversight-hook.test.js`: replaced the two spawn-per-assertion fail-open tests (which false-failed under full-suite CPU starvation, not a hook bug) with a source-guard assertion + installer idempotency/coexistence tests. Test resolves the repo hook copy.
|
|
14
|
+
- `.gsd-t/contracts/graph-metrics-contract.md`: refreshed the `doMetrics` line citation (shifted by the installer addition).
|
|
15
|
+
|
|
16
|
+
## [5.0.10] - 2026-07-12
|
|
17
|
+
|
|
18
|
+
### Added — `/gsd-t-architect`: run the Architect's Oversight pass on demand
|
|
19
|
+
|
|
20
|
+
A standalone command that runs the M101 Six-Stage Pass (Objective → Conflict → Reuse → Simplicity → Reuse-forecast → Risk) on **existing** work — an already-frozen plan, a messy subsystem, or a pasted tangle of problems — and produces the simplest correct solution as plain-English pseudocode, plus the traps each stage surfaces and what's already reusable. Major bump: this is the on-demand front door to design-first, reuse-first development, not an incremental command. Where the plan/milestone workflow runs the pass *while generating* a plan, this runs it as a standalone audit over work that already exists.
|
|
21
|
+
|
|
22
|
+
- `commands/gsd-t-architect.md`: prose-driven command — spawns one opus analysis subagent, reasons from the code graph (reuse/duplication) and real code, not memory. Default = plan-only then offers to build; `--build` auto-builds the simplest fix; `--chat-only` skips writing a file. Always prints a findings + plan summary to the session, even in auto-build. Reuses the existing prose-command + Task-subagent pattern (`/gsd-t-status`, `/gsd-t-impact`) — no new workflow file (the doctrine obeying its own Stage 3/4).
|
|
23
|
+
- `README.md` + `commands/gsd-t-help.md`: command documented.
|
|
24
|
+
- `test/filesystem.test.js`: command counts 54→55 / 48→49.
|
|
25
|
+
|
|
5
26
|
## [4.20.11] - 2026-07-12
|
|
6
27
|
|
|
7
28
|
### Added — M101: Architect's Oversight Doctrine
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# GSD-T: Contract-Driven Development for Claude Code
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**v5.0.11** - A methodology for reliable, parallelizable development using Claude Code with optional Agent Teams support.
|
|
4
4
|
|
|
5
5
|
**Eliminates context rot** — task-level fresh dispatch (one subagent per task, ~10-20% context each) means compaction never triggers.
|
|
6
6
|
**Compaction-proof debug loops** — `gsd-t headless --debug-loop` runs test-fix-retest cycles as separate `claude -p` sessions. A JSONL debug ledger persists all hypothesis/fix/learning history across fresh sessions. Anti-repetition preamble injection prevents retrying failed hypotheses. Escalation tiers (sonnet → opus → human) and a hard iteration ceiling enforced externally.
|
|
@@ -200,6 +200,7 @@ This will replace changed command files, back up your CLAUDE.md if customized, a
|
|
|
200
200
|
| `/gsd-t-partition` | Decompose into domains + contracts | In wave |
|
|
201
201
|
| `/gsd-t-plan` | Create atomic task lists per domain (tasks auto-split to fit one context window) | In wave |
|
|
202
202
|
| `/gsd-t-impact` | Analyze downstream effects | In wave |
|
|
203
|
+
| `/gsd-t-architect` | Run the Architect's Oversight Six-Stage Pass on existing work — finds the simplest solution + reuse + traps, as plain-English pseudocode (plan-only; `--build` to auto-build) | Manual |
|
|
203
204
|
| `/gsd-t-execute` | Run tasks — task-level fresh dispatch, worktree isolation, adaptive replanning | In wave |
|
|
204
205
|
| `/gsd-t-test-sync` | Sync tests with code changes | In wave |
|
|
205
206
|
| `/gsd-t-qa` | QA agent — test generation, execution, gap reporting | Auto-spawned |
|
package/bin/gsd-t.js
CHANGED
|
@@ -485,6 +485,15 @@ const READ_INTERCEPT_HOOK_MARKER = "gsd-t-read-intercept";
|
|
|
485
485
|
const READ_INTERCEPT_HOOK_COMMAND =
|
|
486
486
|
'bash -c \'[ -f "$(npm root -g)/@tekyzinc/gsd-t/scripts/gsd-t-read-intercept.js" ] && node "$(npm root -g)/@tekyzinc/gsd-t/scripts/gsd-t-read-intercept.js" || true\'';
|
|
487
487
|
|
|
488
|
+
// M101 — architect-oversight PreToolUse hook on Write|Edit. Same global-package
|
|
489
|
+
// pattern as the intercept hooks: runs the script from the globally-installed
|
|
490
|
+
// package, and the script fails-open (no-op) in non-GSD-T projects / prose writes,
|
|
491
|
+
// so it is safe to register globally with a Write|Edit matcher. It reminds the model
|
|
492
|
+
// to run the Architect's Oversight Six-Stage Pass before writing code (M101).
|
|
493
|
+
const ARCHITECT_HOOK_MARKER = "gsd-t-architect-oversight-guard";
|
|
494
|
+
const ARCHITECT_HOOK_COMMAND =
|
|
495
|
+
'bash -c \'[ -f "$(npm root -g)/@tekyzinc/gsd-t/scripts/gsd-t-architect-oversight-guard.js" ] && node "$(npm root -g)/@tekyzinc/gsd-t/scripts/gsd-t-architect-oversight-guard.js" || true\'';
|
|
496
|
+
|
|
488
497
|
// Append entries to {projectDir}/.gitignore. Each entry added only if absent.
|
|
489
498
|
// Idempotent. Returns true if any entries were added, false otherwise.
|
|
490
499
|
function ensureGitignoreEntries(projectDir, entries) {
|
|
@@ -928,6 +937,60 @@ function configureReadInterceptHook(settingsPath) {
|
|
|
928
937
|
return { installed: true, action };
|
|
929
938
|
}
|
|
930
939
|
|
|
940
|
+
// M101 — register the architect-oversight PreToolUse hook (matcher "Write|Edit").
|
|
941
|
+
// Idempotent: find-by-marker, refresh stale command, else add. Mirrors the M98
|
|
942
|
+
// read-intercept installer but on PreToolUse. The script fails-open so this is
|
|
943
|
+
// safe globally (silent in non-GSD-T projects and on prose/doc writes).
|
|
944
|
+
function configureArchitectHook(settingsPath) {
|
|
945
|
+
const targetPath = settingsPath || SETTINGS_JSON;
|
|
946
|
+
let settings = {};
|
|
947
|
+
if (fs.existsSync(targetPath)) {
|
|
948
|
+
try {
|
|
949
|
+
settings = JSON.parse(fs.readFileSync(targetPath, "utf8"));
|
|
950
|
+
if (!settings || typeof settings !== "object") settings = {};
|
|
951
|
+
} catch {
|
|
952
|
+
warn("settings.json has invalid JSON — cannot configure architect hook");
|
|
953
|
+
return { installed: false, action: "noop" };
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
if (!settings.hooks) settings.hooks = {};
|
|
957
|
+
if (!Array.isArray(settings.hooks.PreToolUse)) settings.hooks.PreToolUse = [];
|
|
958
|
+
|
|
959
|
+
const cmd = ARCHITECT_HOOK_COMMAND;
|
|
960
|
+
let action = "noop";
|
|
961
|
+
let found = false;
|
|
962
|
+
for (const entry of settings.hooks.PreToolUse) {
|
|
963
|
+
if (!entry || !Array.isArray(entry.hooks)) continue;
|
|
964
|
+
for (const h of entry.hooks) {
|
|
965
|
+
if (!h || typeof h.command !== "string") continue;
|
|
966
|
+
if (h.command === cmd || h.command.includes(ARCHITECT_HOOK_MARKER)) {
|
|
967
|
+
found = true;
|
|
968
|
+
if (h.command !== cmd) { h.command = cmd; action = "updated"; }
|
|
969
|
+
if (entry.matcher !== "Write|Edit") { entry.matcher = "Write|Edit"; action = action === "noop" ? "updated" : action; }
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
if (!found) {
|
|
974
|
+
settings.hooks.PreToolUse.push({
|
|
975
|
+
matcher: "Write|Edit",
|
|
976
|
+
hooks: [{ type: "command", command: cmd }],
|
|
977
|
+
});
|
|
978
|
+
action = "added";
|
|
979
|
+
}
|
|
980
|
+
if (action === "noop") return { installed: true, action: "noop" };
|
|
981
|
+
if (isSymlink(targetPath)) {
|
|
982
|
+
warn("Skipping settings.json write — target is a symlink");
|
|
983
|
+
return { installed: false, action: "noop" };
|
|
984
|
+
}
|
|
985
|
+
try {
|
|
986
|
+
fs.writeFileSync(targetPath, JSON.stringify(settings, null, 2));
|
|
987
|
+
} catch (e) {
|
|
988
|
+
warn(`Failed to write settings.json: ${e.message}`);
|
|
989
|
+
return { installed: false, action: "noop" };
|
|
990
|
+
}
|
|
991
|
+
return { installed: true, action };
|
|
992
|
+
}
|
|
993
|
+
|
|
931
994
|
// M98 — remove the GSD-T intercept PostToolUse hooks (grep + read) from settings.json.
|
|
932
995
|
// Used during uninstall. Marker-based; leaves all other hooks intact. Idempotent.
|
|
933
996
|
function removeInterceptHooks(settingsPath) {
|
|
@@ -941,17 +1004,28 @@ function removeInterceptHooks(settingsPath) {
|
|
|
941
1004
|
warn("settings.json has invalid JSON — cannot remove intercept hooks");
|
|
942
1005
|
return false;
|
|
943
1006
|
}
|
|
944
|
-
if (!settings.hooks
|
|
1007
|
+
if (!settings.hooks) return false;
|
|
945
1008
|
|
|
946
|
-
const
|
|
947
|
-
const
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1009
|
+
const postMarkers = [GRAPH_INTERCEPT_HOOK_MARKER, READ_INTERCEPT_HOOK_MARKER];
|
|
1010
|
+
const preMarkers = [ARCHITECT_HOOK_MARKER];
|
|
1011
|
+
let removed = 0;
|
|
1012
|
+
|
|
1013
|
+
const stripByMarkers = (arr, markers) => {
|
|
1014
|
+
if (!Array.isArray(arr)) return arr;
|
|
1015
|
+
const before = arr.length;
|
|
1016
|
+
const out = arr.filter((entry) => {
|
|
1017
|
+
if (!entry || !Array.isArray(entry.hooks)) return true;
|
|
1018
|
+
return !entry.hooks.some(
|
|
1019
|
+
(h) => h && typeof h.command === "string" && markers.some((m) => h.command.includes(m))
|
|
1020
|
+
);
|
|
1021
|
+
});
|
|
1022
|
+
removed += before - out.length;
|
|
1023
|
+
return out;
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1026
|
+
settings.hooks.PostToolUse = stripByMarkers(settings.hooks.PostToolUse, postMarkers);
|
|
1027
|
+
settings.hooks.PreToolUse = stripByMarkers(settings.hooks.PreToolUse, preMarkers);
|
|
1028
|
+
if (removed === 0) return false;
|
|
955
1029
|
|
|
956
1030
|
if (isSymlink(targetPath)) {
|
|
957
1031
|
warn("Skipping settings.json write — target is a symlink");
|
|
@@ -1915,6 +1989,13 @@ async function doInstall(opts = {}) {
|
|
|
1915
1989
|
else info("Read-intercept hook already configured");
|
|
1916
1990
|
}
|
|
1917
1991
|
|
|
1992
|
+
const archHook = configureArchitectHook(SETTINGS_JSON);
|
|
1993
|
+
if (archHook.installed) {
|
|
1994
|
+
if (archHook.action === "added") success("Architect-oversight hook added (Six-Stage Pass reminder before writing code — M101)");
|
|
1995
|
+
else if (archHook.action === "updated") success("Architect-oversight hook refreshed");
|
|
1996
|
+
else info("Architect-oversight hook already configured");
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1918
1999
|
heading("Graph Engine (CGC)");
|
|
1919
2000
|
installCgc();
|
|
1920
2001
|
|
|
@@ -4909,6 +4990,7 @@ module.exports = {
|
|
|
4909
4990
|
// M97/M98: intercept hook installers
|
|
4910
4991
|
configureGraphInterceptHook,
|
|
4911
4992
|
configureReadInterceptHook,
|
|
4993
|
+
configureArchitectHook,
|
|
4912
4994
|
removeInterceptHooks,
|
|
4913
4995
|
promptForApiKeyIfMissing,
|
|
4914
4996
|
resolveApiKeyEnvVar,
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# GSD-T: Architect — Run the Architect's Oversight Six-Stage Pass on Existing Work
|
|
2
|
+
|
|
3
|
+
You are the **architect**. You assess a plan, a subsystem, or a tangle of problems the user
|
|
4
|
+
points you at, and you find the **simplest correct solution** — reusing what already exists,
|
|
5
|
+
surfacing the traps, and writing the answer in plain-English pseudocode the user can approve
|
|
6
|
+
BEFORE any code is written.
|
|
7
|
+
|
|
8
|
+
This is a standalone, on-demand run of the **Architect's Oversight Doctrine** (see the project
|
|
9
|
+
`CLAUDE.md` / `~/.claude/CLAUDE.md` § Architect's Oversight, and
|
|
10
|
+
`.gsd-t/contracts/architects-oversight-contract.md`). Use it when a plan already exists (or is
|
|
11
|
+
half-formed) and you want it interrogated for simplicity + reuse before building.
|
|
12
|
+
|
|
13
|
+
Unlike the plan/milestone workflow (which runs the Six-Stage Pass *while generating* a plan),
|
|
14
|
+
this command runs it as a **standalone pass over existing work** — an already-frozen plan, a
|
|
15
|
+
messy subsystem, or a pasted description of problems.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Argument Parsing
|
|
20
|
+
|
|
21
|
+
Parse `$ARGUMENTS`:
|
|
22
|
+
- **First positional** = `$TARGET` — what to assess. Either a plain-English description
|
|
23
|
+
("the feed scanning stalls — image watcher, completeness, comment finder"), a file/dir path,
|
|
24
|
+
or "the current plan" (→ read `.gsd-t/domains/*/tasks.md` + `.gsd-t/progress.md` Current Milestone).
|
|
25
|
+
- **`--build`** — after producing the plan, AUTO-BUILD the simplest solution in the same run
|
|
26
|
+
(do not stop to ask). Default (no flag): produce the plan, then OFFER to build.
|
|
27
|
+
- **`--chat-only`** — report in the session only; do NOT write a pseudocode file to disk.
|
|
28
|
+
Default: write the pseudocode artifact to `.gsd-t/pseudocode/`.
|
|
29
|
+
|
|
30
|
+
If `$TARGET` is empty, ask the user what to assess. Do not guess.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Behavior contract (what the user asked for)
|
|
35
|
+
|
|
36
|
+
1. **Default = plan, then offer to build.** Produce the assessment + plan, then end by asking
|
|
37
|
+
"Build the simplest solution now?" — unless `--build` was passed, in which case auto-build.
|
|
38
|
+
2. **`--build` = auto-build after planning.** Assess → plan → implement the simplest solution,
|
|
39
|
+
without pausing — BUT still print the findings + plan summary to the session first.
|
|
40
|
+
3. **ALWAYS print a session summary** — even in auto-build mode. The user scans the conversation
|
|
41
|
+
for anything that catches their eye while it keeps moving. Never silently proceed.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Step 1: Launch the architect via a Task subagent
|
|
46
|
+
|
|
47
|
+
Give the assessment a fresh context window. Spawn ONE Task subagent (`model: opus`) — this is
|
|
48
|
+
high-stakes design judgment, top tier. Pass it the target and this protocol.
|
|
49
|
+
|
|
50
|
+
**Before spawning**, gather evidence sources so the subagent reasons from facts, not memory:
|
|
51
|
+
- If a code graph exists (`.gsd-t/graph.db`), the subagent uses `gsd-t graph` for reuse/caller
|
|
52
|
+
queries (Stage 3 + Stage 5 duplication check). If absent, it greps/reads and says so LOUDLY
|
|
53
|
+
(reuse-detection is reduced — never a silent "nothing found").
|
|
54
|
+
- Read the relevant code the target names (or the plan files).
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Step 2: The subagent runs the Six-Stage Pass (with EVIDENCE, never conviction)
|
|
59
|
+
|
|
60
|
+
The subagent works through the six stages IN ORDER. Each can kill or reshape the plan. Every
|
|
61
|
+
"am I sure?" is answered by looking (grep / Read / graph), not by asserting.
|
|
62
|
+
|
|
63
|
+
1. **OBJECTIVE** — What is the core objective, in one plain sentence? Why is it the objective?
|
|
64
|
+
(Often the traps shrink once this is pinned down.)
|
|
65
|
+
2. **CONFLICT** — Does solving this conflict with another objective? Must a previously-built
|
|
66
|
+
piece be re-examined/re-planned?
|
|
67
|
+
3. **REUSE** — Have I already accomplished any piece of this? Can I reuse the **process**, or
|
|
68
|
+
the **output** (a value already computed/stored)? *Query the graph, not memory.* This is the
|
|
69
|
+
stage that kills redundant work (e.g. re-deriving a value already stored locally).
|
|
70
|
+
**Also — is this the SAME pattern repeated elsewhere?** If the target is one instance of a
|
|
71
|
+
bug, search for the other instances (one fix for a class beats N fixes for N instances).
|
|
72
|
+
4. **SIMPLICITY** — What is the simplest, most efficient solution? Prove it's simplest.
|
|
73
|
+
5. **REUSE FORECAST & DUPLICATION** — For anything new: HIGH reuse likelihood (core entity /
|
|
74
|
+
recurs / pure transform) → build clean + extractable; LOW → simplest inline. If a similar
|
|
75
|
+
thing exists: same JOB → extract a shared core (do NOT mutate the working original); if
|
|
76
|
+
stability forbids touching it → build new BUT register the duplication (a "reuse-candidate"
|
|
77
|
+
note) so it's visible, never a silent rogue twin.
|
|
78
|
+
6. **RISK** — Does the proposed fix create security or stability/scalability risk? **And prove
|
|
79
|
+
the simpler fix actually works** — if the plan says "handled elsewhere / picked up later,"
|
|
80
|
+
VERIFY that's true; do not assert self-healing you haven't checked. (This is the trap that
|
|
81
|
+
hides inside a simplification.)
|
|
82
|
+
|
|
83
|
+
A stage the subagent cannot answer with evidence is a HALT — surface it as an open question for
|
|
84
|
+
the user, do not paper over it with a guess.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Step 3: The subagent produces the output
|
|
89
|
+
|
|
90
|
+
**A — Plain-English pseudocode** (the artifact), in the house style — title + one-line purpose,
|
|
91
|
+
`CURRENT` (what it does today) and `PROPOSED` (the simplest fix) blocks, `# plain comment` inline,
|
|
92
|
+
a summary table, near-zero preamble. For each CURRENT block, say **why it does what it does now**
|
|
93
|
+
— and flag explicitly if it's a "got complicated over time" accretion (mechanisms stacked by
|
|
94
|
+
successive fixes). Unless `--chat-only`, write it to `.gsd-t/pseudocode/PseudoCode-<Target>.md`.
|
|
95
|
+
|
|
96
|
+
**B — Session summary** (always printed, even under `--build`):
|
|
97
|
+
- **Core objective** (one line)
|
|
98
|
+
- **Is this a "complicated over time" issue?** (yes/no + the accretion history if yes)
|
|
99
|
+
- **What's reusable** (process or a stored output already available)
|
|
100
|
+
- **Same pattern elsewhere?** (other instances of the bug/design found)
|
|
101
|
+
- **Simplest solution** (one paragraph)
|
|
102
|
+
- **Traps surfaced** (each stage's kill/risk finding — especially the Stage-6 "does the fix
|
|
103
|
+
really self-heal?" check)
|
|
104
|
+
- **Open questions** (any HALT stages needing the user)
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Step 4: Build decision
|
|
109
|
+
|
|
110
|
+
- **No `--build` flag (default):** end with the plain-English summary and ask:
|
|
111
|
+
*"Build the simplest solution now?"* — offer it, do not proceed.
|
|
112
|
+
- **`--build` flag:** proceed to implement the simplest solution immediately (still after
|
|
113
|
+
printing the summary). Follow the normal build discipline — smallest change that hits the
|
|
114
|
+
crux, Pre-Commit Gate, run affected tests. Report what was built.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Document Ripple
|
|
119
|
+
|
|
120
|
+
The underlying assessment updates (when it writes / when a build follows):
|
|
121
|
+
- `.gsd-t/pseudocode/PseudoCode-<Target>.md` — the plain-English design (unless `--chat-only`).
|
|
122
|
+
- `.gsd-t/progress.md` Decision Log — one line recording the architect run + verdict.
|
|
123
|
+
- If `--build` produced code: the standard Pre-Commit Gate ripple (contracts, docs, tests) for
|
|
124
|
+
whatever the build touched.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Notes
|
|
129
|
+
|
|
130
|
+
- **This command plans; it does not force a build.** The default keeps the architect a pure
|
|
131
|
+
"think before build" gate. `--build` is the explicit opt-in to act on its own conclusion.
|
|
132
|
+
- **Reuse over rebuild** (the doctrine obeying itself): this command is prose-driven and spawns
|
|
133
|
+
a single analysis subagent — it does NOT add a new workflow file. It reuses the existing
|
|
134
|
+
prose-command + Task-subagent pattern (like `/gsd-t-status`, `/gsd-t-impact`).
|
|
135
|
+
- Standalone command — no successor in the Next-Up map.
|
package/commands/gsd-t-help.md
CHANGED
|
@@ -241,6 +241,13 @@ Use these when user asks for help on a specific command:
|
|
|
241
241
|
- **Creates**: `.gsd-t/impact-report.md`
|
|
242
242
|
- **Use when**: Before making changes, to understand what might break
|
|
243
243
|
|
|
244
|
+
### architect
|
|
245
|
+
- **Summary**: Run the Architect's Oversight Six-Stage Pass (Objective → Conflict → Reuse → Simplicity → Reuse-forecast → Risk) on existing work — an already-frozen plan, a messy subsystem, or a pasted tangle of problems. Finds the simplest correct solution, what's already reusable (process or a stored value), and the traps each stage surfaces — written as plain-English pseudocode you can approve before any code.
|
|
246
|
+
- **Auto-invoked**: No (standalone, on-demand)
|
|
247
|
+
- **Args**: `/gsd-t-architect "<what to assess>"` — plus `--build` (auto-build the simplest fix after planning) and `--chat-only` (report in session, don't write a pseudocode file).
|
|
248
|
+
- **Creates**: `.gsd-t/pseudocode/PseudoCode-<Target>.md` (unless `--chat-only`)
|
|
249
|
+
- **Use when**: A plan already exists (or is half-formed) and you want it interrogated for simplicity + reuse before building; or a subsystem "got complicated over time" and you want the simplest version. Default is plan-only, then it offers to build.
|
|
250
|
+
|
|
244
251
|
### execute
|
|
245
252
|
- **Summary**: Run tasks from plan, solo or with agent teams
|
|
246
253
|
- **Auto-invoked**: Yes (in wave, after impact)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tekyzinc/gsd-t",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.11",
|
|
4
4
|
"description": "GSD-T: Contract-Driven Development for Claude Code — 54 slash commands with headless-by-default workflow spawning, unattended supervisor relay with event stream, graph-powered code analysis, real-time agent dashboard, task telemetry, doc-ripple enforcement, backlog management, impact analysis, test sync, milestone archival, and PRD generation",
|
|
5
5
|
"author": "Tekyz, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* GSD-T PreToolUse hook (Write|Edit) — Architect's Oversight trigger (M101).
|
|
4
|
+
*
|
|
5
|
+
* The Architect's Oversight Doctrine lives in ~/.claude/CLAUDE.md, but a doctrine
|
|
6
|
+
* carried in context can be MISSED under load. This hook fires the TRIGGER at the
|
|
7
|
+
* exact moment it matters — right before code is written/edited — and injects a
|
|
8
|
+
* ONE-LINE pointer back to the doctrine. It carries NO nuance (that stays in
|
|
9
|
+
* CLAUDE.md); it only guarantees the Six-Stage Pass is CONSIDERED before a build.
|
|
10
|
+
*
|
|
11
|
+
* Design (mirrors the doctrine's §Enforcement three-layer split):
|
|
12
|
+
* - CLAUDE.md = the definition (what the doctrine IS)
|
|
13
|
+
* - THIS hook = the trigger (don't forget it right now, no context bloat)
|
|
14
|
+
* - workflow = the execution (actually run the stages, with evidence)
|
|
15
|
+
*
|
|
16
|
+
* Receives JSON on stdin: { tool_name, tool_input: { file_path, ... }, cwd, ... }
|
|
17
|
+
* Emits (stdout, PreToolUse additionalContext): a single reminder line, or nothing.
|
|
18
|
+
*
|
|
19
|
+
* NON-NEGOTIABLE: fail-open. Never block the tool, never throw, never exit non-zero.
|
|
20
|
+
* A malformed payload, missing field, or any error → silent pass-through (exit 0,
|
|
21
|
+
* no output). This hook can only ADD a reminder; it can never stop a write.
|
|
22
|
+
*
|
|
23
|
+
* Scope gates (emit ONLY when all hold), to avoid noise:
|
|
24
|
+
* 1. GSD-T project — cwd contains .gsd-t/ (matches the auto-route/profile gate).
|
|
25
|
+
* 2. The target is CODE, not prose — skip .md / .txt / pseudocode / docs, since
|
|
26
|
+
* the doctrine's own artifacts (CLAUDE.md, pseudocode, contracts) are writes
|
|
27
|
+
* too, and reminding while writing the reminder is noise. Code = the moment
|
|
28
|
+
* the Binvoice waste would have been caught.
|
|
29
|
+
*
|
|
30
|
+
* Zero-dep by design: runs from ~/.claude/scripts where the package may be absent.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
const fs = require("fs");
|
|
34
|
+
const path = require("path");
|
|
35
|
+
|
|
36
|
+
// One line. A pointer, not the doctrine. Keeps context cost ~nil.
|
|
37
|
+
const REMINDER =
|
|
38
|
+
"[GSD-T ARCHITECT] About to write/edit code — run the Architect's Oversight " +
|
|
39
|
+
"Six-Stage Pass FIRST (Objective → Conflict → Reuse[query the graph] → " +
|
|
40
|
+
"Simplicity → Reuse-forecast → Risk), each answered with evidence not conviction. " +
|
|
41
|
+
"Is this the simplest design, and does something reusable already exist? " +
|
|
42
|
+
"See ~/.claude/CLAUDE.md § Architect's Oversight Doctrine.";
|
|
43
|
+
|
|
44
|
+
// File extensions that are PROSE/config, not code — skip the reminder for these.
|
|
45
|
+
// (The doctrine's own artifacts are markdown; reminding while authoring them is noise.)
|
|
46
|
+
const PROSE_EXT = new Set([
|
|
47
|
+
".md", ".markdown", ".txt", ".rst", ".adoc",
|
|
48
|
+
".json", ".yaml", ".yml", ".toml", ".lock",
|
|
49
|
+
".csv", ".tsv", ".svg", ".png", ".jpg", ".jpeg", ".gif", ".pdf",
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Decide whether to emit the reminder for a given cwd + target file.
|
|
54
|
+
* Pure + total: never throws, returns a boolean.
|
|
55
|
+
* @param {string} cwd
|
|
56
|
+
* @param {string} filePath — the Write/Edit target
|
|
57
|
+
* @returns {boolean}
|
|
58
|
+
*/
|
|
59
|
+
function shouldRemind(cwd, filePath) {
|
|
60
|
+
try {
|
|
61
|
+
if (!cwd || typeof cwd !== "string") return false;
|
|
62
|
+
// Gate 1 — GSD-T project only.
|
|
63
|
+
if (!fs.existsSync(path.join(cwd, ".gsd-t"))) return false;
|
|
64
|
+
// No target path → can't classify → stay quiet (fail-open toward silence).
|
|
65
|
+
if (!filePath || typeof filePath !== "string") return false;
|
|
66
|
+
|
|
67
|
+
const lower = filePath.toLowerCase();
|
|
68
|
+
const ext = path.extname(lower);
|
|
69
|
+
|
|
70
|
+
// Gate 2 — skip prose/config/asset writes (incl. the doctrine's own artifacts).
|
|
71
|
+
if (PROSE_EXT.has(ext)) return false;
|
|
72
|
+
// Skip anything under a docs/ or pseudocode/ tree even if code-extensioned.
|
|
73
|
+
if (/[\\/](docs|pseudocode)[\\/]/.test(lower)) return false;
|
|
74
|
+
|
|
75
|
+
return true;
|
|
76
|
+
} catch (_) {
|
|
77
|
+
return false; // fail-open: any error → no reminder, never block
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (require.main === module) {
|
|
82
|
+
let input = "";
|
|
83
|
+
let done = false;
|
|
84
|
+
process.stdin.setEncoding("utf8");
|
|
85
|
+
process.stdin.on("data", (c) => { input += c; });
|
|
86
|
+
|
|
87
|
+
const finish = () => {
|
|
88
|
+
if (done) return; // run once — whichever of end/error/watchdog fires first
|
|
89
|
+
done = true;
|
|
90
|
+
try {
|
|
91
|
+
let data = null;
|
|
92
|
+
try { data = JSON.parse(input); } catch (_) { process.exit(0); }
|
|
93
|
+
if (!data || typeof data !== "object") process.exit(0);
|
|
94
|
+
|
|
95
|
+
const cwd = (typeof data.cwd === "string" && data.cwd) ? data.cwd : process.cwd();
|
|
96
|
+
const ti = data.tool_input && typeof data.tool_input === "object" ? data.tool_input : {};
|
|
97
|
+
const filePath = typeof ti.file_path === "string" ? ti.file_path : "";
|
|
98
|
+
|
|
99
|
+
if (shouldRemind(cwd, filePath)) {
|
|
100
|
+
process.stdout.write(REMINDER + "\n");
|
|
101
|
+
}
|
|
102
|
+
} catch (_) {
|
|
103
|
+
// Belt-and-suspenders: never block a write.
|
|
104
|
+
}
|
|
105
|
+
process.exit(0);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
process.stdin.on("end", finish);
|
|
109
|
+
process.stdin.on("error", finish); // stdin read error → fail-open, never hang
|
|
110
|
+
// Watchdog: if stdin never delivers EOF (spawn-under-load edge, closed pipe),
|
|
111
|
+
// proceed anyway with whatever we have. A hook must NEVER hang and block a write.
|
|
112
|
+
const wd = setTimeout(finish, 1500);
|
|
113
|
+
if (wd.unref) wd.unref(); // don't keep the event loop alive solely for the watchdog
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = { shouldRemind, REMINDER };
|