@nusoft/nuos-build-catalogue 0.17.1 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +49 -2
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.js +69 -0
- package/dist/commands/memory.d.ts +42 -0
- package/dist/commands/memory.js +116 -0
- package/dist/setup/ollama-detect.d.ts +35 -0
- package/dist/setup/ollama-detect.js +83 -0
- package/dist/setup/ollama-install.d.ts +52 -0
- package/dist/setup/ollama-install.js +140 -0
- package/dist/setup/ollama-pull.d.ts +40 -0
- package/dist/setup/ollama-pull.js +104 -0
- package/dist/setup/progress-bar.d.ts +51 -0
- package/dist/setup/progress-bar.js +85 -0
- package/dist/setup/run-llm-setup.d.ts +71 -0
- package/dist/setup/run-llm-setup.js +242 -0
- package/dist/setup/types.d.ts +99 -0
- package/dist/setup/types.js +20 -0
- package/package.json +2 -2
- package/scripts/hooks/post-commit +96 -0
- package/scripts/hooks/pre-commit +162 -0
- package/scripts/install-hooks.sh +44 -0
- package/templates/agents/architect.md +16 -0
- package/templates/agents/coder.md +15 -0
- package/templates/agents/debugger.md +15 -0
- package/templates/agents/researcher.md +14 -0
- package/templates/agents/reviewer.md +16 -0
- package/templates/agents/tester.md +15 -0
- package/templates/protocols/build-wu.md +30 -1
- package/templates/starter-kit/methodfile.json +2 -2
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the LLM-setup phase of `init` (WU 135).
|
|
3
|
+
*
|
|
4
|
+
* The setup phase runs after the scaffold and is responsible for
|
|
5
|
+
* detecting Ollama, offering to install it where reliable, and pulling
|
|
6
|
+
* the default embedding model (`qwen3-embedding:0.6b`, ~600MB) with a
|
|
7
|
+
* live progress bar.
|
|
8
|
+
*
|
|
9
|
+
* @module setup/types
|
|
10
|
+
*/
|
|
11
|
+
/** Node `process.platform` narrowed to the cases we handle. */
|
|
12
|
+
export type Platform = 'darwin' | 'linux' | 'win32' | 'other';
|
|
13
|
+
/** Result of probing for the Ollama CLI binary on PATH. */
|
|
14
|
+
export interface OllamaCliProbe {
|
|
15
|
+
found: boolean;
|
|
16
|
+
/** Resolved path when `found`. */
|
|
17
|
+
path?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Result of probing the Ollama HTTP API. */
|
|
20
|
+
export interface OllamaApiProbe {
|
|
21
|
+
reachable: boolean;
|
|
22
|
+
/** Host the probe used (e.g. "http://localhost:11434"). */
|
|
23
|
+
host: string;
|
|
24
|
+
/** Error message when `!reachable`. */
|
|
25
|
+
error?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Result of querying the local model list. */
|
|
28
|
+
export interface ModelProbe {
|
|
29
|
+
present: boolean;
|
|
30
|
+
/** Model identifier we probed for (e.g. "qwen3-embedding:0.6b"). */
|
|
31
|
+
model: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* One event from the Ollama `/api/pull` NDJSON stream. The status
|
|
35
|
+
* strings come straight from Ollama; we treat them as opaque except for
|
|
36
|
+
* the distinguished cases used to render the progress bar.
|
|
37
|
+
*
|
|
38
|
+
* Known status values observed in practice:
|
|
39
|
+
* - "pulling manifest"
|
|
40
|
+
* - "downloading" (carries digest + total + completed)
|
|
41
|
+
* - "verifying sha256 digest"
|
|
42
|
+
* - "writing manifest"
|
|
43
|
+
* - "removing any unused layers"
|
|
44
|
+
* - "success"
|
|
45
|
+
*
|
|
46
|
+
* An `error` field is set instead of `status` on failure.
|
|
47
|
+
*/
|
|
48
|
+
export interface PullEvent {
|
|
49
|
+
status?: string;
|
|
50
|
+
digest?: string;
|
|
51
|
+
total?: number;
|
|
52
|
+
completed?: number;
|
|
53
|
+
error?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Outcome of the LLM-setup phase. Returned to the caller (init or the
|
|
57
|
+
* standalone `setup-llm` command) so the surrounding UX can render an
|
|
58
|
+
* appropriate summary line.
|
|
59
|
+
*/
|
|
60
|
+
export type LlmSetupResult = {
|
|
61
|
+
kind: 'already_ready';
|
|
62
|
+
} | {
|
|
63
|
+
kind: 'installed_and_pulled';
|
|
64
|
+
} | {
|
|
65
|
+
kind: 'pulled_only';
|
|
66
|
+
} | {
|
|
67
|
+
kind: 'install_offered_declined';
|
|
68
|
+
} | {
|
|
69
|
+
kind: 'install_failed';
|
|
70
|
+
error: string;
|
|
71
|
+
} | {
|
|
72
|
+
kind: 'ollama_installed_but_not_running';
|
|
73
|
+
} | {
|
|
74
|
+
kind: 'pull_failed';
|
|
75
|
+
error: string;
|
|
76
|
+
} | {
|
|
77
|
+
kind: 'skipped';
|
|
78
|
+
reason: string;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Per-platform install offer the CLI can present to the user. The
|
|
82
|
+
* `canAutoInstall` flag is the gate for offering to run the install
|
|
83
|
+
* command directly — false on Windows (no reliable CLI install path).
|
|
84
|
+
*/
|
|
85
|
+
export interface InstallOffer {
|
|
86
|
+
platform: Platform;
|
|
87
|
+
/** The shell command the offer would run (empty string when !canAutoInstall). */
|
|
88
|
+
primaryCommand: string;
|
|
89
|
+
/** Plain-English description of the primary path. */
|
|
90
|
+
primaryDescription: string;
|
|
91
|
+
/** Download page URL — always present as the safe fallback. */
|
|
92
|
+
fallbackUrl: string;
|
|
93
|
+
/** Whether we have a reliable CLI install path to offer running. */
|
|
94
|
+
canAutoInstall: boolean;
|
|
95
|
+
/** Whether the primary command needs sudo. Used to phrase the prompt. */
|
|
96
|
+
requiresElevation: boolean;
|
|
97
|
+
}
|
|
98
|
+
/** Narrow Node's process.platform string to our Platform union. */
|
|
99
|
+
export declare function narrowPlatform(p: NodeJS.Platform): Platform;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the LLM-setup phase of `init` (WU 135).
|
|
3
|
+
*
|
|
4
|
+
* The setup phase runs after the scaffold and is responsible for
|
|
5
|
+
* detecting Ollama, offering to install it where reliable, and pulling
|
|
6
|
+
* the default embedding model (`qwen3-embedding:0.6b`, ~600MB) with a
|
|
7
|
+
* live progress bar.
|
|
8
|
+
*
|
|
9
|
+
* @module setup/types
|
|
10
|
+
*/
|
|
11
|
+
/** Narrow Node's process.platform string to our Platform union. */
|
|
12
|
+
export function narrowPlatform(p) {
|
|
13
|
+
if (p === 'darwin')
|
|
14
|
+
return 'darwin';
|
|
15
|
+
if (p === 'linux')
|
|
16
|
+
return 'linux';
|
|
17
|
+
if (p === 'win32')
|
|
18
|
+
return 'win32';
|
|
19
|
+
return 'other';
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nusoft/nuos-build-catalogue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.1",
|
|
4
4
|
"description": "NuOS build-catalogue tooling: semantic search (WU 110) + migration runner that lifts markdown artefacts into JSON-backed workflow records (WU 111, Phase G).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"build": "rm -rf dist && tsc && chmod +x dist/cli.js",
|
|
20
20
|
"prepublishOnly": "npm run build",
|
|
21
21
|
"verify-storage": "tsx scripts/verify-persistence.ts",
|
|
22
|
-
"test": "tsx --test tests/chunk.test.ts tests/metadata.test.ts tests/crawl.test.ts tests/migrate.test.ts tests/commands-read.test.ts tests/regenerate.test.ts tests/commands-write.test.ts tests/ac-parse.test.ts tests/create.test.ts tests/init.test.ts tests/wu-111-soak-findings.test.ts tests/plan.test.ts tests/swarm.test.ts",
|
|
22
|
+
"test": "tsx --test tests/chunk.test.ts tests/metadata.test.ts tests/crawl.test.ts tests/migrate.test.ts tests/commands-read.test.ts tests/regenerate.test.ts tests/commands-write.test.ts tests/ac-parse.test.ts tests/create.test.ts tests/init.test.ts tests/wu-111-soak-findings.test.ts tests/plan.test.ts tests/swarm.test.ts tests/setup-progress-bar.test.ts tests/setup-ollama-pull.test.ts tests/setup-run-llm-setup.test.ts",
|
|
23
23
|
"typecheck": "tsc --noEmit",
|
|
24
24
|
"index": "tsx src/cli.ts index",
|
|
25
25
|
"search": "tsx src/cli.ts search"
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# NuOS catalogue post-commit hook — auto-refresh the semantic-search index
|
|
4
|
+
# after every commit that touched docs/build/**.
|
|
5
|
+
#
|
|
6
|
+
# Why this hook:
|
|
7
|
+
# `nuos-catalogue search` only finds what's in the NuVector index. The
|
|
8
|
+
# index is hash-based and incremental, but it doesn't update itself —
|
|
9
|
+
# you have to run `nuos-catalogue index` after meaningful changes for
|
|
10
|
+
# new content to be searchable. Running it manually is too easy to
|
|
11
|
+
# forget; the discipline argument that gave us the pre-commit hook
|
|
12
|
+
# (index-drift, accepted-decision immutability) applies equally here.
|
|
13
|
+
#
|
|
14
|
+
# Behaviour:
|
|
15
|
+
# - Skip if the just-landed commit did NOT touch docs/build/** (most
|
|
16
|
+
# code commits don't need a reindex)
|
|
17
|
+
# - Skip if `nuos-catalogue` isn't resolvable (the CLI may not be
|
|
18
|
+
# installed yet on a fresh clone; this hook should never block)
|
|
19
|
+
# - Otherwise: run the index in the BACKGROUND so the user's terminal
|
|
20
|
+
# isn't held while we embed. All output goes to .nuos-enforcement.log.
|
|
21
|
+
#
|
|
22
|
+
# The hook respects two env vars:
|
|
23
|
+
# NUOS_CATALOGUE_INDEX_DIR default: <repo>/.nuos-catalogue
|
|
24
|
+
# NUOS_CATALOGUE_OLLAMA_MODEL passed through to the CLI
|
|
25
|
+
#
|
|
26
|
+
# This hook never blocks. If indexing fails (Ollama not running, model
|
|
27
|
+
# not pulled, dimension mismatch with existing index), the error goes
|
|
28
|
+
# to the log and the user can investigate. The commit itself already
|
|
29
|
+
# landed by the time post-commit fires.
|
|
30
|
+
|
|
31
|
+
set -uo pipefail
|
|
32
|
+
|
|
33
|
+
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
|
34
|
+
LOG="$REPO_ROOT/.nuos-enforcement.log"
|
|
35
|
+
|
|
36
|
+
dim() { printf '\033[2m%s\033[0m\n' "$*"; }
|
|
37
|
+
yellow() { printf '\033[33m%s\033[0m\n' "$*"; }
|
|
38
|
+
|
|
39
|
+
# ---- Skip-paths --------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
# Skip if this project doesn't have a catalogue at all.
|
|
42
|
+
if [[ ! -d "$REPO_ROOT/docs/build" ]]; then
|
|
43
|
+
exit 0
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Skip if the just-landed commit didn't touch docs/build/**.
|
|
47
|
+
if ! git diff-tree --no-commit-id --name-only -r HEAD 2>/dev/null | grep -q '^docs/build/'; then
|
|
48
|
+
exit 0
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# Resolve the CLI: prefer globally-installed `nuos-catalogue`; fall back
|
|
52
|
+
# to `npx --yes` which fetches from npm on demand.
|
|
53
|
+
INDEX_CMD=""
|
|
54
|
+
if command -v nuos-catalogue >/dev/null 2>&1; then
|
|
55
|
+
INDEX_CMD="nuos-catalogue"
|
|
56
|
+
elif command -v npx >/dev/null 2>&1; then
|
|
57
|
+
INDEX_CMD="npx --yes @nusoft/nuos-build-catalogue"
|
|
58
|
+
else
|
|
59
|
+
yellow "[nuos:post-commit] neither nuos-catalogue nor npx found; skipping index refresh"
|
|
60
|
+
printf '%s | post-commit-skip | no CLI available\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" >> "$LOG"
|
|
61
|
+
exit 0
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# ---- Background index refresh ------------------------------------------
|
|
65
|
+
|
|
66
|
+
# Default the index dir to project-local if the user hasn't set one.
|
|
67
|
+
: "${NUOS_CATALOGUE_INDEX_DIR:=$REPO_ROOT/.nuos-catalogue}"
|
|
68
|
+
export NUOS_CATALOGUE_INDEX_DIR
|
|
69
|
+
|
|
70
|
+
# Detach from the terminal so the post-commit returns immediately. All
|
|
71
|
+
# output (stdout + stderr) goes to the enforcement log so the user can
|
|
72
|
+
# tail it if they want to see progress.
|
|
73
|
+
(
|
|
74
|
+
start=$(date +%s)
|
|
75
|
+
printf '%s | post-commit-index | start (model=%s, dir=%s)\n' \
|
|
76
|
+
"$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
|
|
77
|
+
"${NUOS_CATALOGUE_OLLAMA_MODEL:-default}" \
|
|
78
|
+
"$NUOS_CATALOGUE_INDEX_DIR" \
|
|
79
|
+
>> "$LOG"
|
|
80
|
+
|
|
81
|
+
if cd "$REPO_ROOT" && $INDEX_CMD index >> "$LOG" 2>&1; then
|
|
82
|
+
end=$(date +%s)
|
|
83
|
+
printf '%s | post-commit-index | done in %ss\n' \
|
|
84
|
+
"$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
|
|
85
|
+
$((end - start)) \
|
|
86
|
+
>> "$LOG"
|
|
87
|
+
else
|
|
88
|
+
printf '%s | post-commit-index | FAILED (see lines above in %s)\n' \
|
|
89
|
+
"$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
|
|
90
|
+
"$(basename "$LOG")" \
|
|
91
|
+
>> "$LOG"
|
|
92
|
+
fi
|
|
93
|
+
) </dev/null >/dev/null 2>&1 &
|
|
94
|
+
disown 2>/dev/null || true
|
|
95
|
+
|
|
96
|
+
dim "[nuos:post-commit] index refresh started in background — see .nuos-enforcement.log"
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# NuOS catalogue pre-commit hook (WU 111 enforcement phase).
|
|
4
|
+
#
|
|
5
|
+
# Catches drift before commit. After WU 111's Phase J ship, the
|
|
6
|
+
# accepted-decision rule has flipped from warning → block (per the
|
|
7
|
+
# pack's narrower-than-originally-planned enforcement scope, recorded
|
|
8
|
+
# in WU 111's "Forward-compatibility commitments" section). Other
|
|
9
|
+
# rules described in WU 128's original aggressive list are NOT shipping
|
|
10
|
+
# — distinguishing tool-written from human-written content was deemed
|
|
11
|
+
# overengineering for a planning-artefact catalogue.
|
|
12
|
+
#
|
|
13
|
+
# Active rules:
|
|
14
|
+
# 1. index-drift detection — every WU/decision/open-question/risk file
|
|
15
|
+
# must have a matching row in its _index.md (and vice versa)
|
|
16
|
+
# 2. active-decision modification block — modifying a committed
|
|
17
|
+
# `accepted` decision file is BLOCKED (not just warned). The
|
|
18
|
+
# discipline is to write a superseding D-NNN+1 and link forward.
|
|
19
|
+
# To deliberately fix a typo or link in an accepted decision,
|
|
20
|
+
# use `git commit --no-verify` (CLAUDE.md prohibits this for
|
|
21
|
+
# substantive changes; reserve it for typo-only fixes).
|
|
22
|
+
#
|
|
23
|
+
# Sentinel-protected sections (e.g. STATE.md's `nuos:sentinel`) remain
|
|
24
|
+
# protected via the existing `.claude/hooks/check-catalogue-write.sh`
|
|
25
|
+
# Claude Code hook. That rule continues unchanged at WU 111 ship.
|
|
26
|
+
#
|
|
27
|
+
# Bypass: this hook respects --no-verify like any other. The CLAUDE.md
|
|
28
|
+
# policy explicitly prohibits --no-verify use for substantive changes;
|
|
29
|
+
# the technical block fires at the CI server-side check (a future WU).
|
|
30
|
+
|
|
31
|
+
set -uo pipefail
|
|
32
|
+
|
|
33
|
+
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
|
34
|
+
ENFORCEMENT_LOG="$REPO_ROOT/.nuos-enforcement.log"
|
|
35
|
+
EXIT_CODE=0
|
|
36
|
+
|
|
37
|
+
red() { printf '\033[31m%s\033[0m\n' "$*"; }
|
|
38
|
+
yellow() { printf '\033[33m%s\033[0m\n' "$*"; }
|
|
39
|
+
green() { printf '\033[32m%s\033[0m\n' "$*"; }
|
|
40
|
+
dim() { printf '\033[2m%s\033[0m\n' "$*"; }
|
|
41
|
+
|
|
42
|
+
log_event() {
|
|
43
|
+
printf '%s | %s | %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$1" "$2" >> "$ENFORCEMENT_LOG"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# ---------- Generic index-drift checker ---------------------------------
|
|
47
|
+
#
|
|
48
|
+
# Args:
|
|
49
|
+
# $1 — kind label (for messages)
|
|
50
|
+
# $2 — directory (relative to repo root)
|
|
51
|
+
# $3 — _index.md path (relative to repo root)
|
|
52
|
+
# $4 — filename regex (matches IDs the directory contains)
|
|
53
|
+
# $5 — index-row ID regex (a Perl-compatible regex that anchors on the
|
|
54
|
+
# leftmost column of an index table row)
|
|
55
|
+
#
|
|
56
|
+
# The two regexes must extract the SAME set of IDs (e.g. "001", "030g",
|
|
57
|
+
# "D042") so set comparison works.
|
|
58
|
+
|
|
59
|
+
check_index_drift() {
|
|
60
|
+
local kind="$1" dir="$2" index="$3" file_regex="$4" row_regex="$5"
|
|
61
|
+
|
|
62
|
+
if [[ ! -d "$REPO_ROOT/$dir" ]]; then return 0; fi
|
|
63
|
+
if [[ ! -f "$REPO_ROOT/$index" ]]; then return 0; fi
|
|
64
|
+
|
|
65
|
+
# IDs extracted from filenames in the directory (top-level + one subdir
|
|
66
|
+
# like done/, resolved/, superseded/)
|
|
67
|
+
local ids_in_tree
|
|
68
|
+
ids_in_tree=$(cd "$REPO_ROOT/$dir" && {
|
|
69
|
+
find . -maxdepth 2 -type f -name "*.md" \
|
|
70
|
+
-not -name "_index.md" \
|
|
71
|
+
-not -name "*-template.md" 2>/dev/null \
|
|
72
|
+
| sed -nE "$file_regex" \
|
|
73
|
+
| sort -u
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
# IDs extracted from leftmost column of table rows in the index
|
|
77
|
+
local ids_in_index
|
|
78
|
+
ids_in_index=$(sed -nE "$row_regex" "$REPO_ROOT/$index" | sort -u)
|
|
79
|
+
|
|
80
|
+
local missing_from_index
|
|
81
|
+
missing_from_index=$(comm -23 <(printf '%s\n' "$ids_in_tree") <(printf '%s\n' "$ids_in_index"))
|
|
82
|
+
|
|
83
|
+
if [[ -n "$missing_from_index" ]]; then
|
|
84
|
+
red "✖ index-drift ($kind): on disk but missing from $index:"
|
|
85
|
+
while IFS= read -r id; do echo " — $id"; done <<< "$missing_from_index"
|
|
86
|
+
log_event "index-drift" "$kind missing from index: $(echo "$missing_from_index" | tr '\n' ',')"
|
|
87
|
+
EXIT_CODE=1
|
|
88
|
+
fi
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
dim "[nuos:pre-commit] index-drift check"
|
|
92
|
+
|
|
93
|
+
# Note: BSD sed (macOS default) is fussy about `|` as both delimiter and
|
|
94
|
+
# regex content. Using `#` as the s/// delimiter sidesteps the collision.
|
|
95
|
+
|
|
96
|
+
# Work units: filenames are NNN-slug.md or NNNa-slug.md (with optional letter).
|
|
97
|
+
# Index rows are `| NNN |` or `| NNNa |` in the leftmost column.
|
|
98
|
+
check_index_drift \
|
|
99
|
+
"work-units" \
|
|
100
|
+
"docs/build/work-units" \
|
|
101
|
+
"docs/build/work-units/_index.md" \
|
|
102
|
+
's#^\./(done/)?([0-9]{3}[a-z]?)-[^/]*\.md$#\2#p' \
|
|
103
|
+
's#^\| ([0-9]{3}[a-z]?) \|.*$#\1#p'
|
|
104
|
+
|
|
105
|
+
# Decisions: filenames are DNNN-slug.md.
|
|
106
|
+
# Index rows: `| DNNN |` or `| [DNNN](...) |`.
|
|
107
|
+
check_index_drift \
|
|
108
|
+
"decisions" \
|
|
109
|
+
"docs/build/decisions" \
|
|
110
|
+
"docs/build/decisions/_index.md" \
|
|
111
|
+
's#^\./(done/|superseded/)?(D[0-9]{3})-[^/]*\.md$#\2#p' \
|
|
112
|
+
's#^\| \[?(D[0-9]{3}).*$#\1#p'
|
|
113
|
+
|
|
114
|
+
# Open questions: filenames are QNNN-slug.md.
|
|
115
|
+
check_index_drift \
|
|
116
|
+
"open-questions" \
|
|
117
|
+
"docs/build/open-questions" \
|
|
118
|
+
"docs/build/open-questions/_index.md" \
|
|
119
|
+
's#^\./(resolved/)?(Q[0-9]{3})-[^/]*\.md$#\2#p' \
|
|
120
|
+
's#^\| \[?(Q[0-9]{3}).*$#\1#p'
|
|
121
|
+
|
|
122
|
+
# Risks: per current convention, individual risk files are inline in
|
|
123
|
+
# risks/_index.md (no per-risk .md files yet). Skip the check entirely
|
|
124
|
+
# until that pattern changes.
|
|
125
|
+
if compgen -G "$REPO_ROOT/docs/build/risks/R[0-9][0-9][0-9]-*.md" > /dev/null; then
|
|
126
|
+
check_index_drift \
|
|
127
|
+
"risks" \
|
|
128
|
+
"docs/build/risks" \
|
|
129
|
+
"docs/build/risks/_index.md" \
|
|
130
|
+
's#^\./(R[0-9]{3})-[^/]*\.md$#\1#p' \
|
|
131
|
+
's#^\| \[?(R[0-9]{3}).*$#\1#p'
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
# ---------- Rule 2: active-decision modification block (WU 111 ship) ---
|
|
135
|
+
|
|
136
|
+
dim "[nuos:pre-commit] active-decision modification check"
|
|
137
|
+
modified_decisions=$(git diff --cached --name-only --diff-filter=M \
|
|
138
|
+
| grep -E '^docs/build/decisions/D[0-9]+.*\.md$' \
|
|
139
|
+
| grep -v '/superseded/' \
|
|
140
|
+
|| true)
|
|
141
|
+
|
|
142
|
+
if [[ -n "$modified_decisions" ]]; then
|
|
143
|
+
red "✖ active-decision modification — BLOCKED (WU 111 enforcement):"
|
|
144
|
+
while IFS= read -r f; do echo " — $f"; done <<< "$modified_decisions"
|
|
145
|
+
red " Decisions are immutable once accepted. The discipline is to write a"
|
|
146
|
+
red " superseding D-NNN+1 and link forward. Use:"
|
|
147
|
+
red " nuos-catalogue decision supersede <target> --by=<new-D> --reason=\"...\""
|
|
148
|
+
red ""
|
|
149
|
+
red " If this edit is a non-substantive typo fix or link cleanup that does"
|
|
150
|
+
red " not change the decision's meaning, you may bypass this block with"
|
|
151
|
+
red " --no-verify. CLAUDE.md prohibits --no-verify for substantive changes."
|
|
152
|
+
log_event "active-decision-block" "$(echo "$modified_decisions" | tr '\n' ',')"
|
|
153
|
+
EXIT_CODE=1
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
# ---------- Result ------------------------------------------------------
|
|
157
|
+
|
|
158
|
+
if [[ $EXIT_CODE -eq 0 ]]; then
|
|
159
|
+
green "[nuos:pre-commit] all rules pass (WU 111 enforcement)"
|
|
160
|
+
log_event "pre-commit-pass" "$(git diff --cached --name-only | wc -l | tr -d ' ') files"
|
|
161
|
+
fi
|
|
162
|
+
exit $EXIT_CODE
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Install the catalogue's git hooks into .git/hooks/.
|
|
4
|
+
#
|
|
5
|
+
# Why this script (not husky):
|
|
6
|
+
# The nuos repo is a markdown catalogue, not an npm package. Adding a
|
|
7
|
+
# package.json + node_modules just to install hooks would be infrastructure
|
|
8
|
+
# tax for what is otherwise a doc repo. A small bash installer copies the
|
|
9
|
+
# hooks from the version-controlled scripts/hooks/ into .git/hooks/.
|
|
10
|
+
#
|
|
11
|
+
# Usage:
|
|
12
|
+
# bash scripts/install-hooks.sh
|
|
13
|
+
#
|
|
14
|
+
# Re-run any time scripts/hooks/ changes; the installer is idempotent.
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
|
19
|
+
SOURCE="$REPO_ROOT/scripts/hooks"
|
|
20
|
+
TARGET="$REPO_ROOT/.git/hooks"
|
|
21
|
+
|
|
22
|
+
if [[ ! -d "$SOURCE" ]]; then
|
|
23
|
+
echo "✖ scripts/hooks/ not found; nothing to install" >&2
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
mkdir -p "$TARGET"
|
|
28
|
+
|
|
29
|
+
installed=0
|
|
30
|
+
for hook in "$SOURCE"/*; do
|
|
31
|
+
name="$(basename "$hook")"
|
|
32
|
+
cp "$hook" "$TARGET/$name"
|
|
33
|
+
chmod +x "$TARGET/$name"
|
|
34
|
+
installed=$((installed + 1))
|
|
35
|
+
done
|
|
36
|
+
|
|
37
|
+
echo "✓ installed $installed hook(s) into .git/hooks/"
|
|
38
|
+
echo
|
|
39
|
+
echo "Active rules (WU 111 enforcement):"
|
|
40
|
+
echo " • index-drift detection (work-units, decisions, open-questions, risks)"
|
|
41
|
+
echo " • active-decision modification BLOCK (was warning under WU 128 light-touch)"
|
|
42
|
+
echo
|
|
43
|
+
echo "To verify the install: \`git hook list\` (git ≥2.36) or \`ls .git/hooks/\`"
|
|
44
|
+
echo "To uninstall: \`rm .git/hooks/pre-commit\`"
|
|
@@ -9,6 +9,22 @@ You are the **architect** for a project using the NuOS Build Method catalogue. Y
|
|
|
9
9
|
|
|
10
10
|
**You design. You do not implement.** You produce decisions, contract files, architecture files, and the structural outline for work units — never source code.
|
|
11
11
|
|
|
12
|
+
## Cross-agent memory
|
|
13
|
+
|
|
14
|
+
Before you start: search for prior relevant design decisions across all past swarm runs.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
nuos-catalogue memory search --query="<the design problem you're about to solve>" --agent=architect
|
|
18
|
+
nuos-catalogue memory search --query="<the module or contract name>" --limit=5
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
After you finish: store your key findings so future architects (and the debugger) can find them.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
nuos-catalogue memory store --value="<what you decided and why>" --wu=<handle> --agent=architect --key="<short label>"
|
|
25
|
+
# Store one entry per load-bearing decision. Include the alternatives you rejected.
|
|
26
|
+
```
|
|
27
|
+
|
|
12
28
|
## What you read before you decide
|
|
13
29
|
|
|
14
30
|
Always start by reading:
|
|
@@ -9,6 +9,21 @@ You are the **coder** for a project using the NuOS Build Method catalogue. Your
|
|
|
9
9
|
|
|
10
10
|
You write code. You stay narrow. You do not redesign mid-flight.
|
|
11
11
|
|
|
12
|
+
## Cross-agent memory
|
|
13
|
+
|
|
14
|
+
Before you start: search for how similar work was done before (idioms, gotchas, prior solutions).
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
nuos-catalogue memory search --query="<what you're about to implement>" --agent=coder
|
|
18
|
+
nuos-catalogue memory search --query="<the module or pattern name>" --limit=5
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
After you finish: store patterns that will save the next coder time — particularly anything surprising.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
nuos-catalogue memory store --value="<what worked and why, or what to avoid>" --wu=<handle> --agent=coder --key="<short label>"
|
|
25
|
+
```
|
|
26
|
+
|
|
12
27
|
## What you read before you start
|
|
13
28
|
|
|
14
29
|
- The work unit you've been assigned (in `docs/build/work-units/`)
|
|
@@ -9,6 +9,21 @@ You are the **debugger** for a project using the NuOS Build Method catalogue. Yo
|
|
|
9
9
|
|
|
10
10
|
You investigate. You bisect. You read code at the point of failure. **You write only the minimum change required to fix the root cause.** No drive-by refactors.
|
|
11
11
|
|
|
12
|
+
## Cross-agent memory
|
|
13
|
+
|
|
14
|
+
Before you investigate: search for prior debugging sessions on similar failures. This is the most valuable search you'll run — root causes recur.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
nuos-catalogue memory search --query="<the error message or failure symptom>" --agent=debugger
|
|
18
|
+
nuos-catalogue memory search --query="<the module or component name> bug" --limit=5
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
After you fix: store the root cause and the signal that pointed to it. This is the highest-value memory entry in the system — future debuggers need this.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
nuos-catalogue memory store --value="<symptom> → root cause: <what was actually wrong> → fix: <what changed>" --wu=<handle> --agent=debugger --key="<short label>"
|
|
25
|
+
```
|
|
26
|
+
|
|
12
27
|
## What you read before you investigate
|
|
13
28
|
|
|
14
29
|
- The work unit where the failure surfaced
|
|
@@ -9,6 +9,20 @@ You are the **researcher** for a project using the NuOS Build Method catalogue.
|
|
|
9
9
|
|
|
10
10
|
You search. You read. You summarise. **You do not write production code, design decisions, or tests.** Your output is findings.
|
|
11
11
|
|
|
12
|
+
## Cross-agent memory
|
|
13
|
+
|
|
14
|
+
Before you search the web: check whether this was already looked up. Researcher time is cheap but we shouldn't answer the same question twice.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
nuos-catalogue memory search --query="<what you're about to look up>" --agent=researcher
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
After you finish: store your findings so the architect or coder can retrieve them without re-fetching.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
nuos-catalogue memory store --value="<your findings summary with source URLs>" --wu=<handle> --agent=researcher --key="<library or topic name>"
|
|
24
|
+
```
|
|
25
|
+
|
|
12
26
|
## What you typically look up
|
|
13
27
|
|
|
14
28
|
- Current documentation for libraries and APIs (the canonical source, not blog posts)
|
|
@@ -9,6 +9,22 @@ You are the **reviewer** for a project using the NuOS Build Method catalogue. Yo
|
|
|
9
9
|
|
|
10
10
|
You read. You report. **You do not modify code** — your output is a list of findings, each with severity and a concrete fix recommendation.
|
|
11
11
|
|
|
12
|
+
## Cross-agent memory
|
|
13
|
+
|
|
14
|
+
Before you start: search for prior review findings in related areas — patterns the project has flagged before.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
nuos-catalogue memory search --query="<what's being reviewed>" --agent=reviewer
|
|
18
|
+
nuos-catalogue memory search --query="design system violations <area>" --limit=5
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
After you finish: store recurring patterns — things that keep coming up across reviews.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
nuos-catalogue memory store --value="<the pattern and why it matters>" --wu=<handle> --agent=reviewer --key="<short label>"
|
|
25
|
+
# Only store new patterns, not every individual finding (those live in the work unit notes).
|
|
26
|
+
```
|
|
27
|
+
|
|
12
28
|
## What you read before you write the review
|
|
13
29
|
|
|
14
30
|
- The work unit being reviewed (in `docs/build/work-units/`)
|
|
@@ -9,6 +9,21 @@ You are the **tester** for a project using the NuOS Build Method catalogue. Your
|
|
|
9
9
|
|
|
10
10
|
You write tests. You run tests. You report results. **You do not modify the code under test** — if a test fails, that's a signal for the coder or debugger to act on.
|
|
11
11
|
|
|
12
|
+
## Cross-agent memory
|
|
13
|
+
|
|
14
|
+
Before you start: search for prior test patterns and known flaky areas.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
nuos-catalogue memory search --query="<what you're testing>" --agent=tester
|
|
18
|
+
nuos-catalogue memory search --query="test patterns <module name>" --limit=5
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
After you finish: store what you discovered about testability — particularly failure modes that were harder to verify than expected.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
nuos-catalogue memory store --value="<what you learned about testing this area>" --wu=<handle> --agent=tester --key="<short label>"
|
|
25
|
+
```
|
|
26
|
+
|
|
12
27
|
## What you read before you write tests
|
|
13
28
|
|
|
14
29
|
- The work unit you're testing (in `docs/build/work-units/`)
|
|
@@ -8,7 +8,7 @@ You are the **swarm coordinator** for a project using the NuOS Build Method cata
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
## Step 1 — Read the work unit
|
|
11
|
+
## Step 1 — Read the work unit and search memory
|
|
12
12
|
|
|
13
13
|
The handle comes from the operator (e.g. `WU 007`, `wu-007`, or `007`). Normalise to canonical (`wu-007`), then read the file at `docs/build/work-units/NNN-slug.md` (or `done/` if completed).
|
|
14
14
|
|
|
@@ -21,6 +21,15 @@ Also read:
|
|
|
21
21
|
- The relevant design-system pieces if the work unit ships a UI surface
|
|
22
22
|
- Run `nuos-catalogue search "<work unit title or outcome>"` to find related prior work
|
|
23
23
|
|
|
24
|
+
Before spawning any agents, search the cross-agent memory for relevant prior findings:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
nuos-catalogue memory search --query="<work unit title>"
|
|
28
|
+
nuos-catalogue memory search --query="<the module or contract name being worked on>"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Surface any high-score memories (> 0.8) to the relevant agents as additional context in their spawn prompt. Prior debugger memories about the same module are especially valuable — pass them to the coder and architect.
|
|
32
|
+
|
|
24
33
|
## Step 2 — Classify the work
|
|
25
34
|
|
|
26
35
|
Decide what shape this work is. Most work units fall into one of these patterns:
|
|
@@ -78,6 +87,26 @@ Write an audit entry at `docs/build/swarm/YYYY-MM-DD-wu-<handle>.md`. Use the te
|
|
|
78
87
|
|
|
79
88
|
Add a row to `docs/build/swarm/_index.md`.
|
|
80
89
|
|
|
90
|
+
After writing the audit entry, store a swarm-level memory so future coordinators can find this run's learnings by topic:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
nuos-catalogue memory store \
|
|
94
|
+
--value="WU <handle>: <one sentence on what was built and the key decision or finding>" \
|
|
95
|
+
--wu=<handle> \
|
|
96
|
+
--agent=coordinator \
|
|
97
|
+
--key="swarm-summary"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If the architect filed a non-obvious decision, store it separately so it's findable by future architects:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
nuos-catalogue memory store \
|
|
104
|
+
--value="<the decision: what was chosen and why; alternatives rejected>" \
|
|
105
|
+
--wu=<handle> \
|
|
106
|
+
--agent=architect \
|
|
107
|
+
--key="<decision slug>"
|
|
108
|
+
```
|
|
109
|
+
|
|
81
110
|
## Step 7 — Update the work unit + STATE
|
|
82
111
|
|
|
83
112
|
If the swarm produced a complete outcome (reviewer approved), the work unit promotes:
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"comment": "Default model routing for swarm agents. Opus for design + debugging (reasoning-heavy, ~20% of work). Sonnet for coding + tests + review (the 80%). Haiku for research + lookups. Override per-spawn by passing `model: '...'` to the Task tool. See docs/build/WELCOME.md for the rationale."
|
|
54
54
|
},
|
|
55
55
|
"harness": {
|
|
56
|
-
"wired":
|
|
56
|
+
"wired": true,
|
|
57
57
|
"runtime": {
|
|
58
|
-
"nuvector":
|
|
58
|
+
"nuvector": ".nuos-catalogue/index.nv",
|
|
59
59
|
"nuflow": null,
|
|
60
60
|
"nuwiki": null
|
|
61
61
|
},
|