@venizia/vulcan 0.1.0-1 → 0.2.0-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -5
- package/base/claude/settings.json +2 -2
- package/base/hooks/guard-writes.ts +22 -7
- package/base/make/vulcan.mk +30 -21
- package/base/rules.md +13 -9
- package/base/skills/docs-writing/references/before-after.md +1 -1
- package/base/skills/docs-writing/references/page-anatomy.md +2 -2
- package/base/skills/knowledge-sync/SKILL.md +70 -136
- package/base/skills/knowledge-sync/knowledge-sync.workflow.js +43 -43
- package/base/skills/knowledge-sync/references/workflow.md +44 -0
- package/package.json +4 -4
- package/src/commands/help.command.ts +2 -1
- package/src/commands/sync.command.ts +11 -2
- package/src/commands/upgrade.command.ts +1 -2
- package/src/commands/x.command.ts +42 -1
- package/src/common/constants.ts +4 -0
- package/src/common/paths.ts +17 -1
- package/src/common/types.ts +3 -1
- package/src/config/common/constants.ts +10 -0
- package/src/config/common/types.ts +1 -1
- package/src/config/index.ts +1 -0
- package/src/config/packages.ts +33 -0
- package/src/config/schema.ts +101 -8
- package/src/doctor/checks.ts +99 -29
- package/src/doctor/common/constants.ts +6 -0
- package/src/doctor/common/types.ts +1 -1
- package/src/doctor/index.ts +1 -0
- package/src/doctor/runner.ts +8 -0
- package/src/doctor/skills.ts +157 -0
- package/src/doctor/tags.ts +79 -0
- package/src/hooks/common/types.ts +1 -1
- package/src/hooks/session-digest.ts +28 -10
- package/src/init/common/types.ts +1 -1
- package/src/manifest/index.ts +1 -0
- package/src/manifest/render.ts +80 -0
- package/src/okf.ts +13 -0
- package/src/router.ts +60 -0
- package/src/rules/base.ts +19 -0
- package/src/rules/common/constants.ts +3 -0
- package/src/rules/index.ts +1 -0
- package/src/rules/parser.ts +35 -0
- package/src/sync/base-rules.ts +72 -0
- package/src/sync/common/constants.ts +14 -0
- package/src/sync/common/types.ts +11 -2
- package/src/sync/index.ts +2 -0
- package/src/sync/planner.ts +29 -7
- package/src/sync/prune.ts +132 -0
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ flag `bun x` fetches it when `@venizia/vulcan` is not installed yet.
|
|
|
17
17
|
| Command | What it does |
|
|
18
18
|
|---|---|
|
|
19
19
|
| `init [--config ts\|mts\|mjs\|js]` | Scaffold the project layer: `AGENTS.md`, `.configs/vulcan.config.*`, the three lint configs, `.agents/rules.md`, `.agents/knowledge/index.md`, a Makefile `-include`. Never overwrites; prints what to add to existing files, and the atlas `.mcp.json` entry for projects with a wiki |
|
|
20
|
-
| `sync [--dry-run]` | Write the gitignored agent adapters: `CLAUDE.md` (`@AGENTS.md`), `.claude/settings.json` (shipped + slot + project hooks + `claude.settings` over your personal keys; what it applied is recorded in `.claude/vulcan-managed.json`, so a removed choice is removed), `.claude/skills/` links. Idempotent |
|
|
20
|
+
| `sync [--dry-run] [--prune]` | Write the gitignored agent adapters: `CLAUDE.md` (`@AGENTS.md`), `.claude/settings.json` (shipped + slot + project hooks + `claude.settings` over your personal keys; what it applied is recorded in `.claude/vulcan-managed.json`, so a removed choice is removed), `.claude/skills/` links, and the committed `.agents/vulcan.manifest.json`. Prints each base rule added, changed or removed since the manifest last recorded it, with its new text, then records the new hashes. `--prune` also removes what sync proves stale and did not write: an old VULCAN or plugin-era hook command (a shipped hook in an old form, or a `.agents/` hook whose file is gone) and a dead `.claude/skills` link - never a developer's own hook or a real directory. Idempotent |
|
|
21
21
|
| `doctor` | Check the project follows VULCAN; exit 1 on any violation |
|
|
22
22
|
| `upgrade [<version\|tag>]` | Install the target `@venizia/vulcan` (default: the `next` dist-tag), then run `sync` from the newly installed CLI |
|
|
23
23
|
| `x <tool> [args...]` | Run a shipped tool at the pinned version: `okf`, `atlas` |
|
|
@@ -39,6 +39,7 @@ export default {
|
|
|
39
39
|
knowledge: { bundle: '.agents/knowledge' },
|
|
40
40
|
hooks: [{ event: 'Stop', command: 'echo done' }],
|
|
41
41
|
claude: { settings: { permissions: { allow: ['Bash(make test)'] } } }, // team-shared, committed
|
|
42
|
+
digest: { oftenDropped: ['V-B-03', 'W-00'] }, // repeated at every session start; base or own IDs
|
|
42
43
|
} satisfies VulcanConfig;
|
|
43
44
|
```
|
|
44
45
|
|
|
@@ -46,7 +47,7 @@ An unknown key is an error; every error names the file and the field.
|
|
|
46
47
|
|
|
47
48
|
## What ships (`base/`)
|
|
48
49
|
|
|
49
|
-
- `rules.md` - the base rules: write boundaries, security, process, build, and the IGNIS coding style V-C-01..V-C-18 (37 rules; V-W-05, V-C-03 and V-C-05
|
|
50
|
+
- `rules.md` - the base rules: write boundaries, security, process, build, and the IGNIS coding style V-C-01..V-C-18 (37 rules; it lists V-W-05, V-C-03 and V-C-05 as retired).
|
|
50
51
|
- `slots.json` - rules a project picks a wording for (V-W-01 today).
|
|
51
52
|
- `skills/` - `knowledge-sync`, `docs-writing` (project-neutral; a project-specific skill stays in its project).
|
|
52
53
|
- `hooks/` - `session-start.ts` (prints the rules digest) and `guard-writes.ts` (asks before a database write, a migration, a deploy or a mutating HTTP call).
|
|
@@ -57,10 +58,13 @@ or shadows a shipped one.
|
|
|
57
58
|
|
|
58
59
|
## `doctor` checks
|
|
59
60
|
|
|
60
|
-
`config` (exactly one valid config) · `layout` (AGENTS.md, rules, knowledge bundle) · `rule-ids` (
|
|
61
|
-
project rule
|
|
61
|
+
`config` (exactly one valid config) · `layout` (AGENTS.md, rules, knowledge bundle) · `rule-ids` (every
|
|
62
|
+
`V-` ID a project rule points at - an `Extends` list or a first cell - is a base rule, not a retired one) · `rule-slots` (every slot chosen, valid option) · `skills` (no shipped skill
|
|
62
63
|
shadowed) · `make` (includes `vulcan.mk`, no shipped target redefined) · `hooks` (shipped hooks are
|
|
63
64
|
not re-registered) · `adapters` (sync is current, no hand-written `CLAUDE.md`, valid settings) ·
|
|
64
|
-
`
|
|
65
|
+
`prune` (no stale hook command or dead skill link - `sync --prune` removes them) ·
|
|
66
|
+
`style` (`@venizia/dev-configs` declared by the package holding the lint config or the root, every lint config builds on it).
|
|
67
|
+
|
|
68
|
+
The session-start digest prints the base write boundaries, the slot choices, the project's own rules (bold `| **W-00** |` rows and `| V-W-02, V-W-03 |` rows that elaborate base rules), the project's `<!-- minimap-shape:start -->` ... `<!-- minimap-shape:end -->` block from `.agents/rules.md` verbatim, and the `digest.oftenDropped` rules.
|
|
65
69
|
|
|
66
70
|
MIT licensed - see [LICENSE.md](LICENSE.md).
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"hooks": [
|
|
8
8
|
{
|
|
9
9
|
"type": "command",
|
|
10
|
-
"command": "
|
|
10
|
+
"command": "f=\"${CLAUDE_PROJECT_DIR}/node_modules/@venizia/vulcan/base/hooks/session-start.ts\"; if [ -f \"$f\" ] && command -v bun >/dev/null 2>&1; then bun \"$f\"; s=$?; [ \"$s\" -eq 0 ] && exit 0; exit 2; fi; echo \"vulcan: the session-start hook cannot run (node_modules/@venizia/vulcan or bun is missing) - run bun install\" >&2; exit 2"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"hooks": [
|
|
19
19
|
{
|
|
20
20
|
"type": "command",
|
|
21
|
-
"command": "
|
|
21
|
+
"command": "f=\"${CLAUDE_PROJECT_DIR}/node_modules/@venizia/vulcan/base/hooks/guard-writes.ts\"; if [ -f \"$f\" ] && command -v bun >/dev/null 2>&1; then bun \"$f\"; s=$?; [ \"$s\" -eq 0 ] && exit 0; exit 2; fi; if grep -Eq '\"command\" *: *\"bun (install|i)( --?[a-z][a-z0-9-]*(=[A-Za-z0-9._-]+)?)*\"'; then exit 0; fi; echo \"vulcan: the guard-writes hook cannot run (node_modules/@venizia/vulcan or bun is missing) - run bun install (the one command that passes until then)\" >&2; exit 2"
|
|
22
22
|
}
|
|
23
23
|
]
|
|
24
24
|
}
|
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PreToolUse hook on Bash: catches the writes V-W-02 and V-W-03 reserve for a human, reading the
|
|
3
3
|
* command and any local script it runs. It asks rather than denies (src/hooks/common/constants.ts).
|
|
4
|
+
*
|
|
5
|
+
* It fails closed: Claude Code blocks a PreToolUse call only on exit 2, so a hook that throws - a
|
|
6
|
+
* partial install, say, where its own modules are missing - would let every command through. The
|
|
7
|
+
* modules load inside the try for that reason.
|
|
4
8
|
*/
|
|
5
|
-
import { buildGuardDecision, inspectCommand, parseHookCommand } from '../../src/hooks/index.ts';
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
? inspectCommand({ command: hookCommand.command, cwd: hookCommand.cwd ?? process.cwd() })
|
|
10
|
-
: [];
|
|
10
|
+
// A module, so the awaits below are top-level; it has no static import, by design.
|
|
11
|
+
export {};
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
try {
|
|
14
|
+
const { buildGuardDecision, inspectCommand, parseHookCommand } =
|
|
15
|
+
await import('../../src/hooks/index.ts');
|
|
16
|
+
const hookCommand = parseHookCommand({ text: await Bun.stdin.text() });
|
|
17
|
+
const hits = hookCommand
|
|
18
|
+
? inspectCommand({ command: hookCommand.command, cwd: hookCommand.cwd ?? process.cwd() })
|
|
19
|
+
: [];
|
|
20
|
+
|
|
21
|
+
if (hits.length > 0) {
|
|
22
|
+
console.log(JSON.stringify(buildGuardDecision({ hits })));
|
|
23
|
+
}
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error(
|
|
26
|
+
`vulcan: the guard-writes hook failed (${error instanceof Error ? error.message : String(error)}) - blocked; run bun install`,
|
|
27
|
+
);
|
|
28
|
+
process.exit(2);
|
|
14
29
|
}
|
package/base/make/vulcan.mk
CHANGED
|
@@ -5,48 +5,57 @@
|
|
|
5
5
|
VULCAN ?= bun x --no-install vulcan
|
|
6
6
|
|
|
7
7
|
.PHONY: vulcan-sync vulcan-doctor agent-setup okf-check okf-check-strict okf-gen okf-coverage okf-viz \
|
|
8
|
-
surface-gen surface-check symbols
|
|
8
|
+
surface-gen surface-check atlas-symbols atlas-releases changelogs-migrate \
|
|
9
|
+
knowledge-symbols-check
|
|
9
10
|
|
|
10
|
-
vulcan-sync:
|
|
11
|
+
vulcan-sync: ## Write the agent adapters, settings, skill links and manifest from the config
|
|
11
12
|
@$(VULCAN) sync
|
|
12
13
|
|
|
13
|
-
vulcan-doctor:
|
|
14
|
+
vulcan-doctor: ## Check the project against the VULCAN contract
|
|
14
15
|
@$(VULCAN) doctor
|
|
15
16
|
|
|
16
|
-
# The
|
|
17
|
-
agent-setup: vulcan-sync
|
|
17
|
+
# The older name for the same job, kept for muscle memory.
|
|
18
|
+
agent-setup: vulcan-sync ## The older name for vulcan-sync
|
|
18
19
|
|
|
19
20
|
# OKF v0.2 conformance only; okf-check-strict adds the house rules (links, style, coverage, freshness).
|
|
20
|
-
okf-check:
|
|
21
|
+
okf-check: ## Check the knowledge bundle against OKF v0.2
|
|
21
22
|
@$(VULCAN) x okf check
|
|
22
23
|
|
|
23
|
-
okf-check-strict:
|
|
24
|
+
okf-check-strict: ## okf-check plus the house rules: links, style, coverage, freshness
|
|
24
25
|
@$(VULCAN) x okf check --strict
|
|
25
26
|
|
|
26
|
-
okf-gen:
|
|
27
|
+
okf-gen: ## Regenerate the generated pages and regions of the knowledge bundle
|
|
27
28
|
@$(VULCAN) x okf gen
|
|
28
29
|
|
|
29
|
-
okf-coverage:
|
|
30
|
+
okf-coverage: ## Report how much of the code the knowledge bundle covers
|
|
30
31
|
@$(VULCAN) x okf coverage
|
|
31
32
|
|
|
32
|
-
okf-viz:
|
|
33
|
+
okf-viz: ## Build the knowledge graph view
|
|
33
34
|
@$(VULCAN) x okf viz
|
|
34
35
|
|
|
35
|
-
# The
|
|
36
|
-
|
|
36
|
+
# The public surface: an optional API gate a project commits and checks. It reads the built .d.ts -
|
|
37
|
+
# build first.
|
|
38
|
+
surface-gen: ## Write the public API surface from the built .d.ts
|
|
37
39
|
@$(VULCAN) x atlas surface gen
|
|
38
40
|
|
|
39
|
-
surface-check:
|
|
41
|
+
surface-check: ## Fail when the public API surface differs from the committed one
|
|
40
42
|
@$(VULCAN) x atlas surface check
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
# Symbols are read from the built or installed .d.ts when atlas is asked - nothing to commit.
|
|
45
|
+
# atlas-symbols prints what atlas reads, to see what symbol answers from. Build first.
|
|
46
|
+
atlas-symbols: ## Print the symbols atlas reads from the built or installed .d.ts
|
|
47
|
+
@$(VULCAN) x atlas symbols
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
# Releases are computed from tags when atlas reads the project - nothing to generate or commit.
|
|
50
|
+
# atlas-releases prints the computed table, to see what version and changes answer from.
|
|
51
|
+
atlas-releases: ## Print the release table atlas computes from the tags
|
|
52
|
+
@$(VULCAN) x atlas releases
|
|
47
53
|
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
# Writes the packages: list into every changelog entry that declares none - once, then review it.
|
|
55
|
+
changelogs-migrate: ## Write the packages: list into changelog entries that declare none
|
|
56
|
+
@$(VULCAN) x atlas changelogs migrate
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
|
|
58
|
+
# A concept may name code (`symbols:` in its frontmatter); this fails when a named symbol is gone or its
|
|
59
|
+
# signature changed since `vulcan x atlas concepts stamp`. It reads the built .d.ts - run it after build.
|
|
60
|
+
knowledge-symbols-check: ## Fail when a symbol a concept names is gone or its signature changed
|
|
61
|
+
@$(VULCAN) x atlas concepts check
|
package/base/rules.md
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
# Rules - VULCAN base
|
|
2
2
|
|
|
3
3
|
<!-- Shipped by @venizia/vulcan. Never edit in a project: add extensions in .agents/rules.md.
|
|
4
|
-
W, S, P, B are INTERIM until the base-rules work reconciles the rules
|
|
5
|
-
C is
|
|
4
|
+
W, S, P, B are INTERIM until the base-rules work reconciles the rules the projects share.
|
|
5
|
+
C is the shared coding style, shipped to every project; a rule that binds one project's own stack
|
|
6
|
+
lives in that project. -->
|
|
6
7
|
|
|
7
8
|
Cite by ID. Every rule has "Enforced by". Base IDs carry the `V-` namespace (`V-W-01`, `V-C-04`).
|
|
8
9
|
A project extends this set in its own `.agents/rules.md` with bare IDs (`W-06`, `C-19`), which can
|
|
9
|
-
never collide with a base ID
|
|
10
|
+
never collide with a base ID. A `V-` ID there points at a base rule (`Extends V-W-01`); `vulcan doctor`
|
|
11
|
+
fails one the base does not carry or has retired.
|
|
10
12
|
|
|
11
|
-
Retired IDs are never reused
|
|
12
|
-
|
|
13
|
-
`V-
|
|
13
|
+
Retired IDs are never reused (2026-10-17):
|
|
14
|
+
|
|
15
|
+
- `V-W-05` - the task-manager loop
|
|
16
|
+
- `V-C-03` - `@inject` on container-built classes, moved to the project whose stack it binds
|
|
17
|
+
- `V-C-05` - `getError` / `ApplicationError`, moved to the project whose stack it binds, with the hard stack once in `V-C-18`
|
|
14
18
|
|
|
15
19
|
## W - Write boundaries
|
|
16
20
|
|
|
@@ -58,8 +62,8 @@ classes) and `V-C-05` (`getError` / `ApplicationError`) - the last two, with the
|
|
|
58
62
|
| ID | Rule | Enforced by |
|
|
59
63
|
|----|------|-------------|
|
|
60
64
|
| V-C-01 | **English only in code** - identifiers, comments, commit messages, logs, docs. Vietnamese belongs in chat. | SOFT |
|
|
61
|
-
| V-C-02 | **
|
|
62
|
-
| V-C-04 | **Never abbreviate identifiers:** `ProductRepository` not `ProductRepo`, `ProductDocument` not `ProductDoc`; type parameters too (`TDocument`, not `TDoc`). A project lists its own exceptions in its rules (
|
|
65
|
+
| V-C-02 | **One options object first, at most 5 parameters.** Fold every argument you can into a single options object in the first position: `fn({ key, value })`, not `fn(key, value)`, and one parameter is not an exception - `isValidName({ name })`, not `isValidName(name)`. A second parameter is allowed only where the first object cannot carry it, for example a repository method that takes its data and its query options separately. Never more than 5 parameters. A single positional parameter reads fine until the second one arrives, and by then the method is published and every call site pays. The cost is highest on an interface others implement: `IStorageHelper` carried three positional methods for exactly this reason and the migration touched 72 call sites. Mixing the two styles in one interface is itself the defect - a reader cannot tell which shape a method takes without opening it. | SOFT - lint (`venizia/max-params-own`, 5) once `@venizia/dev-configs` ships `houseConfigs` |
|
|
66
|
+
| V-C-04 | **Never abbreviate identifiers:** `ProductRepository` not `ProductRepo`, `ProductDocument` not `ProductDoc`; type parameters too (`TDocument`, not `TDoc`). A project lists its own exceptions in its rules (for example `tz` for a time zone). | SOFT |
|
|
63
67
|
| V-C-06 | **Never a silent catch - log it.** Always braces. Early return. `switch` with `default` over a long if-else chain. Strict TypeScript; no `any` where a type exists. | LINT (braces, floating promises) + SOFT |
|
|
64
68
|
| V-C-07 | **A function name opens with its verb** - `generate` `build` `to` `is` `has` `assert` `extract` `enrich` `get` `resolve`. `is*` returns a boolean and leaves the branch to the caller; `assert*` throws and returns `void`, so the code after it needs none - reach for `assert*` when every caller would throw on `false` anyway. `has*` is the ownership question (`hasBucket`, never `isBucketExists`). That list is for UTILITY functions; service methods lean on a wider set. **Arrow functions, not `function` declarations** (do not churn existing ones). State plus the operations on it live in a class with static members - the `LoggerFactory` shape - never module-level `let` plus exported arrows. | SOFT |
|
|
65
69
|
| V-C-08 | **Enumerable strings are a const class plus `TConstValue`,** never a raw string-literal union. Every such class carries `static readonly SCHEME_SET = new Set([...])` over its values and `static isValid(value: string): boolean` reading it, so a runtime check exists wherever a value crosses a boundary (`IsolationLevels` in connectors is the model; a subclass redeclares `SCHEME_SET` with `...Parent.SCHEME_SET` first). The `T`/`I` prefix follows the declaration keyword: `type` gets `T`, `interface` gets `I`; an interface turned into a type alias is renamed, and no tool catches it - grep both directions. | SOFT |
|
|
@@ -67,7 +71,7 @@ classes) and `V-C-05` (`getError` / `ApplicationError`) - the last two, with the
|
|
|
67
71
|
| V-C-10 | **No explicit cast in new code.** `as X`, `as any`, `as unknown as X` and `as never` assert nothing; they silence the compiler where the type is wrong. Fix the type instead: a generic on the setter, a narrower parameter, a typed helper, `satisfies`. A pre-existing cast is removed when the line is touched, never copied. Generic parameters are full words (`ApplicationType`, `TDocument`), never `App` or `TDoc` (V-C-04). | SOFT |
|
|
68
72
|
| V-C-11 | **SIMPLE FIRST, in code and in prose.** Fewest concepts, plainest words, smallest surface. Complexity must buy correctness, speed or safety the simple version cannot, and the artifact says what it bought. Something a reader cannot follow in one pass is a defect even when it works. Fix the root cause with the smallest change; never layer an abstraction on a misdiagnosed problem. | SOFT |
|
|
69
73
|
| V-C-12 | **Consistent, never self-invented.** Before writing anything new - a constant, file, binding key, error shape - find the nearest precedent in this repo and copy its shape. Binding keys are namespaced (`controllers.X`, `services.X`, `repositories.X`, `datasources.X`). Every scope is one folder with nested `common/{types,constants}.ts` and an index barrel (`inversion` is the model). A second style for something that already has one is a defect. | SOFT |
|
|
70
|
-
| V-C-13 | **Docs style: hyphen `-`, never an em-dash or en-dash. A brand is spelled the way its owner spells it (
|
|
74
|
+
| V-C-13 | **Docs style: hyphen `-`, never an em-dash or en-dash. A brand is spelled the way its owner spells it (VULCAN, never "Vulcan").** English prose. The human-facing docs site stays native to its generator (for example plain VitePress, no custom components or theme CSS). The knowledge bundle is agent-facing; never conflate the two. | SOFT - `okf check --strict` (bundle) |
|
|
71
75
|
| V-C-14 | **Our types are camelCase.** A snake_case wire name exists only at the mapper boundary, through a string-literal key - never through an eslint-disable. | LINT (naming convention) + SOFT |
|
|
72
76
|
| V-C-15 | **One method with a mode option, not several specialized methods.** Payload variants are zod-per-variant with `z.infer`, discriminated. | SOFT |
|
|
73
77
|
| V-C-16 | **One concept, one implementation.** When the same question is answered in several places, the bug lives at the seam and no tool catches it. Consolidate to one home before building on top. | SOFT |
|
|
@@ -15,7 +15,7 @@ If a page's sections resolve to different quadrants, it is two pages wearing one
|
|
|
15
15
|
|
|
16
16
|
## Skeleton 1 - Tutorial (getting started)
|
|
17
17
|
|
|
18
|
-
1. **Title** - an achievement: "Build your first
|
|
18
|
+
1. **Title** - an achievement: "Build your first API", never "Learn the framework".
|
|
19
19
|
2. **Goal + outcome preview** - 1-3 sentences: "In this tutorial we build a working X." Never "you will learn".
|
|
20
20
|
3. **Prerequisites** - exact versions and tools, once.
|
|
21
21
|
4. **Numbered steps** - ONE path, zero choices. Every step ends in a visible result with the expected output shown ("After a few seconds you'll see...").
|
|
@@ -52,7 +52,7 @@ Governing rule: describe and only describe. Structure mirrors the code. You cons
|
|
|
52
52
|
1. **Title** - accepts an implicit "About...": "Understanding the DI container".
|
|
53
53
|
2. **The question** - what "why" this page answers. It is also the page's boundary.
|
|
54
54
|
3. **The picture** - the mental model, a diagram if code and words fail.
|
|
55
|
-
4. **Design decisions** - why
|
|
55
|
+
4. **Design decisions** - why the project chose this (prior art: LoopBack, NestJS, Spring), constraints, trade-offs.
|
|
56
56
|
5. **Alternatives and objections** - weigh them honestly (Tailwind's "Why not just use inline styles?" move).
|
|
57
57
|
6. **Boundaries + links** - where the topic ends; link the reference and how-tos.
|
|
58
58
|
|
|
@@ -1,146 +1,80 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: knowledge-sync
|
|
3
|
-
description: Re-
|
|
3
|
+
description: Re-syncs a project's OKF knowledge bundle against its source code - verifies the curated concepts whose code changed since the last sync (delta) or every concept (full), applies the confirmed fixes and logs the sync. Use when the user asks to sync knowledge, refresh the knowledge bundle, audit concepts against code, or run a periodic knowledge audit.
|
|
4
4
|
user-invocable: true
|
|
5
5
|
allowed-tools: Read, Write, Edit, Grep, Glob, Bash, Agent, Workflow
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Knowledge
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
2. **Curate, do not dump.** Concepts stay tight: fix wrong/stale, fold in only durable high-value
|
|
23
|
-
missing facts, skip volatile detail (dependency lists, config keys, version numbers).
|
|
24
|
-
3. **Cheap by default.** Delta mode only verifies concepts whose code areas changed since the last
|
|
25
|
-
sync. Full mode (everything + critics) is for monthly/quarterly.
|
|
26
|
-
4. **Nothing is committed.** The agent edits the bundle + `log.md`; the user reviews and commits.
|
|
27
|
-
5. **Subagents never run state-changing git commands.** Read-only `git log`/`diff`/`show` only.
|
|
28
|
-
|
|
29
|
-
## Mode selection
|
|
30
|
-
|
|
31
|
-
| What the user asked for | Mode |
|
|
32
|
-
|---|---|
|
|
33
|
-
| daily / weekly / bi-weekly / "sync knowledge" (no qualifier) | `delta` |
|
|
34
|
-
| monthly / quarterly / "full" / "toàn bộ" / last **full** sync > 30 days ago (check `log.md`) | `full` |
|
|
35
|
-
|
|
36
|
-
`full` = delta verifiers **plus** 6 directory spot-auditors over every other concept **plus**
|
|
37
|
-
completeness + usability critics.
|
|
38
|
-
|
|
39
|
-
## Step 0 - Baseline
|
|
40
|
-
|
|
41
|
-
1. `make okf-gen` then `make okf-check` - refresh the generated layer first so verifiers never chase
|
|
42
|
-
facts `gen` already fixes. `check` must be clean before proceeding.
|
|
43
|
-
2. **Anchor the last sync by COMMIT, not by date:**
|
|
44
|
-
```bash
|
|
45
|
-
LAST_SYNC=$(git log -1 --format=%H -G '^## [0-9-]+ - knowledge-sync' -- .agents/knowledge/log.md)
|
|
46
|
-
```
|
|
47
|
-
The scan range is `$LAST_SYNC..HEAD`. Anchor on the sync's own log heading, never on the last
|
|
48
|
-
edit of `log.md`: every ordinary change appends to it (OKF §9), so the last edit is almost never
|
|
49
|
-
the last sync and the range would come out empty. The date in the heading is only a display label.
|
|
50
|
-
|
|
51
|
-
**If `LAST_SYNC` is empty** no entry carries the `knowledge-sync` heading yet (or `log.md` was renamed). Do not
|
|
52
|
-
build a `..HEAD` range from it - that silently means "everything". Either anchor on the commit
|
|
53
|
-
that introduced the bundle (`git log --diff-filter=A --format=%H -- .agents/knowledge/index.md`)
|
|
54
|
-
or run `full` mode, which does not depend on the range for its spot-auditors.
|
|
55
|
-
Never use a bare `--since=YYYY-MM-DD`: git's approxidate reads a date equal to *today* as "since
|
|
56
|
-
the current wall-clock time" and silently returns empty, and same-day commits made before the
|
|
57
|
-
last sync get double-counted. A hash range has neither problem.
|
|
58
|
-
3. Changed-area scan:
|
|
59
|
-
```bash
|
|
60
|
-
git log $LAST_SYNC..HEAD --no-merges --name-only --format= -- packages/ examples/ Makefile make/ .github/ .githooks/ scripts/ \
|
|
61
|
-
| sort -u | awk -F/ '{print $1"/"$2}' | sort | uniq -c | sort -rn
|
|
62
|
-
git log $LAST_SYNC..HEAD --no-merges --oneline
|
|
63
|
-
git diff HEAD --stat -- packages/ examples/ Makefile make/ .github/ .githooks/ scripts/ package.json
|
|
64
|
-
```
|
|
65
|
-
The last line is uncommitted code. `okf gen` regenerates from the working tree and the verifiers
|
|
66
|
-
read the working tree, so uncommitted changes count as changed areas too - say which are
|
|
67
|
-
uncommitted in the target hint. Commit subjects become verifier hints. Ignore commits touching
|
|
68
|
-
only `.agents/knowledge/` or `docs/` - that is knowledge maintenance, not code drift.
|
|
69
|
-
4. **Early exit (delta mode):** if no code areas changed, report "bundle already in sync", run the
|
|
70
|
-
gates (Step 3), stop. No workflow, no log entry - unless `gen` changed generated files, then a
|
|
71
|
-
one-line entry.
|
|
72
|
-
|
|
73
|
-
## Step 1 - Build delta targets
|
|
74
|
-
|
|
75
|
-
One target per changed area, from this map. Extend it when a new area appears, and keep it in sync
|
|
76
|
-
as concepts are added.
|
|
77
|
-
|
|
78
|
-
| Changed area | Concepts to verify (under `.agents/knowledge/`) |
|
|
79
|
-
|---|---|
|
|
80
|
-
| `packages/core-server/src/base/applications` | architecture/application-lifecycle, packages/core-server |
|
|
81
|
-
| `packages/core-server/src/components` | architecture/component-model, architecture/controller-system, architecture/authentication, architecture/authorization-casbin, process/adding-a-component |
|
|
82
|
-
| `packages/kernel/src/base/repositories`, `packages/kernel/src/base/datasources` | architecture/repository-hierarchy, architecture/datasource-hierarchy, architecture/transactions, packages/kernel |
|
|
83
|
-
| `packages/kernel/src/common/bindings.ts` | conventions/binding-key-namespaces |
|
|
84
|
-
| `packages/kernel` (broad/other) | packages/kernel, architecture/di-container, architecture/controller-system, architecture/error-handling-flow |
|
|
85
|
-
| `packages/connectors` | packages/connectors, architecture/relational-connector, architecture/sqlite-connector, architecture/search-typesense, architecture/transactions |
|
|
86
|
-
| `packages/filter` | packages/filter, architecture/filter-system |
|
|
87
|
-
| `packages/core-worker` | packages/core-worker |
|
|
88
|
-
| `packages/atlas` | packages/atlas |
|
|
89
|
-
| `packages/core-server` (broad/other) | packages/core-server, architecture/error-handling-flow, conventions/gotchas |
|
|
90
|
-
| `packages/boot` | packages/boot, architecture/boot-lifecycle |
|
|
91
|
-
| `packages/inversion` | packages/inversion, architecture/di-container, conventions/gotchas |
|
|
92
|
-
| `packages/helpers` | packages/helpers, conventions/error-handling, process/adding-a-helper |
|
|
93
|
-
| `packages/dev-configs` | packages/dev-configs, conventions/coding-style, conventions/testing-conventions |
|
|
94
|
-
| `examples/<x>` | examples/<x> |
|
|
95
|
-
| `Makefile`, `make/`, `scripts/`, `.githooks/`, root `package.json` | process/build-system, process/testing, process/git-workflow, overview/build-run-test, conventions/gotchas |
|
|
96
|
-
| `.github/workflows/` | process/release-publish, process/updating-the-wiki |
|
|
97
|
-
| `docs/wiki` | process/updating-the-wiki |
|
|
98
|
-
|
|
99
|
-
Per-target fields: `key`, `area` (git pathspec), `concepts`, `hint` (summarize the commit subjects -
|
|
100
|
-
the verifier is told to verify, not trust), `model` - `opus` for heavy or architecture-critical areas
|
|
101
|
-
(core, inversion, big diffs), `sonnet` for small ones. Ignore noise-only areas (formatting,
|
|
102
|
-
lockfiles, generated files). Merge tiny areas (<=3 files each) into one combined target.
|
|
103
|
-
|
|
104
|
-
## Step 2 - Run the workflow
|
|
105
|
-
|
|
106
|
-
Invoke the Workflow tool with the saved script. Do not rewrite the orchestration inline:
|
|
8
|
+
# Knowledge sync
|
|
9
|
+
|
|
10
|
+
The generated layer (`vulcan x okf gen`) heals itself; curated concepts stay true only when someone
|
|
11
|
+
re-reads the code. Code is ground truth - never fix a concept from docs, `AGENTS.md` or memory. Every
|
|
12
|
+
finding cites a `file:line` witness. Nothing is committed: the user reviews the diff.
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
- Bun, git, and `@venizia/vulcan` installed in the project (`bun x --no-install vulcan`).
|
|
17
|
+
- The Workflow tool, for the fan-out in Step 3.
|
|
18
|
+
|
|
19
|
+
## Checklist
|
|
20
|
+
|
|
21
|
+
Copy it into your reply and tick it off:
|
|
107
22
|
|
|
108
23
|
```
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
gitRange: '<LAST_SYNC hash>..HEAD', // what verifiers actually diff
|
|
116
|
-
deltaTargets: [...],
|
|
117
|
-
},
|
|
118
|
-
})
|
|
24
|
+
- [ ] 1. Prerequisites hold
|
|
25
|
+
- [ ] 2. Baseline: gen, check, last sync, changed areas
|
|
26
|
+
- [ ] 3. Targets built, workflow run
|
|
27
|
+
- [ ] 4. Gaps decided
|
|
28
|
+
- [ ] 5. Gates green (loop until they are)
|
|
29
|
+
- [ ] 6. Log entry written; reported
|
|
119
30
|
```
|
|
120
31
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
`
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
3.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
32
|
+
## 1. Prerequisites
|
|
33
|
+
|
|
34
|
+
1. `bun x --no-install vulcan doctor` passes - the manifest is fresh. Fix what it names first.
|
|
35
|
+
2. Read `.agents/vulcan.manifest.json`: `knowledge.bundle` (the bundle), `packages[].path` (the code
|
|
36
|
+
areas), `knowledge.syncAreas` (the area map, optional), `name` (the brand, upper case).
|
|
37
|
+
|
|
38
|
+
## 2. Baseline
|
|
39
|
+
|
|
40
|
+
1. `bun x --no-install vulcan x okf gen`, then `vulcan x okf check --strict` - it must pass before
|
|
41
|
+
anything else, so no verifier chases a fact `gen` fixes.
|
|
42
|
+
2. Anchor the last sync by commit, never by date:
|
|
43
|
+
`LAST_SYNC=$(git log -1 --format=%H -G '^## [0-9-]+ - knowledge-sync' -- <bundle>/log.md)`.
|
|
44
|
+
Empty: no sync yet - run `full`, or anchor on the commit that added `<bundle>/index.md`. A bare
|
|
45
|
+
`--since=<date>` is wrong: git reads today's date as "now" and returns nothing.
|
|
46
|
+
3. Changed areas: `git log $LAST_SYNC..HEAD --no-merges --name-only --format= -- <package paths> Makefile make/ scripts/ .github/`,
|
|
47
|
+
plus `git diff HEAD --stat` for uncommitted code. Commits that touch only the bundle or `docs/` are
|
|
48
|
+
knowledge maintenance, not drift.
|
|
49
|
+
4. Delta mode, nothing changed: report "already in sync", run Step 5's gates, stop.
|
|
50
|
+
|
|
51
|
+
## 3. Targets and the workflow
|
|
52
|
+
|
|
53
|
+
Mode: `delta` by default; `full` when asked (monthly, quarterly, "full") or when the last full sync
|
|
54
|
+
in `log.md` is over 30 days old. Build the targets and run the workflow as
|
|
55
|
+
[references/workflow.md](references/workflow.md) describes - one target per changed area, from the
|
|
56
|
+
area map when the project has one, else from each concept's `resource`.
|
|
57
|
+
|
|
58
|
+
## 4. Gaps
|
|
59
|
+
|
|
60
|
+
For each gap the critics propose: durable, load-bearing, and no existing home? Create the concept -
|
|
61
|
+
copy frontmatter, voice and length from 2-3 siblings, verify every claim in source, link it from
|
|
62
|
+
`index.md`. A gap that is really one fact in several files: make one file its home, the rest point
|
|
63
|
+
to it. Never lose a unique fact.
|
|
64
|
+
|
|
65
|
+
## 5. Gates - validate, fix, repeat
|
|
66
|
+
|
|
67
|
+
1. `vulcan x okf gen`
|
|
68
|
+
2. `vulcan x okf check --strict`
|
|
69
|
+
3. `vulcan x okf coverage --min 100` - structural coverage stays at 100%.
|
|
70
|
+
|
|
71
|
+
A gate that fails: fix what it names, run all three again. Stop only when all three pass.
|
|
72
|
+
|
|
73
|
+
## 6. Log and report
|
|
74
|
+
|
|
75
|
+
1. Prepend to `<bundle>/log.md`: `## YYYY-MM-DD - knowledge-sync (<mode>): <summary>` - the
|
|
76
|
+
`knowledge-sync` word is what the next sync anchors on - then one line of method (verifiers,
|
|
77
|
+
findings, confirmed, files touched) and bullets for the corrections that change how someone works.
|
|
78
|
+
2. Report in the user's language: gate status and scale first (findings applied, files, claims
|
|
79
|
+
confirmed), then each notable correction (was -> is, with its witness), new or merged concepts,
|
|
80
|
+
and anything an applier skipped, with the reason. Do not commit.
|