@haaaiawd/second-nature 0.1.26 → 0.1.29
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/SKILL.md +35 -0
- package/agent-inner-guide.md +144 -0
- package/index.js +280 -2
- package/openclaw.plugin.json +2 -2
- package/package.json +4 -1
- package/runtime/cli/commands/connector-behavior.d.ts +20 -0
- package/runtime/cli/commands/connector-behavior.js +160 -0
- package/runtime/cli/commands/index.js +8 -0
- package/runtime/cli/index.js +9 -2
- package/runtime/cli/ops/manual-run-dispatcher.d.ts +79 -0
- package/runtime/cli/ops/manual-run-dispatcher.js +110 -0
- package/runtime/cli/ops/ops-router.d.ts +45 -4
- package/runtime/cli/ops/ops-router.js +543 -2
- package/runtime/cli/read-models/index.js +35 -18
- package/runtime/cli/read-models/types.d.ts +1 -0
- package/runtime/connectors/agent-network/agent-world/adapter.d.ts +1 -0
- package/runtime/connectors/agent-network/agent-world/adapter.js +2 -2
- package/runtime/connectors/base/contract.d.ts +4 -1
- package/runtime/connectors/base/contract.js +5 -1
- package/runtime/connectors/base/effect-commit-ledger-sqlite.d.ts +31 -0
- package/runtime/connectors/base/effect-commit-ledger-sqlite.js +86 -0
- package/runtime/connectors/base/failure-taxonomy.js +5 -0
- package/runtime/connectors/base/manifest-v7.d.ts +151 -0
- package/runtime/connectors/base/manifest-v7.js +170 -0
- package/runtime/connectors/base/manifest.d.ts +3 -13
- package/runtime/connectors/base/manifest.js +7 -7
- package/runtime/connectors/base/route-planner.js +11 -8
- package/runtime/connectors/base/structured-unavailable-reason.d.ts +59 -0
- package/runtime/connectors/base/structured-unavailable-reason.js +113 -0
- package/runtime/connectors/base/wet-probe-runner.d.ts +40 -0
- package/runtime/connectors/base/wet-probe-runner.js +132 -0
- package/runtime/connectors/manifest/manifest-schema.d.ts +4 -0
- package/runtime/connectors/manifest/manifest-schema.js +2 -0
- package/runtime/connectors/services/connector-executor-adapter.d.ts +1 -0
- package/runtime/connectors/services/connector-executor-adapter.js +132 -26
- package/runtime/core/second-nature/body/behavior-promotion/behavior-promotion-loop.d.ts +45 -0
- package/runtime/core/second-nature/body/behavior-promotion/behavior-promotion-loop.js +132 -0
- package/runtime/core/second-nature/body/circuit-breaker/circuit-breaker-manager.d.ts +60 -0
- package/runtime/core/second-nature/body/circuit-breaker/circuit-breaker-manager.js +174 -0
- package/runtime/core/second-nature/body/probe-signal-adapter.d.ts +38 -0
- package/runtime/core/second-nature/body/probe-signal-adapter.js +60 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-assembler.d.ts +51 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-assembler.js +129 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-context-scope.d.ts +30 -0
- package/runtime/core/second-nature/body/tool-affordance/affordance-context-scope.js +92 -0
- package/runtime/core/second-nature/body/tool-experience/experience-writer.d.ts +34 -0
- package/runtime/core/second-nature/body/tool-experience/experience-writer.js +67 -0
- package/runtime/core/second-nature/body/tool-experience/pain-signal-query.d.ts +37 -0
- package/runtime/core/second-nature/body/tool-experience/pain-signal-query.js +62 -0
- package/runtime/core/second-nature/heartbeat/decision-trace-emitter.d.ts +29 -0
- package/runtime/core/second-nature/heartbeat/decision-trace-emitter.js +28 -0
- package/runtime/core/second-nature/heartbeat/embodied-context-assembler.d.ts +54 -0
- package/runtime/core/second-nature/heartbeat/embodied-context-assembler.js +164 -0
- package/runtime/core/second-nature/heartbeat/goal-lifecycle-policy.d.ts +37 -0
- package/runtime/core/second-nature/heartbeat/goal-lifecycle-policy.js +61 -0
- package/runtime/core/second-nature/heartbeat/idle-curiosity-policy.d.ts +37 -0
- package/runtime/core/second-nature/heartbeat/idle-curiosity-policy.js +60 -0
- package/runtime/core/second-nature/heartbeat/index.d.ts +4 -0
- package/runtime/core/second-nature/heartbeat/index.js +5 -0
- package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle-v7.d.ts +63 -0
- package/runtime/core/second-nature/heartbeat/run-heartbeat-cycle-v7.js +118 -0
- package/runtime/core/second-nature/orchestrator/downstream-intent-orchestrator.d.ts +41 -0
- package/runtime/core/second-nature/orchestrator/downstream-intent-orchestrator.js +43 -0
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +2 -1
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +2 -0
- package/runtime/core/second-nature/orchestrator/hard-guard-evaluator.d.ts +31 -0
- package/runtime/core/second-nature/orchestrator/hard-guard-evaluator.js +102 -0
- package/runtime/core/second-nature/orchestrator/index.d.ts +5 -0
- package/runtime/core/second-nature/orchestrator/index.js +7 -0
- package/runtime/core/second-nature/quiet/claim-synthesizer.d.ts +53 -0
- package/runtime/core/second-nature/quiet/claim-synthesizer.js +153 -0
- package/runtime/core/second-nature/quiet/daily-diary-writer.d.ts +29 -0
- package/runtime/core/second-nature/quiet/daily-diary-writer.js +92 -0
- package/runtime/core/second-nature/quiet/index.d.ts +5 -0
- package/runtime/core/second-nature/quiet/index.js +5 -0
- package/runtime/core/second-nature/quiet/run-source-backed-quiet.js +19 -12
- package/runtime/core/second-nature/types.d.ts +2 -0
- package/runtime/guidance/channel-feedback-ingestion-service.d.ts +88 -0
- package/runtime/guidance/channel-feedback-ingestion-service.js +231 -0
- package/runtime/guidance/guidance-draft-service.d.ts +60 -0
- package/runtime/guidance/guidance-draft-service.js +80 -0
- package/runtime/guidance/index.d.ts +3 -0
- package/runtime/guidance/index.js +3 -0
- package/runtime/guidance/outreach-draft-schema.d.ts +8 -8
- package/runtime/guidance/outreach-strategy-selector.d.ts +77 -0
- package/runtime/guidance/outreach-strategy-selector.js +211 -0
- package/runtime/observability/audit/append-only-audit-store.d.ts +20 -2
- package/runtime/observability/audit/append-only-audit-store.js +32 -6
- package/runtime/observability/audit/audit-envelope.d.ts +2 -1
- package/runtime/observability/audit/audit-envelope.js +8 -7
- package/runtime/observability/audit/audit-family-registry.json +66 -0
- package/runtime/observability/audit/family-registry.d.ts +43 -0
- package/runtime/observability/audit/family-registry.js +70 -0
- package/runtime/observability/index.d.ts +6 -1
- package/runtime/observability/index.js +6 -1
- package/runtime/observability/redaction/policy.d.ts +24 -3
- package/runtime/observability/redaction/policy.js +74 -0
- package/runtime/observability/services/heartbeat-digest-assembler.d.ts +152 -0
- package/runtime/observability/services/heartbeat-digest-assembler.js +248 -0
- package/runtime/observability/services/lived-experience-audit.js +6 -6
- package/runtime/observability/services/narrative-timeline-query-service.d.ts +136 -0
- package/runtime/observability/services/narrative-timeline-query-service.js +169 -0
- package/runtime/observability/services/restore-audit-service.d.ts +74 -0
- package/runtime/observability/services/restore-audit-service.js +79 -0
- package/runtime/observability/services/runtime-secret-anchor-view.d.ts +77 -0
- package/runtime/observability/services/runtime-secret-anchor-view.js +168 -0
- package/runtime/observability/services/self-health-snapshot.d.ts +92 -0
- package/runtime/observability/services/self-health-snapshot.js +251 -0
- package/runtime/shared/types/goal.d.ts +62 -0
- package/runtime/shared/types/goal.js +20 -0
- package/runtime/shared/types/index.d.ts +3 -0
- package/runtime/shared/types/index.js +3 -0
- package/runtime/shared/types/source-ref.d.ts +14 -0
- package/runtime/shared/types/source-ref.js +1 -0
- package/runtime/shared/types/v7-entities.d.ts +206 -0
- package/runtime/shared/types/v7-entities.js +27 -0
- package/runtime/storage/db/index.js +3 -0
- package/runtime/storage/db/migration-runner.d.ts +30 -0
- package/runtime/storage/db/migration-runner.js +93 -0
- package/runtime/storage/db/migrations/index.d.ts +5 -0
- package/runtime/storage/db/migrations/index.js +13 -0
- package/runtime/storage/db/migrations/v7-001-foundation.d.ts +13 -0
- package/runtime/storage/db/migrations/v7-001-foundation.js +144 -0
- package/runtime/storage/db/migrations/v7-002-effect-commit-ledger.d.ts +8 -0
- package/runtime/storage/db/migrations/v7-002-effect-commit-ledger.js +27 -0
- package/runtime/storage/db/migrations/v7-003-circuit-breaker.d.ts +7 -0
- package/runtime/storage/db/migrations/v7-003-circuit-breaker.js +26 -0
- package/runtime/storage/db/migrations/v7-004-behavior-promotion.d.ts +7 -0
- package/runtime/storage/db/migrations/v7-004-behavior-promotion.js +26 -0
- package/runtime/storage/db/schema/agent-goal.d.ts +38 -0
- package/runtime/storage/db/schema/agent-goal.js +2 -0
- package/runtime/storage/db/transaction-utils.d.ts +14 -0
- package/runtime/storage/db/transaction-utils.js +29 -0
- package/runtime/storage/db/write-queue.d.ts +38 -0
- package/runtime/storage/db/write-queue.js +97 -0
- package/runtime/storage/quiet/persist-quiet-artifact.js +2 -1
- package/runtime/storage/services/credential-vault.js +31 -17
- package/runtime/storage/services/diary-dream-store.d.ts +35 -0
- package/runtime/storage/services/diary-dream-store.js +165 -0
- package/runtime/storage/services/embodied-context-state-port.d.ts +77 -0
- package/runtime/storage/services/embodied-context-state-port.js +115 -0
- package/runtime/storage/services/goal-lifecycle-store.d.ts +42 -0
- package/runtime/storage/services/goal-lifecycle-store.js +181 -0
- package/runtime/storage/services/history-digest-store.d.ts +33 -0
- package/runtime/storage/services/history-digest-store.js +140 -0
- package/runtime/storage/services/identity-profile-store.d.ts +25 -0
- package/runtime/storage/services/identity-profile-store.js +81 -0
- package/runtime/storage/services/interaction-snapshot-projector.d.ts +15 -0
- package/runtime/storage/services/interaction-snapshot-projector.js +35 -0
- package/runtime/storage/services/restore-snapshot-store.d.ts +52 -0
- package/runtime/storage/services/restore-snapshot-store.js +193 -0
- package/runtime/storage/services/runtime-secret-anchor-store.d.ts +26 -0
- package/runtime/storage/services/runtime-secret-anchor-store.js +82 -0
- package/runtime/storage/services/tool-experience-store.d.ts +25 -0
- package/runtime/storage/services/tool-experience-store.js +116 -0
- package/runtime/storage/services/write-validation-gate.d.ts +46 -0
- package/runtime/storage/services/write-validation-gate.js +200 -0
- package/workspace-ops-bridge.js +16 -1
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OutreachStrategySelector — T-GVS.C.3
|
|
3
|
+
*
|
|
4
|
+
* Core logic: select expression frequency, phrasing style and fallback copy
|
|
5
|
+
* based on RelationshipMemory; apply DR-031 language quality lint (3 rules).
|
|
6
|
+
* style_lint_failed is a degraded marker — it never blocks delivery.
|
|
7
|
+
* fallback copy always has information value (not empty string).
|
|
8
|
+
*
|
|
9
|
+
* DR-031 lint rules:
|
|
10
|
+
* 1. no_dry_filler — no hollow phrases ("reach out", "touch base", "just checking in", etc.)
|
|
11
|
+
* 2. anchored — must contain a concrete source anchor (specific fact/observation reference)
|
|
12
|
+
* 3. no_over_explain — no excessive qualifications (≥3 hedge phrases in one draft)
|
|
13
|
+
*
|
|
14
|
+
* Boundary:
|
|
15
|
+
* - Reads RelationshipMemory (channelPreferences, responsePatterns, trustDelta).
|
|
16
|
+
* - Does NOT write state; returns OutreachStrategy recommendation only.
|
|
17
|
+
* - style_lint checks run on draft text passed in; strategy selection itself is rule-based.
|
|
18
|
+
*
|
|
19
|
+
* Test coverage:
|
|
20
|
+
* tests/unit/guidance/outreach-strategy-selector.test.ts
|
|
21
|
+
* tests/unit/guidance/outreach-style-fixtures.test.ts
|
|
22
|
+
*/
|
|
23
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
24
|
+
/** DR-031: hollow filler phrases that indicate "dry/plain" copy */
|
|
25
|
+
const DRY_FILLER_PATTERNS = [
|
|
26
|
+
/\bjust checking in\b/i,
|
|
27
|
+
/\breach(?:ing)? out\b/i,
|
|
28
|
+
/\btouch(?:ing)? base\b/i,
|
|
29
|
+
/\bcircle(?:ing)? back\b/i,
|
|
30
|
+
/\bfollowing up\b/i,
|
|
31
|
+
/\bhoping (?:this|to)\b/i,
|
|
32
|
+
/\b没什么特别的\b/,
|
|
33
|
+
/\b只是想聊聊\b/,
|
|
34
|
+
/\b随便问问\b/,
|
|
35
|
+
];
|
|
36
|
+
/** DR-031: patterns that signal a concrete anchor is present */
|
|
37
|
+
const ANCHOR_PATTERNS = [
|
|
38
|
+
/\b(?:because|since|given that|based on|after|when|you (?:said|mentioned|shared|noted))\b/i,
|
|
39
|
+
/\b(?:上次|你说|你提到|你分享|你提过|基于|根据|因为|之后|在.*之后)\b/,
|
|
40
|
+
/\[.*?\]/, // inline reference bracket
|
|
41
|
+
/\[ref:/i, // explicit source ref notation
|
|
42
|
+
];
|
|
43
|
+
/** DR-031: hedge phrases that over-explain */
|
|
44
|
+
const HEDGE_PHRASES = [
|
|
45
|
+
/\bnot sure if\b/i,
|
|
46
|
+
/\bperhaps\b/i,
|
|
47
|
+
/\bmaybe\b/i,
|
|
48
|
+
/\bpossibly\b/i,
|
|
49
|
+
/\bif that makes sense\b/i,
|
|
50
|
+
/\bi (?:don't|do not) know if\b/i,
|
|
51
|
+
/\bi could be wrong\b/i,
|
|
52
|
+
/\b也许\b/,
|
|
53
|
+
/\b可能\b/,
|
|
54
|
+
/\b说不定\b/,
|
|
55
|
+
/\b不确定\b/,
|
|
56
|
+
/\b不知道是否\b/,
|
|
57
|
+
];
|
|
58
|
+
const HEDGE_THRESHOLD = 3; // ≥3 in one draft → over_explain
|
|
59
|
+
/** Trust thresholds for frequency selection */
|
|
60
|
+
const TRUST_MINIMAL = -0.4;
|
|
61
|
+
const TRUST_REDUCED = -0.1;
|
|
62
|
+
/** No-reply signal: if ≥ this ratio of recent patterns are "ignore", reduce frequency */
|
|
63
|
+
const NO_REPLY_RATIO_THRESHOLD = 0.5;
|
|
64
|
+
const RECENT_PATTERNS_WINDOW = 5;
|
|
65
|
+
// ─── Language Quality Lint (DR-031) ─────────────────────────────────────────
|
|
66
|
+
/**
|
|
67
|
+
* Run DR-031 language quality checklist on a draft text.
|
|
68
|
+
* Returns StyleLintResult. style_lint_failed is a degraded marker — never blocks delivery.
|
|
69
|
+
*/
|
|
70
|
+
export function runStyleLint(draftText) {
|
|
71
|
+
const violations = [];
|
|
72
|
+
const hitRules = [];
|
|
73
|
+
// Rule 1: no_dry_filler
|
|
74
|
+
const hasDryFiller = DRY_FILLER_PATTERNS.some((p) => p.test(draftText));
|
|
75
|
+
if (hasDryFiller) {
|
|
76
|
+
violations.push({
|
|
77
|
+
rule: "no_dry_filler",
|
|
78
|
+
description: "Draft contains hollow filler phrases (e.g. 'just checking in', 'reach out'). Replace with source-backed opener.",
|
|
79
|
+
});
|
|
80
|
+
hitRules.push("no_dry_filler");
|
|
81
|
+
}
|
|
82
|
+
// Rule 2: anchored — must have at least one concrete anchor
|
|
83
|
+
const hasAnchor = ANCHOR_PATTERNS.some((p) => p.test(draftText));
|
|
84
|
+
if (!hasAnchor) {
|
|
85
|
+
violations.push({
|
|
86
|
+
rule: "anchored",
|
|
87
|
+
description: "Draft lacks a concrete source anchor. Every claim should trace to observed evidence.",
|
|
88
|
+
});
|
|
89
|
+
hitRules.push("anchored");
|
|
90
|
+
}
|
|
91
|
+
// Rule 3: no_over_explain — count hedge phrase matches
|
|
92
|
+
const hedgeCount = HEDGE_PHRASES.reduce((acc, p) => {
|
|
93
|
+
const matches = draftText.match(new RegExp(p.source, p.flags + "g"));
|
|
94
|
+
return acc + (matches ? matches.length : 0);
|
|
95
|
+
}, 0);
|
|
96
|
+
if (hedgeCount >= HEDGE_THRESHOLD) {
|
|
97
|
+
violations.push({
|
|
98
|
+
rule: "no_over_explain",
|
|
99
|
+
description: `Draft contains ${hedgeCount} hedge phrases (threshold: ${HEDGE_THRESHOLD}). Remove qualifications unsupported by evidence.`,
|
|
100
|
+
});
|
|
101
|
+
hitRules.push("no_over_explain");
|
|
102
|
+
}
|
|
103
|
+
const passed = violations.length === 0;
|
|
104
|
+
return {
|
|
105
|
+
passed,
|
|
106
|
+
violations,
|
|
107
|
+
lintStatus: passed ? "passed" : "style_lint_failed",
|
|
108
|
+
hitRules,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// ─── Fallback Copy Builder ───────────────────────────────────────────────────
|
|
112
|
+
/**
|
|
113
|
+
* Build channel-safe fallback copy that always has information value (DR-031 G4).
|
|
114
|
+
* Never returns empty string. Includes sourceRefs anchor and human-readable channel reason.
|
|
115
|
+
*/
|
|
116
|
+
export function buildFallbackCopy(ctx) {
|
|
117
|
+
const anchor = ctx.sourceRefs.length > 0 ? ctx.sourceRefs[0] : undefined;
|
|
118
|
+
// Construct informative text — not just a status message
|
|
119
|
+
let text;
|
|
120
|
+
if (anchor) {
|
|
121
|
+
text = `[channel-safe] Based on ${anchor}: ${ctx.reason}`;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
text = `[channel-safe] ${ctx.reason}`;
|
|
125
|
+
}
|
|
126
|
+
// Ensure the text contains an unsupported-claim-free, factual statement
|
|
127
|
+
const channelSafeReason = `Delivery currently unavailable via ${ctx.channelId ?? "this channel"}. ${ctx.reason}`;
|
|
128
|
+
return {
|
|
129
|
+
text,
|
|
130
|
+
hasInformationValue: true,
|
|
131
|
+
sourceAnchor: anchor,
|
|
132
|
+
channelSafeReason,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// ─── Strategy Selection ──────────────────────────────────────────────────────
|
|
136
|
+
/**
|
|
137
|
+
* Compute outreach frequency from RelationshipMemory.
|
|
138
|
+
* - noReply signals: if ≥50% of last 5 patterns are "ignore" → reduce frequency
|
|
139
|
+
* - trustDelta: negative trust pushes toward minimal/paused
|
|
140
|
+
*/
|
|
141
|
+
function computeFrequency(memory) {
|
|
142
|
+
const recent = memory.responsePatterns.slice(-RECENT_PATTERNS_WINDOW);
|
|
143
|
+
const noReplyCount = recent.filter((p) => p.reaction === "ignore" || p.reaction === "block").length;
|
|
144
|
+
const noReplyRatio = recent.length > 0 ? noReplyCount / recent.length : 0;
|
|
145
|
+
// Block reaction → always paused regardless of trust
|
|
146
|
+
const hasBlock = memory.responsePatterns.some((p) => p.reaction === "block");
|
|
147
|
+
if (hasBlock)
|
|
148
|
+
return "paused";
|
|
149
|
+
// Trust-based floor
|
|
150
|
+
if (memory.trustDelta <= TRUST_MINIMAL)
|
|
151
|
+
return "minimal";
|
|
152
|
+
if (memory.trustDelta <= TRUST_REDUCED)
|
|
153
|
+
return "reduced";
|
|
154
|
+
// No-reply signal override
|
|
155
|
+
if (noReplyRatio >= NO_REPLY_RATIO_THRESHOLD && recent.length >= 2)
|
|
156
|
+
return "reduced";
|
|
157
|
+
return "standard";
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Compute phrasing style from RelationshipMemory.
|
|
161
|
+
* - positive tone patterns → warm_anchored
|
|
162
|
+
* - neutral or mixed → concise_factual
|
|
163
|
+
* - degraded trust / mostly negative → light_check
|
|
164
|
+
*/
|
|
165
|
+
function computeStyle(memory, frequency) {
|
|
166
|
+
if (frequency === "paused" || frequency === "minimal")
|
|
167
|
+
return "light_check";
|
|
168
|
+
const recent = memory.responsePatterns.slice(-RECENT_PATTERNS_WINDOW);
|
|
169
|
+
const positiveCount = recent.filter((p) => p.tone === "positive").length;
|
|
170
|
+
const negativeCount = recent.filter((p) => p.tone === "negative").length;
|
|
171
|
+
if (positiveCount > negativeCount && positiveCount >= 2)
|
|
172
|
+
return "warm_anchored";
|
|
173
|
+
if (negativeCount > positiveCount)
|
|
174
|
+
return "light_check";
|
|
175
|
+
return "concise_factual";
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Compute rationale string summarising why this strategy was chosen.
|
|
179
|
+
* Used for transparency / explain bundle — not for delivery copy.
|
|
180
|
+
*/
|
|
181
|
+
function buildRationale(memory, frequency, style) {
|
|
182
|
+
const parts = [];
|
|
183
|
+
parts.push(`trust_delta=${memory.trustDelta.toFixed(2)}`);
|
|
184
|
+
parts.push(`patterns=${memory.responsePatterns.length}`);
|
|
185
|
+
const hasBlock = memory.responsePatterns.some((p) => p.reaction === "block");
|
|
186
|
+
if (hasBlock)
|
|
187
|
+
parts.push("block_detected");
|
|
188
|
+
const recent = memory.responsePatterns.slice(-RECENT_PATTERNS_WINDOW);
|
|
189
|
+
const noReplyCount = recent.filter((p) => p.reaction === "ignore").length;
|
|
190
|
+
if (noReplyCount > 0)
|
|
191
|
+
parts.push(`no_reply_signals=${noReplyCount}`);
|
|
192
|
+
parts.push(`→ frequency=${frequency} style=${style}`);
|
|
193
|
+
return parts.join("; ");
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Select outreach strategy based on RelationshipMemory.
|
|
197
|
+
* Returns OutreachStrategy (frequency + style + fallbackCopy + rationale).
|
|
198
|
+
* Does NOT write state.
|
|
199
|
+
*/
|
|
200
|
+
export function selectOutreachStrategy(memory, options) {
|
|
201
|
+
const frequency = computeFrequency(memory);
|
|
202
|
+
const style = computeStyle(memory, frequency);
|
|
203
|
+
const rationale = buildRationale(memory, frequency, style);
|
|
204
|
+
const fallbackCtx = options?.fallbackContext ?? {
|
|
205
|
+
sourceRefs: [],
|
|
206
|
+
reason: "Outreach conditions not met at this time.",
|
|
207
|
+
channelId: undefined,
|
|
208
|
+
};
|
|
209
|
+
const fallbackCopy = buildFallbackCopy(fallbackCtx);
|
|
210
|
+
return { frequency, style, fallbackCopy, rationale };
|
|
211
|
+
}
|
|
@@ -1,14 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* In-memory append-only audit store with hash-chain verification hooks.
|
|
3
|
+
* v7 (DR-033): per-family lastHashCache for O(1) previousHash lookup.
|
|
3
4
|
*
|
|
4
|
-
* Core logic:
|
|
5
|
+
* Core logic:
|
|
6
|
+
* - reject broken previousHash links per audit family
|
|
7
|
+
* - maintain in-memory lastHashCache so append() is O(1) regardless of store size
|
|
8
|
+
* - seedFamilyHash() for post-restart backfill from DB latest record
|
|
5
9
|
*
|
|
6
10
|
* Test coverage: tests/unit/observability/audit-envelope.test.ts
|
|
7
11
|
*/
|
|
8
12
|
import type { AuditEnvelope } from "./audit-envelope.js";
|
|
9
13
|
export declare class AppendOnlyAuditStore {
|
|
10
14
|
private readonly events;
|
|
15
|
+
private readonly lastHashCache;
|
|
11
16
|
append<T>(envelope: AuditEnvelope<T>): void;
|
|
12
17
|
list(): readonly AuditEnvelope<unknown>[];
|
|
13
|
-
|
|
18
|
+
/** O(1) per-family previousHash; falls back to global last when family omitted (backward compat). */
|
|
19
|
+
lastRecordHash(family?: string): string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Seed cache after process restart from DB latest record (DR-033 backfill).
|
|
22
|
+
*
|
|
23
|
+
* TODO(T-OBS.C.1): wire a startup bootstrap routine that queries the DB audit_log
|
|
24
|
+
* table for the latest recordHash per family and calls seedFamilyHash().
|
|
25
|
+
* Blocked: the observability DB schema does not yet have an audit_log table
|
|
26
|
+
* with previousHash/recordHash columns; once added, backfill should be
|
|
27
|
+
* invoked in the store constructor or at app bootstrap time.
|
|
28
|
+
*/
|
|
29
|
+
seedFamilyHash(family: string, hash: string): void;
|
|
30
|
+
/** Expose cached families for diagnostics / testing. */
|
|
31
|
+
cachedFamilies(): readonly string[];
|
|
14
32
|
}
|
|
@@ -1,21 +1,47 @@
|
|
|
1
1
|
export class AppendOnlyAuditStore {
|
|
2
2
|
events = [];
|
|
3
|
+
lastHashCache = new Map();
|
|
3
4
|
append(envelope) {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const family = envelope.family;
|
|
6
|
+
const cachedHash = this.lastHashCache.get(family);
|
|
7
|
+
if (cachedHash !== undefined) {
|
|
8
|
+
if (envelope.integrity.previousHash !== cachedHash) {
|
|
7
9
|
throw new Error("audit_previous_hash_mismatch");
|
|
8
10
|
}
|
|
9
11
|
}
|
|
10
|
-
else
|
|
11
|
-
|
|
12
|
+
else {
|
|
13
|
+
// No family cache — first event for this family
|
|
14
|
+
if (envelope.integrity.previousHash !== undefined) {
|
|
15
|
+
throw new Error("audit_genesis_previous_hash");
|
|
16
|
+
}
|
|
12
17
|
}
|
|
13
18
|
this.events.push(envelope);
|
|
19
|
+
this.lastHashCache.set(family, envelope.integrity.recordHash);
|
|
14
20
|
}
|
|
15
21
|
list() {
|
|
16
22
|
return this.events;
|
|
17
23
|
}
|
|
18
|
-
|
|
24
|
+
/** O(1) per-family previousHash; falls back to global last when family omitted (backward compat). */
|
|
25
|
+
lastRecordHash(family) {
|
|
26
|
+
if (family) {
|
|
27
|
+
return this.lastHashCache.get(family);
|
|
28
|
+
}
|
|
19
29
|
return this.events[this.events.length - 1]?.integrity.recordHash;
|
|
20
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Seed cache after process restart from DB latest record (DR-033 backfill).
|
|
33
|
+
*
|
|
34
|
+
* TODO(T-OBS.C.1): wire a startup bootstrap routine that queries the DB audit_log
|
|
35
|
+
* table for the latest recordHash per family and calls seedFamilyHash().
|
|
36
|
+
* Blocked: the observability DB schema does not yet have an audit_log table
|
|
37
|
+
* with previousHash/recordHash columns; once added, backfill should be
|
|
38
|
+
* invoked in the store constructor or at app bootstrap time.
|
|
39
|
+
*/
|
|
40
|
+
seedFamilyHash(family, hash) {
|
|
41
|
+
this.lastHashCache.set(family, hash);
|
|
42
|
+
}
|
|
43
|
+
/** Expose cached families for diagnostics / testing. */
|
|
44
|
+
cachedFamilies() {
|
|
45
|
+
return Array.from(this.lastHashCache.keys());
|
|
46
|
+
}
|
|
21
47
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type RedactionManifest as FieldRedactionManifest } from "../redaction/manifest.js";
|
|
2
2
|
export type AuditPlane = "decision" | "delivery" | "source_coverage" | "governance" | "telemetry";
|
|
3
|
-
export type AuditEventFamily = "heartbeat.decision" | "delivery" | "source_coverage" | "guidance.grounding" | "host_capability" | "connector.attempt" | "state.governance" | "narrative.trace" | "dream.trace";
|
|
3
|
+
export type AuditEventFamily = "heartbeat.decision" | "delivery" | "source_coverage" | "guidance.grounding" | "host_capability" | "connector.attempt" | "state.governance" | "narrative.trace" | "dream.trace" | "restore.audit" | "health.probe" | "narrative.snapshot" | "secret.anchor";
|
|
4
4
|
export type AuditEnvelopeSensitivity = "public" | "internal" | "private" | "credential" | "sensitive";
|
|
5
5
|
export interface AuditRedactionManifest {
|
|
6
6
|
manifestId: string;
|
|
@@ -32,6 +32,7 @@ export interface RedactAuditEventResult<TPayload> {
|
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Apply field redaction rules and lift manifests to audit path vocabulary (observability-system.detail §2).
|
|
35
|
+
* T-OBS.C.1: now delegates to the unified redactPayload gate (DR-033).
|
|
35
36
|
*/
|
|
36
37
|
export declare function redactAuditEvent<TPayload extends object>(payload: TPayload): RedactAuditEventResult<TPayload>;
|
|
37
38
|
export interface BuildAuditEnvelopeInput<TPayload extends object> {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Test coverage: tests/unit/observability/audit-envelope.test.ts
|
|
12
12
|
*/
|
|
13
13
|
import * as crypto from "node:crypto";
|
|
14
|
-
import {
|
|
14
|
+
import { redactPayload } from "../redaction/policy.js";
|
|
15
15
|
function fieldPathToAuditPath(field) {
|
|
16
16
|
if (field.startsWith("/")) {
|
|
17
17
|
return field;
|
|
@@ -34,16 +34,17 @@ function mapSensitivity(level) {
|
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Apply field redaction rules and lift manifests to audit path vocabulary (observability-system.detail §2).
|
|
37
|
+
* T-OBS.C.1: now delegates to the unified redactPayload gate (DR-033).
|
|
37
38
|
*/
|
|
38
39
|
export function redactAuditEvent(payload) {
|
|
39
|
-
const { redacted, manifest } =
|
|
40
|
+
const { payload: redacted, manifest } = redactPayload(payload);
|
|
40
41
|
const redaction = {
|
|
41
|
-
manifestId:
|
|
42
|
-
maskedPaths: manifest.
|
|
43
|
-
erasedPaths: manifest.
|
|
44
|
-
hashedPaths: manifest.
|
|
42
|
+
manifestId: `rm:${Date.now()}:${crypto.randomBytes(4).toString("hex")}`,
|
|
43
|
+
maskedPaths: manifest.maskedPaths.map(fieldPathToAuditPath),
|
|
44
|
+
erasedPaths: manifest.erasedPaths.map(fieldPathToAuditPath),
|
|
45
|
+
hashedPaths: manifest.hashedPaths.map(fieldPathToAuditPath),
|
|
45
46
|
contentRefPaths: [],
|
|
46
|
-
sensitivity: mapSensitivity(manifest.
|
|
47
|
+
sensitivity: mapSensitivity(manifest.sensitivity),
|
|
47
48
|
};
|
|
48
49
|
return { payload: redacted, redaction };
|
|
49
50
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "audit-family-registry/v1",
|
|
3
|
+
"description": "Registered audit families for all 8 v7 systems. Unknown families are rejected at write time.",
|
|
4
|
+
"families": [
|
|
5
|
+
{
|
|
6
|
+
"family": "heartbeat.decision",
|
|
7
|
+
"plane": "decision",
|
|
8
|
+
"systemId": "control-plane-system",
|
|
9
|
+
"description": "Heartbeat decision cycle trace"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"family": "delivery",
|
|
13
|
+
"plane": "delivery",
|
|
14
|
+
"systemId": "guidance-voice-system",
|
|
15
|
+
"description": "Guidance delivery attempt and outcome"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"family": "source_coverage",
|
|
19
|
+
"plane": "source_coverage",
|
|
20
|
+
"systemId": "observability-health-system",
|
|
21
|
+
"description": "Source grounding and coverage assertions"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"family": "guidance.grounding",
|
|
25
|
+
"plane": "governance",
|
|
26
|
+
"systemId": "guidance-voice-system",
|
|
27
|
+
"description": "Guidance draft grounding and voice audit"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"family": "host_capability",
|
|
31
|
+
"plane": "telemetry",
|
|
32
|
+
"systemId": "runtime-ops-system",
|
|
33
|
+
"description": "Host capability probe and environment telemetry"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"family": "connector.attempt",
|
|
37
|
+
"plane": "telemetry",
|
|
38
|
+
"systemId": "connector-system",
|
|
39
|
+
"description": "Connector execution attempt and circuit breaker events"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"family": "state.governance",
|
|
43
|
+
"plane": "governance",
|
|
44
|
+
"systemId": "state-memory-system",
|
|
45
|
+
"description": "State mutation governance and write validation"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"family": "narrative.trace",
|
|
49
|
+
"plane": "telemetry",
|
|
50
|
+
"systemId": "observability-health-system",
|
|
51
|
+
"description": "Narrative timeline change trace"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"family": "dream.trace",
|
|
55
|
+
"plane": "telemetry",
|
|
56
|
+
"systemId": "dream-quiet-system",
|
|
57
|
+
"description": "Dream and quiet pipeline execution trace"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"family": "body.tool_experience",
|
|
61
|
+
"plane": "telemetry",
|
|
62
|
+
"systemId": "body-tool-system",
|
|
63
|
+
"description": "Tool experience logging and affordance map events"
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit family registry runtime (DR-040).
|
|
3
|
+
*
|
|
4
|
+
* Core logic:
|
|
5
|
+
* - Loads registered families from `audit-family-registry.json`.
|
|
6
|
+
* - Provides lookup and validation for audit write operations.
|
|
7
|
+
* - Rejects writes from unknown (unregistered) families with
|
|
8
|
+
* `unknown_audit_family` error.
|
|
9
|
+
* - Covers all 8 v7 system boundaries.
|
|
10
|
+
*
|
|
11
|
+
* Dependencies: audit-family-registry.json (co-located).
|
|
12
|
+
* Boundary: Called before any audit write to validate family membership.
|
|
13
|
+
* Test coverage: tests/unit/observability/family-registry.test.ts
|
|
14
|
+
*/
|
|
15
|
+
export interface AuditFamilyEntry {
|
|
16
|
+
family: string;
|
|
17
|
+
plane: string;
|
|
18
|
+
systemId: string;
|
|
19
|
+
description: string;
|
|
20
|
+
}
|
|
21
|
+
export interface AuditFamilyRegistryData {
|
|
22
|
+
$schema: string;
|
|
23
|
+
description: string;
|
|
24
|
+
families: AuditFamilyEntry[];
|
|
25
|
+
}
|
|
26
|
+
export declare class AuditFamilyRegistry {
|
|
27
|
+
private readonly entries;
|
|
28
|
+
constructor(families: readonly AuditFamilyEntry[]);
|
|
29
|
+
isRegistered(family: string): boolean;
|
|
30
|
+
getEntry(family: string): AuditFamilyEntry | undefined;
|
|
31
|
+
validateFamily(family: string): {
|
|
32
|
+
ok: true;
|
|
33
|
+
} | {
|
|
34
|
+
ok: false;
|
|
35
|
+
error: string;
|
|
36
|
+
};
|
|
37
|
+
listFamilies(): readonly AuditFamilyEntry[];
|
|
38
|
+
listSystemIds(): string[];
|
|
39
|
+
familiesForSystem(systemId: string): AuditFamilyEntry[];
|
|
40
|
+
get size(): number;
|
|
41
|
+
}
|
|
42
|
+
export declare function loadAuditFamilyRegistry(): AuditFamilyRegistry;
|
|
43
|
+
export declare function createAuditFamilyRegistry(families: readonly AuditFamilyEntry[]): AuditFamilyRegistry;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit family registry runtime (DR-040).
|
|
3
|
+
*
|
|
4
|
+
* Core logic:
|
|
5
|
+
* - Loads registered families from `audit-family-registry.json`.
|
|
6
|
+
* - Provides lookup and validation for audit write operations.
|
|
7
|
+
* - Rejects writes from unknown (unregistered) families with
|
|
8
|
+
* `unknown_audit_family` error.
|
|
9
|
+
* - Covers all 8 v7 system boundaries.
|
|
10
|
+
*
|
|
11
|
+
* Dependencies: audit-family-registry.json (co-located).
|
|
12
|
+
* Boundary: Called before any audit write to validate family membership.
|
|
13
|
+
* Test coverage: tests/unit/observability/family-registry.test.ts
|
|
14
|
+
*/
|
|
15
|
+
import { readFileSync } from "node:fs";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
export class AuditFamilyRegistry {
|
|
19
|
+
entries;
|
|
20
|
+
constructor(families) {
|
|
21
|
+
const map = new Map();
|
|
22
|
+
for (const entry of families) {
|
|
23
|
+
map.set(entry.family, entry);
|
|
24
|
+
}
|
|
25
|
+
this.entries = map;
|
|
26
|
+
}
|
|
27
|
+
isRegistered(family) {
|
|
28
|
+
return this.entries.has(family);
|
|
29
|
+
}
|
|
30
|
+
getEntry(family) {
|
|
31
|
+
return this.entries.get(family);
|
|
32
|
+
}
|
|
33
|
+
validateFamily(family) {
|
|
34
|
+
if (this.entries.has(family)) {
|
|
35
|
+
return { ok: true };
|
|
36
|
+
}
|
|
37
|
+
return { ok: false, error: `unknown_audit_family: ${family}` };
|
|
38
|
+
}
|
|
39
|
+
listFamilies() {
|
|
40
|
+
return [...this.entries.values()];
|
|
41
|
+
}
|
|
42
|
+
listSystemIds() {
|
|
43
|
+
const ids = new Set();
|
|
44
|
+
for (const entry of this.entries.values()) {
|
|
45
|
+
ids.add(entry.systemId);
|
|
46
|
+
}
|
|
47
|
+
return [...ids].sort();
|
|
48
|
+
}
|
|
49
|
+
familiesForSystem(systemId) {
|
|
50
|
+
return [...this.entries.values()].filter((e) => e.systemId === systemId);
|
|
51
|
+
}
|
|
52
|
+
get size() {
|
|
53
|
+
return this.entries.size;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
let defaultRegistry;
|
|
57
|
+
export function loadAuditFamilyRegistry() {
|
|
58
|
+
if (defaultRegistry) {
|
|
59
|
+
return defaultRegistry;
|
|
60
|
+
}
|
|
61
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
62
|
+
const jsonPath = path.join(__dirname, "audit-family-registry.json");
|
|
63
|
+
const raw = readFileSync(jsonPath, "utf-8");
|
|
64
|
+
const data = JSON.parse(raw);
|
|
65
|
+
defaultRegistry = new AuditFamilyRegistry(data.families);
|
|
66
|
+
return defaultRegistry;
|
|
67
|
+
}
|
|
68
|
+
export function createAuditFamilyRegistry(families) {
|
|
69
|
+
return new AuditFamilyRegistry(families);
|
|
70
|
+
}
|
|
@@ -3,7 +3,7 @@ export * as obsSchema from "./db/schema/index.js";
|
|
|
3
3
|
export { buildAuditEnvelope, computeAuditRecordHash, redactAuditEvent, auditManifestFromFieldManifest, type AuditEnvelope, type AuditEnvelopeSensitivity, type AuditEventFamily, type AuditPlane, type AuditRedactionManifest, type AuditIntegrity, type BuildAuditEnvelopeInput, type RedactAuditEventResult, } from "./audit/audit-envelope.js";
|
|
4
4
|
export { AppendOnlyAuditStore } from "./audit/append-only-audit-store.js";
|
|
5
5
|
export { verifyAuditHashChain, createAppendOnlyAuditStoreRangeLoader, type AuditExportRange, type AuditHashChainVerificationReport, type AuditHashChainVerificationStatus, type VerifyAuditHashChainDeps, } from "./audit/verify-audit-hash-chain.js";
|
|
6
|
-
export { REDACTION_CONFIG, DEFAULT_REDACTION_POLICY, getFieldRedactionRule, type RedactionPolicy, type RedactionRule, type SensitivityLevel, } from "./redaction/policy.js";
|
|
6
|
+
export { REDACTION_CONFIG, DEFAULT_REDACTION_POLICY, getFieldRedactionRule, redactPayload, type RedactionPolicy, type RedactionRule, type SensitivityLevel, type RedactPayloadManifest, type RedactPayloadResult, } from "./redaction/policy.js";
|
|
7
7
|
export { redactEvent, createEmptyManifest, mergeManifests, type RedactionManifest, type RedactionResult, } from "./redaction/manifest.js";
|
|
8
8
|
export { DecisionLedger, type QuietLifecycleEvent, type OutreachDecision, type HeartbeatDecisionEvent } from "./services/decision-ledger.js";
|
|
9
9
|
export { GovernanceAudit, type CredentialLifecycleAudit } from "./services/governance-audit.js";
|
|
@@ -18,3 +18,8 @@ export type { EvidenceQuery, EvidenceBundle, EvidenceResolutionPlan, GovernanceE
|
|
|
18
18
|
export { projectReflectionAudit, type ReflectionAudit, type ReflectionAuditProjection, } from "./projections/reflection-audit.js";
|
|
19
19
|
export { projectOutreachQualityAudit, type OutreachQualityAudit, type OutreachQualityProjection, } from "./projections/outreach-quality-audit.js";
|
|
20
20
|
export { projectGuidanceParticipationAudit, type GuidanceParticipationAudit, type GuidanceParticipationProjection, } from "./projections/guidance-audit.js";
|
|
21
|
+
export { getSelfHealthSnapshot, registerHealthProbe, unregisterHealthProbe, clearHealthProbeRegistry, ensureMinimumProbes, getRegisteredProbes, MINIMUM_REQUIRED_DIMENSIONS, type HealthStatus, type DimensionHealth, type SelfHealthSnapshot, type HealthProbeFunction, type RegisteredProbe, type HealthProbeScope, } from "./services/self-health-snapshot.js";
|
|
22
|
+
export { generateHeartbeatDigest, type HeartbeatDigest, type HeartbeatDigestAssemblerDeps, type StateMemoryDigestPort, type ConnectorDaySummary, type GoalDaySummary, type QuietDreamDaySummary, type HealthDaySummary, type DeliveryProofRef, type DigestDeliveryAdapter, type DigestDeliveryResult, } from "./services/heartbeat-digest-assembler.js";
|
|
23
|
+
export { queryNarrativeTimeline, queryNarrativeDiff, encodeCursor, decodeCursor, NarrativeQueryRangeError, NarrativeVersionNotFoundError, type NarrativeTimelineEntry, type NarrativeTimelinePage, type NarrativeFieldChange, type NarrativeDiff, type NarrativeTimelineRow, type NarrativeSnapshotRow, type NarrativeTimelinePort, type NarrativeTimelineDeps, } from "./services/narrative-timeline-query-service.js";
|
|
24
|
+
export { viewSecretAnchor, type RuntimeSecretAnchorView, type SecretAnchorStatus, type HealthProbeReasonCode, type RecoveryStep, type SampleDecryptResult, type SecretAnchorRuntimeOpsPort, type SecretAnchorCredentialPort, type SecretAnchorDeps, } from "./services/runtime-secret-anchor-view.js";
|
|
25
|
+
export { writeRestoreAudit, type RestoreAuditEvent, type RestoreTarget, type RestoreTrigger, type WriteRestoreAuditResult, } from "./services/restore-audit-service.js";
|
|
@@ -3,7 +3,7 @@ export * as obsSchema from "./db/schema/index.js";
|
|
|
3
3
|
export { buildAuditEnvelope, computeAuditRecordHash, redactAuditEvent, auditManifestFromFieldManifest, } from "./audit/audit-envelope.js";
|
|
4
4
|
export { AppendOnlyAuditStore } from "./audit/append-only-audit-store.js";
|
|
5
5
|
export { verifyAuditHashChain, createAppendOnlyAuditStoreRangeLoader, } from "./audit/verify-audit-hash-chain.js";
|
|
6
|
-
export { REDACTION_CONFIG, DEFAULT_REDACTION_POLICY, getFieldRedactionRule, } from "./redaction/policy.js";
|
|
6
|
+
export { REDACTION_CONFIG, DEFAULT_REDACTION_POLICY, getFieldRedactionRule, redactPayload, } from "./redaction/policy.js";
|
|
7
7
|
export { redactEvent, createEmptyManifest, mergeManifests, } from "./redaction/manifest.js";
|
|
8
8
|
export { DecisionLedger } from "./services/decision-ledger.js";
|
|
9
9
|
export { GovernanceAudit } from "./services/governance-audit.js";
|
|
@@ -17,3 +17,8 @@ export { EvidenceQueryEngine, } from "./query/evidence-query-engine.js";
|
|
|
17
17
|
export { projectReflectionAudit, } from "./projections/reflection-audit.js";
|
|
18
18
|
export { projectOutreachQualityAudit, } from "./projections/outreach-quality-audit.js";
|
|
19
19
|
export { projectGuidanceParticipationAudit, } from "./projections/guidance-audit.js";
|
|
20
|
+
export { getSelfHealthSnapshot, registerHealthProbe, unregisterHealthProbe, clearHealthProbeRegistry, ensureMinimumProbes, getRegisteredProbes, MINIMUM_REQUIRED_DIMENSIONS, } from "./services/self-health-snapshot.js";
|
|
21
|
+
export { generateHeartbeatDigest, } from "./services/heartbeat-digest-assembler.js";
|
|
22
|
+
export { queryNarrativeTimeline, queryNarrativeDiff, encodeCursor, decodeCursor, NarrativeQueryRangeError, NarrativeVersionNotFoundError, } from "./services/narrative-timeline-query-service.js";
|
|
23
|
+
export { viewSecretAnchor, } from "./services/runtime-secret-anchor-view.js";
|
|
24
|
+
export { writeRestoreAudit, } from "./services/restore-audit-service.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const REDACTION_CONFIG: {
|
|
2
|
-
readonly maskedFieldNames: readonly ["token", "access_token", "refresh_token", "api_key", "apiSecret", "secret", "password", "bearer_token", "authorization", "node_secret"];
|
|
3
|
-
readonly eraseFieldNames: readonly ["full_message", "full_post", "private_message", "prompt", "system_prompt", "completion", "response_content"];
|
|
4
|
-
readonly hashFieldNames: readonly ["user_id", "session_id", "trace_id", "content_hash"];
|
|
2
|
+
readonly maskedFieldNames: readonly ["token", "access_token", "refresh_token", "api_key", "apiSecret", "secret", "password", "bearer_token", "authorization", "node_secret", "encryption_key", "key_material"];
|
|
3
|
+
readonly eraseFieldNames: readonly ["full_message", "full_post", "private_message", "prompt", "system_prompt", "completion", "response_content", "raw_payload", "credential_value", "raw_prompt"];
|
|
4
|
+
readonly hashFieldNames: readonly ["user_id", "session_id", "trace_id", "content_hash", "message_hash"];
|
|
5
5
|
readonly sensitivityLevels: readonly ["public", "internal", "confidential", "restricted"];
|
|
6
6
|
};
|
|
7
7
|
export type SensitivityLevel = (typeof REDACTION_CONFIG)["sensitivityLevels"][number];
|
|
@@ -17,3 +17,24 @@ export interface RedactionPolicy {
|
|
|
17
17
|
}
|
|
18
18
|
export declare const DEFAULT_REDACTION_POLICY: RedactionPolicy;
|
|
19
19
|
export declare function getFieldRedactionRule(fieldName: string, policy?: RedactionPolicy): RedactionRule;
|
|
20
|
+
export interface RedactPayloadManifest {
|
|
21
|
+
maskedPaths: string[];
|
|
22
|
+
erasedPaths: string[];
|
|
23
|
+
hashedPaths: string[];
|
|
24
|
+
sensitivity: SensitivityLevel;
|
|
25
|
+
}
|
|
26
|
+
export interface RedactPayloadResult<T> {
|
|
27
|
+
payload: T;
|
|
28
|
+
manifest: RedactPayloadManifest;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Unified redaction gate — all audit-bound payloads must pass through this
|
|
32
|
+
* before persistence. Recursively applies mask/erase/hash rules from the
|
|
33
|
+
* active RedactionPolicy, preserving object shape (erase → null, not delete).
|
|
34
|
+
*
|
|
35
|
+
* Boundary:
|
|
36
|
+
* - Arrays are not recursed (avoid unbounded complexity).
|
|
37
|
+
* - erase fields become null so downstream JSON schema stays stable.
|
|
38
|
+
* - hash uses SHA-256 of the stringified original value.
|
|
39
|
+
*/
|
|
40
|
+
export declare function redactPayload<T extends object>(payload: T, policy?: RedactionPolicy): RedactPayloadResult<T>;
|