@phyzess/pappra 0.0.0-stage → 0.1.0-beta.2
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/LICENSE +21 -0
- package/README.md +80 -2
- package/THIRD_PARTY_NOTICES.md +16 -0
- package/assets/integrations/skills/pappra/SKILL.md +68 -0
- package/assets/integrations/skills/pappra/references/hosts.md +30 -0
- package/assets/integrations/skills/pappra/references/lifecycle.md +37 -0
- package/assets/integrations/skills/pappra/references/operations.md +14 -0
- package/assets/manifest.json +4 -0
- package/dist/app/collaboration.d.ts +170 -0
- package/dist/app/collaboration.js +1650 -0
- package/dist/app/doctor.d.ts +9 -0
- package/dist/app/doctor.js +1030 -0
- package/dist/app/init.d.ts +143 -0
- package/dist/app/init.js +1111 -0
- package/dist/cli/commands/code.d.ts +16 -0
- package/dist/cli/commands/code.js +127 -0
- package/dist/cli/commands/collaboration.d.ts +13 -0
- package/dist/cli/commands/collaboration.js +186 -0
- package/dist/cli/commands/continuity.d.ts +29 -0
- package/dist/cli/commands/continuity.js +133 -0
- package/dist/cli/commands/docs.d.ts +11 -0
- package/dist/cli/commands/docs.js +133 -0
- package/dist/cli/commands/doctor.d.ts +14 -0
- package/dist/cli/commands/doctor.js +57 -0
- package/dist/cli/commands/host.d.ts +13 -0
- package/dist/cli/commands/host.js +125 -0
- package/dist/cli/commands/init.d.ts +51 -0
- package/dist/cli/commands/init.js +668 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +10 -0
- package/dist/cli/output.d.ts +4 -0
- package/dist/cli/output.js +1 -0
- package/dist/cli/run.d.ts +2 -0
- package/dist/cli/run.js +597 -0
- package/dist/code/budget.d.ts +14 -0
- package/dist/code/budget.js +39 -0
- package/dist/code/exec.d.ts +23 -0
- package/dist/code/exec.js +133 -0
- package/dist/code/identity.d.ts +13 -0
- package/dist/code/identity.js +214 -0
- package/dist/code/index.d.ts +6 -0
- package/dist/code/index.js +3 -0
- package/dist/code/providers/codegraph.d.ts +59 -0
- package/dist/code/providers/codegraph.js +567 -0
- package/dist/code/registration.d.ts +9 -0
- package/dist/code/registration.js +293 -0
- package/dist/code/service.d.ts +53 -0
- package/dist/code/service.js +633 -0
- package/dist/code/text.d.ts +3 -0
- package/dist/code/text.js +202 -0
- package/dist/collab/admission.d.ts +450 -0
- package/dist/collab/admission.js +797 -0
- package/dist/collab/canonical.d.ts +26 -0
- package/dist/collab/canonical.js +136 -0
- package/dist/collab/contracts.d.ts +73 -0
- package/dist/collab/contracts.js +76 -0
- package/dist/collab/envelope.d.ts +52 -0
- package/dist/collab/envelope.js +241 -0
- package/dist/collab/fingerprint.d.ts +7 -0
- package/dist/collab/fingerprint.js +58 -0
- package/dist/collab/handoff.d.ts +350 -0
- package/dist/collab/handoff.js +513 -0
- package/dist/collab/index.d.ts +9 -0
- package/dist/collab/index.js +8 -0
- package/dist/collab/lifecycle.d.ts +449 -0
- package/dist/collab/lifecycle.js +534 -0
- package/dist/collab/messages.d.ts +148 -0
- package/dist/collab/messages.js +583 -0
- package/dist/collab/notify.d.ts +47 -0
- package/dist/collab/notify.js +140 -0
- package/dist/collab/preflight.d.ts +31 -0
- package/dist/collab/preflight.js +271 -0
- package/dist/collab/resources.d.ts +119 -0
- package/dist/collab/resources.js +451 -0
- package/dist/collab/store.d.ts +143 -0
- package/dist/collab/store.js +606 -0
- package/dist/collab/types.d.ts +354 -0
- package/dist/collab/types.js +1 -0
- package/dist/collab/validation.d.ts +10 -0
- package/dist/collab/validation.js +303 -0
- package/dist/continuity/context.d.ts +24 -0
- package/dist/continuity/context.js +179 -0
- package/dist/continuity/index.d.ts +3 -0
- package/dist/continuity/index.js +1 -0
- package/dist/continuity/paths.d.ts +37 -0
- package/dist/continuity/paths.js +258 -0
- package/dist/continuity/service.d.ts +59 -0
- package/dist/continuity/service.js +1258 -0
- package/dist/hosts/claude/native.d.ts +79 -0
- package/dist/hosts/claude/native.js +853 -0
- package/dist/hosts/codex/native.d.ts +345 -0
- package/dist/hosts/codex/native.js +1528 -0
- package/dist/hosts/codex/protocol.d.ts +51 -0
- package/dist/hosts/codex/protocol.js +42 -0
- package/dist/hosts/detect.d.ts +28 -0
- package/dist/hosts/detect.js +73 -0
- package/dist/hosts/index.d.ts +10 -0
- package/dist/hosts/index.js +10 -0
- package/dist/hosts/integration/bundle.d.ts +16 -0
- package/dist/hosts/integration/bundle.js +81 -0
- package/dist/hosts/integration/hook-entry.d.ts +1 -0
- package/dist/hosts/integration/hook-entry.js +68 -0
- package/dist/hosts/integration/hook.d.ts +32 -0
- package/dist/hosts/integration/hook.js +781 -0
- package/dist/hosts/integration/pi-extension-runtime.d.ts +18 -0
- package/dist/hosts/integration/pi-extension-runtime.js +89 -0
- package/dist/hosts/integration/pi-template.d.ts +3 -0
- package/dist/hosts/integration/pi-template.js +5 -0
- package/dist/hosts/integration/service.d.ts +41 -0
- package/dist/hosts/integration/service.js +1381 -0
- package/dist/hosts/integration/support.d.ts +36 -0
- package/dist/hosts/integration/support.js +41 -0
- package/dist/hosts/integration/templates.d.ts +22 -0
- package/dist/hosts/integration/templates.js +70 -0
- package/dist/hosts/pi/protocol.d.ts +22 -0
- package/dist/hosts/pi/protocol.js +28 -0
- package/dist/hosts/pi/query-result.d.ts +22 -0
- package/dist/hosts/pi/query-result.js +710 -0
- package/dist/hosts/pi/rpc.d.ts +937 -0
- package/dist/hosts/pi/rpc.js +1621 -0
- package/dist/hosts/pilot.d.ts +485 -0
- package/dist/hosts/pilot.js +593 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/infra/fs.d.ts +27 -0
- package/dist/infra/fs.js +130 -0
- package/dist/infra/git.d.ts +60 -0
- package/dist/infra/git.js +358 -0
- package/dist/infra/owned-process-group.d.ts +173 -0
- package/dist/infra/owned-process-group.js +571 -0
- package/dist/install/apply.d.ts +65 -0
- package/dist/install/apply.js +663 -0
- package/dist/install/index.d.ts +5 -0
- package/dist/install/index.js +5 -0
- package/dist/install/ownership.d.ts +85 -0
- package/dist/install/ownership.js +430 -0
- package/dist/install/plan.d.ts +39 -0
- package/dist/install/plan.js +97 -0
- package/dist/install/rollback.d.ts +18 -0
- package/dist/install/rollback.js +544 -0
- package/dist/install/runtime.d.ts +76 -0
- package/dist/install/runtime.js +1145 -0
- package/dist/knowledge/catalog.d.ts +47 -0
- package/dist/knowledge/catalog.js +308 -0
- package/dist/knowledge/context.d.ts +28 -0
- package/dist/knowledge/context.js +61 -0
- package/dist/knowledge/index.d.ts +3 -0
- package/dist/knowledge/index.js +1 -0
- package/dist/knowledge/journal.d.ts +16 -0
- package/dist/knowledge/journal.js +109 -0
- package/dist/knowledge/lifecycle.d.ts +8 -0
- package/dist/knowledge/lifecycle.js +1001 -0
- package/dist/knowledge/paths.d.ts +37 -0
- package/dist/knowledge/paths.js +236 -0
- package/dist/knowledge/refs.d.ts +36 -0
- package/dist/knowledge/refs.js +267 -0
- package/dist/knowledge/service.d.ts +21 -0
- package/dist/knowledge/service.js +393 -0
- package/dist/knowledge/types.d.ts +171 -0
- package/dist/knowledge/types.js +1 -0
- package/dist/knowledge/write.d.ts +8 -0
- package/dist/knowledge/write.js +1223 -0
- package/dist/package-info.d.ts +6 -0
- package/dist/package-info.js +19 -0
- package/dist/schemas/code.d.ts +377 -0
- package/dist/schemas/code.js +145 -0
- package/dist/schemas/collaboration.d.ts +115 -0
- package/dist/schemas/collaboration.js +106 -0
- package/dist/schemas/continuity.d.ts +315 -0
- package/dist/schemas/continuity.js +199 -0
- package/dist/schemas/diagnostics.d.ts +28 -0
- package/dist/schemas/diagnostics.js +27 -0
- package/dist/schemas/doctor.d.ts +157 -0
- package/dist/schemas/doctor.js +75 -0
- package/dist/schemas/document.d.ts +644 -0
- package/dist/schemas/document.js +296 -0
- package/dist/schemas/errors.d.ts +177 -0
- package/dist/schemas/errors.js +176 -0
- package/dist/schemas/evidence.d.ts +24 -0
- package/dist/schemas/evidence.js +16 -0
- package/dist/schemas/host.d.ts +436 -0
- package/dist/schemas/host.js +201 -0
- package/dist/schemas/index.d.ts +15 -0
- package/dist/schemas/index.js +15 -0
- package/dist/schemas/init.d.ts +121 -0
- package/dist/schemas/init.js +94 -0
- package/dist/schemas/install.d.ts +213 -0
- package/dist/schemas/install.js +139 -0
- package/dist/schemas/machine.d.ts +43 -0
- package/dist/schemas/machine.js +96 -0
- package/dist/schemas/outcome.d.ts +23 -0
- package/dist/schemas/outcome.js +17 -0
- package/dist/schemas/paths.d.ts +19 -0
- package/dist/schemas/paths.js +63 -0
- package/dist/schemas/workspace.d.ts +120 -0
- package/dist/schemas/workspace.js +201 -0
- package/dist/workspace/config-file.d.ts +36 -0
- package/dist/workspace/config-file.js +237 -0
- package/dist/workspace/config.d.ts +28 -0
- package/dist/workspace/config.js +79 -0
- package/dist/workspace/discover.d.ts +34 -0
- package/dist/workspace/discover.js +195 -0
- package/dist/workspace/documents.d.ts +21 -0
- package/dist/workspace/documents.js +395 -0
- package/dist/workspace/ignore.d.ts +10 -0
- package/dist/workspace/ignore.js +48 -0
- package/dist/workspace/index.d.ts +7 -0
- package/dist/workspace/index.js +3 -0
- package/dist/workspace/repositories.d.ts +24 -0
- package/dist/workspace/repositories.js +411 -0
- package/dist/workspace/resolve.d.ts +24 -0
- package/dist/workspace/resolve.js +268 -0
- package/dist/workspace/types.d.ts +71 -0
- package/dist/workspace/types.js +1 -0
- package/dist/workspace/validation.d.ts +18 -0
- package/dist/workspace/validation.js +197 -0
- package/package.json +105 -4
- package/skills/pappra/SKILL.md +68 -0
- package/skills/pappra/references/hosts.md +30 -0
- package/skills/pappra/references/lifecycle.md +37 -0
- package/skills/pappra/references/operations.md +14 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Diagnostic } from '../schemas/diagnostics.js';
|
|
2
|
+
import { type DocumentCatalog, type DocumentLocation, type DocumentRecord } from '../schemas/document.js';
|
|
3
|
+
import { type Outcome } from '../schemas/outcome.js';
|
|
4
|
+
import type { KnowledgeContext } from './context.js';
|
|
5
|
+
import { type KnowledgePaths } from './paths.js';
|
|
6
|
+
export declare const DEFAULT_CATALOG_MAX_BYTES: number;
|
|
7
|
+
export type CatalogScope = 'shared' | 'private';
|
|
8
|
+
export interface CatalogFileState {
|
|
9
|
+
readonly scope: CatalogScope;
|
|
10
|
+
readonly path: string;
|
|
11
|
+
readonly exists: boolean;
|
|
12
|
+
readonly digest: string | null;
|
|
13
|
+
readonly catalog: DocumentCatalog | null;
|
|
14
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
15
|
+
readonly valid: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface KnowledgeCatalogs {
|
|
18
|
+
readonly paths: KnowledgePaths;
|
|
19
|
+
readonly shared: CatalogFileState;
|
|
20
|
+
readonly private: CatalogFileState;
|
|
21
|
+
readonly records: ReadonlyMap<string, DocumentRecord>;
|
|
22
|
+
readonly idConflicts: ReadonlySet<string>;
|
|
23
|
+
readonly locationConflicts: ReadonlySet<string>;
|
|
24
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
25
|
+
readonly catalogDigest: string;
|
|
26
|
+
readonly ok: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare function emptyCatalog(context: KnowledgeContext, updatedAt?: string): DocumentCatalog;
|
|
29
|
+
export declare function catalogDigestFor(catalogs: KnowledgeCatalogs, scope: CatalogScope): string | null;
|
|
30
|
+
export declare function catalogScopeFor(record: DocumentRecord): CatalogScope;
|
|
31
|
+
export declare function locationKey(location: DocumentLocation): string;
|
|
32
|
+
export declare function loadKnowledgeCatalogs(context: KnowledgeContext): Promise<KnowledgeCatalogs>;
|
|
33
|
+
export declare function recordScope(catalogs: KnowledgeCatalogs, record: DocumentRecord): CatalogScope;
|
|
34
|
+
export declare function catalogFor(catalogs: KnowledgeCatalogs, scope: CatalogScope, context: KnowledgeContext): DocumentCatalog;
|
|
35
|
+
export declare function recordsForCatalog(catalog: DocumentCatalog, documentId: string, next: DocumentRecord | null): DocumentRecord[];
|
|
36
|
+
export declare function setCatalogRecord(context: KnowledgeContext, catalogs: KnowledgeCatalogs, record: DocumentRecord): {
|
|
37
|
+
readonly scope: CatalogScope;
|
|
38
|
+
readonly catalog: DocumentCatalog;
|
|
39
|
+
};
|
|
40
|
+
export declare function removeCatalogRecord(context: KnowledgeContext, catalogs: KnowledgeCatalogs, record: DocumentRecord): {
|
|
41
|
+
readonly scope: CatalogScope;
|
|
42
|
+
readonly catalog: DocumentCatalog;
|
|
43
|
+
};
|
|
44
|
+
export declare function writeCatalogFile(context: KnowledgeContext, scope: CatalogScope, catalog: DocumentCatalog, expectedDigest: string | null): Promise<Outcome<{
|
|
45
|
+
readonly path: string;
|
|
46
|
+
readonly digest: string;
|
|
47
|
+
}>>;
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdir, open, rename, rm } from 'node:fs/promises';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { createDiagnostic } from '../schemas/diagnostics.js';
|
|
5
|
+
import { diagnosticCodes } from '../schemas/errors.js';
|
|
6
|
+
import { DOCUMENT_CATALOG_SCHEMA, documentCatalogSchema, } from '../schemas/document.js';
|
|
7
|
+
import { failed, succeeded } from '../schemas/outcome.js';
|
|
8
|
+
import { observePath, readFileBounded, readTextFileBounded, sha256Digest, } from '../infra/fs.js';
|
|
9
|
+
import { ensureKnowledgePathBoundary, knowledgePaths, } from './paths.js';
|
|
10
|
+
export const DEFAULT_CATALOG_MAX_BYTES = 8 * 1024 * 1024;
|
|
11
|
+
export function emptyCatalog(context, updatedAt = new Date().toISOString()) {
|
|
12
|
+
return {
|
|
13
|
+
schema: DOCUMENT_CATALOG_SCHEMA,
|
|
14
|
+
workspaceId: context.config.workspaceId,
|
|
15
|
+
updatedAt,
|
|
16
|
+
records: [],
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export function catalogDigestFor(catalogs, scope) {
|
|
20
|
+
return scope === 'shared' ? catalogs.shared.digest : catalogs.private.digest;
|
|
21
|
+
}
|
|
22
|
+
export function catalogScopeFor(record) {
|
|
23
|
+
return record.visibility === 'shareable' ? 'shared' : 'private';
|
|
24
|
+
}
|
|
25
|
+
export function locationKey(location) {
|
|
26
|
+
return location.kind === 'workspace'
|
|
27
|
+
? `workspace:${location.path}`
|
|
28
|
+
: `source:${location.sourceId}:${location.path}`;
|
|
29
|
+
}
|
|
30
|
+
function catalogDiagnostic(code, message, source, hint) {
|
|
31
|
+
return createDiagnostic({ code, severity: 'error', message, source, hint });
|
|
32
|
+
}
|
|
33
|
+
function isUnknownRecord(value) {
|
|
34
|
+
return typeof value === 'object' && value !== null;
|
|
35
|
+
}
|
|
36
|
+
async function readCatalogFile(context, scope, path) {
|
|
37
|
+
let observation;
|
|
38
|
+
try {
|
|
39
|
+
observation = await observePath(path);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
return {
|
|
43
|
+
scope,
|
|
44
|
+
path,
|
|
45
|
+
exists: true,
|
|
46
|
+
digest: null,
|
|
47
|
+
catalog: null,
|
|
48
|
+
diagnostics: [
|
|
49
|
+
catalogDiagnostic(diagnosticCodes.fileUnreadable, `Cannot inspect document catalog ${path}: ${error instanceof Error ? error.message : String(error)}`, path, 'Check permissions; Pappra does not overwrite an unreadable catalog.'),
|
|
50
|
+
],
|
|
51
|
+
valid: false,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (observation.kind === 'missing') {
|
|
55
|
+
return {
|
|
56
|
+
scope,
|
|
57
|
+
path,
|
|
58
|
+
exists: false,
|
|
59
|
+
digest: null,
|
|
60
|
+
catalog: null,
|
|
61
|
+
diagnostics: [],
|
|
62
|
+
valid: true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (observation.kind !== 'file') {
|
|
66
|
+
return {
|
|
67
|
+
scope,
|
|
68
|
+
path,
|
|
69
|
+
exists: true,
|
|
70
|
+
digest: null,
|
|
71
|
+
catalog: null,
|
|
72
|
+
diagnostics: [
|
|
73
|
+
catalogDiagnostic(diagnosticCodes.document_catalog_invalid, `Document catalog is not a regular file: ${path}`, path, 'Inspect the catalog; Pappra does not follow or replace it automatically.'),
|
|
74
|
+
],
|
|
75
|
+
valid: false,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const read = await readTextFileBounded(path, DEFAULT_CATALOG_MAX_BYTES);
|
|
79
|
+
if (!read.ok) {
|
|
80
|
+
return {
|
|
81
|
+
scope,
|
|
82
|
+
path,
|
|
83
|
+
exists: true,
|
|
84
|
+
digest: null,
|
|
85
|
+
catalog: null,
|
|
86
|
+
diagnostics: [
|
|
87
|
+
catalogDiagnostic(read.code, read.message, path, read.nextAction ?? 'Inspect the catalog file.'),
|
|
88
|
+
],
|
|
89
|
+
valid: false,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
let raw;
|
|
93
|
+
try {
|
|
94
|
+
raw = JSON.parse(read.value.text);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return {
|
|
98
|
+
scope,
|
|
99
|
+
path,
|
|
100
|
+
exists: true,
|
|
101
|
+
digest: null,
|
|
102
|
+
catalog: null,
|
|
103
|
+
diagnostics: [
|
|
104
|
+
catalogDiagnostic(diagnosticCodes.document_catalog_invalid, `Document catalog is not valid JSON: ${error instanceof Error ? error.message : String(error)}`, path, 'Repair the catalog manually; Pappra does not overwrite corrupted records.'),
|
|
105
|
+
],
|
|
106
|
+
valid: false,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (isUnknownRecord(raw) &&
|
|
110
|
+
'schema' in raw &&
|
|
111
|
+
typeof raw.schema === 'string' &&
|
|
112
|
+
raw.schema !== DOCUMENT_CATALOG_SCHEMA) {
|
|
113
|
+
return {
|
|
114
|
+
scope,
|
|
115
|
+
path,
|
|
116
|
+
exists: true,
|
|
117
|
+
digest: read.value.digest,
|
|
118
|
+
catalog: null,
|
|
119
|
+
diagnostics: [
|
|
120
|
+
catalogDiagnostic(diagnosticCodes.document_catalog_unsupported, `Unsupported document catalog schema: ${raw.schema}`, path, 'Keep the catalog read-only until a migration is explicitly reviewed.'),
|
|
121
|
+
],
|
|
122
|
+
valid: false,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const parsed = documentCatalogSchema.safeParse(raw);
|
|
126
|
+
if (!parsed.success) {
|
|
127
|
+
return {
|
|
128
|
+
scope,
|
|
129
|
+
path,
|
|
130
|
+
exists: true,
|
|
131
|
+
digest: read.value.digest,
|
|
132
|
+
catalog: null,
|
|
133
|
+
diagnostics: [
|
|
134
|
+
catalogDiagnostic(diagnosticCodes.document_catalog_invalid, `Document catalog is invalid: ${parsed.error.issues[0]?.message ?? 'unknown issue'}`, path, 'Repair the catalog manually; Pappra does not migrate or overwrite it.'),
|
|
135
|
+
],
|
|
136
|
+
valid: false,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const diagnostics = [];
|
|
140
|
+
if (parsed.data.workspaceId !== context.config.workspaceId) {
|
|
141
|
+
diagnostics.push(catalogDiagnostic(diagnosticCodes.document_catalog_conflict, `Catalog belongs to workspace ${parsed.data.workspaceId}, not ${context.config.workspaceId}.`, path, 'Inspect the catalog identity; do not reuse a catalog from another workspace.'));
|
|
142
|
+
}
|
|
143
|
+
for (const record of parsed.data.records) {
|
|
144
|
+
const expectedScope = catalogScopeFor(record);
|
|
145
|
+
if (expectedScope !== scope) {
|
|
146
|
+
diagnostics.push(catalogDiagnostic(diagnosticCodes.document_catalog_conflict, `${scope} catalog contains a ${record.visibility} record ${record.documentId}.`, path, 'Private and shareable records belong in their respective catalogs.'));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
scope,
|
|
151
|
+
path,
|
|
152
|
+
exists: true,
|
|
153
|
+
digest: read.value.digest,
|
|
154
|
+
catalog: parsed.data,
|
|
155
|
+
diagnostics,
|
|
156
|
+
valid: diagnostics.length === 0,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function combineDiagnostics(shared, privateState) {
|
|
160
|
+
return [...shared.diagnostics, ...privateState.diagnostics];
|
|
161
|
+
}
|
|
162
|
+
export async function loadKnowledgeCatalogs(context) {
|
|
163
|
+
const paths = knowledgePaths(context.root);
|
|
164
|
+
const shared = await readCatalogFile(context, 'shared', paths.sharedCatalog);
|
|
165
|
+
const privateState = await readCatalogFile(context, 'private', paths.privateCatalog);
|
|
166
|
+
const diagnostics = combineDiagnostics(shared, privateState);
|
|
167
|
+
const records = new Map();
|
|
168
|
+
const locations = new Map();
|
|
169
|
+
const idConflicts = new Set();
|
|
170
|
+
const locationConflicts = new Set();
|
|
171
|
+
for (const file of [shared, privateState]) {
|
|
172
|
+
if (file.catalog === null)
|
|
173
|
+
continue;
|
|
174
|
+
for (const record of file.catalog.records) {
|
|
175
|
+
const existing = records.get(record.documentId);
|
|
176
|
+
if (existing !== undefined) {
|
|
177
|
+
idConflicts.add(record.documentId);
|
|
178
|
+
diagnostics.push(catalogDiagnostic(diagnosticCodes.document_duplicate_id, `Document id ${record.documentId} appears more than once.`, file.path, 'Resolve the duplicate manually; Pappra does not choose a record.'));
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
records.set(record.documentId, record);
|
|
182
|
+
}
|
|
183
|
+
const key = locationKey(record.location);
|
|
184
|
+
const owner = locations.get(key);
|
|
185
|
+
if (owner !== undefined && owner !== record.documentId) {
|
|
186
|
+
locationConflicts.add(key);
|
|
187
|
+
diagnostics.push(catalogDiagnostic(diagnosticCodes.document_location_conflict, `Location ${key} is registered by both ${owner} and ${record.documentId}.`, file.path, 'Resolve the location conflict manually; Pappra does not overwrite either record.'));
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
locations.set(key, record.documentId);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const catalogDigest = sha256Digest(`${shared.digest ?? 'missing'}\n${privateState.digest ?? 'missing'}\n`);
|
|
195
|
+
return {
|
|
196
|
+
paths,
|
|
197
|
+
shared,
|
|
198
|
+
private: privateState,
|
|
199
|
+
records,
|
|
200
|
+
idConflicts,
|
|
201
|
+
locationConflicts,
|
|
202
|
+
diagnostics,
|
|
203
|
+
catalogDigest,
|
|
204
|
+
ok: diagnostics.every((entry) => entry.severity !== 'error'),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
export function recordScope(catalogs, record) {
|
|
208
|
+
if (catalogs.shared.catalog?.records.some((entry) => entry.documentId === record.documentId) === true) {
|
|
209
|
+
return 'shared';
|
|
210
|
+
}
|
|
211
|
+
return 'private';
|
|
212
|
+
}
|
|
213
|
+
export function catalogFor(catalogs, scope, context) {
|
|
214
|
+
const file = scope === 'shared' ? catalogs.shared : catalogs.private;
|
|
215
|
+
return file.catalog ?? emptyCatalog(context);
|
|
216
|
+
}
|
|
217
|
+
export function recordsForCatalog(catalog, documentId, next) {
|
|
218
|
+
const records = catalog.records.filter((record) => record.documentId !== documentId);
|
|
219
|
+
if (next !== null)
|
|
220
|
+
records.push(next);
|
|
221
|
+
return records.sort((left, right) => left.documentId.localeCompare(right.documentId));
|
|
222
|
+
}
|
|
223
|
+
export function setCatalogRecord(context, catalogs, record) {
|
|
224
|
+
const scope = catalogScopeFor(record);
|
|
225
|
+
const catalog = catalogFor(catalogs, scope, context);
|
|
226
|
+
return {
|
|
227
|
+
scope,
|
|
228
|
+
catalog: {
|
|
229
|
+
...catalog,
|
|
230
|
+
updatedAt: new Date().toISOString(),
|
|
231
|
+
records: recordsForCatalog(catalog, record.documentId, record),
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
export function removeCatalogRecord(context, catalogs, record) {
|
|
236
|
+
const scope = recordScope(catalogs, record);
|
|
237
|
+
const catalog = catalogFor(catalogs, scope, context);
|
|
238
|
+
return {
|
|
239
|
+
scope,
|
|
240
|
+
catalog: {
|
|
241
|
+
...catalog,
|
|
242
|
+
updatedAt: new Date().toISOString(),
|
|
243
|
+
records: recordsForCatalog(catalog, record.documentId, null),
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
export async function writeCatalogFile(context, scope, catalog, expectedDigest) {
|
|
248
|
+
const path = scope === 'shared'
|
|
249
|
+
? knowledgePaths(context.root).sharedCatalog
|
|
250
|
+
: knowledgePaths(context.root).privateCatalog;
|
|
251
|
+
const boundary = await ensureKnowledgePathBoundary(context.root, path);
|
|
252
|
+
if (!boundary.ok)
|
|
253
|
+
return boundary;
|
|
254
|
+
const current = await observePath(path);
|
|
255
|
+
if (current.kind !== 'missing' && current.kind !== 'file') {
|
|
256
|
+
return failed(diagnosticCodes.document_path_unsafe, `Catalog path is not a regular file: ${path}`, { nextAction: 'Inspect the catalog path; it was not replaced.' });
|
|
257
|
+
}
|
|
258
|
+
if (catalog.workspaceId !== context.config.workspaceId) {
|
|
259
|
+
return failed(diagnosticCodes.document_catalog_conflict, 'Refusing to write a catalog for a different workspace id.', { nextAction: 'Inspect the workspace and catalog identity.' });
|
|
260
|
+
}
|
|
261
|
+
const parsed = documentCatalogSchema.safeParse(catalog);
|
|
262
|
+
if (!parsed.success) {
|
|
263
|
+
return failed(diagnosticCodes.document_record_invalid, `Refusing to write an invalid catalog: ${parsed.error.issues[0]?.message ?? 'unknown issue'}`, { nextAction: 'Fix the record; no catalog bytes were written.' });
|
|
264
|
+
}
|
|
265
|
+
const bytes = Buffer.from(`${JSON.stringify(parsed.data, null, 2)}\n`);
|
|
266
|
+
const temporary = `${path}.tmp-${randomUUID()}`;
|
|
267
|
+
let handle;
|
|
268
|
+
try {
|
|
269
|
+
await mkdir(dirname(path), { recursive: true });
|
|
270
|
+
handle = await open(temporary, 'wx', scope === 'shared' ? 0o644 : 0o600);
|
|
271
|
+
await handle.writeFile(bytes);
|
|
272
|
+
await handle.sync();
|
|
273
|
+
await handle.close();
|
|
274
|
+
handle = undefined;
|
|
275
|
+
const currentObservation = await observePath(path).catch(() => null);
|
|
276
|
+
let currentDigest = null;
|
|
277
|
+
if (currentObservation?.kind === 'missing') {
|
|
278
|
+
currentDigest = null;
|
|
279
|
+
}
|
|
280
|
+
else if (currentObservation?.kind === 'file') {
|
|
281
|
+
const current = await readFileBounded(path, DEFAULT_CATALOG_MAX_BYTES);
|
|
282
|
+
if (!current.ok) {
|
|
283
|
+
await rm(temporary, { force: true }).catch(() => undefined);
|
|
284
|
+
return current;
|
|
285
|
+
}
|
|
286
|
+
currentDigest = current.value.digest;
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
await rm(temporary, { force: true }).catch(() => undefined);
|
|
290
|
+
return failed(diagnosticCodes.document_catalog_conflict, `Catalog path changed to a non-regular file during commit: ${path}`, { nextAction: 'Inspect the catalog; no replacement was committed.' });
|
|
291
|
+
}
|
|
292
|
+
if (currentDigest !== expectedDigest) {
|
|
293
|
+
await rm(temporary, { force: true }).catch(() => undefined);
|
|
294
|
+
return failed(diagnosticCodes.document_catalog_conflict, `Catalog changed before commit: ${path}`, {
|
|
295
|
+
nextAction: 'Reload the catalog and regenerate the proposal; no catalog replacement was committed.',
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
await rename(temporary, path);
|
|
299
|
+
return succeeded({ path, digest: sha256Digest(bytes) });
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
await handle?.close().catch(() => undefined);
|
|
303
|
+
await rm(temporary, { force: true }).catch(() => undefined);
|
|
304
|
+
return failed(diagnosticCodes.fileUnreadable, `Cannot write document catalog ${path}: ${error instanceof Error ? error.message : String(error)}`, {
|
|
305
|
+
nextAction: 'Inspect permissions and available disk space; no catalog replacement was claimed.',
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Diagnostic } from '../schemas/diagnostics.js';
|
|
2
|
+
import type { MachineConfig } from '../schemas/machine.js';
|
|
3
|
+
import type { WorkspaceConfig } from '../schemas/workspace.js';
|
|
4
|
+
import type { DiscoveredRepository } from '../workspace/types.js';
|
|
5
|
+
export interface KnowledgeContext {
|
|
6
|
+
readonly root: string;
|
|
7
|
+
readonly config: WorkspaceConfig;
|
|
8
|
+
readonly machine: MachineConfig | null;
|
|
9
|
+
readonly configPath: string;
|
|
10
|
+
readonly machinePath: string;
|
|
11
|
+
readonly repositories: readonly DiscoveredRepository[];
|
|
12
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
13
|
+
readonly observedAt: string;
|
|
14
|
+
readonly rootIdentity: {
|
|
15
|
+
readonly dev: number;
|
|
16
|
+
readonly ino: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface KnowledgeContextResult {
|
|
20
|
+
readonly ok: boolean;
|
|
21
|
+
readonly context: KnowledgeContext | null;
|
|
22
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
23
|
+
}
|
|
24
|
+
export declare function loadKnowledgeContext(inputRoot: string): Promise<KnowledgeContextResult>;
|
|
25
|
+
export declare function sameRootIdentity(context: KnowledgeContext, identity: {
|
|
26
|
+
readonly dev: number;
|
|
27
|
+
readonly ino: number;
|
|
28
|
+
}): boolean;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { createDiagnostic } from '../schemas/diagnostics.js';
|
|
3
|
+
import { diagnosticCodes } from '../schemas/errors.js';
|
|
4
|
+
import { inspectMachineConfig, inspectWorkspaceConfig, } from '../workspace/config.js';
|
|
5
|
+
import { discoverRepositories } from '../workspace/repositories.js';
|
|
6
|
+
import { observePath } from '../infra/fs.js';
|
|
7
|
+
const repositoryDiscoveryOptions = {
|
|
8
|
+
scanDepth: 0,
|
|
9
|
+
maxDirectories: 1,
|
|
10
|
+
maxDocuments: 1,
|
|
11
|
+
maxEntriesPerDirectory: 1,
|
|
12
|
+
gitTimeoutMs: 5_000,
|
|
13
|
+
};
|
|
14
|
+
export async function loadKnowledgeContext(inputRoot) {
|
|
15
|
+
const workspace = await inspectWorkspaceConfig(inputRoot);
|
|
16
|
+
const diagnostics = [...workspace.diagnostics];
|
|
17
|
+
if (workspace.value === null) {
|
|
18
|
+
return { ok: false, context: null, diagnostics };
|
|
19
|
+
}
|
|
20
|
+
const machineInspection = await inspectMachineConfig(workspace.root);
|
|
21
|
+
diagnostics.push(...machineInspection.diagnostics);
|
|
22
|
+
const machine = machineInspection.value;
|
|
23
|
+
const discovered = await discoverRepositories({
|
|
24
|
+
root: workspace.root,
|
|
25
|
+
config: workspace.value,
|
|
26
|
+
machine,
|
|
27
|
+
configPath: workspace.path,
|
|
28
|
+
options: repositoryDiscoveryOptions,
|
|
29
|
+
});
|
|
30
|
+
diagnostics.push(...discovered.diagnostics);
|
|
31
|
+
const rootObservation = await observePath(workspace.root);
|
|
32
|
+
if (rootObservation.stats === null) {
|
|
33
|
+
diagnostics.push(createDiagnostic({
|
|
34
|
+
code: diagnosticCodes.document_path_unsafe,
|
|
35
|
+
severity: 'error',
|
|
36
|
+
message: `Cannot observe workspace root identity: ${workspace.root}`,
|
|
37
|
+
source: workspace.root,
|
|
38
|
+
hint: 'Use an existing readable workspace directory.',
|
|
39
|
+
}));
|
|
40
|
+
return { ok: false, context: null, diagnostics };
|
|
41
|
+
}
|
|
42
|
+
const context = {
|
|
43
|
+
root: workspace.root,
|
|
44
|
+
config: workspace.value,
|
|
45
|
+
machine,
|
|
46
|
+
configPath: workspace.path,
|
|
47
|
+
machinePath: join(workspace.root, '.pappra', 'local', 'machine.json'),
|
|
48
|
+
repositories: discovered.repositories,
|
|
49
|
+
diagnostics,
|
|
50
|
+
observedAt: new Date().toISOString(),
|
|
51
|
+
rootIdentity: {
|
|
52
|
+
dev: rootObservation.stats.dev,
|
|
53
|
+
ino: rootObservation.stats.ino,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
return { ok: true, context, diagnostics };
|
|
57
|
+
}
|
|
58
|
+
export function sameRootIdentity(context, identity) {
|
|
59
|
+
return (context.rootIdentity.dev === identity.dev &&
|
|
60
|
+
context.rootIdentity.ino === identity.ino);
|
|
61
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { KnowledgeService } from './service.js';
|
|
2
|
+
export type { ApplyWriteResult, ArchiveDocumentResult, DeleteExplicitInput, DeleteExplicitResult, DocumentCheckEntry, DocumentCheckResult, KnowledgeServiceOptions, ListDocumentsOptions, ListDocumentsResult, PreviewDeleteInput, PreviewDeleteResult, ProposeWriteInput, ProposeWriteResult, ReadDocumentResult, RegisterDocumentInput, RegisterDocumentResult, ShareDocumentResult, SupersedeDocumentInput, SupersedeDocumentResult, } from './types.js';
|
|
3
|
+
export type { FreshnessReport, Freshness } from './refs.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { KnowledgeService } from './service.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Outcome } from '../schemas/outcome.js';
|
|
2
|
+
import { type KnowledgeJournal, type KnowledgeLock } from '../schemas/document.js';
|
|
3
|
+
import type { KnowledgeContext } from './context.js';
|
|
4
|
+
export interface KnowledgeLockAcquireResult {
|
|
5
|
+
readonly ok: boolean;
|
|
6
|
+
readonly status: 'acquired' | 'locked' | 'failed';
|
|
7
|
+
readonly lock: KnowledgeLock | null;
|
|
8
|
+
readonly path: string;
|
|
9
|
+
readonly message: string | null;
|
|
10
|
+
}
|
|
11
|
+
export declare function acquireKnowledgeLock(context: KnowledgeContext, operation: KnowledgeLock['operation']): Promise<KnowledgeLockAcquireResult>;
|
|
12
|
+
export declare function releaseKnowledgeLock(lock: KnowledgeLock, path: string): Promise<Outcome<null>>;
|
|
13
|
+
export declare function knowledgeJournalPath(context: KnowledgeContext, operationId: string): string;
|
|
14
|
+
export declare function writeKnowledgeJournal(context: KnowledgeContext, journal: KnowledgeJournal): Promise<Outcome<{
|
|
15
|
+
readonly path: string;
|
|
16
|
+
}>>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdir, open, rename, rm, unlink } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { diagnosticCodes } from '../schemas/errors.js';
|
|
5
|
+
import { errorMessage, failed, succeeded } from '../schemas/outcome.js';
|
|
6
|
+
import { knowledgeJournalSchema, knowledgeLockSchema, } from '../schemas/document.js';
|
|
7
|
+
import { readTextFileBounded } from '../infra/fs.js';
|
|
8
|
+
import { ensureKnowledgePathBoundary, knowledgePaths } from './paths.js';
|
|
9
|
+
function lockFailure(path, status, message) {
|
|
10
|
+
return { ok: false, status, lock: null, path, message };
|
|
11
|
+
}
|
|
12
|
+
export async function acquireKnowledgeLock(context, operation) {
|
|
13
|
+
const path = knowledgePaths(context.root).lockPath;
|
|
14
|
+
const boundary = await ensureKnowledgePathBoundary(context.root, path);
|
|
15
|
+
if (!boundary.ok) {
|
|
16
|
+
return lockFailure(path, 'failed', boundary.message);
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
await mkdir(dirname(path), { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
return lockFailure(path, 'failed', `Cannot create knowledge state directory: ${errorMessage(error)}`);
|
|
23
|
+
}
|
|
24
|
+
const lock = {
|
|
25
|
+
schema: 'pappra/knowledge-lock/1',
|
|
26
|
+
token: randomUUID(),
|
|
27
|
+
operation,
|
|
28
|
+
pid: process.pid,
|
|
29
|
+
createdAt: new Date().toISOString(),
|
|
30
|
+
};
|
|
31
|
+
let handle;
|
|
32
|
+
try {
|
|
33
|
+
handle = await open(path, 'wx', 0o600);
|
|
34
|
+
await handle.writeFile(Buffer.from(`${JSON.stringify(lock, null, 2)}\n`));
|
|
35
|
+
await handle.sync();
|
|
36
|
+
await handle.close();
|
|
37
|
+
handle = undefined;
|
|
38
|
+
return { ok: true, status: 'acquired', lock, path, message: null };
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
await handle?.close().catch(() => undefined);
|
|
42
|
+
const code = typeof error === 'object' &&
|
|
43
|
+
error !== null &&
|
|
44
|
+
'code' in error &&
|
|
45
|
+
typeof error.code === 'string'
|
|
46
|
+
? error.code
|
|
47
|
+
: null;
|
|
48
|
+
return code === 'EEXIST'
|
|
49
|
+
? lockFailure(path, 'locked', `Knowledge mutation is already locked: ${path}`)
|
|
50
|
+
: lockFailure(path, 'failed', `Cannot acquire knowledge lock ${path}: ${errorMessage(error)}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export async function releaseKnowledgeLock(lock, path) {
|
|
54
|
+
const read = await readTextFileBounded(path);
|
|
55
|
+
if (!read.ok) {
|
|
56
|
+
return failed(diagnosticCodes.document_locked, `Cannot verify knowledge lock ${path}: ${read.message}`, { nextAction: 'Inspect the lock manually; it was not removed.' });
|
|
57
|
+
}
|
|
58
|
+
let parsed;
|
|
59
|
+
try {
|
|
60
|
+
parsed = JSON.parse(read.value.text);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return failed(diagnosticCodes.document_locked, `Knowledge lock is not valid JSON: ${path}`, { nextAction: 'Inspect the lock manually; it was not removed.' });
|
|
64
|
+
}
|
|
65
|
+
const valid = knowledgeLockSchema.safeParse(parsed);
|
|
66
|
+
if (!valid.success || valid.data.token !== lock.token) {
|
|
67
|
+
return failed(diagnosticCodes.document_locked, `Knowledge lock ownership changed: ${path}`, { nextAction: 'Inspect the lock manually; it was not removed.' });
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
await unlink(path);
|
|
71
|
+
return succeeded(null);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return failed(diagnosticCodes.document_locked, `Cannot release knowledge lock ${path}: ${errorMessage(error)}`, { nextAction: 'Inspect the lock manually; it remains as evidence.' });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export function knowledgeJournalPath(context, operationId) {
|
|
78
|
+
return join(knowledgePaths(context.root).journalsDir, `${operationId}.json`);
|
|
79
|
+
}
|
|
80
|
+
export async function writeKnowledgeJournal(context, journal) {
|
|
81
|
+
const parsed = knowledgeJournalSchema.safeParse(journal);
|
|
82
|
+
if (!parsed.success) {
|
|
83
|
+
return failed(diagnosticCodes.document_journal_failed, `Knowledge journal is invalid: ${parsed.error.issues[0]?.message ?? 'unknown issue'}`, {
|
|
84
|
+
nextAction: 'Inspect the operation state; no recovery state was written.',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const path = knowledgeJournalPath(context, parsed.data.operationId);
|
|
88
|
+
const boundary = await ensureKnowledgePathBoundary(context.root, path);
|
|
89
|
+
if (!boundary.ok)
|
|
90
|
+
return boundary;
|
|
91
|
+
const temporary = `${path}.tmp-${randomUUID()}`;
|
|
92
|
+
const bytes = Buffer.from(`${JSON.stringify(parsed.data, null, 2)}\n`);
|
|
93
|
+
let handle;
|
|
94
|
+
try {
|
|
95
|
+
await mkdir(dirname(path), { recursive: true });
|
|
96
|
+
handle = await open(temporary, 'wx', 0o600);
|
|
97
|
+
await handle.writeFile(bytes);
|
|
98
|
+
await handle.sync();
|
|
99
|
+
await handle.close();
|
|
100
|
+
handle = undefined;
|
|
101
|
+
await rename(temporary, path);
|
|
102
|
+
return succeeded({ path });
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
await handle?.close().catch(() => undefined);
|
|
106
|
+
await rm(temporary, { force: true }).catch(() => undefined);
|
|
107
|
+
return failed(diagnosticCodes.document_journal_failed, `Cannot write knowledge journal ${path}: ${errorMessage(error)}`, { nextAction: 'Resolve the local state write failure before retrying.' });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type KnowledgeDeletePlan } from '../schemas/document.js';
|
|
2
|
+
import type { KnowledgeContext } from './context.js';
|
|
3
|
+
import type { ArchiveDocumentResult, DeleteExplicitResult, PreviewDeleteInput, PreviewDeleteResult, ShareDocumentResult, SupersedeDocumentInput, SupersedeDocumentResult } from './types.js';
|
|
4
|
+
export declare function archiveDocument(context: KnowledgeContext, documentId: string): Promise<ArchiveDocumentResult>;
|
|
5
|
+
export declare function supersedeDocument(context: KnowledgeContext, input: SupersedeDocumentInput): Promise<SupersedeDocumentResult>;
|
|
6
|
+
export declare function shareDocument(context: KnowledgeContext, documentId: string): Promise<ShareDocumentResult>;
|
|
7
|
+
export declare function previewDelete(context: KnowledgeContext, input: PreviewDeleteInput): Promise<PreviewDeleteResult>;
|
|
8
|
+
export declare function deleteExplicit(context: KnowledgeContext, plan: KnowledgeDeletePlan): Promise<DeleteExplicitResult>;
|