mewkit 1.11.1 → 1.12.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/dist/commands/build-plugin.d.ts +8 -0
- package/dist/commands/build-plugin.d.ts.map +1 -0
- package/dist/commands/build-plugin.js +48 -0
- package/dist/commands/build-plugin.js.map +1 -0
- package/dist/commands/doctor-checks.d.ts +9 -0
- package/dist/commands/doctor-checks.d.ts.map +1 -1
- package/dist/commands/doctor-checks.js +42 -0
- package/dist/commands/doctor-checks.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +2 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/index-command.d.ts.map +1 -1
- package/dist/commands/index-command.js +2 -1
- package/dist/commands/index-command.js.map +1 -1
- package/dist/commands/validate.d.ts +3 -1
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +9 -0
- package/dist/commands/validate.js.map +1 -1
- package/dist/core/check-plugin-manifests.d.ts +10 -0
- package/dist/core/check-plugin-manifests.d.ts.map +1 -0
- package/dist/core/check-plugin-manifests.js +150 -0
- package/dist/core/check-plugin-manifests.js.map +1 -0
- package/dist/core/derived-index.d.ts +5 -3
- package/dist/core/derived-index.d.ts.map +1 -1
- package/dist/core/derived-index.js +35 -10
- package/dist/core/derived-index.js.map +1 -1
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/plugin-agent-refs.d.ts +22 -0
- package/dist/core/plugin-agent-refs.d.ts.map +1 -0
- package/dist/core/plugin-agent-refs.js +87 -0
- package/dist/core/plugin-agent-refs.js.map +1 -0
- package/dist/core/plugin-hooks.d.ts +15 -0
- package/dist/core/plugin-hooks.d.ts.map +1 -0
- package/dist/core/plugin-hooks.js +58 -0
- package/dist/core/plugin-hooks.js.map +1 -0
- package/dist/core/plugin-manifest.d.ts +289 -0
- package/dist/core/plugin-manifest.d.ts.map +1 -0
- package/dist/core/plugin-manifest.js +125 -0
- package/dist/core/plugin-manifest.js.map +1 -0
- package/dist/core/plugin-payload.d.ts +26 -0
- package/dist/core/plugin-payload.d.ts.map +1 -0
- package/dist/core/plugin-payload.js +138 -0
- package/dist/core/plugin-payload.js.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/dist/wiki/application/ports.d.ts +111 -0
- package/dist/wiki/application/ports.d.ts.map +1 -0
- package/dist/wiki/application/ports.js +33 -0
- package/dist/wiki/application/ports.js.map +1 -0
- package/dist/wiki/application/queries.d.ts +5 -0
- package/dist/wiki/application/queries.d.ts.map +1 -0
- package/dist/wiki/application/queries.js +10 -0
- package/dist/wiki/application/queries.js.map +1 -0
- package/dist/wiki/application/research.d.ts +16 -0
- package/dist/wiki/application/research.d.ts.map +1 -0
- package/dist/wiki/application/research.js +48 -0
- package/dist/wiki/application/research.js.map +1 -0
- package/dist/wiki/application/service.d.ts +27 -0
- package/dist/wiki/application/service.d.ts.map +1 -0
- package/dist/wiki/application/service.js +153 -0
- package/dist/wiki/application/service.js.map +1 -0
- package/dist/wiki/domain/index.d.ts +5 -0
- package/dist/wiki/domain/index.d.ts.map +1 -0
- package/dist/wiki/domain/index.js +6 -0
- package/dist/wiki/domain/index.js.map +1 -0
- package/dist/wiki/domain/invariants.d.ts +28 -0
- package/dist/wiki/domain/invariants.d.ts.map +1 -0
- package/dist/wiki/domain/invariants.js +84 -0
- package/dist/wiki/domain/invariants.js.map +1 -0
- package/dist/wiki/domain/salience.d.ts +11 -0
- package/dist/wiki/domain/salience.d.ts.map +1 -0
- package/dist/wiki/domain/salience.js +40 -0
- package/dist/wiki/domain/salience.js.map +1 -0
- package/dist/wiki/domain/types.d.ts +151 -0
- package/dist/wiki/domain/types.d.ts.map +1 -0
- package/dist/wiki/domain/types.js +27 -0
- package/dist/wiki/domain/types.js.map +1 -0
- package/dist/wiki/domain/write-decision.d.ts +25 -0
- package/dist/wiki/domain/write-decision.d.ts.map +1 -0
- package/dist/wiki/domain/write-decision.js +71 -0
- package/dist/wiki/domain/write-decision.js.map +1 -0
- package/dist/wiki/infrastructure/fetcher-adapter.d.ts +45 -0
- package/dist/wiki/infrastructure/fetcher-adapter.d.ts.map +1 -0
- package/dist/wiki/infrastructure/fetcher-adapter.js +99 -0
- package/dist/wiki/infrastructure/fetcher-adapter.js.map +1 -0
- package/dist/wiki/infrastructure/inventory-adapter.d.ts +13 -0
- package/dist/wiki/infrastructure/inventory-adapter.d.ts.map +1 -0
- package/dist/wiki/infrastructure/inventory-adapter.js +46 -0
- package/dist/wiki/infrastructure/inventory-adapter.js.map +1 -0
- package/dist/wiki/infrastructure/markdown-repository.d.ts +23 -0
- package/dist/wiki/infrastructure/markdown-repository.d.ts.map +1 -0
- package/dist/wiki/infrastructure/markdown-repository.js +168 -0
- package/dist/wiki/infrastructure/markdown-repository.js.map +1 -0
- package/dist/wiki/infrastructure/scan-patterns.d.ts +20 -0
- package/dist/wiki/infrastructure/scan-patterns.d.ts.map +1 -0
- package/dist/wiki/infrastructure/scan-patterns.js +106 -0
- package/dist/wiki/infrastructure/scan-patterns.js.map +1 -0
- package/dist/wiki/infrastructure/scanner-adapter.d.ts +10 -0
- package/dist/wiki/infrastructure/scanner-adapter.d.ts.map +1 -0
- package/dist/wiki/infrastructure/scanner-adapter.js +147 -0
- package/dist/wiki/infrastructure/scanner-adapter.js.map +1 -0
- package/dist/wiki/infrastructure/sqlite-index.d.ts +9 -0
- package/dist/wiki/infrastructure/sqlite-index.d.ts.map +1 -0
- package/dist/wiki/infrastructure/sqlite-index.js +36 -0
- package/dist/wiki/infrastructure/sqlite-index.js.map +1 -0
- package/dist/wiki/infrastructure/trace-adapter.d.ts +7 -0
- package/dist/wiki/infrastructure/trace-adapter.d.ts.map +1 -0
- package/dist/wiki/infrastructure/trace-adapter.js +42 -0
- package/dist/wiki/infrastructure/trace-adapter.js.map +1 -0
- package/dist/wiki/infrastructure/wiki-ingest.d.ts +14 -0
- package/dist/wiki/infrastructure/wiki-ingest.d.ts.map +1 -0
- package/dist/wiki/infrastructure/wiki-ingest.js +138 -0
- package/dist/wiki/infrastructure/wiki-ingest.js.map +1 -0
- package/dist/wiki/infrastructure/wiki-query.d.ts +15 -0
- package/dist/wiki/infrastructure/wiki-query.d.ts.map +1 -0
- package/dist/wiki/infrastructure/wiki-query.js +46 -0
- package/dist/wiki/infrastructure/wiki-query.js.map +1 -0
- package/dist/wiki/infrastructure/wiki-schema.d.ts +3 -0
- package/dist/wiki/infrastructure/wiki-schema.d.ts.map +1 -0
- package/dist/wiki/infrastructure/wiki-schema.js +43 -0
- package/dist/wiki/infrastructure/wiki-schema.js.map +1 -0
- package/dist/wiki/interface/cli.d.ts +7 -0
- package/dist/wiki/interface/cli.d.ts.map +1 -0
- package/dist/wiki/interface/cli.js +160 -0
- package/dist/wiki/interface/cli.js.map +1 -0
- package/dist/wiki/render.d.ts +3 -0
- package/dist/wiki/render.d.ts.map +1 -0
- package/dist/wiki/render.js +58 -0
- package/dist/wiki/render.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Pure domain invariants. No IO. These are the security-bearing guards that
|
|
2
|
+
// every upper layer inherits: path-traversal rejection, provenance completeness,
|
|
3
|
+
// claim sourcing, and the state-transition machine.
|
|
4
|
+
/** Reject any path segment that could escape the wiki root. Pure string check —
|
|
5
|
+
* the caller passes a repo-relative path, never an absolute one. */
|
|
6
|
+
export function assertNoTraversal(path) {
|
|
7
|
+
if (path.length === 0) {
|
|
8
|
+
throw new Error("path must be non-empty");
|
|
9
|
+
}
|
|
10
|
+
if (path.includes("\0")) {
|
|
11
|
+
throw new Error(`path contains a null byte: ${JSON.stringify(path)}`);
|
|
12
|
+
}
|
|
13
|
+
if (path.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(path)) {
|
|
14
|
+
throw new Error(`path must be repo-relative, got absolute: ${JSON.stringify(path)}`);
|
|
15
|
+
}
|
|
16
|
+
if (path.includes("\\")) {
|
|
17
|
+
throw new Error(`path must use forward slashes: ${JSON.stringify(path)}`);
|
|
18
|
+
}
|
|
19
|
+
const segments = path.split("/");
|
|
20
|
+
if (segments.some((segment) => segment === ".." || segment === ".")) {
|
|
21
|
+
throw new Error(`path contains a traversal segment: ${JSON.stringify(path)}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** A canonical page must carry title, slug, created_at, updated_at, and a
|
|
25
|
+
* provenance with a named origin (invariant). */
|
|
26
|
+
export function assertCanonicalComplete(page) {
|
|
27
|
+
const missing = [];
|
|
28
|
+
if (!page.title)
|
|
29
|
+
missing.push("title");
|
|
30
|
+
if (!page.slug)
|
|
31
|
+
missing.push("slug");
|
|
32
|
+
if (!page.createdAt)
|
|
33
|
+
missing.push("createdAt");
|
|
34
|
+
if (!page.updatedAt)
|
|
35
|
+
missing.push("updatedAt");
|
|
36
|
+
if (!page.provenance || !page.provenance.origin)
|
|
37
|
+
missing.push("provenance.origin");
|
|
38
|
+
if (missing.length > 0) {
|
|
39
|
+
throw new Error(`canonical page is missing required fields: ${missing.join(", ")}`);
|
|
40
|
+
}
|
|
41
|
+
assertNoTraversal(page.path);
|
|
42
|
+
}
|
|
43
|
+
/** A claim drawn from an external source must name that source. */
|
|
44
|
+
export function assertClaimHasSource(claim) {
|
|
45
|
+
if (claim.external && !claim.sourceId) {
|
|
46
|
+
throw new Error(`external claim ${JSON.stringify(claim.id)} requires a sourceId`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// --- State-transition machine ----------------------------------------------
|
|
50
|
+
const ALLOWED_TRANSITIONS = {
|
|
51
|
+
proposed: ["scanned", "quarantined", "rejected"],
|
|
52
|
+
scanned: ["approved", "quarantined", "rejected"],
|
|
53
|
+
approved: ["committed", "rejected"],
|
|
54
|
+
committed: [],
|
|
55
|
+
quarantined: [],
|
|
56
|
+
rejected: [],
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Decide whether a lifecycle transition is permitted. Two security invariants
|
|
60
|
+
* are enforced structurally:
|
|
61
|
+
* - Only `scanned` content can reach `approved` (unscanned content is barred).
|
|
62
|
+
* - Agent-origin content can never reach `committed` (no self-commit).
|
|
63
|
+
*/
|
|
64
|
+
export function canTransition(from, to, ctx) {
|
|
65
|
+
if (from === to) {
|
|
66
|
+
return { ok: false, reason: `no-op transition: ${from} → ${to}` };
|
|
67
|
+
}
|
|
68
|
+
if (!ALLOWED_TRANSITIONS[from].includes(to)) {
|
|
69
|
+
return { ok: false, reason: `illegal transition: ${from} → ${to}` };
|
|
70
|
+
}
|
|
71
|
+
if (to === "committed" && ctx.origin === "agent") {
|
|
72
|
+
return { ok: false, reason: "agent-origin content cannot transition to committed" };
|
|
73
|
+
}
|
|
74
|
+
return { ok: true };
|
|
75
|
+
}
|
|
76
|
+
/** Throwing wrapper around `canTransition` for call sites that treat an illegal
|
|
77
|
+
* transition as a programming error. */
|
|
78
|
+
export function assertTransition(from, to, ctx) {
|
|
79
|
+
const result = canTransition(from, to, ctx);
|
|
80
|
+
if (!result.ok) {
|
|
81
|
+
throw new Error(result.reason);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=invariants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invariants.js","sourceRoot":"","sources":["../../../src/wiki/domain/invariants.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SalienceComponents, SalienceScore } from "./types.js";
|
|
2
|
+
/** Inclusive [min, max] bound for every salience component. */
|
|
3
|
+
export declare const SALIENCE_BOUNDS: Record<keyof SalienceComponents, readonly [number, number]>;
|
|
4
|
+
/**
|
|
5
|
+
* Score a set of salience components. Each component is clamped to its declared
|
|
6
|
+
* bound before summing, so `total` is always within the rubric's range
|
|
7
|
+
* (max +16 from the seven positive components, min −8 from the two penalties).
|
|
8
|
+
* The returned `components` are the clamped values actually used.
|
|
9
|
+
*/
|
|
10
|
+
export declare function scoreSalience(input: SalienceComponents): SalienceScore;
|
|
11
|
+
//# sourceMappingURL=salience.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salience.d.ts","sourceRoot":"","sources":["../../../src/wiki/domain/salience.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE,+DAA+D;AAC/D,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,kBAAkB,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAUvF,CAAC;AAWF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAUtE"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Salience rubric. Salience is an evaluated heuristic, NOT truth —
|
|
2
|
+
// it is an explicit, testable scoring function with named, bounded components.
|
|
3
|
+
// All weights and bounds live in one constant so they can be tuned in one place.
|
|
4
|
+
/** Inclusive [min, max] bound for every salience component. */
|
|
5
|
+
export const SALIENCE_BOUNDS = {
|
|
6
|
+
explicit_user_intent: [0, 3],
|
|
7
|
+
verified_outcome: [0, 3],
|
|
8
|
+
recurrence_or_friction: [0, 2],
|
|
9
|
+
novelty_vs_existing_wiki: [0, 2],
|
|
10
|
+
future_reuse_likelihood: [0, 2],
|
|
11
|
+
source_quality: [0, 2],
|
|
12
|
+
blast_radius: [0, 2],
|
|
13
|
+
security_risk_penalty: [-5, 0],
|
|
14
|
+
staleness_penalty: [-3, 0],
|
|
15
|
+
};
|
|
16
|
+
const COMPONENT_KEYS = Object.keys(SALIENCE_BOUNDS);
|
|
17
|
+
function clamp(value, min, max) {
|
|
18
|
+
if (Number.isNaN(value)) {
|
|
19
|
+
return min;
|
|
20
|
+
}
|
|
21
|
+
return Math.min(max, Math.max(min, value));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Score a set of salience components. Each component is clamped to its declared
|
|
25
|
+
* bound before summing, so `total` is always within the rubric's range
|
|
26
|
+
* (max +16 from the seven positive components, min −8 from the two penalties).
|
|
27
|
+
* The returned `components` are the clamped values actually used.
|
|
28
|
+
*/
|
|
29
|
+
export function scoreSalience(input) {
|
|
30
|
+
const components = {};
|
|
31
|
+
let total = 0;
|
|
32
|
+
for (const key of COMPONENT_KEYS) {
|
|
33
|
+
const [min, max] = SALIENCE_BOUNDS[key];
|
|
34
|
+
const clamped = clamp(input[key], min, max);
|
|
35
|
+
components[key] = clamped;
|
|
36
|
+
total += clamped;
|
|
37
|
+
}
|
|
38
|
+
return { total, components };
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=salience.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salience.js","sourceRoot":"","sources":["../../../src/wiki/domain/salience.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,+EAA+E;AAC/E,iFAAiF;AAIjF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,eAAe,GAAgE;IAC3F,oBAAoB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAC5B,gBAAgB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACxB,sBAAsB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9B,wBAAwB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAChC,uBAAuB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAC/B,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACtB,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACpB,qBAAqB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9B,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CAC1B,CAAC;AAEF,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAiC,CAAC;AAEpF,SAAS,KAAK,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW;IACrD,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC;IACZ,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACtD,MAAM,UAAU,GAAG,EAAwB,CAAC;IAC5C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAC5C,UAAU,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;QAC1B,KAAK,IAAI,OAAO,CAAC;IAClB,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
declare const brand: unique symbol;
|
|
2
|
+
type Brand<T, B extends string> = T & {
|
|
3
|
+
readonly [brand]: B;
|
|
4
|
+
};
|
|
5
|
+
/** A validated wiki slug: lowercase alphanumerics joined by single hyphens. */
|
|
6
|
+
export type WikiSlug = Brand<string, "WikiSlug">;
|
|
7
|
+
/** A stable wiki page identifier. */
|
|
8
|
+
export type WikiPageId = Brand<string, "WikiPageId">;
|
|
9
|
+
/** Slug grammar. The pattern forbids `.`, `/`, and whitespace, so a valid slug
|
|
10
|
+
* can never carry a path-traversal sequence. */
|
|
11
|
+
export declare const WIKI_SLUG_PATTERN: RegExp;
|
|
12
|
+
export declare function isWikiSlug(value: string): value is WikiSlug;
|
|
13
|
+
/** Smart constructor for a slug. Throws on invalid input — callers never
|
|
14
|
+
* fabricate a branded slug by assertion. */
|
|
15
|
+
export declare function makeWikiSlug(value: string): WikiSlug;
|
|
16
|
+
export declare function makeWikiPageId(value: string): WikiPageId;
|
|
17
|
+
/** Who originated a piece of content. Agent-origin content can never self-commit. */
|
|
18
|
+
export type WikiOrigin = "agent" | "human" | "system";
|
|
19
|
+
/** Lifecycle state shared by candidates and pages. */
|
|
20
|
+
export type WikiState = "proposed" | "scanned" | "approved" | "committed" | "quarantined" | "rejected";
|
|
21
|
+
export type WikiSourceKind = "web" | "arxiv" | "github" | "internal";
|
|
22
|
+
export type SeedStatus = "queued" | "fetched" | "done" | "failed";
|
|
23
|
+
export type VerificationState = "unverified" | "verified" | "rejected";
|
|
24
|
+
export type ScanStatus = "clean" | "injection" | "secret";
|
|
25
|
+
/** Result of the multi-pass injection + secret scan. `status` carries the worst
|
|
26
|
+
* finding; `clean` is the only status that may gate content toward `approved`. */
|
|
27
|
+
export interface InjectionVerdict {
|
|
28
|
+
status: ScanStatus;
|
|
29
|
+
/** Number of scan passes performed. */
|
|
30
|
+
passes: number;
|
|
31
|
+
findings: string[];
|
|
32
|
+
}
|
|
33
|
+
export declare function isClean(verdict: InjectionVerdict): boolean;
|
|
34
|
+
/** The 9 salience components. Keys are snake_case rubric identifiers
|
|
35
|
+
* kept verbatim from the report so they map 1:1 to the wiki_salience store. */
|
|
36
|
+
export interface SalienceComponents {
|
|
37
|
+
explicit_user_intent: number;
|
|
38
|
+
verified_outcome: number;
|
|
39
|
+
recurrence_or_friction: number;
|
|
40
|
+
novelty_vs_existing_wiki: number;
|
|
41
|
+
future_reuse_likelihood: number;
|
|
42
|
+
source_quality: number;
|
|
43
|
+
blast_radius: number;
|
|
44
|
+
security_risk_penalty: number;
|
|
45
|
+
staleness_penalty: number;
|
|
46
|
+
}
|
|
47
|
+
export interface SalienceScore {
|
|
48
|
+
total: number;
|
|
49
|
+
components: SalienceComponents;
|
|
50
|
+
}
|
|
51
|
+
export interface WikiSource {
|
|
52
|
+
id: string;
|
|
53
|
+
kind: WikiSourceKind;
|
|
54
|
+
url: string;
|
|
55
|
+
title?: string;
|
|
56
|
+
fetchedAt: string;
|
|
57
|
+
contentHash?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface WikiClaim {
|
|
60
|
+
id: string;
|
|
61
|
+
text: string;
|
|
62
|
+
/** True when the claim is drawn from an external source. */
|
|
63
|
+
external: boolean;
|
|
64
|
+
/** Required when `external` is true (invariant). */
|
|
65
|
+
sourceId?: string;
|
|
66
|
+
pageId?: WikiPageId;
|
|
67
|
+
}
|
|
68
|
+
export interface WikiSeed {
|
|
69
|
+
id: string;
|
|
70
|
+
query: string;
|
|
71
|
+
kind: WikiSourceKind;
|
|
72
|
+
status: SeedStatus;
|
|
73
|
+
createdAt: string;
|
|
74
|
+
}
|
|
75
|
+
export interface WikiProvenance {
|
|
76
|
+
origin: WikiOrigin;
|
|
77
|
+
sourceIds: string[];
|
|
78
|
+
/** The candidate this page was approved from, if any. */
|
|
79
|
+
candidateId?: string;
|
|
80
|
+
/** The human who approved the canonical write, if any. */
|
|
81
|
+
approvedBy?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface WikiCandidate {
|
|
84
|
+
id: string;
|
|
85
|
+
slug: WikiSlug;
|
|
86
|
+
origin: WikiOrigin;
|
|
87
|
+
title: string;
|
|
88
|
+
content: string;
|
|
89
|
+
whySave: string;
|
|
90
|
+
evidence: string;
|
|
91
|
+
sourceIds: string[];
|
|
92
|
+
noveltyDelta: number;
|
|
93
|
+
reuseScope: string;
|
|
94
|
+
verificationState: VerificationState;
|
|
95
|
+
riskScore: number;
|
|
96
|
+
salience: SalienceScore;
|
|
97
|
+
state: WikiState;
|
|
98
|
+
createdAt: string;
|
|
99
|
+
/** Review-after date or TTL marker. */
|
|
100
|
+
reviewAfter?: string;
|
|
101
|
+
}
|
|
102
|
+
export interface WikiPage {
|
|
103
|
+
id: WikiPageId;
|
|
104
|
+
slug: WikiSlug;
|
|
105
|
+
title: string;
|
|
106
|
+
/** Repo-relative path under tasks/wikis/<slug>/pages/. */
|
|
107
|
+
path: string;
|
|
108
|
+
content: string;
|
|
109
|
+
state: WikiState;
|
|
110
|
+
createdAt: string;
|
|
111
|
+
updatedAt: string;
|
|
112
|
+
provenance: WikiProvenance;
|
|
113
|
+
links: WikiPageId[];
|
|
114
|
+
}
|
|
115
|
+
export type InterventionKind = "reject" | "quarantine" | "override" | "link";
|
|
116
|
+
export interface WikiIntervention {
|
|
117
|
+
id: string;
|
|
118
|
+
kind: InterventionKind;
|
|
119
|
+
candidateId?: string;
|
|
120
|
+
reason: string;
|
|
121
|
+
verdict?: InjectionVerdict;
|
|
122
|
+
actor: WikiOrigin;
|
|
123
|
+
createdAt: string;
|
|
124
|
+
}
|
|
125
|
+
/** Outcome of `decideWrite`. By construction NONE of these writes a canonical
|
|
126
|
+
* page — the strongest outcome is a candidate. Canonical pages are produced only
|
|
127
|
+
* by the human-driven approve path in the application layer. */
|
|
128
|
+
export type WikiWriteDecision = {
|
|
129
|
+
kind: "quarantine";
|
|
130
|
+
reason: string;
|
|
131
|
+
} | {
|
|
132
|
+
kind: "link-existing";
|
|
133
|
+
existingPageId: WikiPageId;
|
|
134
|
+
reason: string;
|
|
135
|
+
} | {
|
|
136
|
+
kind: "append-candidate";
|
|
137
|
+
reason: string;
|
|
138
|
+
} | {
|
|
139
|
+
kind: "propose-candidate";
|
|
140
|
+
reason: string;
|
|
141
|
+
} | {
|
|
142
|
+
kind: "discard";
|
|
143
|
+
reason: string;
|
|
144
|
+
};
|
|
145
|
+
/** Duplicate-check result fed to `decideWrite`. */
|
|
146
|
+
export interface DupCheck {
|
|
147
|
+
isHighDuplicate: boolean;
|
|
148
|
+
existingPageId?: WikiPageId;
|
|
149
|
+
}
|
|
150
|
+
export {};
|
|
151
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/wiki/domain/types.ts"],"names":[],"mappings":"AAMA,OAAO,CAAC,MAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AACnC,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAE9D,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACjD,qCAAqC;AACrC,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAErD;gDACgD;AAChD,eAAO,MAAM,iBAAiB,QAA+B,CAAC;AAE9D,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAED;4CAC4C;AAC5C,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAKpD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAKxD;AAID,qFAAqF;AACrF,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEtD,sDAAsD;AACtD,MAAM,MAAM,SAAS,GAClB,UAAU,GACV,SAAS,GACT,UAAU,GACV,WAAW,GACX,aAAa,GACb,UAAU,CAAC;AAEd,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAErE,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAElE,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;AAIvE,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE1D;kFACkF;AAClF,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,UAAU,CAAC;IACnB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAE1D;AAID;+EAC+E;AAC/E,MAAM,WAAW,kBAAkB;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wBAAwB,EAAE,MAAM,CAAC;IACjC,uBAAuB,EAAE,MAAM,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,kBAAkB,CAAC;CAC/B;AAID,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,QAAQ,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;IACrB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,cAAc,CAAC;IAC3B,KAAK,EAAE,UAAU,EAAE,CAAC;CACpB;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;AAE7E,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CAClB;AAID;;gEAEgE;AAChE,MAAM,MAAM,iBAAiB,GAC1B;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,cAAc,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC,mDAAmD;AACnD,MAAM,WAAW,QAAQ;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,UAAU,CAAC;CAC5B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Wiki domain types. Pure vocabulary — no IO, no fs, no DB, no network.
|
|
2
|
+
// Mirrors the pure-domain shape of repository-harness/crates/harness-cli/src/domain.rs.
|
|
3
|
+
// Type names track the domain model; salience component keys track the salience rubric.
|
|
4
|
+
/** Slug grammar. The pattern forbids `.`, `/`, and whitespace, so a valid slug
|
|
5
|
+
* can never carry a path-traversal sequence. */
|
|
6
|
+
export const WIKI_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
7
|
+
export function isWikiSlug(value) {
|
|
8
|
+
return WIKI_SLUG_PATTERN.test(value);
|
|
9
|
+
}
|
|
10
|
+
/** Smart constructor for a slug. Throws on invalid input — callers never
|
|
11
|
+
* fabricate a branded slug by assertion. */
|
|
12
|
+
export function makeWikiSlug(value) {
|
|
13
|
+
if (!isWikiSlug(value)) {
|
|
14
|
+
throw new Error(`invalid wiki slug: ${JSON.stringify(value)}`);
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
export function makeWikiPageId(value) {
|
|
19
|
+
if (value.length === 0) {
|
|
20
|
+
throw new Error("wiki page id must be non-empty");
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
export function isClean(verdict) {
|
|
25
|
+
return verdict.status === "clean";
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/wiki/domain/types.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,wFAAwF;AACxF,wFAAwF;AAYxF;gDACgD;AAChD,MAAM,CAAC,MAAM,iBAAiB,GAAG,4BAA4B,CAAC;AAE9D,MAAM,UAAU,UAAU,CAAC,KAAa;IACvC,OAAO,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;4CAC4C;AAC5C,MAAM,UAAU,YAAY,CAAC,KAAa;IACzC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,KAAiB,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa;IAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,KAAmB,CAAC;AAC5B,CAAC;AAmCD,MAAM,UAAU,OAAO,CAAC,OAAyB;IAChD,OAAO,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DupCheck, InjectionVerdict, SalienceScore, WikiWriteDecision } from "./types.js";
|
|
2
|
+
/** Salience thresholds, kept in one place for tuning. */
|
|
3
|
+
export declare const SALIENCE_THRESHOLDS: {
|
|
4
|
+
/** Total ≥ this proposes a candidate for human approval. */
|
|
5
|
+
readonly proposeCandidate: 8;
|
|
6
|
+
/** Total ≥ this, with a strong verified signal, may auto-append to
|
|
7
|
+
* candidates.jsonl (still never a canonical page). */
|
|
8
|
+
readonly appendCandidate: 10;
|
|
9
|
+
};
|
|
10
|
+
/** Minimum scan passes for a "clean" verdict to be trusted. A clean
|
|
11
|
+
* verdict with fewer passes is treated as
|
|
12
|
+
* incompletely scanned and quarantined — `isClean` reports findings only, it
|
|
13
|
+
* does NOT imply the content was scanned enough to write. */
|
|
14
|
+
export declare const MIN_SCAN_PASSES = 2;
|
|
15
|
+
/**
|
|
16
|
+
* Decide what to do with a proposed write. Precedence:
|
|
17
|
+
* 1. Any injection/secret finding → quarantine (security wins over salience).
|
|
18
|
+
* 2. A clean verdict with too few scan passes → quarantine (incompletely scanned).
|
|
19
|
+
* 3. High duplication → link to the existing page, never a new one.
|
|
20
|
+
* 4. Total ≥ 10 with a strong verified signal → append to candidates.jsonl.
|
|
21
|
+
* 5. Total ≥ 8 and scan clean → propose a candidate for approval.
|
|
22
|
+
* 6. Otherwise → discard.
|
|
23
|
+
*/
|
|
24
|
+
export declare function decideWrite(score: SalienceScore, verdict: InjectionVerdict, dup: DupCheck): WikiWriteDecision;
|
|
25
|
+
//# sourceMappingURL=write-decision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-decision.d.ts","sourceRoot":"","sources":["../../../src/wiki/domain/write-decision.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACX,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,MAAM,YAAY,CAAC;AAGpB,yDAAyD;AACzD,eAAO,MAAM,mBAAmB;IAC/B,4DAA4D;;IAE5D;0DACsD;;CAE7C,CAAC;AAEX;;;6DAG6D;AAC7D,eAAO,MAAM,eAAe,IAAI,CAAC;AASjC;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAC1B,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,QAAQ,GACX,iBAAiB,CAyCnB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Write-decision logic. Maps a salience score + scan verdict + dup
|
|
2
|
+
// check onto a write decision. By construction this NEVER decides to write a
|
|
3
|
+
// canonical page — the strongest outcome is a candidate. Canonical pages come
|
|
4
|
+
// only from the human approve path in the application layer.
|
|
5
|
+
import { isClean } from "./types.js";
|
|
6
|
+
/** Salience thresholds, kept in one place for tuning. */
|
|
7
|
+
export const SALIENCE_THRESHOLDS = {
|
|
8
|
+
/** Total ≥ this proposes a candidate for human approval. */
|
|
9
|
+
proposeCandidate: 8,
|
|
10
|
+
/** Total ≥ this, with a strong verified signal, may auto-append to
|
|
11
|
+
* candidates.jsonl (still never a canonical page). */
|
|
12
|
+
appendCandidate: 10,
|
|
13
|
+
};
|
|
14
|
+
/** Minimum scan passes for a "clean" verdict to be trusted. A clean
|
|
15
|
+
* verdict with fewer passes is treated as
|
|
16
|
+
* incompletely scanned and quarantined — `isClean` reports findings only, it
|
|
17
|
+
* does NOT imply the content was scanned enough to write. */
|
|
18
|
+
export const MIN_SCAN_PASSES = 2;
|
|
19
|
+
/** A "strong verified signal" (accepted fix + passing tests +
|
|
20
|
+
* human-authored note) is encoded as the verified_outcome component at its max.
|
|
21
|
+
* Callers set verified_outcome to 3 only when that bundle holds. */
|
|
22
|
+
function hasStrongVerifiedSignal(score) {
|
|
23
|
+
return score.components.verified_outcome >= 3;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Decide what to do with a proposed write. Precedence:
|
|
27
|
+
* 1. Any injection/secret finding → quarantine (security wins over salience).
|
|
28
|
+
* 2. A clean verdict with too few scan passes → quarantine (incompletely scanned).
|
|
29
|
+
* 3. High duplication → link to the existing page, never a new one.
|
|
30
|
+
* 4. Total ≥ 10 with a strong verified signal → append to candidates.jsonl.
|
|
31
|
+
* 5. Total ≥ 8 and scan clean → propose a candidate for approval.
|
|
32
|
+
* 6. Otherwise → discard.
|
|
33
|
+
*/
|
|
34
|
+
export function decideWrite(score, verdict, dup) {
|
|
35
|
+
if (!isClean(verdict)) {
|
|
36
|
+
return {
|
|
37
|
+
kind: "quarantine",
|
|
38
|
+
reason: `scan found ${verdict.status}; quarantined`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (verdict.passes < MIN_SCAN_PASSES) {
|
|
42
|
+
return {
|
|
43
|
+
kind: "quarantine",
|
|
44
|
+
reason: `scan incomplete (${verdict.passes} < ${MIN_SCAN_PASSES} passes); quarantined pending full scan`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (dup.isHighDuplicate && dup.existingPageId) {
|
|
48
|
+
return {
|
|
49
|
+
kind: "link-existing",
|
|
50
|
+
existingPageId: dup.existingPageId,
|
|
51
|
+
reason: "high duplication; linked to existing page",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (score.total >= SALIENCE_THRESHOLDS.appendCandidate && hasStrongVerifiedSignal(score)) {
|
|
55
|
+
return {
|
|
56
|
+
kind: "append-candidate",
|
|
57
|
+
reason: `salience ${score.total} ≥ ${SALIENCE_THRESHOLDS.appendCandidate} with verified signal`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (score.total >= SALIENCE_THRESHOLDS.proposeCandidate) {
|
|
61
|
+
return {
|
|
62
|
+
kind: "propose-candidate",
|
|
63
|
+
reason: `salience ${score.total} ≥ ${SALIENCE_THRESHOLDS.proposeCandidate}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
kind: "discard",
|
|
68
|
+
reason: `salience ${score.total} below threshold ${SALIENCE_THRESHOLDS.proposeCandidate}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=write-decision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-decision.js","sourceRoot":"","sources":["../../../src/wiki/domain/write-decision.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,6EAA6E;AAC7E,8EAA8E;AAC9E,6DAA6D;AAQ7D,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,yDAAyD;AACzD,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAClC,4DAA4D;IAC5D,gBAAgB,EAAE,CAAC;IACnB;0DACsD;IACtD,eAAe,EAAE,EAAE;CACV,CAAC;AAEX;;;6DAG6D;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC;;oEAEoE;AACpE,SAAS,uBAAuB,CAAC,KAAoB;IACpD,OAAO,KAAK,CAAC,UAAU,CAAC,gBAAgB,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAC1B,KAAoB,EACpB,OAAyB,EACzB,GAAa;IAEb,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACvB,OAAO;YACN,IAAI,EAAE,YAAY;YAClB,MAAM,EAAE,cAAc,OAAO,CAAC,MAAM,eAAe;SACnD,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACtC,OAAO;YACN,IAAI,EAAE,YAAY;YAClB,MAAM,EAAE,oBAAoB,OAAO,CAAC,MAAM,MAAM,eAAe,yCAAyC;SACxG,CAAC;IACH,CAAC;IAED,IAAI,GAAG,CAAC,eAAe,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;QAC/C,OAAO;YACN,IAAI,EAAE,eAAe;YACrB,cAAc,EAAE,GAAG,CAAC,cAAc;YAClC,MAAM,EAAE,2CAA2C;SACnD,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,IAAI,mBAAmB,CAAC,eAAe,IAAI,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1F,OAAO;YACN,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,YAAY,KAAK,CAAC,KAAK,MAAM,mBAAmB,CAAC,eAAe,uBAAuB;SAC/F,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,IAAI,mBAAmB,CAAC,gBAAgB,EAAE,CAAC;QACzD,OAAO;YACN,IAAI,EAAE,mBAAmB;YACzB,MAAM,EAAE,YAAY,KAAK,CAAC,KAAK,MAAM,mBAAmB,CAAC,gBAAgB,EAAE;SAC3E,CAAC;IACH,CAAC;IAED,OAAO;QACN,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,YAAY,KAAK,CAAC,KAAK,oBAAoB,mBAAmB,CAAC,gBAAgB,EAAE;KACzF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { WikiSeed } from "../domain/index.js";
|
|
2
|
+
import type { Fetcher, FetchedDoc } from "../application/ports.js";
|
|
3
|
+
interface FetchResponse {
|
|
4
|
+
status: number;
|
|
5
|
+
ok: boolean;
|
|
6
|
+
headers: {
|
|
7
|
+
get(name: string): string | null;
|
|
8
|
+
};
|
|
9
|
+
body: {
|
|
10
|
+
getReader(): {
|
|
11
|
+
read(): Promise<{
|
|
12
|
+
done: boolean;
|
|
13
|
+
value?: Uint8Array;
|
|
14
|
+
}>;
|
|
15
|
+
cancel(): Promise<void>;
|
|
16
|
+
};
|
|
17
|
+
} | null;
|
|
18
|
+
text(): Promise<string>;
|
|
19
|
+
}
|
|
20
|
+
export type FetchImpl = (url: string, init: {
|
|
21
|
+
redirect: "manual";
|
|
22
|
+
signal: unknown;
|
|
23
|
+
headers: Record<string, string>;
|
|
24
|
+
}) => Promise<FetchResponse>;
|
|
25
|
+
export interface FetcherOptions {
|
|
26
|
+
fetchImpl?: FetchImpl;
|
|
27
|
+
maxBytes?: number;
|
|
28
|
+
maxHops?: number;
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
}
|
|
31
|
+
export declare class FetcherAdapter implements Fetcher {
|
|
32
|
+
private readonly fetchImpl;
|
|
33
|
+
private readonly maxBytes;
|
|
34
|
+
private readonly maxHops;
|
|
35
|
+
private readonly timeoutMs;
|
|
36
|
+
constructor(opts?: FetcherOptions);
|
|
37
|
+
/** Map a seed to a fetch URL. Web seeds carry a URL; arXiv/GitHub map to their public APIs. */
|
|
38
|
+
buildUrl(seed: WikiSeed): string;
|
|
39
|
+
fetch(seed: WikiSeed): Promise<FetchedDoc>;
|
|
40
|
+
/** url-guard at EVERY hop; manual redirects; size cap; timeout. */
|
|
41
|
+
private safeGet;
|
|
42
|
+
private readCapped;
|
|
43
|
+
}
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=fetcher-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetcher-adapter.d.ts","sourceRoot":"","sources":["../../../src/wiki/infrastructure/fetcher-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAUnE,UAAU,aAAa;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC9C,IAAI,EAAE;QAAE,SAAS,IAAI;YAAE,IAAI,IAAI,OAAO,CAAC;gBAAE,IAAI,EAAE,OAAO,CAAC;gBAAC,KAAK,CAAC,EAAE,UAAU,CAAA;aAAE,CAAC,CAAC;YAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;SAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IAClH,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACxB;AACD,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AAEhJ,MAAM,WAAW,cAAc;IAC9B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,qBAAa,cAAe,YAAW,OAAO;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,IAAI,GAAE,cAAmB;IAQrC,+FAA+F;IAC/F,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM;IAa1B,KAAK,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAahD,mEAAmE;YACrD,OAAO;YA2BP,UAAU;CAqBxB"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { isSafeSourceUrl, MAX_CONTENT_BYTES } from "./scanner-adapter.js";
|
|
3
|
+
function sha16(s) {
|
|
4
|
+
return createHash("sha256").update(s).digest("hex").slice(0, 16);
|
|
5
|
+
}
|
|
6
|
+
export class FetcherAdapter {
|
|
7
|
+
fetchImpl;
|
|
8
|
+
maxBytes;
|
|
9
|
+
maxHops;
|
|
10
|
+
timeoutMs;
|
|
11
|
+
constructor(opts = {}) {
|
|
12
|
+
// Builtin fetch is structurally compatible with FetchResponse (undici). Cast at the boundary.
|
|
13
|
+
this.fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
14
|
+
this.maxBytes = opts.maxBytes ?? MAX_CONTENT_BYTES;
|
|
15
|
+
this.maxHops = opts.maxHops ?? 3;
|
|
16
|
+
this.timeoutMs = opts.timeoutMs ?? 15000;
|
|
17
|
+
}
|
|
18
|
+
/** Map a seed to a fetch URL. Web seeds carry a URL; arXiv/GitHub map to their public APIs. */
|
|
19
|
+
buildUrl(seed) {
|
|
20
|
+
switch (seed.kind) {
|
|
21
|
+
case "web":
|
|
22
|
+
return seed.query;
|
|
23
|
+
case "arxiv":
|
|
24
|
+
return "http://export.arxiv.org/api/query?search_query=all:" + encodeURIComponent(seed.query) + "&max_results=1";
|
|
25
|
+
case "github":
|
|
26
|
+
return "https://api.github.com/search/repositories?q=" + encodeURIComponent(seed.query) + "&per_page=1";
|
|
27
|
+
default:
|
|
28
|
+
throw new Error("seed kind is not fetchable: " + seed.kind);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async fetch(seed) {
|
|
32
|
+
const url = this.buildUrl(seed);
|
|
33
|
+
const content = await this.safeGet(url);
|
|
34
|
+
const source = {
|
|
35
|
+
id: "src-" + sha16(url),
|
|
36
|
+
kind: seed.kind,
|
|
37
|
+
url,
|
|
38
|
+
fetchedAt: new Date().toISOString(),
|
|
39
|
+
contentHash: sha16(content),
|
|
40
|
+
};
|
|
41
|
+
return { content, sourceUrl: url, source };
|
|
42
|
+
}
|
|
43
|
+
/** url-guard at EVERY hop; manual redirects; size cap; timeout. */
|
|
44
|
+
async safeGet(startUrl) {
|
|
45
|
+
let url = startUrl;
|
|
46
|
+
for (let hop = 0; hop <= this.maxHops; hop++) {
|
|
47
|
+
if (!isSafeSourceUrl(url))
|
|
48
|
+
throw new Error("blocked unsafe URL: " + url);
|
|
49
|
+
const ctrl = new AbortController();
|
|
50
|
+
const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);
|
|
51
|
+
let res;
|
|
52
|
+
try {
|
|
53
|
+
res = await this.fetchImpl(url, { redirect: "manual", signal: ctrl.signal, headers: { "user-agent": "mewkit-wiki-research" } });
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
}
|
|
58
|
+
if (res.status >= 300 && res.status < 400) {
|
|
59
|
+
const loc = res.headers.get("location");
|
|
60
|
+
if (!loc)
|
|
61
|
+
throw new Error("redirect without Location header");
|
|
62
|
+
url = new URL(loc, url).toString(); // resolve relative; re-validated at loop top
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (!res.ok)
|
|
66
|
+
throw new Error("fetch failed: HTTP " + res.status);
|
|
67
|
+
const cl = Number(res.headers.get("content-length") ?? "0");
|
|
68
|
+
// Finite-guard: a non-numeric header coerces to NaN; the streaming cap is the real backstop.
|
|
69
|
+
if (Number.isFinite(cl) && cl > this.maxBytes)
|
|
70
|
+
throw new Error("size cap exceeded (content-length)");
|
|
71
|
+
return await this.readCapped(res);
|
|
72
|
+
}
|
|
73
|
+
throw new Error("too many redirects (> " + this.maxHops + ")");
|
|
74
|
+
}
|
|
75
|
+
async readCapped(res) {
|
|
76
|
+
// Fail closed on a body-less response — res.text() would read unbounded into memory with
|
|
77
|
+
// no streaming cap. A normal GET 200 always exposes a readable body.
|
|
78
|
+
if (!res.body)
|
|
79
|
+
throw new Error("response has no readable body");
|
|
80
|
+
const reader = res.body.getReader();
|
|
81
|
+
const chunks = [];
|
|
82
|
+
let total = 0;
|
|
83
|
+
for (;;) {
|
|
84
|
+
const { done, value } = await reader.read();
|
|
85
|
+
if (done)
|
|
86
|
+
break;
|
|
87
|
+
if (value) {
|
|
88
|
+
total += value.length;
|
|
89
|
+
if (total > this.maxBytes) {
|
|
90
|
+
await reader.cancel();
|
|
91
|
+
throw new Error("size cap exceeded during stream");
|
|
92
|
+
}
|
|
93
|
+
chunks.push(value);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=fetcher-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetcher-adapter.js","sourceRoot":"","sources":["../../../src/wiki/infrastructure/fetcher-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InventoryRegistrar } from "../application/ports.js";
|
|
2
|
+
/** The wiki serves the existing "project-memory" responsibility (see core/substrate.ts TAXONOMY). */
|
|
3
|
+
export declare const WIKI_RESPONSIBILITY = "project-memory";
|
|
4
|
+
export declare class InventoryAdapter implements InventoryRegistrar {
|
|
5
|
+
private readonly claudeDir;
|
|
6
|
+
constructor(claudeDir: string);
|
|
7
|
+
private file;
|
|
8
|
+
register(artifactPath: string, meta?: {
|
|
9
|
+
criticality?: string;
|
|
10
|
+
status?: string;
|
|
11
|
+
}): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=inventory-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory-adapter.d.ts","sourceRoot":"","sources":["../../../src/wiki/infrastructure/inventory-adapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAOlE,qGAAqG;AACrG,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AAOpD,qBAAa,gBAAiB,YAAW,kBAAkB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM;IAE9C,OAAO,CAAC,IAAI;IAIZ,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,IAAI;CA0B1F"}
|