crewly 1.20.20 → 1.20.21
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/config/roles/generalist/prompt.md +8 -2
- package/config/roles/team-leader/prompt.md +2 -1
- package/config/skills/agent/core/wiki-query/SKILL.md +11 -0
- package/config/skills/agent/core/wiki-query/execute.sh +22 -3
- package/config/skills/orchestrator/wiki-ingest/SKILL.md +19 -0
- package/config/skills/orchestrator/wiki-ingest/execute.sh +36 -1
- package/config/skills/team-leader/wiki-review-proposals/SKILL.md +35 -0
- package/config/skills/team-leader/wiki-review-proposals/execute.sh +40 -0
- package/config/skills/team-leader/wiki-supersede/SKILL.md +38 -0
- package/config/skills/team-leader/wiki-supersede/execute.sh +44 -0
- package/dist/backend/backend/src/constants.d.ts +32 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +30 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.d.ts +29 -0
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.js +196 -4
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.routes.js +9 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.routes.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +3 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/memory/memory.service.d.ts +2 -0
- package/dist/backend/backend/src/services/memory/memory.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/memory.service.js +16 -4
- package/dist/backend/backend/src/services/memory/memory.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/schema-loader.service.d.ts +9 -0
- package/dist/backend/backend/src/services/wiki/schema-loader.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/schema-loader.service.js +40 -1
- package/dist/backend/backend/src/services/wiki/schema-loader.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.d.ts +32 -0
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.js +63 -1
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.d.ts +2 -0
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.js +9 -2
- package/dist/backend/backend/src/services/wiki/wiki-cleanup.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-curation.service.d.ts +106 -0
- package/dist/backend/backend/src/services/wiki/wiki-curation.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-curation.service.js +211 -0
- package/dist/backend/backend/src/services/wiki/wiki-curation.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-history.service.d.ts +63 -0
- package/dist/backend/backend/src/services/wiki/wiki-history.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-history.service.js +124 -0
- package/dist/backend/backend/src/services/wiki/wiki-history.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-index.service.d.ts +119 -0
- package/dist/backend/backend/src/services/wiki/wiki-index.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-index.service.js +263 -0
- package/dist/backend/backend/src/services/wiki/wiki-index.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.d.ts +66 -11
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.js +162 -44
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.d.ts +31 -0
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.js +69 -0
- package/dist/backend/backend/src/services/wiki/wiki-lint.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-owner.resolver.d.ts +29 -0
- package/dist/backend/backend/src/services/wiki/wiki-owner.resolver.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-owner.resolver.js +55 -0
- package/dist/backend/backend/src/services/wiki/wiki-owner.resolver.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-page.d.ts +101 -0
- package/dist/backend/backend/src/services/wiki/wiki-page.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-page.js +130 -0
- package/dist/backend/backend/src/services/wiki/wiki-page.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-policy.d.ts +35 -0
- package/dist/backend/backend/src/services/wiki/wiki-policy.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-policy.js +44 -0
- package/dist/backend/backend/src/services/wiki/wiki-policy.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-process.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-process.service.js +5 -2
- package/dist/backend/backend/src/services/wiki/wiki-process.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-query.service.d.ts +57 -13
- package/dist/backend/backend/src/services/wiki/wiki-query.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-query.service.js +91 -54
- package/dist/backend/backend/src/services/wiki/wiki-query.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-redaction.d.ts +74 -0
- package/dist/backend/backend/src/services/wiki/wiki-redaction.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-redaction.js +94 -0
- package/dist/backend/backend/src/services/wiki/wiki-redaction.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-search.service.d.ts +12 -3
- package/dist/backend/backend/src/services/wiki/wiki-search.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-search.service.js +19 -9
- package/dist/backend/backend/src/services/wiki/wiki-search.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-usage.service.d.ts +96 -0
- package/dist/backend/backend/src/services/wiki/wiki-usage.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-usage.service.js +147 -0
- package/dist/backend/backend/src/services/wiki/wiki-usage.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-vault-walk.d.ts +25 -0
- package/dist/backend/backend/src/services/wiki/wiki-vault-walk.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-vault-walk.js +52 -0
- package/dist/backend/backend/src/services/wiki/wiki-vault-walk.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.d.ts +19 -1
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.js +47 -6
- package/dist/backend/backend/src/services/wiki/wiki-workitem-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki.types.d.ts +24 -0
- package/dist/backend/backend/src/services/wiki/wiki.types.d.ts.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +32 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +30 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/memory/memory.service.d.ts +2 -0
- package/dist/cli/backend/src/services/memory/memory.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/memory/memory.service.js +16 -4
- package/dist/cli/backend/src/services/memory/memory.service.js.map +1 -1
- package/dist/cli/backend/src/services/wiki/schema-loader.service.d.ts +9 -0
- package/dist/cli/backend/src/services/wiki/schema-loader.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/wiki/schema-loader.service.js +40 -1
- package/dist/cli/backend/src/services/wiki/schema-loader.service.js.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-history.service.d.ts +63 -0
- package/dist/cli/backend/src/services/wiki/wiki-history.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-history.service.js +124 -0
- package/dist/cli/backend/src/services/wiki/wiki-history.service.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-index.service.d.ts +119 -0
- package/dist/cli/backend/src/services/wiki/wiki-index.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-index.service.js +263 -0
- package/dist/cli/backend/src/services/wiki/wiki-index.service.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.d.ts +66 -11
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.js +162 -44
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.js.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-page.d.ts +101 -0
- package/dist/cli/backend/src/services/wiki/wiki-page.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-page.js +130 -0
- package/dist/cli/backend/src/services/wiki/wiki-page.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-policy.d.ts +35 -0
- package/dist/cli/backend/src/services/wiki/wiki-policy.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-policy.js +44 -0
- package/dist/cli/backend/src/services/wiki/wiki-policy.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-redaction.d.ts +74 -0
- package/dist/cli/backend/src/services/wiki/wiki-redaction.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-redaction.js +94 -0
- package/dist/cli/backend/src/services/wiki/wiki-redaction.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-search.service.d.ts +12 -3
- package/dist/cli/backend/src/services/wiki/wiki-search.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-search.service.js +19 -9
- package/dist/cli/backend/src/services/wiki/wiki-search.service.js.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-usage.service.d.ts +96 -0
- package/dist/cli/backend/src/services/wiki/wiki-usage.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-usage.service.js +147 -0
- package/dist/cli/backend/src/services/wiki/wiki-usage.service.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-vault-walk.d.ts +25 -0
- package/dist/cli/backend/src/services/wiki/wiki-vault-walk.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-vault-walk.js +52 -0
- package/dist/cli/backend/src/services/wiki/wiki-vault-walk.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki.types.d.ts +24 -0
- package/dist/cli/backend/src/services/wiki/wiki.types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* WikiIngestService — write
|
|
2
|
+
* WikiIngestService — write into a vault's `llm-curated/`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Two kinds of write:
|
|
5
|
+
* - **log entry** (default): append to `llm-curated/log.md`. Cheap,
|
|
6
|
+
* append-only, no gate beyond confidentiality. This is where "maybe
|
|
7
|
+
* useful" goes — the default is NOT to keep.
|
|
8
|
+
* - **page** (`targetRelativePath` under llm-curated/): a piece of
|
|
9
|
+
* knowledge. Passes the retention gate (title + one-line summary +
|
|
10
|
+
* keep_because), the vault's write policy (a `proposed_only` role's
|
|
11
|
+
* page lands in `_proposed/` until a canonical role accepts), the
|
|
12
|
+
* confidentiality gate (secrets never; PII per vault), gets YAML
|
|
13
|
+
* frontmatter, an index line, and a history snapshot of what it
|
|
14
|
+
* replaced.
|
|
8
15
|
*
|
|
9
16
|
* Frozen-path contract (§2): refuses ANY write whose target lives under a
|
|
10
17
|
* `hardcoded:` folder. SchemaLoaderService.isFrozenPath() is the gate.
|
|
@@ -16,6 +23,12 @@ import * as fs from 'fs/promises';
|
|
|
16
23
|
import { existsSync } from 'fs';
|
|
17
24
|
import { LoggerService } from '../core/logger.service.js';
|
|
18
25
|
import { SchemaLoaderService } from './schema-loader.service.js';
|
|
26
|
+
import { WIKI_KB_CONSTANTS } from '../../constants.js';
|
|
27
|
+
import { checkRetention, parsePage, serializePage, oneLine } from './wiki-page.js';
|
|
28
|
+
import { applyPrivacyGate } from './wiki-redaction.js';
|
|
29
|
+
import { decideWrite } from './wiki-policy.js';
|
|
30
|
+
import { WikiIndexService } from './wiki-index.service.js';
|
|
31
|
+
import { WikiHistoryService } from './wiki-history.service.js';
|
|
19
32
|
const DEFAULT_LOG_RELATIVE_PATH = 'llm-curated/log.md';
|
|
20
33
|
const MAX_BODY_BYTES = 64 * 1024;
|
|
21
34
|
// Spec note (Steve, 2026-05-22): the earlier keyword-based
|
|
@@ -33,9 +46,13 @@ export class WikiIngestService {
|
|
|
33
46
|
static instance = null;
|
|
34
47
|
logger;
|
|
35
48
|
schemaLoader;
|
|
36
|
-
|
|
49
|
+
index;
|
|
50
|
+
history;
|
|
51
|
+
constructor(schemaLoader, index, history) {
|
|
37
52
|
this.logger = LoggerService.getInstance().createComponentLogger('WikiIngest');
|
|
38
53
|
this.schemaLoader = schemaLoader ?? new SchemaLoaderService();
|
|
54
|
+
this.index = index ?? WikiIndexService.getInstance();
|
|
55
|
+
this.history = history ?? WikiHistoryService.getInstance();
|
|
39
56
|
}
|
|
40
57
|
static getInstance() {
|
|
41
58
|
if (!this.instance) {
|
|
@@ -70,7 +87,7 @@ export class WikiIngestService {
|
|
|
70
87
|
message: err.message,
|
|
71
88
|
};
|
|
72
89
|
}
|
|
73
|
-
const target = input.targetRelativePath ?? DEFAULT_LOG_RELATIVE_PATH;
|
|
90
|
+
const target = (input.targetRelativePath ?? DEFAULT_LOG_RELATIVE_PATH).replace(/\\/g, '/').replace(/^\/+/, '');
|
|
74
91
|
if (this.schemaLoader.isFrozenPath(schema, target)) {
|
|
75
92
|
return {
|
|
76
93
|
ok: false,
|
|
@@ -79,24 +96,145 @@ export class WikiIngestService {
|
|
|
79
96
|
frozenFolders: this.schemaLoader.getFrozenPaths(schema),
|
|
80
97
|
};
|
|
81
98
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
99
|
+
if (target.includes('..')) {
|
|
100
|
+
return { ok: false, reason: 'invalid_input', message: 'targetRelativePath may not contain ".."' };
|
|
101
|
+
}
|
|
102
|
+
// Confidentiality gate — applies to log entries and pages alike.
|
|
103
|
+
const gate = applyPrivacyGate(input.sourceBody, schema.privacy);
|
|
104
|
+
if (!gate.ok) {
|
|
105
|
+
this.logger.warn('WikiIngest refused by the confidentiality gate', { vault: input.vaultPath, target, reason: gate.reason, patterns: gate.patterns });
|
|
106
|
+
return { ok: false, reason: gate.reason, message: gate.message, details: gate.patterns };
|
|
107
|
+
}
|
|
108
|
+
const safeInput = { ...input, sourceBody: gate.body };
|
|
109
|
+
const isLogTarget = path.basename(target) === 'log.md';
|
|
110
|
+
if (isLogTarget) {
|
|
111
|
+
const absoluteTarget = path.join(input.vaultPath, target);
|
|
112
|
+
await fs.mkdir(path.dirname(absoluteTarget), { recursive: true });
|
|
113
|
+
const logEntry = this.formatLogEntry(safeInput);
|
|
114
|
+
await this.appendOrCreate(absoluteTarget, logEntry);
|
|
115
|
+
this.logger.info('WikiIngest wrote log entry', {
|
|
116
|
+
vault: input.vaultPath,
|
|
117
|
+
target,
|
|
118
|
+
sourceType: input.sourceType,
|
|
119
|
+
sourceRef: input.sourceRef,
|
|
120
|
+
bodyBytes: safeInput.sourceBody.length,
|
|
121
|
+
});
|
|
122
|
+
return { ok: true, pagesWritten: [target], logEntry, frozenPathsTouched: [], masked: gate.masked };
|
|
123
|
+
}
|
|
124
|
+
return this.writePage(schema, target, safeInput, gate.masked);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Write (create, append to, or replace) a knowledge page. See the module
|
|
128
|
+
* header for the gates it passes.
|
|
129
|
+
*
|
|
130
|
+
* @param schema - Vault schema
|
|
131
|
+
* @param target - Vault-relative page path (validated, not frozen)
|
|
132
|
+
* @param input - Ingest input with a body that already passed the privacy gate
|
|
133
|
+
* @param masked - PII pattern names masked in the body
|
|
134
|
+
* @returns Outcome
|
|
135
|
+
*/
|
|
136
|
+
async writePage(schema, target, input, masked) {
|
|
137
|
+
if (!target.startsWith('llm-curated/')) {
|
|
138
|
+
return { ok: false, reason: 'invalid_input', message: 'pages live under llm-curated/ (log entries go to llm-curated/log.md)' };
|
|
139
|
+
}
|
|
140
|
+
const existingAbs = path.join(input.vaultPath, target);
|
|
141
|
+
const existing = existsSync(existingAbs) ? parsePage(await fs.readFile(existingAbs, 'utf8')) : null;
|
|
142
|
+
// Retention gate: a page needs title + summary + keep_because. An
|
|
143
|
+
// append to an existing page that already has them inherits them.
|
|
144
|
+
const supplied = {
|
|
145
|
+
...(existing?.frontmatter ?? {}),
|
|
146
|
+
...(input.title ? { title: oneLine(input.title, WIKI_KB_CONSTANTS.TITLE_MAX_CHARS) } : {}),
|
|
147
|
+
...(input.summary ? { summary: oneLine(input.summary, WIKI_KB_CONSTANTS.SUMMARY_MAX_CHARS + 1) } : {}),
|
|
148
|
+
...(input.keepBecause ? { keep_because: input.keepBecause } : {}),
|
|
149
|
+
...(input.tags ? { tags: input.tags } : {}),
|
|
150
|
+
...(input.visibility ? { visibility: input.visibility } : {}),
|
|
151
|
+
};
|
|
152
|
+
if (!supplied.title && existing === null)
|
|
153
|
+
supplied.title = this.titleFromBody(input.sourceBody);
|
|
154
|
+
const refusal = checkRetention(supplied);
|
|
155
|
+
if (refusal) {
|
|
156
|
+
return { ok: false, reason: 'retention_gate', message: refusal.message, details: refusal.missing };
|
|
157
|
+
}
|
|
158
|
+
if (!schema.retention.keep_because.includes(String(supplied.keep_because))) {
|
|
159
|
+
return {
|
|
160
|
+
ok: false,
|
|
161
|
+
reason: 'retention_gate',
|
|
162
|
+
message: `This vault keeps pages only for: ${schema.retention.keep_because.join(' | ')}.`,
|
|
163
|
+
details: ['keep_because'],
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
// Write policy: proposed_only roles land in _proposed/.
|
|
167
|
+
const decision = decideWrite(schema, input.callerRole);
|
|
168
|
+
const proposed = decision === 'proposed';
|
|
169
|
+
const finalTarget = proposed && !target.startsWith(`${WIKI_KB_CONSTANTS.PROPOSED_DIR}/`)
|
|
170
|
+
? `${WIKI_KB_CONSTANTS.PROPOSED_DIR}/${target.replace(/^llm-curated\//, '')}`
|
|
171
|
+
: target;
|
|
172
|
+
const abs = path.join(input.vaultPath, finalTarget);
|
|
173
|
+
const prior = existsSync(abs) ? parsePage(await fs.readFile(abs, 'utf8')) : null;
|
|
174
|
+
const now = new Date().toISOString();
|
|
175
|
+
const author = input.callerSession ?? input.sourceRef;
|
|
176
|
+
const fm = {
|
|
177
|
+
...(prior?.frontmatter ?? {}),
|
|
178
|
+
...supplied,
|
|
179
|
+
source: oneLine(input.sourceRef, 200),
|
|
180
|
+
caller: oneLine(author, 80),
|
|
181
|
+
recorded: prior?.frontmatter.recorded ?? now,
|
|
182
|
+
updated: now,
|
|
183
|
+
...(proposed ? { proposed_by: oneLine(author, 80) } : {}),
|
|
184
|
+
};
|
|
185
|
+
if (!fm.visibility && schema.privacy.default_visibility.length > 0)
|
|
186
|
+
fm.visibility = schema.privacy.default_visibility;
|
|
187
|
+
const entry = this.formatPageEntry(input);
|
|
188
|
+
const body = prior && !input.replace
|
|
189
|
+
? `${prior.body.replace(/\s+$/, '')}\n${entry}`
|
|
190
|
+
: `# ${fm.title}\n${entry}`;
|
|
191
|
+
await this.history.snapshot(input.vaultPath, finalTarget, author, 'write');
|
|
192
|
+
await fs.mkdir(path.dirname(abs), { recursive: true });
|
|
193
|
+
await fs.writeFile(abs, serializePage(fm, body), 'utf8');
|
|
194
|
+
let indexUpdated = false;
|
|
195
|
+
if (!proposed) {
|
|
196
|
+
await this.index.upsert(input.vaultPath, finalTarget, fm);
|
|
197
|
+
indexUpdated = true;
|
|
198
|
+
}
|
|
199
|
+
this.logger.info(proposed ? 'WikiIngest wrote a proposed page' : 'WikiIngest wrote page', {
|
|
87
200
|
vault: input.vaultPath,
|
|
88
|
-
target,
|
|
201
|
+
target: finalTarget,
|
|
89
202
|
sourceType: input.sourceType,
|
|
90
|
-
|
|
91
|
-
|
|
203
|
+
keepBecause: fm.keep_because,
|
|
204
|
+
callerRole: input.callerRole ?? 'owner',
|
|
205
|
+
appended: !!prior && !input.replace,
|
|
92
206
|
});
|
|
93
207
|
return {
|
|
94
208
|
ok: true,
|
|
95
|
-
pagesWritten: [
|
|
96
|
-
logEntry,
|
|
209
|
+
pagesWritten: [finalTarget],
|
|
210
|
+
logEntry: entry,
|
|
97
211
|
frozenPathsTouched: [],
|
|
212
|
+
proposed,
|
|
213
|
+
masked,
|
|
214
|
+
indexUpdated,
|
|
98
215
|
};
|
|
99
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* The provenance block appended to a page for each ingest.
|
|
219
|
+
*
|
|
220
|
+
* @param input - Ingest input
|
|
221
|
+
* @returns Markdown block
|
|
222
|
+
*/
|
|
223
|
+
formatPageEntry(input) {
|
|
224
|
+
const ts = new Date().toISOString();
|
|
225
|
+
const caller = this.sanitizeOneLine(input.callerSession ?? input.sourceRef, 80);
|
|
226
|
+
return [
|
|
227
|
+
'',
|
|
228
|
+
this.sanitizeBody(input.sourceBody),
|
|
229
|
+
'',
|
|
230
|
+
`<sub>${input.sourceType} · ${this.sanitizeOneLine(input.sourceRef, 200)} · ${caller} · ${ts}</sub>`,
|
|
231
|
+
'',
|
|
232
|
+
].join('\n');
|
|
233
|
+
}
|
|
234
|
+
titleFromBody(body) {
|
|
235
|
+
const heading = body.match(/^#\s+(.+)$/m);
|
|
236
|
+
return oneLine(heading ? heading[1] : body, WIKI_KB_CONSTANTS.TITLE_MAX_CHARS);
|
|
237
|
+
}
|
|
100
238
|
// ---------------------------------------------------------------------------
|
|
101
239
|
// Internals
|
|
102
240
|
// ---------------------------------------------------------------------------
|
|
@@ -156,41 +294,21 @@ export class WikiIngestService {
|
|
|
156
294
|
'',
|
|
157
295
|
].join('\n');
|
|
158
296
|
}
|
|
159
|
-
async appendOrCreate(absolutePath, entry
|
|
297
|
+
async appendOrCreate(absolutePath, entry) {
|
|
160
298
|
if (!existsSync(absolutePath)) {
|
|
161
|
-
const header = this.buildPageHeader(
|
|
299
|
+
const header = this.buildPageHeader();
|
|
162
300
|
await fs.writeFile(absolutePath, header + entry, 'utf8');
|
|
163
301
|
return;
|
|
164
302
|
}
|
|
165
303
|
await fs.appendFile(absolutePath, entry, 'utf8');
|
|
166
304
|
}
|
|
167
305
|
/**
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* - anything else → minimal title block from the source ref
|
|
306
|
+
* Header for a freshly-created `log.md` (pages are built by {@link writePage}).
|
|
307
|
+
*
|
|
308
|
+
* @returns The activity-log preamble
|
|
172
309
|
*/
|
|
173
|
-
buildPageHeader(
|
|
174
|
-
|
|
175
|
-
if (basename === 'log.md') {
|
|
176
|
-
return '# Activity log\n\nAppend-only log of ingested sources. Each entry: `## [<ISO>] <sourceType> | <caller>`.\n';
|
|
177
|
-
}
|
|
178
|
-
if (absolutePath.includes('/decisions/')) {
|
|
179
|
-
const title = this.sanitizeOneLine(input.sourceBody, 80);
|
|
180
|
-
const caller = input.callerSession ?? input.sourceRef;
|
|
181
|
-
return [
|
|
182
|
-
`# ${title}`,
|
|
183
|
-
'',
|
|
184
|
-
`> **source:** \`${this.sanitizeOneLine(input.sourceRef, 200)}\` `,
|
|
185
|
-
`> **caller:** \`${this.sanitizeOneLine(caller, 80)}\` `,
|
|
186
|
-
`> **recorded:** ${new Date().toISOString()}`,
|
|
187
|
-
'',
|
|
188
|
-
'---',
|
|
189
|
-
'',
|
|
190
|
-
].join('\n');
|
|
191
|
-
}
|
|
192
|
-
// Generic non-log target: minimal title block.
|
|
193
|
-
return `# ${this.sanitizeOneLine(input.sourceRef, 80)}\n\n`;
|
|
310
|
+
buildPageHeader() {
|
|
311
|
+
return '# Activity log\n\nAppend-only log of ingested sources. Each entry: `## [<ISO>] <sourceType> | <caller>`.\n';
|
|
194
312
|
}
|
|
195
313
|
/**
|
|
196
314
|
* Defuse markers a future skill might mis-route on: `[CHAT]`, `[NOTIFY]`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wiki-ingest.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-ingest.service.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"wiki-ingest.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-ingest.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The page contract of the LLM-wiki.
|
|
3
|
+
*
|
|
4
|
+
* A vault page is markdown with YAML frontmatter. Two fields make a page a
|
|
5
|
+
* piece of knowledge rather than a bookmark: `summary` (the one-line
|
|
6
|
+
* conclusion — what this means for us) and `keep_because` (the reason it
|
|
7
|
+
* earns a place at all). Without them a write goes to `log.md`, not to a
|
|
8
|
+
* page. This module parses/serialises that shape and applies the gate;
|
|
9
|
+
* everything else (index, history, supersede) builds on it.
|
|
10
|
+
*
|
|
11
|
+
* @module services/wiki/wiki-page
|
|
12
|
+
*/
|
|
13
|
+
import { type WikiKeepBecause } from '../../constants.js';
|
|
14
|
+
/** Frontmatter every page carries (agents set the first block; the system fills the rest). */
|
|
15
|
+
export interface WikiPageFrontmatter {
|
|
16
|
+
title: string;
|
|
17
|
+
/** One-line conclusion: what this page means for the team/project. */
|
|
18
|
+
summary: string;
|
|
19
|
+
keep_because: WikiKeepBecause;
|
|
20
|
+
tags?: string[];
|
|
21
|
+
/** Roles allowed to read the page; empty/absent = everyone in the vault's instance. */
|
|
22
|
+
visibility?: string[];
|
|
23
|
+
source?: string;
|
|
24
|
+
caller?: string;
|
|
25
|
+
recorded?: string;
|
|
26
|
+
updated?: string;
|
|
27
|
+
superseded_by?: string;
|
|
28
|
+
superseded_at?: string;
|
|
29
|
+
superseded_reason?: string;
|
|
30
|
+
proposed_by?: string;
|
|
31
|
+
/** Anything else on the page (migrated fields such as `confidence`, `migrated_from`). */
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
}
|
|
34
|
+
/** A parsed page. */
|
|
35
|
+
export interface WikiPage {
|
|
36
|
+
frontmatter: Partial<WikiPageFrontmatter>;
|
|
37
|
+
body: string;
|
|
38
|
+
/** True when the file had a `---` block at all. */
|
|
39
|
+
hadFrontmatter: boolean;
|
|
40
|
+
}
|
|
41
|
+
/** Why a page write was refused by the retention gate. */
|
|
42
|
+
export interface RetentionRefusal {
|
|
43
|
+
reason: 'retention_gate';
|
|
44
|
+
missing: string[];
|
|
45
|
+
message: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Split a page into frontmatter + body. Tolerant: a page without a block
|
|
49
|
+
* parses as `{ frontmatter: {}, body: raw }`; a malformed block is left in
|
|
50
|
+
* the body untouched.
|
|
51
|
+
*
|
|
52
|
+
* @param raw - File content
|
|
53
|
+
* @returns The parsed page
|
|
54
|
+
*/
|
|
55
|
+
export declare function parsePage(raw: string): WikiPage;
|
|
56
|
+
/**
|
|
57
|
+
* Serialise frontmatter + body back into a file. Keys are written in the
|
|
58
|
+
* canonical order of {@link WIKI_KB_CONSTANTS.FRONTMATTER_KEYS} first, then
|
|
59
|
+
* any extra keys, so diffs stay readable.
|
|
60
|
+
*
|
|
61
|
+
* @param frontmatter - Fields to write (undefined values are dropped)
|
|
62
|
+
* @param body - Markdown body
|
|
63
|
+
* @returns File content
|
|
64
|
+
*/
|
|
65
|
+
export declare function serializePage(frontmatter: Partial<WikiPageFrontmatter>, body: string): string;
|
|
66
|
+
/**
|
|
67
|
+
* Apply the retention gate to a page write: `title`, a non-empty `summary`
|
|
68
|
+
* and a valid `keep_because` are required. Returns null when the page
|
|
69
|
+
* passes.
|
|
70
|
+
*
|
|
71
|
+
* @param fm - Frontmatter the writer supplied
|
|
72
|
+
* @returns A refusal describing what is missing, or null
|
|
73
|
+
*/
|
|
74
|
+
export declare function checkRetention(fm: Partial<WikiPageFrontmatter>): RetentionRefusal | null;
|
|
75
|
+
/**
|
|
76
|
+
* The single index line for a page: `- [title](path) — summary`, with a
|
|
77
|
+
* `⟶ superseded by <path>` marker when applicable.
|
|
78
|
+
*
|
|
79
|
+
* @param relativePath - Vault-relative page path
|
|
80
|
+
* @param fm - The page's frontmatter
|
|
81
|
+
* @returns One markdown list line
|
|
82
|
+
*/
|
|
83
|
+
export declare function indexLineFor(relativePath: string, fm: Partial<WikiPageFrontmatter>): string;
|
|
84
|
+
/**
|
|
85
|
+
* Whether a viewer role may read a page. No `visibility` list = public
|
|
86
|
+
* within the instance; a canonical role (owner/orchestrator) always may.
|
|
87
|
+
*
|
|
88
|
+
* @param fm - Page frontmatter
|
|
89
|
+
* @param viewerRole - Role of the reader, or undefined for the owner/UI
|
|
90
|
+
* @returns True when readable
|
|
91
|
+
*/
|
|
92
|
+
export declare function isVisibleTo(fm: Partial<WikiPageFrontmatter>, viewerRole?: string): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Collapse whitespace and cut to a maximum length (with an ellipsis).
|
|
95
|
+
*
|
|
96
|
+
* @param value - Text
|
|
97
|
+
* @param max - Maximum characters
|
|
98
|
+
* @returns One line
|
|
99
|
+
*/
|
|
100
|
+
export declare function oneLine(value: string, max: number): string;
|
|
101
|
+
//# sourceMappingURL=wiki-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki-page.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE7E,8FAA8F;AAC9F,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,eAAe,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,uFAAuF;IACvF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yFAAyF;IACzF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qBAAqB;AACrB,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAW/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAU7F;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAiBxF;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,MAAM,CAK3F;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAM1F;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG1D"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The page contract of the LLM-wiki.
|
|
3
|
+
*
|
|
4
|
+
* A vault page is markdown with YAML frontmatter. Two fields make a page a
|
|
5
|
+
* piece of knowledge rather than a bookmark: `summary` (the one-line
|
|
6
|
+
* conclusion — what this means for us) and `keep_because` (the reason it
|
|
7
|
+
* earns a place at all). Without them a write goes to `log.md`, not to a
|
|
8
|
+
* page. This module parses/serialises that shape and applies the gate;
|
|
9
|
+
* everything else (index, history, supersede) builds on it.
|
|
10
|
+
*
|
|
11
|
+
* @module services/wiki/wiki-page
|
|
12
|
+
*/
|
|
13
|
+
import { parse as parseYAML, stringify as stringifyYAML } from 'yaml';
|
|
14
|
+
import { WIKI_KB_CONSTANTS } from '../../constants.js';
|
|
15
|
+
/**
|
|
16
|
+
* Split a page into frontmatter + body. Tolerant: a page without a block
|
|
17
|
+
* parses as `{ frontmatter: {}, body: raw }`; a malformed block is left in
|
|
18
|
+
* the body untouched.
|
|
19
|
+
*
|
|
20
|
+
* @param raw - File content
|
|
21
|
+
* @returns The parsed page
|
|
22
|
+
*/
|
|
23
|
+
export function parsePage(raw) {
|
|
24
|
+
const normalized = raw.replace(/\r\n/g, '\n');
|
|
25
|
+
const m = normalized.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
26
|
+
if (!m)
|
|
27
|
+
return { frontmatter: {}, body: normalized, hadFrontmatter: false };
|
|
28
|
+
try {
|
|
29
|
+
const parsed = parseYAML(m[1]);
|
|
30
|
+
const fm = parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};
|
|
31
|
+
return { frontmatter: fm, body: m[2], hadFrontmatter: true };
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { frontmatter: {}, body: normalized, hadFrontmatter: false };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Serialise frontmatter + body back into a file. Keys are written in the
|
|
39
|
+
* canonical order of {@link WIKI_KB_CONSTANTS.FRONTMATTER_KEYS} first, then
|
|
40
|
+
* any extra keys, so diffs stay readable.
|
|
41
|
+
*
|
|
42
|
+
* @param frontmatter - Fields to write (undefined values are dropped)
|
|
43
|
+
* @param body - Markdown body
|
|
44
|
+
* @returns File content
|
|
45
|
+
*/
|
|
46
|
+
export function serializePage(frontmatter, body) {
|
|
47
|
+
const ordered = {};
|
|
48
|
+
for (const key of WIKI_KB_CONSTANTS.FRONTMATTER_KEYS) {
|
|
49
|
+
if (frontmatter[key] !== undefined)
|
|
50
|
+
ordered[key] = frontmatter[key];
|
|
51
|
+
}
|
|
52
|
+
for (const [key, value] of Object.entries(frontmatter)) {
|
|
53
|
+
if (!(key in ordered) && value !== undefined)
|
|
54
|
+
ordered[key] = value;
|
|
55
|
+
}
|
|
56
|
+
const yaml = stringifyYAML(ordered).trimEnd();
|
|
57
|
+
return `---\n${yaml}\n---\n${body.replace(/^\n+/, '')}`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Apply the retention gate to a page write: `title`, a non-empty `summary`
|
|
61
|
+
* and a valid `keep_because` are required. Returns null when the page
|
|
62
|
+
* passes.
|
|
63
|
+
*
|
|
64
|
+
* @param fm - Frontmatter the writer supplied
|
|
65
|
+
* @returns A refusal describing what is missing, or null
|
|
66
|
+
*/
|
|
67
|
+
export function checkRetention(fm) {
|
|
68
|
+
const missing = [];
|
|
69
|
+
if (!fm.title || !String(fm.title).trim())
|
|
70
|
+
missing.push('title');
|
|
71
|
+
const summary = typeof fm.summary === 'string' ? fm.summary.trim() : '';
|
|
72
|
+
if (!summary)
|
|
73
|
+
missing.push('summary');
|
|
74
|
+
else if (summary.length > WIKI_KB_CONSTANTS.SUMMARY_MAX_CHARS)
|
|
75
|
+
missing.push(`summary (≤ ${WIKI_KB_CONSTANTS.SUMMARY_MAX_CHARS} chars)`);
|
|
76
|
+
if (!fm.keep_because || !WIKI_KB_CONSTANTS.KEEP_BECAUSE.includes(String(fm.keep_because))) {
|
|
77
|
+
missing.push(`keep_because (one of ${WIKI_KB_CONSTANTS.KEEP_BECAUSE.join(' | ')})`);
|
|
78
|
+
}
|
|
79
|
+
if (missing.length === 0)
|
|
80
|
+
return null;
|
|
81
|
+
return {
|
|
82
|
+
reason: 'retention_gate',
|
|
83
|
+
missing,
|
|
84
|
+
message: `A page needs ${missing.join(', ')}. Default is to NOT keep: write a page only when it changes a decision, ` +
|
|
85
|
+
`contradicts what we believed, is a citable hard fact, or a reusable method — otherwise append to llm-curated/log.md.`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The single index line for a page: `- [title](path) — summary`, with a
|
|
90
|
+
* `⟶ superseded by <path>` marker when applicable.
|
|
91
|
+
*
|
|
92
|
+
* @param relativePath - Vault-relative page path
|
|
93
|
+
* @param fm - The page's frontmatter
|
|
94
|
+
* @returns One markdown list line
|
|
95
|
+
*/
|
|
96
|
+
export function indexLineFor(relativePath, fm) {
|
|
97
|
+
const title = oneLine(String(fm.title ?? relativePath.split('/').pop() ?? relativePath), WIKI_KB_CONSTANTS.TITLE_MAX_CHARS);
|
|
98
|
+
const summary = oneLine(String(fm.summary ?? ''), WIKI_KB_CONSTANTS.SUMMARY_MAX_CHARS);
|
|
99
|
+
const superseded = fm.superseded_by ? ` ⟶ superseded by ${fm.superseded_by}` : '';
|
|
100
|
+
return `- [${title}](${relativePath})${summary ? ` — ${summary}` : ''}${superseded}`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Whether a viewer role may read a page. No `visibility` list = public
|
|
104
|
+
* within the instance; a canonical role (owner/orchestrator) always may.
|
|
105
|
+
*
|
|
106
|
+
* @param fm - Page frontmatter
|
|
107
|
+
* @param viewerRole - Role of the reader, or undefined for the owner/UI
|
|
108
|
+
* @returns True when readable
|
|
109
|
+
*/
|
|
110
|
+
export function isVisibleTo(fm, viewerRole) {
|
|
111
|
+
const list = Array.isArray(fm.visibility) ? fm.visibility.map((v) => String(v).toLowerCase()) : [];
|
|
112
|
+
if (list.length === 0)
|
|
113
|
+
return true;
|
|
114
|
+
if (!viewerRole)
|
|
115
|
+
return true;
|
|
116
|
+
const role = viewerRole.toLowerCase();
|
|
117
|
+
return role === 'orchestrator' || role === 'owner' || list.includes(role);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Collapse whitespace and cut to a maximum length (with an ellipsis).
|
|
121
|
+
*
|
|
122
|
+
* @param value - Text
|
|
123
|
+
* @param max - Maximum characters
|
|
124
|
+
* @returns One line
|
|
125
|
+
*/
|
|
126
|
+
export function oneLine(value, max) {
|
|
127
|
+
const flat = value.replace(/\\n/g, ' ').replace(/\s+/g, ' ').trim();
|
|
128
|
+
return flat.length <= max ? flat : `${flat.slice(0, max - 1)}…`;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=wiki-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki-page.js","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-page.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write-policy decisions for a vault (SCHEMA.md `write_policy`).
|
|
3
|
+
*
|
|
4
|
+
* Who wrote is resolved by the server from the `X-Agent-Session` header
|
|
5
|
+
* (session → team member → role), never from a role the caller claims.
|
|
6
|
+
* The owner (dashboard, no session) and the orchestrator are canonical.
|
|
7
|
+
*
|
|
8
|
+
* @module services/wiki/wiki-policy
|
|
9
|
+
*/
|
|
10
|
+
import type { VaultSchema } from './wiki.types.js';
|
|
11
|
+
/** What a write by a given role becomes. */
|
|
12
|
+
export type WriteDecision = 'canonical' | 'proposed';
|
|
13
|
+
/**
|
|
14
|
+
* Decide whether a writer's page lands directly or as a proposal.
|
|
15
|
+
*
|
|
16
|
+
* Rules, in order: no role (owner/UI) → canonical; role listed in
|
|
17
|
+
* `canonical` → canonical; role listed in `proposed_only` → proposed;
|
|
18
|
+
* `worker` in `proposed_only` covers every role not listed elsewhere;
|
|
19
|
+
* an unlisted role with no `worker` catch-all → proposed (safe default).
|
|
20
|
+
*
|
|
21
|
+
* @param schema - Vault schema
|
|
22
|
+
* @param role - Writer's role (lower-cased inside), or undefined for the owner
|
|
23
|
+
* @returns The decision
|
|
24
|
+
*/
|
|
25
|
+
export declare function decideWrite(schema: Pick<VaultSchema, 'write_policy'>, role: string | undefined): WriteDecision;
|
|
26
|
+
/**
|
|
27
|
+
* Whether a role may accept/reject proposals or supersede pages (a
|
|
28
|
+
* canonical role).
|
|
29
|
+
*
|
|
30
|
+
* @param schema - Vault schema
|
|
31
|
+
* @param role - Role, or undefined for the owner
|
|
32
|
+
* @returns True when allowed
|
|
33
|
+
*/
|
|
34
|
+
export declare function canReview(schema: Pick<VaultSchema, 'write_policy'>, role: string | undefined): boolean;
|
|
35
|
+
//# sourceMappingURL=wiki-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki-policy.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,4CAA4C;AAC5C,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,UAAU,CAAC;AAErD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAO9G;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEtG"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write-policy decisions for a vault (SCHEMA.md `write_policy`).
|
|
3
|
+
*
|
|
4
|
+
* Who wrote is resolved by the server from the `X-Agent-Session` header
|
|
5
|
+
* (session → team member → role), never from a role the caller claims.
|
|
6
|
+
* The owner (dashboard, no session) and the orchestrator are canonical.
|
|
7
|
+
*
|
|
8
|
+
* @module services/wiki/wiki-policy
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Decide whether a writer's page lands directly or as a proposal.
|
|
12
|
+
*
|
|
13
|
+
* Rules, in order: no role (owner/UI) → canonical; role listed in
|
|
14
|
+
* `canonical` → canonical; role listed in `proposed_only` → proposed;
|
|
15
|
+
* `worker` in `proposed_only` covers every role not listed elsewhere;
|
|
16
|
+
* an unlisted role with no `worker` catch-all → proposed (safe default).
|
|
17
|
+
*
|
|
18
|
+
* @param schema - Vault schema
|
|
19
|
+
* @param role - Writer's role (lower-cased inside), or undefined for the owner
|
|
20
|
+
* @returns The decision
|
|
21
|
+
*/
|
|
22
|
+
export function decideWrite(schema, role) {
|
|
23
|
+
if (!role)
|
|
24
|
+
return 'canonical';
|
|
25
|
+
const r = role.toLowerCase();
|
|
26
|
+
if (r === 'orchestrator' || r === 'owner')
|
|
27
|
+
return 'canonical';
|
|
28
|
+
const canonical = schema.write_policy.canonical.map((x) => x.toLowerCase());
|
|
29
|
+
if (canonical.includes(r))
|
|
30
|
+
return 'canonical';
|
|
31
|
+
return 'proposed';
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether a role may accept/reject proposals or supersede pages (a
|
|
35
|
+
* canonical role).
|
|
36
|
+
*
|
|
37
|
+
* @param schema - Vault schema
|
|
38
|
+
* @param role - Role, or undefined for the owner
|
|
39
|
+
* @returns True when allowed
|
|
40
|
+
*/
|
|
41
|
+
export function canReview(schema, role) {
|
|
42
|
+
return decideWrite(schema, role) === 'canonical';
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=wiki-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki-policy.js","sourceRoot":"","sources":["../../../../../../backend/src/services/wiki/wiki-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAC,MAAyC,EAAE,IAAwB;IAC7F,IAAI,CAAC,IAAI;QAAE,OAAO,WAAW,CAAC;IAC9B,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,IAAI,CAAC,KAAK,cAAc,IAAI,CAAC,KAAK,OAAO;QAAE,OAAO,WAAW,CAAC;IAC9D,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5E,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC;IAC9C,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,MAAyC,EAAE,IAAwB;IAC3F,OAAO,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,WAAW,CAAC;AACnD,CAAC"}
|