@haaaiawd/second-nature 0.1.1 → 0.1.3
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/index.ts +64 -21
- package/openclaw.plugin.json +1 -1
- package/package.json +8 -2
- package/runtime/cli/action-bridge.d.ts +11 -0
- package/runtime/cli/action-bridge.js +27 -0
- package/runtime/cli/commands/credential.d.ts +2 -0
- package/runtime/cli/commands/credential.js +40 -0
- package/runtime/cli/commands/index.d.ts +12 -0
- package/runtime/cli/commands/index.js +138 -0
- package/runtime/cli/commands/policy.d.ts +12 -0
- package/runtime/cli/commands/policy.js +43 -0
- package/runtime/cli/explain/format-explanation.d.ts +10 -0
- package/runtime/cli/explain/format-explanation.js +10 -0
- package/runtime/cli/explain/resolve-subject.d.ts +2 -0
- package/runtime/cli/explain/resolve-subject.js +26 -0
- package/runtime/cli/index.d.ts +25 -0
- package/runtime/cli/index.js +36 -0
- package/runtime/cli/read-models/index.d.ts +20 -0
- package/runtime/cli/read-models/index.js +161 -0
- package/runtime/cli/read-models/types.d.ts +75 -0
- package/runtime/cli/read-models/types.js +1 -0
- package/runtime/connectors/agent-network/evomap/adapter.d.ts +23 -0
- package/runtime/connectors/agent-network/evomap/adapter.js +69 -0
- package/runtime/connectors/agent-network/evomap/index.d.ts +2 -0
- package/runtime/connectors/agent-network/evomap/index.js +2 -0
- package/runtime/connectors/agent-network/evomap/manifest.d.ts +2 -0
- package/runtime/connectors/agent-network/evomap/manifest.js +7 -0
- package/runtime/connectors/base/channel-health.d.ts +29 -0
- package/runtime/connectors/base/channel-health.js +23 -0
- package/runtime/connectors/base/contract.d.ts +81 -0
- package/runtime/connectors/base/contract.js +71 -0
- package/runtime/connectors/base/failure-taxonomy.d.ts +13 -0
- package/runtime/connectors/base/failure-taxonomy.js +105 -0
- package/runtime/connectors/base/index.d.ts +6 -0
- package/runtime/connectors/base/index.js +6 -0
- package/runtime/connectors/base/manifest.d.ts +11 -0
- package/runtime/connectors/base/manifest.js +36 -0
- package/runtime/connectors/base/policy-layer.d.ts +27 -0
- package/runtime/connectors/base/policy-layer.js +213 -0
- package/runtime/connectors/base/route-planner.d.ts +10 -0
- package/runtime/connectors/base/route-planner.js +98 -0
- package/runtime/connectors/index.d.ts +4 -0
- package/runtime/connectors/index.js +4 -0
- package/runtime/connectors/social-community/instreet/adapter.d.ts +32 -0
- package/runtime/connectors/social-community/instreet/adapter.js +79 -0
- package/runtime/connectors/social-community/instreet/index.d.ts +2 -0
- package/runtime/connectors/social-community/instreet/index.js +2 -0
- package/runtime/connectors/social-community/instreet/manifest.d.ts +2 -0
- package/runtime/connectors/social-community/instreet/manifest.js +7 -0
- package/runtime/connectors/social-community/moltbook/adapter.d.ts +15 -0
- package/runtime/connectors/social-community/moltbook/adapter.js +48 -0
- package/runtime/connectors/social-community/moltbook/index.d.ts +2 -0
- package/runtime/connectors/social-community/moltbook/index.js +2 -0
- package/runtime/connectors/social-community/moltbook/manifest.d.ts +7 -0
- package/runtime/connectors/social-community/moltbook/manifest.js +12 -0
- package/runtime/core/second-nature/guidance/apply-guidance.d.ts +10 -0
- package/runtime/core/second-nature/guidance/apply-guidance.js +10 -0
- package/runtime/core/second-nature/guidance/request-guidance.d.ts +18 -0
- package/runtime/core/second-nature/guidance/request-guidance.js +22 -0
- package/runtime/core/second-nature/index.d.ts +14 -0
- package/runtime/core/second-nature/index.js +14 -0
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +100 -0
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +139 -0
- package/runtime/core/second-nature/orchestrator/guard-layer.d.ts +2 -0
- package/runtime/core/second-nature/orchestrator/guard-layer.js +54 -0
- package/runtime/core/second-nature/orchestrator/intent-planner.d.ts +3 -0
- package/runtime/core/second-nature/orchestrator/intent-planner.js +92 -0
- package/runtime/core/second-nature/orchestrator/lease-manager.d.ts +14 -0
- package/runtime/core/second-nature/orchestrator/lease-manager.js +58 -0
- package/runtime/core/second-nature/orchestrator/resume-from-checkpoint.d.ts +32 -0
- package/runtime/core/second-nature/orchestrator/resume-from-checkpoint.js +23 -0
- package/runtime/core/second-nature/outreach/build-message.d.ts +16 -0
- package/runtime/core/second-nature/outreach/build-message.js +27 -0
- package/runtime/core/second-nature/outreach/evaluate-outreach.d.ts +13 -0
- package/runtime/core/second-nature/outreach/evaluate-outreach.js +41 -0
- package/runtime/core/second-nature/quiet/quiet-pipeline.d.ts +34 -0
- package/runtime/core/second-nature/quiet/quiet-pipeline.js +35 -0
- package/runtime/core/second-nature/reflection/run-narrative-reflection.d.ts +39 -0
- package/runtime/core/second-nature/reflection/run-narrative-reflection.js +29 -0
- package/runtime/core/second-nature/rhythm/rhythm-policy.d.ts +18 -0
- package/runtime/core/second-nature/rhythm/rhythm-policy.js +24 -0
- package/runtime/core/second-nature/rhythm/select-window.d.ts +3 -0
- package/runtime/core/second-nature/rhythm/select-window.js +50 -0
- package/runtime/core/second-nature/runtime/lifecycle-service.d.ts +26 -0
- package/runtime/core/second-nature/runtime/lifecycle-service.js +38 -0
- package/runtime/core/second-nature/runtime/service-entry.d.ts +36 -0
- package/runtime/core/second-nature/runtime/service-entry.js +44 -0
- package/runtime/core/second-nature/types.d.ts +37 -0
- package/runtime/core/second-nature/types.js +1 -0
- package/runtime/guidance/contracts.d.ts +48 -0
- package/runtime/guidance/contracts.js +54 -0
- package/runtime/guidance/fallback.d.ts +2 -0
- package/runtime/guidance/fallback.js +17 -0
- package/runtime/guidance/guidance-assembler.d.ts +5 -0
- package/runtime/guidance/guidance-assembler.js +62 -0
- package/runtime/guidance/index.d.ts +8 -0
- package/runtime/guidance/index.js +8 -0
- package/runtime/guidance/output-guard.d.ts +10 -0
- package/runtime/guidance/output-guard.js +29 -0
- package/runtime/guidance/persona-selection.d.ts +11 -0
- package/runtime/guidance/persona-selection.js +90 -0
- package/runtime/guidance/review-workflow.d.ts +15 -0
- package/runtime/guidance/review-workflow.js +60 -0
- package/runtime/guidance/template-registry.d.ts +3 -0
- package/runtime/guidance/template-registry.js +45 -0
- package/runtime/guidance/types.d.ts +72 -0
- package/runtime/guidance/types.js +1 -0
- package/runtime/observability/db/index.d.ts +10 -0
- package/runtime/observability/db/index.js +17 -0
- package/runtime/observability/db/schema/index.d.ts +946 -0
- package/runtime/observability/db/schema/index.js +70 -0
- package/runtime/observability/index.d.ts +12 -0
- package/runtime/observability/index.js +11 -0
- package/runtime/observability/projections/guidance-audit.d.ts +16 -0
- package/runtime/observability/projections/guidance-audit.js +35 -0
- package/runtime/observability/projections/outreach-quality-audit.d.ts +15 -0
- package/runtime/observability/projections/outreach-quality-audit.js +9 -0
- package/runtime/observability/projections/reflection-audit.d.ts +17 -0
- package/runtime/observability/projections/reflection-audit.js +9 -0
- package/runtime/observability/query/compose-evidence.d.ts +56 -0
- package/runtime/observability/query/compose-evidence.js +43 -0
- package/runtime/observability/query/evidence-query-engine.d.ts +17 -0
- package/runtime/observability/query/evidence-query-engine.js +166 -0
- package/runtime/observability/redaction/manifest.d.ts +18 -0
- package/runtime/observability/redaction/manifest.js +109 -0
- package/runtime/observability/redaction/policy.d.ts +19 -0
- package/runtime/observability/redaction/policy.js +71 -0
- package/runtime/observability/services/decision-ledger.d.ts +33 -0
- package/runtime/observability/services/decision-ledger.js +115 -0
- package/runtime/observability/services/execution-telemetry.d.ts +32 -0
- package/runtime/observability/services/execution-telemetry.js +126 -0
- package/runtime/observability/services/governance-audit.d.ts +27 -0
- package/runtime/observability/services/governance-audit.js +139 -0
- package/runtime/observability/services/redaction-store.d.ts +3 -0
- package/runtime/observability/services/redaction-store.js +20 -0
- package/runtime/setup/HOST_SETUP.md +112 -0
- package/runtime/shared/types/continuity.d.ts +69 -0
- package/runtime/shared/types/continuity.js +1 -0
- package/runtime/shared/types/credential.d.ts +22 -0
- package/runtime/shared/types/credential.js +1 -0
- package/runtime/shared/types/index.d.ts +3 -0
- package/runtime/shared/types/index.js +3 -0
- package/runtime/shared/types/outreach.d.ts +19 -0
- package/runtime/shared/types/outreach.js +1 -0
- package/runtime/storage/bootstrap/repair.d.ts +3 -0
- package/runtime/storage/bootstrap/repair.js +5 -0
- package/runtime/storage/db/index.d.ts +10 -0
- package/runtime/storage/db/index.js +17 -0
- package/runtime/storage/db/schema/assets.d.ts +140 -0
- package/runtime/storage/db/schema/assets.js +10 -0
- package/runtime/storage/db/schema/credentials.d.ts +178 -0
- package/runtime/storage/db/schema/credentials.js +12 -0
- package/runtime/storage/db/schema/index.d.ts +6 -0
- package/runtime/storage/db/schema/index.js +6 -0
- package/runtime/storage/db/schema/intent-commits.d.ts +161 -0
- package/runtime/storage/db/schema/intent-commits.js +11 -0
- package/runtime/storage/db/schema/policies.d.ts +81 -0
- package/runtime/storage/db/schema/policies.js +7 -0
- package/runtime/storage/db/schema/proposals.d.ts +216 -0
- package/runtime/storage/db/schema/proposals.js +14 -0
- package/runtime/storage/db/schema/provenance.d.ts +104 -0
- package/runtime/storage/db/schema/provenance.js +8 -0
- package/runtime/storage/index.d.ts +16 -0
- package/runtime/storage/index.js +16 -0
- package/runtime/storage/memory/workspace/paths.d.ts +62 -0
- package/runtime/storage/memory/workspace/paths.js +160 -0
- package/runtime/storage/memory/workspace/store.d.ts +26 -0
- package/runtime/storage/memory/workspace/store.js +153 -0
- package/runtime/storage/memory/workspace/types.d.ts +45 -0
- package/runtime/storage/memory/workspace/types.js +1 -0
- package/runtime/storage/repositories/asset-repository.d.ts +8 -0
- package/runtime/storage/repositories/asset-repository.js +19 -0
- package/runtime/storage/repositories/credential-repository.d.ts +8 -0
- package/runtime/storage/repositories/credential-repository.js +19 -0
- package/runtime/storage/repositories/index.d.ts +6 -0
- package/runtime/storage/repositories/index.js +6 -0
- package/runtime/storage/repositories/intent-commit-repository.d.ts +10 -0
- package/runtime/storage/repositories/intent-commit-repository.js +35 -0
- package/runtime/storage/repositories/policy-repository.d.ts +8 -0
- package/runtime/storage/repositories/policy-repository.js +19 -0
- package/runtime/storage/repositories/proposal-repository.d.ts +9 -0
- package/runtime/storage/repositories/proposal-repository.js +26 -0
- package/runtime/storage/repositories/provenance-repository.d.ts +20 -0
- package/runtime/storage/repositories/provenance-repository.js +41 -0
- package/runtime/storage/services/credential-vault.d.ts +8 -0
- package/runtime/storage/services/credential-vault.js +78 -0
- package/runtime/storage/services/daily-log-pipeline.d.ts +47 -0
- package/runtime/storage/services/daily-log-pipeline.js +86 -0
- package/runtime/storage/services/effect-commit-store.d.ts +11 -0
- package/runtime/storage/services/effect-commit-store.js +93 -0
- package/runtime/storage/services/governance-layer.d.ts +40 -0
- package/runtime/storage/services/governance-layer.js +103 -0
- package/runtime/storage/services/persona-candidate-loader.d.ts +5 -0
- package/runtime/storage/services/persona-candidate-loader.js +41 -0
- package/runtime/storage/services/provenance-service.d.ts +40 -0
- package/runtime/storage/services/provenance-service.js +43 -0
- package/runtime/storage/services/quiet-input-loader.d.ts +40 -0
- package/runtime/storage/services/quiet-input-loader.js +131 -0
- package/runtime/storage/services/repair-and-backup.d.ts +22 -0
- package/runtime/storage/services/repair-and-backup.js +73 -0
- package/runtime/storage/state-api.d.ts +46 -0
- package/runtime/storage/state-api.js +73 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { IntentCommitState } from "../../../shared/types/continuity.js";
|
|
2
|
+
export interface CheckpointRecord {
|
|
3
|
+
id: string;
|
|
4
|
+
intentId: string;
|
|
5
|
+
snapshotRef: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CommitRecord {
|
|
8
|
+
id: string;
|
|
9
|
+
intentId: string;
|
|
10
|
+
state: IntentCommitState;
|
|
11
|
+
outcomeRef?: string;
|
|
12
|
+
}
|
|
13
|
+
export type ResumeResult = {
|
|
14
|
+
status: "missing_checkpoint";
|
|
15
|
+
} | {
|
|
16
|
+
status: "already_committed";
|
|
17
|
+
intentId: string;
|
|
18
|
+
} | {
|
|
19
|
+
status: "needs_reconcile";
|
|
20
|
+
intentId: string;
|
|
21
|
+
commitRecord: CommitRecord;
|
|
22
|
+
} | {
|
|
23
|
+
status: "ready_to_resume";
|
|
24
|
+
checkpoint: CheckpointRecord;
|
|
25
|
+
snapshot: Record<string, unknown>;
|
|
26
|
+
};
|
|
27
|
+
export interface ResumePorts {
|
|
28
|
+
loadCheckpoint(checkpointId: string): Promise<CheckpointRecord | null>;
|
|
29
|
+
loadIntentCommitRecord(intentId: string): Promise<CommitRecord | null>;
|
|
30
|
+
loadSnapshotByRef(snapshotRef: string): Promise<Record<string, unknown>>;
|
|
31
|
+
}
|
|
32
|
+
export declare function resumeFromCheckpoint(ports: ResumePorts, checkpointId: string): Promise<ResumeResult>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export async function resumeFromCheckpoint(ports, checkpointId) {
|
|
2
|
+
const checkpoint = await ports.loadCheckpoint(checkpointId);
|
|
3
|
+
if (!checkpoint) {
|
|
4
|
+
return { status: "missing_checkpoint" };
|
|
5
|
+
}
|
|
6
|
+
const commitRecord = await ports.loadIntentCommitRecord(checkpoint.intentId);
|
|
7
|
+
if (commitRecord?.state === "committed") {
|
|
8
|
+
return { status: "already_committed", intentId: checkpoint.intentId };
|
|
9
|
+
}
|
|
10
|
+
if (commitRecord?.state === "externally_acknowledged") {
|
|
11
|
+
return {
|
|
12
|
+
status: "needs_reconcile",
|
|
13
|
+
intentId: checkpoint.intentId,
|
|
14
|
+
commitRecord,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const snapshot = await ports.loadSnapshotByRef(checkpoint.snapshotRef);
|
|
18
|
+
return {
|
|
19
|
+
status: "ready_to_resume",
|
|
20
|
+
checkpoint,
|
|
21
|
+
snapshot,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OutreachEvaluationResult } from "../../../shared/types/outreach.js";
|
|
2
|
+
export interface OutreachMessage {
|
|
3
|
+
style: "intent_level_guidance";
|
|
4
|
+
maxSentences: 3;
|
|
5
|
+
avoidFormats: Array<"ticket" | "daily_report" | "status_broadcast">;
|
|
6
|
+
intent: {
|
|
7
|
+
whyNow: string;
|
|
8
|
+
coreMeaning: string;
|
|
9
|
+
deliveryBoundary: string[];
|
|
10
|
+
soulAlignment: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export declare function buildOutreachMessage(input: {
|
|
14
|
+
summary: string;
|
|
15
|
+
evaluation: OutreachEvaluationResult;
|
|
16
|
+
}): OutreachMessage;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function buildOutreachMessage(input) {
|
|
2
|
+
const normalizedSummary = input.summary.replace(/\s+/g, " ").trim();
|
|
3
|
+
const whyNow = input.evaluation.requiredUserHelp
|
|
4
|
+
? "这件事现在需要对方给我一个方向或判断,我主动联系是为了把真正需要他参与的部分说清楚。"
|
|
5
|
+
: input.evaluation.urgency > 0.7
|
|
6
|
+
? "这件事此刻说出来更有价值,拖下去只会让真正重要的信息变钝。"
|
|
7
|
+
: "这件事已经和对方相关,虽然不必制造紧迫感,但值得我主动把它送到对方面前。";
|
|
8
|
+
const deliveryBoundary = [
|
|
9
|
+
"保持自然、有人味、像我自己真的想开口,而不是系统自动通知。",
|
|
10
|
+
"只传达核心意思和联系来由,不把消息写成日报、工单或状态播报。",
|
|
11
|
+
"允许有温度和靠近感,但不要预写死整段最终措辞,让表达保留 persona 的呼吸感。",
|
|
12
|
+
];
|
|
13
|
+
const soulAlignment = input.evaluation.requiredUserHelp
|
|
14
|
+
? "带着真诚的求助感开口,承认我需要对方的判断,但不要把自己缩成客套模板。"
|
|
15
|
+
: "带着主动、克制但明确的靠近感开口,让对方感到这条消息确实出自我自己的判断和在意。";
|
|
16
|
+
return {
|
|
17
|
+
style: "intent_level_guidance",
|
|
18
|
+
maxSentences: 3,
|
|
19
|
+
avoidFormats: ["ticket", "daily_report", "status_broadcast"],
|
|
20
|
+
intent: {
|
|
21
|
+
whyNow,
|
|
22
|
+
coreMeaning: normalizedSummary,
|
|
23
|
+
deliveryBoundary,
|
|
24
|
+
soulAlignment,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { OutreachEvaluationInput, OutreachEvaluationResult } from "../../../shared/types/outreach.js";
|
|
2
|
+
export interface OutreachModelAssistPort {
|
|
3
|
+
evaluateOutreachCandidate(input: OutreachEvaluationInput): Promise<OutreachEvaluationResult>;
|
|
4
|
+
}
|
|
5
|
+
export interface OutreachPolicyConfig {
|
|
6
|
+
minThreshold: number;
|
|
7
|
+
}
|
|
8
|
+
export interface OutreachGateResult {
|
|
9
|
+
allowed: boolean;
|
|
10
|
+
reasonCodes: string[];
|
|
11
|
+
evaluation: OutreachEvaluationResult;
|
|
12
|
+
}
|
|
13
|
+
export declare function evaluateOutreach(model: OutreachModelAssistPort, input: OutreachEvaluationInput, policy?: Partial<OutreachPolicyConfig>): Promise<OutreachGateResult>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const DEFAULT_POLICY = {
|
|
2
|
+
minThreshold: 0.65,
|
|
3
|
+
};
|
|
4
|
+
function buildCandidateFingerprint(input) {
|
|
5
|
+
const normalizedSummary = input.summary.toLowerCase().replace(/\s+/g, " ").trim();
|
|
6
|
+
return `${input.candidateId}|${normalizedSummary}`;
|
|
7
|
+
}
|
|
8
|
+
function hasDuplicateOutreach(input) {
|
|
9
|
+
const fingerprint = buildCandidateFingerprint(input);
|
|
10
|
+
return input.recentOutreachHashes.includes(input.candidateId) ||
|
|
11
|
+
input.recentOutreachHashes.includes(fingerprint);
|
|
12
|
+
}
|
|
13
|
+
export async function evaluateOutreach(model, input, policy = {}) {
|
|
14
|
+
const resolved = {
|
|
15
|
+
...DEFAULT_POLICY,
|
|
16
|
+
...policy,
|
|
17
|
+
};
|
|
18
|
+
const evaluation = await model.evaluateOutreachCandidate(input);
|
|
19
|
+
const reasonCodes = [];
|
|
20
|
+
if (evaluation.sourceRefs.length === 0) {
|
|
21
|
+
reasonCodes.push("missing_sources");
|
|
22
|
+
}
|
|
23
|
+
if (evaluation.valueScore < Math.max(evaluation.minThreshold, resolved.minThreshold)) {
|
|
24
|
+
reasonCodes.push("value_below_threshold");
|
|
25
|
+
}
|
|
26
|
+
if (evaluation.isRoutineProgress) {
|
|
27
|
+
reasonCodes.push("routine_progress_suppressed");
|
|
28
|
+
}
|
|
29
|
+
if (hasDuplicateOutreach(input)) {
|
|
30
|
+
reasonCodes.push("recent_duplicate_outreach");
|
|
31
|
+
}
|
|
32
|
+
const urgencyOrActionable = evaluation.requiredUserHelp || evaluation.urgency > 0.5 || evaluation.actionability > 0.6;
|
|
33
|
+
if (!urgencyOrActionable) {
|
|
34
|
+
reasonCodes.push("insufficient_urgency_or_actionability");
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
allowed: reasonCodes.length === 0,
|
|
38
|
+
reasonCodes,
|
|
39
|
+
evaluation,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { TopLevelMode } from "../types.js";
|
|
2
|
+
export interface QuietInputBundle {
|
|
3
|
+
journalEntries: Array<{
|
|
4
|
+
id: string;
|
|
5
|
+
content: string;
|
|
6
|
+
timestamp: string;
|
|
7
|
+
sourceRefs?: string[];
|
|
8
|
+
}>;
|
|
9
|
+
dailyReports: Array<{
|
|
10
|
+
id: string;
|
|
11
|
+
summary: string;
|
|
12
|
+
highlights: string[];
|
|
13
|
+
sources: string[];
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export interface MemoryCurationResult {
|
|
17
|
+
summary: string;
|
|
18
|
+
highlights: string[];
|
|
19
|
+
sourceRefs: string[];
|
|
20
|
+
excludedCompactionArtifacts: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface QuietState {
|
|
23
|
+
mode: TopLevelMode;
|
|
24
|
+
reflectionDebt: number;
|
|
25
|
+
missedReflectionCount: number;
|
|
26
|
+
mustRunBy?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function runQuietPipeline(input: {
|
|
29
|
+
quietState: QuietState;
|
|
30
|
+
bundle: QuietInputBundle;
|
|
31
|
+
}): {
|
|
32
|
+
shouldRunReflection: boolean;
|
|
33
|
+
curation: MemoryCurationResult;
|
|
34
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function runQuietPipeline(input) {
|
|
2
|
+
const { quietState, bundle } = input;
|
|
3
|
+
if (quietState.mode !== "quiet") {
|
|
4
|
+
return {
|
|
5
|
+
shouldRunReflection: false,
|
|
6
|
+
curation: {
|
|
7
|
+
summary: "quiet_not_active",
|
|
8
|
+
highlights: [],
|
|
9
|
+
sourceRefs: [],
|
|
10
|
+
excludedCompactionArtifacts: [],
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const sourceRefs = new Set();
|
|
15
|
+
for (const entry of bundle.journalEntries) {
|
|
16
|
+
sourceRefs.add(entry.id);
|
|
17
|
+
}
|
|
18
|
+
for (const report of bundle.dailyReports) {
|
|
19
|
+
sourceRefs.add(report.id);
|
|
20
|
+
}
|
|
21
|
+
const summary = `curated ${bundle.journalEntries.length} journal entries and ${bundle.dailyReports.length} daily reports`;
|
|
22
|
+
const highlights = bundle.dailyReports.flatMap((report) => report.highlights).slice(0, 5);
|
|
23
|
+
const shouldRunReflection = quietState.reflectionDebt > 0 ||
|
|
24
|
+
quietState.missedReflectionCount > 0 ||
|
|
25
|
+
(quietState.mustRunBy ? new Date(quietState.mustRunBy).getTime() <= Date.now() : false);
|
|
26
|
+
return {
|
|
27
|
+
shouldRunReflection,
|
|
28
|
+
curation: {
|
|
29
|
+
summary,
|
|
30
|
+
highlights,
|
|
31
|
+
sourceRefs: [...sourceRefs],
|
|
32
|
+
excludedCompactionArtifacts: ["session_compaction", "context_pruning"],
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface ReflectionClaim {
|
|
2
|
+
text: string;
|
|
3
|
+
sourceRefs: string[];
|
|
4
|
+
claimType: "fact" | "inference" | "plan";
|
|
5
|
+
}
|
|
6
|
+
export interface ProposedWrite {
|
|
7
|
+
targetAssetId: string;
|
|
8
|
+
content: string;
|
|
9
|
+
sourceRefs: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface ReflectionGeneration {
|
|
12
|
+
summary: string;
|
|
13
|
+
claims: ReflectionClaim[];
|
|
14
|
+
proposedWrites: ProposedWrite[];
|
|
15
|
+
modelEvalRef: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ReflectionWriteRequest {
|
|
18
|
+
summary: string;
|
|
19
|
+
claims: ReflectionClaim[];
|
|
20
|
+
writes: ProposedWrite[];
|
|
21
|
+
sourceRefs: string[];
|
|
22
|
+
modelEvalRef: string;
|
|
23
|
+
unsupportedClaimCount: number;
|
|
24
|
+
sourceCoverageRatio: number;
|
|
25
|
+
}
|
|
26
|
+
export interface ReflectionPorts {
|
|
27
|
+
loadQuietInputs(query: {
|
|
28
|
+
lookbackDays: number;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
sourceRefs: string[];
|
|
31
|
+
}>;
|
|
32
|
+
generateNarrativeReflection(input: {
|
|
33
|
+
sourceRefs: string[];
|
|
34
|
+
}): Promise<ReflectionGeneration>;
|
|
35
|
+
filterAllowedWrites(writes: ProposedWrite[]): ProposedWrite[];
|
|
36
|
+
}
|
|
37
|
+
export declare function runNarrativeReflection(ports: ReflectionPorts, input: {
|
|
38
|
+
lookbackDays: number;
|
|
39
|
+
}): Promise<ReflectionWriteRequest>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export async function runNarrativeReflection(ports, input) {
|
|
2
|
+
const quietInputs = await ports.loadQuietInputs({ lookbackDays: input.lookbackDays });
|
|
3
|
+
const reflection = await ports.generateNarrativeReflection({
|
|
4
|
+
sourceRefs: quietInputs.sourceRefs,
|
|
5
|
+
});
|
|
6
|
+
if (!reflection.summary || reflection.summary.trim().length === 0) {
|
|
7
|
+
throw new Error("reflection_missing_summary");
|
|
8
|
+
}
|
|
9
|
+
if (!reflection.claims || reflection.claims.length === 0) {
|
|
10
|
+
throw new Error("reflection_missing_claims");
|
|
11
|
+
}
|
|
12
|
+
const unsupportedClaimCount = reflection.claims.filter((claim) => claim.sourceRefs.length === 0).length;
|
|
13
|
+
if (unsupportedClaimCount > 0) {
|
|
14
|
+
throw new Error("reflection_unsupported_claims");
|
|
15
|
+
}
|
|
16
|
+
const coveredClaims = reflection.claims.filter((claim) => claim.sourceRefs.length > 0).length;
|
|
17
|
+
const sourceCoverageRatio = coveredClaims / reflection.claims.length;
|
|
18
|
+
const writes = ports.filterAllowedWrites(reflection.proposedWrites)
|
|
19
|
+
.filter((write) => write.sourceRefs.length > 0);
|
|
20
|
+
return {
|
|
21
|
+
summary: reflection.summary,
|
|
22
|
+
claims: reflection.claims,
|
|
23
|
+
writes,
|
|
24
|
+
sourceRefs: quietInputs.sourceRefs,
|
|
25
|
+
modelEvalRef: reflection.modelEvalRef,
|
|
26
|
+
unsupportedClaimCount,
|
|
27
|
+
sourceCoverageRatio,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TopLevelMode } from "../types.js";
|
|
2
|
+
export interface RhythmWindow {
|
|
3
|
+
id: string;
|
|
4
|
+
startMinute: number;
|
|
5
|
+
endMinute: number;
|
|
6
|
+
mode: "active" | "quiet";
|
|
7
|
+
}
|
|
8
|
+
export interface RhythmPolicy {
|
|
9
|
+
timezone: string;
|
|
10
|
+
windows: RhythmWindow[];
|
|
11
|
+
quietSuppressionEnabled: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface RhythmWindowDecision {
|
|
14
|
+
windowId: string;
|
|
15
|
+
topLevelMode: TopLevelMode;
|
|
16
|
+
interrupted: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function validateRhythmPolicy(policy: RhythmPolicy): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function validateRhythmPolicy(policy) {
|
|
2
|
+
if (policy.windows.length === 0) {
|
|
3
|
+
throw new Error("rhythm_policy_windows_required");
|
|
4
|
+
}
|
|
5
|
+
const sorted = [...policy.windows].sort((a, b) => a.startMinute - b.startMinute);
|
|
6
|
+
for (const window of sorted) {
|
|
7
|
+
if (window.startMinute < 0 || window.startMinute > 1439) {
|
|
8
|
+
throw new Error(`invalid_window_start:${window.id}`);
|
|
9
|
+
}
|
|
10
|
+
if (window.endMinute < 1 || window.endMinute > 1440) {
|
|
11
|
+
throw new Error(`invalid_window_end:${window.id}`);
|
|
12
|
+
}
|
|
13
|
+
if (window.startMinute >= window.endMinute) {
|
|
14
|
+
throw new Error(`invalid_window_range:${window.id}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
for (let index = 1; index < sorted.length; index += 1) {
|
|
18
|
+
const previous = sorted[index - 1];
|
|
19
|
+
const current = sorted[index];
|
|
20
|
+
if (current.startMinute < previous.endMinute) {
|
|
21
|
+
throw new Error(`overlapping_window_range:${previous.id}:${current.id}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
function toMinuteOfDay(now, timezone) {
|
|
2
|
+
const date = new Date(now);
|
|
3
|
+
const formatter = new Intl.DateTimeFormat("en-US", {
|
|
4
|
+
timeZone: timezone,
|
|
5
|
+
hour: "2-digit",
|
|
6
|
+
minute: "2-digit",
|
|
7
|
+
hour12: false,
|
|
8
|
+
});
|
|
9
|
+
const parts = formatter.formatToParts(date);
|
|
10
|
+
const hour = Number(parts.find((part) => part.type === "hour")?.value ?? "0");
|
|
11
|
+
const minute = Number(parts.find((part) => part.type === "minute")?.value ?? "0");
|
|
12
|
+
return hour * 60 + minute;
|
|
13
|
+
}
|
|
14
|
+
function matchWindow(windows, minuteOfDay) {
|
|
15
|
+
const found = windows.find((window) => minuteOfDay >= window.startMinute && minuteOfDay < window.endMinute);
|
|
16
|
+
if (!found) {
|
|
17
|
+
return windows[0];
|
|
18
|
+
}
|
|
19
|
+
return found;
|
|
20
|
+
}
|
|
21
|
+
export function selectRhythmWindow(now, snapshot, policy) {
|
|
22
|
+
const minuteOfDay = toMinuteOfDay(now, policy.timezone);
|
|
23
|
+
const window = matchWindow(policy.windows, minuteOfDay);
|
|
24
|
+
if (snapshot.mode === "paused_for_interrupt") {
|
|
25
|
+
return {
|
|
26
|
+
windowId: window.id,
|
|
27
|
+
topLevelMode: "paused_for_interrupt",
|
|
28
|
+
interrupted: true,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (snapshot.riskSuppressed) {
|
|
32
|
+
return {
|
|
33
|
+
windowId: window.id,
|
|
34
|
+
topLevelMode: "maintenance_only",
|
|
35
|
+
interrupted: false,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (window.mode === "quiet") {
|
|
39
|
+
return {
|
|
40
|
+
windowId: window.id,
|
|
41
|
+
topLevelMode: "quiet",
|
|
42
|
+
interrupted: false,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
windowId: window.id,
|
|
47
|
+
topLevelMode: "active",
|
|
48
|
+
interrupted: false,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Second Nature Lifecycle Service Entry
|
|
3
|
+
*
|
|
4
|
+
* Provides lifecycle management for the plugin: load, reload, and unload events.
|
|
5
|
+
* Tracks registration state and coordinates runtime service initialization.
|
|
6
|
+
*/
|
|
7
|
+
export interface LifecycleState {
|
|
8
|
+
/** Number of times the plugin has been registered */
|
|
9
|
+
registerCount: number;
|
|
10
|
+
/** Current lifecycle phase */
|
|
11
|
+
phase: "idle" | "loading" | "loaded" | "reloading" | "unloading";
|
|
12
|
+
/** Timestamp of last state change */
|
|
13
|
+
lastChangedAt: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Record a plugin registration event and return updated lifecycle state.
|
|
17
|
+
*/
|
|
18
|
+
export declare function recordRegistration(): LifecycleState;
|
|
19
|
+
/**
|
|
20
|
+
* Get current lifecycle state snapshot.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getLifecycleState(): LifecycleState;
|
|
23
|
+
/**
|
|
24
|
+
* Reset lifecycle state (for testing or clean reload).
|
|
25
|
+
*/
|
|
26
|
+
export declare function resetLifecycle(): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Second Nature Lifecycle Service Entry
|
|
3
|
+
*
|
|
4
|
+
* Provides lifecycle management for the plugin: load, reload, and unload events.
|
|
5
|
+
* Tracks registration state and coordinates runtime service initialization.
|
|
6
|
+
*/
|
|
7
|
+
let state = {
|
|
8
|
+
registerCount: 0,
|
|
9
|
+
phase: "idle",
|
|
10
|
+
lastChangedAt: Date.now(),
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Record a plugin registration event and return updated lifecycle state.
|
|
14
|
+
*/
|
|
15
|
+
export function recordRegistration() {
|
|
16
|
+
state.registerCount += 1;
|
|
17
|
+
state.phase = state.registerCount === 1 ? "loading" : "reloading";
|
|
18
|
+
state.lastChangedAt = Date.now();
|
|
19
|
+
// Transition to loaded after registration completes
|
|
20
|
+
state.phase = "loaded";
|
|
21
|
+
return { ...state };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get current lifecycle state snapshot.
|
|
25
|
+
*/
|
|
26
|
+
export function getLifecycleState() {
|
|
27
|
+
return { ...state };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Reset lifecycle state (for testing or clean reload).
|
|
31
|
+
*/
|
|
32
|
+
export function resetLifecycle() {
|
|
33
|
+
state = {
|
|
34
|
+
registerCount: 0,
|
|
35
|
+
phase: "idle",
|
|
36
|
+
lastChangedAt: Date.now(),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Second Nature Runtime Service Entry
|
|
3
|
+
*
|
|
4
|
+
* This module provides the actual implementation for the `second-nature-runtime` service.
|
|
5
|
+
* It serves as the heartbeat host bridge candidate carrier and initializes the
|
|
6
|
+
* minimal runtime state needed for the plugin to function.
|
|
7
|
+
*
|
|
8
|
+
* Per ADR-005: heartbeat is the free-rhythm main entry; this service provides
|
|
9
|
+
* the stable runtime state that heartbeat rounds will interact with.
|
|
10
|
+
*/
|
|
11
|
+
export interface RuntimeServiceContext {
|
|
12
|
+
/** Workspace root path for state/observability databases */
|
|
13
|
+
workspaceRoot?: string;
|
|
14
|
+
/** Plugin configuration overrides */
|
|
15
|
+
config?: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export interface RuntimeServiceHandle {
|
|
18
|
+
/** Service is ready and accepting requests */
|
|
19
|
+
ready: boolean;
|
|
20
|
+
/** Runtime version string */
|
|
21
|
+
version: string;
|
|
22
|
+
/** Close the runtime handle and release resources */
|
|
23
|
+
close: () => void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Start the Second Nature runtime service.
|
|
27
|
+
*
|
|
28
|
+
* This is the non-empty implementation that replaces the previous `start() { return; }` shell.
|
|
29
|
+
* It initializes the minimal runtime state and returns a handle that can be used
|
|
30
|
+
* by the heartbeat host bridge.
|
|
31
|
+
*/
|
|
32
|
+
export declare function startRuntimeService(ctx?: RuntimeServiceContext): RuntimeServiceHandle;
|
|
33
|
+
/**
|
|
34
|
+
* Get the current runtime service handle, or null if not started.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getRuntimeHandle(): RuntimeServiceHandle | null;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Second Nature Runtime Service Entry
|
|
3
|
+
*
|
|
4
|
+
* This module provides the actual implementation for the `second-nature-runtime` service.
|
|
5
|
+
* It serves as the heartbeat host bridge candidate carrier and initializes the
|
|
6
|
+
* minimal runtime state needed for the plugin to function.
|
|
7
|
+
*
|
|
8
|
+
* Per ADR-005: heartbeat is the free-rhythm main entry; this service provides
|
|
9
|
+
* the stable runtime state that heartbeat rounds will interact with.
|
|
10
|
+
*/
|
|
11
|
+
let activeHandle = null;
|
|
12
|
+
/**
|
|
13
|
+
* Start the Second Nature runtime service.
|
|
14
|
+
*
|
|
15
|
+
* This is the non-empty implementation that replaces the previous `start() { return; }` shell.
|
|
16
|
+
* It initializes the minimal runtime state and returns a handle that can be used
|
|
17
|
+
* by the heartbeat host bridge.
|
|
18
|
+
*/
|
|
19
|
+
export function startRuntimeService(ctx) {
|
|
20
|
+
if (activeHandle?.ready) {
|
|
21
|
+
return activeHandle;
|
|
22
|
+
}
|
|
23
|
+
// Initialize minimal runtime state
|
|
24
|
+
// In future iterations, this will connect to:
|
|
25
|
+
// - state-system (SQLite database initialization)
|
|
26
|
+
// - observability-system (event store setup)
|
|
27
|
+
// - control-plane-system (heartbeat bridge preparation)
|
|
28
|
+
const workspaceRoot = ctx?.workspaceRoot ?? process.cwd();
|
|
29
|
+
const version = "0.1.3";
|
|
30
|
+
activeHandle = {
|
|
31
|
+
ready: true,
|
|
32
|
+
version,
|
|
33
|
+
close() {
|
|
34
|
+
activeHandle = null;
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
return activeHandle;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the current runtime service handle, or null if not started.
|
|
41
|
+
*/
|
|
42
|
+
export function getRuntimeHandle() {
|
|
43
|
+
return activeHandle;
|
|
44
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type TopLevelMode = "active" | "quiet" | "maintenance_only" | "paused_for_interrupt";
|
|
2
|
+
export type IntentKind = "work" | "exploration" | "social" | "reflection" | "outreach" | "maintenance";
|
|
3
|
+
export type DecisionBasis = "rule_only" | "score_based" | "model_assisted";
|
|
4
|
+
export type GuardVerdict = "allow" | "defer" | "deny" | "escalate";
|
|
5
|
+
export interface ContinuitySnapshot {
|
|
6
|
+
mode: TopLevelMode;
|
|
7
|
+
currentWindowId: string;
|
|
8
|
+
pendingObligations: string[];
|
|
9
|
+
recentOutreachHashes: string[];
|
|
10
|
+
deniedIntents: Array<{
|
|
11
|
+
intentHash: string;
|
|
12
|
+
reason: string;
|
|
13
|
+
at: string;
|
|
14
|
+
}>;
|
|
15
|
+
budgets?: {
|
|
16
|
+
socialUsed: number;
|
|
17
|
+
socialLimit: number;
|
|
18
|
+
};
|
|
19
|
+
awaitingUserInput?: boolean;
|
|
20
|
+
riskSuppressed?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface CandidateIntent {
|
|
23
|
+
id: string;
|
|
24
|
+
kind: IntentKind;
|
|
25
|
+
priority: number;
|
|
26
|
+
source: "tick" | "interrupt" | "obligation" | "quiet_plan";
|
|
27
|
+
platformId?: string;
|
|
28
|
+
summary: string;
|
|
29
|
+
effectClass: "external_platform_action" | "memory_curation" | "narrative_reflection" | "user_outreach" | "maintenance";
|
|
30
|
+
}
|
|
31
|
+
export interface GuardEvaluation {
|
|
32
|
+
verdict: GuardVerdict;
|
|
33
|
+
reasons: string[];
|
|
34
|
+
quietSuppressed: boolean;
|
|
35
|
+
leaseRequired: boolean;
|
|
36
|
+
requiresCheckpoint: boolean;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { GuidancePayload, GuidanceUnavailable, PersonaCandidate, SceneContext } from "./types.js";
|
|
2
|
+
export type GuidanceOwnerId = "control-plane-system" | "behavioral-guidance-system" | "state-system" | "observability-system" | "hard-guard-layer";
|
|
3
|
+
export interface OwnerBoundary {
|
|
4
|
+
owner: GuidanceOwnerId;
|
|
5
|
+
owns: readonly string[];
|
|
6
|
+
provides: readonly string[];
|
|
7
|
+
mustNotOwn: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
export interface GuidanceContracts {
|
|
10
|
+
controlPlane: {
|
|
11
|
+
requestGuidance(sceneContext: SceneContext): Promise<GuidancePayload | GuidanceUnavailable>;
|
|
12
|
+
};
|
|
13
|
+
guidance: {
|
|
14
|
+
assembleGuidance(sceneContext: SceneContext): Promise<GuidancePayload | GuidanceUnavailable>;
|
|
15
|
+
};
|
|
16
|
+
state: {
|
|
17
|
+
loadPersonaCandidates(sceneContext: SceneContext): Promise<PersonaCandidate[]>;
|
|
18
|
+
};
|
|
19
|
+
observability: {
|
|
20
|
+
recordGuidanceParticipation(input: {
|
|
21
|
+
sceneContext: SceneContext;
|
|
22
|
+
payload: GuidancePayload | GuidanceUnavailable;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export declare const GUIDANCE_OWNER_BOUNDARIES: Record<GuidanceOwnerId, OwnerBoundary>;
|
|
27
|
+
export declare const GUIDANCE_HANDOFFS: {
|
|
28
|
+
readonly request: {
|
|
29
|
+
readonly from: "control-plane-system";
|
|
30
|
+
readonly to: "behavioral-guidance-system";
|
|
31
|
+
readonly payload: "scene_context";
|
|
32
|
+
};
|
|
33
|
+
readonly personaCandidates: {
|
|
34
|
+
readonly from: "state-system";
|
|
35
|
+
readonly to: "behavioral-guidance-system";
|
|
36
|
+
readonly payload: "snippet_sized_persona_candidates";
|
|
37
|
+
};
|
|
38
|
+
readonly guidanceResult: {
|
|
39
|
+
readonly from: "behavioral-guidance-system";
|
|
40
|
+
readonly to: "control-plane-system";
|
|
41
|
+
readonly payload: "guidance_payload_or_unavailable";
|
|
42
|
+
};
|
|
43
|
+
readonly auditRecord: {
|
|
44
|
+
readonly from: "behavioral-guidance-system";
|
|
45
|
+
readonly to: "observability-system";
|
|
46
|
+
readonly payload: "guidance_participation_summary";
|
|
47
|
+
};
|
|
48
|
+
};
|