@alan512/experienceengine 0.2.1 → 0.3.1
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/.claude-plugin/plugin.json +1 -1
- package/.mcp.json +5 -6
- package/README.md +24 -10
- package/README.zh-CN.md +22 -8
- package/dist/adapters/codex/action-registry.d.ts +23 -1
- package/dist/adapters/codex/action-registry.js +73 -0
- package/dist/adapters/codex/action-registry.js.map +1 -1
- package/dist/adapters/codex/behavior-loop.d.ts +80 -0
- package/dist/adapters/codex/behavior-loop.js +189 -0
- package/dist/adapters/codex/behavior-loop.js.map +1 -0
- package/dist/adapters/codex/mcp-server.d.ts +27 -72
- package/dist/adapters/codex/mcp-server.js +36 -160
- package/dist/adapters/codex/mcp-server.js.map +1 -1
- package/dist/cli/commands/claude-hook.d.ts +4 -0
- package/dist/cli/commands/claude-hook.js +105 -21
- package/dist/cli/commands/claude-hook.js.map +1 -1
- package/dist/cli/commands/codex-hook.d.ts +22 -0
- package/dist/cli/commands/codex-hook.js +298 -0
- package/dist/cli/commands/codex-hook.js.map +1 -0
- package/dist/cli/commands/config.js +9 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/doctor.js +63 -1
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/inspect.d.ts +1 -1
- package/dist/cli/commands/inspect.js +325 -1
- package/dist/cli/commands/inspect.js.map +1 -1
- package/dist/cli/commands/install.js +4 -1
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/maintenance.js +4 -0
- package/dist/cli/commands/maintenance.js.map +1 -1
- package/dist/cli/commands/repair.js +35 -3
- package/dist/cli/commands/repair.js.map +1 -1
- package/dist/cli/commands/status.js +27 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/upgrade.js +2 -0
- package/dist/cli/commands/upgrade.js.map +1 -1
- package/dist/cli/dispatch.js +8 -3
- package/dist/cli/dispatch.js.map +1 -1
- package/dist/config/config-schema.d.ts +8 -0
- package/dist/config/config-schema.js +6 -0
- package/dist/config/config-schema.js.map +1 -1
- package/dist/config/default-config.js +1 -0
- package/dist/config/default-config.js.map +1 -1
- package/dist/config/load-config.js +3 -0
- package/dist/config/load-config.js.map +1 -1
- package/dist/controller/candidate-retriever.d.ts +4 -1
- package/dist/controller/candidate-retriever.js +129 -13
- package/dist/controller/candidate-retriever.js.map +1 -1
- package/dist/controller/injection-renderer.d.ts +2 -2
- package/dist/controller/injection-renderer.js +22 -3
- package/dist/controller/injection-renderer.js.map +1 -1
- package/dist/controller/injection-scorecard.js +3 -0
- package/dist/controller/injection-scorecard.js.map +1 -1
- package/dist/controller/intervention-controller.d.ts +2 -2
- package/dist/controller/intervention-controller.js +183 -25
- package/dist/controller/intervention-controller.js.map +1 -1
- package/dist/controller/model-reranker-mode.d.ts +4 -0
- package/dist/controller/model-reranker-mode.js +14 -0
- package/dist/controller/model-reranker-mode.js.map +1 -0
- package/dist/controller/model-reranker.d.ts +0 -1
- package/dist/controller/model-reranker.js +1 -13
- package/dist/controller/model-reranker.js.map +1 -1
- package/dist/controller/policy-enricher.d.ts +2 -1
- package/dist/controller/policy-enricher.js +71 -11
- package/dist/controller/policy-enricher.js.map +1 -1
- package/dist/evaluation/openclaw-scenarios.js +12 -5
- package/dist/evaluation/openclaw-scenarios.js.map +1 -1
- package/dist/experience-management/repo-policy.d.ts +53 -0
- package/dist/experience-management/repo-policy.js +175 -0
- package/dist/experience-management/repo-policy.js.map +1 -0
- package/dist/hybrid/capsule-builder.js +2 -0
- package/dist/hybrid/capsule-builder.js.map +1 -1
- package/dist/input/scope-resolver.js +16 -4
- package/dist/input/scope-resolver.js.map +1 -1
- package/dist/install/claude-cli.js +38 -21
- package/dist/install/claude-cli.js.map +1 -1
- package/dist/install/claude-code-doctor.js +8 -3
- package/dist/install/claude-code-doctor.js.map +1 -1
- package/dist/install/claude-code-installer.js +5 -2
- package/dist/install/claude-code-installer.js.map +1 -1
- package/dist/install/claude-runtime-target.d.ts +5 -0
- package/dist/install/claude-runtime-target.js +32 -2
- package/dist/install/claude-runtime-target.js.map +1 -1
- package/dist/install/codex-cli.d.ts +7 -0
- package/dist/install/codex-cli.js +43 -20
- package/dist/install/codex-cli.js.map +1 -1
- package/dist/install/codex-hooks.d.ts +42 -0
- package/dist/install/codex-hooks.js +280 -0
- package/dist/install/codex-hooks.js.map +1 -0
- package/dist/install/codex-installer.d.ts +21 -3
- package/dist/install/codex-installer.js +98 -9
- package/dist/install/codex-installer.js.map +1 -1
- package/dist/install/codex-runtime-target.d.ts +20 -0
- package/dist/install/codex-runtime-target.js +85 -17
- package/dist/install/codex-runtime-target.js.map +1 -1
- package/dist/install/openclaw-cli.d.ts +1 -0
- package/dist/install/openclaw-cli.js +52 -3
- package/dist/install/openclaw-cli.js.map +1 -1
- package/dist/install/openclaw-installer.d.ts +5 -0
- package/dist/install/openclaw-installer.js +24 -5
- package/dist/install/openclaw-installer.js.map +1 -1
- package/dist/install/public-install.d.ts +1 -0
- package/dist/install/public-install.js +5 -0
- package/dist/install/public-install.js.map +1 -1
- package/dist/interaction/repo-summary.d.ts +17 -0
- package/dist/interaction/repo-summary.js +33 -15
- package/dist/interaction/repo-summary.js.map +1 -1
- package/dist/interaction/retrieval-policy-inspection.d.ts +19 -0
- package/dist/interaction/retrieval-policy-inspection.js +33 -0
- package/dist/interaction/retrieval-policy-inspection.js.map +1 -0
- package/dist/interaction/service.d.ts +24 -1
- package/dist/interaction/service.js +171 -12
- package/dist/interaction/service.js.map +1 -1
- package/dist/maintenance/claude-validate-print.d.ts +8 -1
- package/dist/maintenance/claude-validate-print.js +52 -2
- package/dist/maintenance/claude-validate-print.js.map +1 -1
- package/dist/maintenance/experience-export-drafts.d.ts +56 -0
- package/dist/maintenance/experience-export-drafts.js +217 -0
- package/dist/maintenance/experience-export-drafts.js.map +1 -0
- package/dist/maintenance/experience-hygiene.d.ts +38 -0
- package/dist/maintenance/experience-hygiene.js +266 -0
- package/dist/maintenance/experience-hygiene.js.map +1 -0
- package/dist/maintenance/operator-review-flow.d.ts +81 -0
- package/dist/maintenance/operator-review-flow.js +172 -0
- package/dist/maintenance/operator-review-flow.js.map +1 -0
- package/dist/plugin/openclaw-plugin.d.ts +5 -0
- package/dist/plugin/runtime-helpers.js +43 -1
- package/dist/plugin/runtime-helpers.js.map +1 -1
- package/dist/runtime/prompt-service.d.ts +51 -0
- package/dist/runtime/prompt-service.js +209 -0
- package/dist/runtime/prompt-service.js.map +1 -0
- package/dist/runtime/service.d.ts +7 -2
- package/dist/runtime/service.js +176 -25
- package/dist/runtime/service.js.map +1 -1
- package/dist/store/sqlite/db.js +15 -0
- package/dist/store/sqlite/db.js.map +1 -1
- package/dist/store/sqlite/repositories/attribution-record-repo.d.ts +15 -0
- package/dist/store/sqlite/repositories/attribution-record-repo.js +111 -0
- package/dist/store/sqlite/repositories/attribution-record-repo.js.map +1 -0
- package/dist/store/sqlite/repositories/episode-repo.d.ts +14 -0
- package/dist/store/sqlite/repositories/episode-repo.js +84 -0
- package/dist/store/sqlite/repositories/episode-repo.js.map +1 -0
- package/dist/store/sqlite/repositories/injection-repo.d.ts +2 -0
- package/dist/store/sqlite/repositories/injection-repo.js +32 -5
- package/dist/store/sqlite/repositories/injection-repo.js.map +1 -1
- package/dist/store/sqlite/repositories/input-record-repo.d.ts +1 -0
- package/dist/store/sqlite/repositories/input-record-repo.js +23 -10
- package/dist/store/sqlite/repositories/input-record-repo.js.map +1 -1
- package/dist/store/sqlite/repositories/node-repo.d.ts +1 -0
- package/dist/store/sqlite/repositories/node-repo.js +10 -0
- package/dist/store/sqlite/repositories/node-repo.js.map +1 -1
- package/dist/store/sqlite/repositories/outcome-record-repo.d.ts +1 -0
- package/dist/store/sqlite/repositories/outcome-record-repo.js +11 -2
- package/dist/store/sqlite/repositories/outcome-record-repo.js.map +1 -1
- package/dist/store/sqlite/repositories/repo-policy-repo.d.ts +11 -0
- package/dist/store/sqlite/repositories/repo-policy-repo.js +87 -0
- package/dist/store/sqlite/repositories/repo-policy-repo.js.map +1 -0
- package/dist/store/sqlite/repositories/review-event-repo.d.ts +1 -0
- package/dist/store/sqlite/repositories/review-event-repo.js +11 -2
- package/dist/store/sqlite/repositories/review-event-repo.js.map +1 -1
- package/dist/store/sqlite/repositories/task-run-repo.d.ts +1 -0
- package/dist/store/sqlite/repositories/task-run-repo.js +11 -2
- package/dist/store/sqlite/repositories/task-run-repo.js.map +1 -1
- package/dist/store/sqlite/schema.sql +43 -0
- package/dist/store/vector/api-embedding-provider.js +14 -3
- package/dist/store/vector/api-embedding-provider.js.map +1 -1
- package/dist/store/vector/embeddings.js +5 -51
- package/dist/store/vector/embeddings.js.map +1 -1
- package/dist/store/vector/local-provider.js +14 -3
- package/dist/store/vector/local-provider.js.map +1 -1
- package/dist/types/domain.d.ts +89 -1
- package/dist/utils/text.js +5 -1
- package/dist/utils/text.js.map +1 -1
- package/docs/assets/readme/inspect-last-example.svg +37 -0
- package/docs/releases/v0.2.1.md +9 -0
- package/docs/releases/v0.3.0.md +20 -0
- package/docs/releases/v0.3.1.md +23 -0
- package/docs/user-guide.md +92 -7
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -3
- package/plugins/claude-code-experienceengine/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code-experienceengine/.mcp.json +3 -9
- package/plugins/claude-code-experienceengine/scripts/install-deps.sh +1 -1
- package/plugins/claude-code-experienceengine/scripts/mcp-server.sh +43 -0
- package/scripts/claude-plugin/claude-hook.sh +6 -1
- package/scripts/claude-plugin/mcp-server.sh +45 -0
|
@@ -10,19 +10,37 @@ const summarizeRecommendation = (benchmark) => {
|
|
|
10
10
|
return "Review the current repo summary and recent interventions before deciding whether to stay live or move back to shadow.";
|
|
11
11
|
}
|
|
12
12
|
};
|
|
13
|
-
export const buildRepoSummary = (input) =>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
export const buildRepoSummary = (input) => {
|
|
14
|
+
const policy = input.policyInspection?.policy ?? input.policy;
|
|
15
|
+
return {
|
|
16
|
+
scope: input.scope,
|
|
17
|
+
recent: {
|
|
18
|
+
latestSessionId: input.latest?.sessionId,
|
|
19
|
+
latestTaskSummary: input.latest?.summary,
|
|
20
|
+
latestActivityAt: input.latest?.createdAt,
|
|
21
|
+
latestIntervention: input.latest?.intervention,
|
|
22
|
+
latestAutoFeedback: input.latest?.autoFeedback,
|
|
23
|
+
latestAutoFeedbackReason: input.latest?.autoFeedbackReason,
|
|
24
|
+
latestDecisionExplanation: input.latest?.decisionExplanation,
|
|
25
|
+
latestTrustSummary: input.latest?.trustSummary
|
|
26
|
+
},
|
|
27
|
+
benchmark: input.learning.benchmark,
|
|
28
|
+
policy: policy
|
|
29
|
+
? {
|
|
30
|
+
configuredMode: policy.configured_mode,
|
|
31
|
+
effectiveMode: policy.effective_mode,
|
|
32
|
+
circuitState: policy.circuit_state,
|
|
33
|
+
circuitReason: policy.circuit_reason,
|
|
34
|
+
liveDiagnosticsDisabled: policy.live_diagnostics_disabled,
|
|
35
|
+
updatedAt: policy.updated_at,
|
|
36
|
+
lastTrippedAt: policy.last_tripped_at,
|
|
37
|
+
restoredAt: policy.restored_at,
|
|
38
|
+
evidenceSummary: input.policyInspection?.evidenceSummary,
|
|
39
|
+
evidence: input.policyInspection?.evidence,
|
|
40
|
+
restoreGuidance: input.policyInspection?.restoreGuidance
|
|
41
|
+
}
|
|
42
|
+
: undefined,
|
|
43
|
+
recommendedNextAction: summarizeRecommendation(input.learning.benchmark)
|
|
44
|
+
};
|
|
45
|
+
};
|
|
28
46
|
//# sourceMappingURL=repo-summary.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repo-summary.js","sourceRoot":"","sources":["../../src/interaction/repo-summary.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"repo-summary.js","sourceRoot":"","sources":["../../src/interaction/repo-summary.ts"],"names":[],"mappings":"AAsCA,MAAM,uBAAuB,GAAG,CAAC,SAA2B,EAAU,EAAE;IACtE,QAAQ,SAAS,CAAC,OAAO,EAAE,CAAC;QAC1B,KAAK,SAAS;YACZ,OAAO,gFAAgF,CAAC;QAC1F,KAAK,YAAY;YACf,OAAO,yGAAyG,CAAC;QACnH,KAAK,SAAS;YACZ,OAAO,sGAAsG,CAAC;QAChH;YACE,OAAO,uHAAuH,CAAC;IACnI,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAUhC,EAAyB,EAAE;IAC1B,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,EAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;IAE9D,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE;YACN,eAAe,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS;YACxC,iBAAiB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;YACxC,gBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS;YACzC,kBAAkB,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY;YAC9C,kBAAkB,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY;YAC9C,wBAAwB,EAAE,KAAK,CAAC,MAAM,EAAE,kBAAkB;YAC1D,yBAAyB,EAAE,KAAK,CAAC,MAAM,EAAE,mBAAmB;YAC5D,kBAAkB,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY;SAC/C;QACD,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS;QACnC,MAAM,EAAE,MAAM;YACZ,CAAC,CAAC;gBACE,cAAc,EAAE,MAAM,CAAC,eAAe;gBACtC,aAAa,EAAE,MAAM,CAAC,cAAc;gBACpC,YAAY,EAAE,MAAM,CAAC,aAAa;gBAClC,aAAa,EAAE,MAAM,CAAC,cAAc;gBACpC,uBAAuB,EAAE,MAAM,CAAC,yBAAyB;gBACzD,SAAS,EAAE,MAAM,CAAC,UAAU;gBAC5B,aAAa,EAAE,MAAM,CAAC,eAAe;gBACrC,UAAU,EAAE,MAAM,CAAC,WAAW;gBAC9B,eAAe,EAAE,KAAK,CAAC,gBAAgB,EAAE,eAAe;gBACxD,QAAQ,EAAE,KAAK,CAAC,gBAAgB,EAAE,QAAQ;gBAC1C,eAAe,EAAE,KAAK,CAAC,gBAAgB,EAAE,eAAe;aACzD;YACH,CAAC,CAAC,SAAS;QACb,qBAAqB,EAAE,uBAAuB,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;KACzE,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { InjectionScorecard, PolicyEnrichmentComponent, RetrievalPolicyStageDiagnostic } from "../types/domain.js";
|
|
2
|
+
export type RetrievalPolicyStageInspection = {
|
|
3
|
+
stage: RetrievalPolicyStageDiagnostic["stage"];
|
|
4
|
+
acceptedCount?: number;
|
|
5
|
+
rejectedCount?: number;
|
|
6
|
+
passedCount?: number;
|
|
7
|
+
reasonCodes: string[];
|
|
8
|
+
};
|
|
9
|
+
export type RetrievalPolicyComponentInspection = PolicyEnrichmentComponent;
|
|
10
|
+
export type RetrievalPolicyInspectionSummary = {
|
|
11
|
+
stages: RetrievalPolicyStageInspection[];
|
|
12
|
+
semanticMode?: "skipped" | "rerank" | "backfill";
|
|
13
|
+
topPolicyComponents: RetrievalPolicyComponentInspection[];
|
|
14
|
+
rejectedCandidates: Array<{
|
|
15
|
+
id: string;
|
|
16
|
+
reasonCodes: string[];
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
export declare const buildRetrievalPolicyInspectionSummary: (scorecard?: InjectionScorecard) => RetrievalPolicyInspectionSummary | undefined;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const SEMANTIC_STAGE = "semantic_rerank_backfill";
|
|
2
|
+
const inferSemanticMode = (stage) => {
|
|
3
|
+
const modeReason = stage?.reasonCodes.find((reason) => reason.startsWith("semantic_mode:"));
|
|
4
|
+
const mode = modeReason?.slice("semantic_mode:".length);
|
|
5
|
+
return mode === "skipped" || mode === "rerank" || mode === "backfill" ? mode : undefined;
|
|
6
|
+
};
|
|
7
|
+
export const buildRetrievalPolicyInspectionSummary = (scorecard) => {
|
|
8
|
+
const stages = scorecard?.retrievalPolicyDiagnostics?.stages ?? [];
|
|
9
|
+
const topCandidate = scorecard?.topCandidates?.[0];
|
|
10
|
+
const topPolicyComponents = [...(topCandidate?.policyComponents ?? [])]
|
|
11
|
+
.sort((left, right) => Math.abs(right.value) - Math.abs(left.value))
|
|
12
|
+
.slice(0, 5);
|
|
13
|
+
const rejectedCandidates = scorecard?.rejectedCandidates?.slice(0, 5).map((candidate) => ({
|
|
14
|
+
id: candidate.id,
|
|
15
|
+
reasonCodes: candidate.reasonCodes
|
|
16
|
+
})) ?? [];
|
|
17
|
+
if (!stages.length && !topPolicyComponents.length && !rejectedCandidates.length) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
stages: stages.map((stage) => ({
|
|
22
|
+
stage: stage.stage,
|
|
23
|
+
acceptedCount: stage.acceptedCount,
|
|
24
|
+
rejectedCount: stage.rejectedCount,
|
|
25
|
+
passedCount: stage.passedCount,
|
|
26
|
+
reasonCodes: stage.reasonCodes
|
|
27
|
+
})),
|
|
28
|
+
semanticMode: inferSemanticMode(stages.find((stage) => stage.stage === SEMANTIC_STAGE)),
|
|
29
|
+
topPolicyComponents,
|
|
30
|
+
rejectedCandidates
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=retrieval-policy-inspection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retrieval-policy-inspection.js","sourceRoot":"","sources":["../../src/interaction/retrieval-policy-inspection.ts"],"names":[],"mappings":"AA0BA,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAElD,MAAM,iBAAiB,GAAG,CACxB,KAAiD,EACC,EAAE;IACpD,MAAM,UAAU,GAAG,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC5F,MAAM,IAAI,GAAG,UAAU,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACxD,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3F,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qCAAqC,GAAG,CACnD,SAA8B,EACgB,EAAE;IAChD,MAAM,MAAM,GAAG,SAAS,EAAE,0BAA0B,EAAE,MAAM,IAAI,EAAE,CAAC;IACnE,MAAM,YAAY,GAAG,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC;IACnD,MAAM,mBAAmB,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,gBAAgB,IAAI,EAAE,CAAC,CAAC;SACpE,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SACnE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACf,MAAM,kBAAkB,GACtB,SAAS,EAAE,kBAAkB,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC7D,EAAE,EAAE,SAAS,CAAC,EAAE;QAChB,WAAW,EAAE,SAAS,CAAC,WAAW;KACnC,CAAC,CAAC,IAAI,EAAE,CAAC;IAEZ,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,mBAAmB,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,CAAC;QAChF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC7B,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;SAC/B,CAAC,CAAC;QACH,YAAY,EAAE,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,cAAc,CAAC,CAAC;QACvF,mBAAmB;QACnB,kBAAkB;KACnB,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { ExperienceEngineConfig } from "../config/config-schema.js";
|
|
2
2
|
import { type BenchmarkSummary } from "../evaluation/benchmark-summary.js";
|
|
3
|
+
import { type HygieneReviewFilters, type HygieneReviewReport } from "../maintenance/experience-hygiene.js";
|
|
4
|
+
import { type ExperienceExportDraftFilters, type ExperienceExportDraftReport } from "../maintenance/experience-export-drafts.js";
|
|
5
|
+
import { type OperatorReviewReport } from "../maintenance/operator-review-flow.js";
|
|
3
6
|
import { type HybridRouteDecision } from "../hybrid/router.js";
|
|
4
|
-
import type { CandidateLifecycleState, DistillationSource, DistillationJobState, EvaluationMode, ExperienceInputRecord, FeedbackAttributionReason, InjectionEvent, InjectionScorecard, ExperienceNode, ExperienceNodeType, ExperienceState, TaskRun } from "../types/domain.js";
|
|
7
|
+
import type { CandidateLifecycleState, DistillationSource, DistillationJobState, EvaluationMode, ExperienceInputRecord, FeedbackAttributionReason, AttributionRecord, EpisodeProjection, InjectionEvent, InjectionScorecard, ExperienceNode, ExperienceNodeType, ExperienceState, TaskRun } from "../types/domain.js";
|
|
5
8
|
import { type ExperienceRepoSummary } from "./repo-summary.js";
|
|
9
|
+
import { type RetrievalPolicyInspectionSummary } from "./retrieval-policy-inspection.js";
|
|
6
10
|
export type ExperienceNodeSummary = {
|
|
7
11
|
id: string;
|
|
8
12
|
type: ExperienceNode["node_type"];
|
|
@@ -53,6 +57,7 @@ export type ExperienceTimelineEntry = {
|
|
|
53
57
|
};
|
|
54
58
|
export type ExperienceLastInspection = {
|
|
55
59
|
sessionId?: string;
|
|
60
|
+
episodeId?: string;
|
|
56
61
|
scopeId: string;
|
|
57
62
|
taskType: ExperienceInputRecord["task_type"];
|
|
58
63
|
intervention: "inject" | "skip" | "shadow" | "holdout";
|
|
@@ -60,6 +65,8 @@ export type ExperienceLastInspection = {
|
|
|
60
65
|
delivered?: boolean;
|
|
61
66
|
autoFeedback: "helped" | "harmed" | "none";
|
|
62
67
|
autoFeedbackReason?: InjectionEvent["attribution_reason"];
|
|
68
|
+
attributionRecords: AttributionRecord[];
|
|
69
|
+
episodeProjection?: EpisodeProjection;
|
|
63
70
|
outcome: ExperienceInputRecord["outcome_signal"];
|
|
64
71
|
injectedNodes: ExperienceNodeSummary[];
|
|
65
72
|
hints: string[];
|
|
@@ -68,6 +75,7 @@ export type ExperienceLastInspection = {
|
|
|
68
75
|
decisionExplanation?: string;
|
|
69
76
|
trustSummary?: string;
|
|
70
77
|
retrievalNotes: string[];
|
|
78
|
+
retrievalPolicySummary?: RetrievalPolicyInspectionSummary;
|
|
71
79
|
timeline: ExperienceTimelineEntry[];
|
|
72
80
|
learningStatus?: TaskRun["learning_status"];
|
|
73
81
|
learningReason?: string;
|
|
@@ -171,6 +179,9 @@ export declare class ExperienceInteractionService {
|
|
|
171
179
|
private readonly hybridWorkerClient;
|
|
172
180
|
private readonly inputRepo;
|
|
173
181
|
private readonly injectionRepo;
|
|
182
|
+
private readonly attributionRecordRepo;
|
|
183
|
+
private readonly repoPolicyRepo;
|
|
184
|
+
private readonly episodeRepo;
|
|
174
185
|
private readonly nodeRepo;
|
|
175
186
|
private readonly candidateRepo;
|
|
176
187
|
private readonly jobRepo;
|
|
@@ -197,8 +208,20 @@ export declare class ExperienceInteractionService {
|
|
|
197
208
|
listNodesByState(state: ExperienceState): ExperienceNodeSummary[];
|
|
198
209
|
listNodesByType(nodeType: ExperienceNodeType): ExperienceNodeSummary[];
|
|
199
210
|
inspectLearningSummary(): ExperienceLearningSummary;
|
|
211
|
+
inspectHygiene(cwd?: string, filters?: Omit<HygieneReviewFilters, "scopeId"> & {
|
|
212
|
+
scopeId?: string;
|
|
213
|
+
}): HygieneReviewReport;
|
|
214
|
+
inspectExportDrafts(cwd?: string, filters?: Omit<ExperienceExportDraftFilters, "scopeId"> & {
|
|
215
|
+
scopeId?: string;
|
|
216
|
+
}): ExperienceExportDraftReport;
|
|
217
|
+
inspectReview(cwd?: string, filters?: {
|
|
218
|
+
scopeId?: string;
|
|
219
|
+
limit?: number;
|
|
220
|
+
}): OperatorReviewReport;
|
|
200
221
|
private buildLearningSummary;
|
|
201
222
|
inspectRepoSummary(cwd?: string): ExperienceRepoSummary;
|
|
223
|
+
inspectRepoPolicy(cwd?: string): import("../experience-management/repo-policy.js").RepoPolicyInspection;
|
|
224
|
+
restoreRepoPolicy(cwd?: string): import("../types/domain.js").RepoPolicy;
|
|
202
225
|
inspectFirstValueReadiness(cwd?: string): ExperienceFirstValueReadiness;
|
|
203
226
|
inspectDecisionHealth(cwd?: string, limit?: number): ExperienceDecisionHealth;
|
|
204
227
|
feedbackLast(feedback: FeedbackValue, cwd?: string): FeedbackResult;
|
|
@@ -3,6 +3,10 @@ import { buildBenchmarkSummary } from "../evaluation/benchmark-summary.js";
|
|
|
3
3
|
import { buildExplainDecisionCapsule } from "../hybrid/capsule-builder.js";
|
|
4
4
|
import { resolveHybridExplainProviderEndpoint } from "../hybrid/explain-provider-client.js";
|
|
5
5
|
import { resolveHybridRolloutState } from "../hybrid/rollout.js";
|
|
6
|
+
import { buildDefaultRepoPolicy, inspectRepoPolicyEvidence } from "../experience-management/repo-policy.js";
|
|
7
|
+
import { buildHygieneReviewReport } from "../maintenance/experience-hygiene.js";
|
|
8
|
+
import { buildExperienceExportDraftReport } from "../maintenance/experience-export-drafts.js";
|
|
9
|
+
import { buildOperatorReviewFlow } from "../maintenance/operator-review-flow.js";
|
|
6
10
|
import { selectHybridRoute } from "../hybrid/router.js";
|
|
7
11
|
import { HybridWorkerClient } from "../hybrid/worker-client.js";
|
|
8
12
|
import { resolveScope } from "../input/scope-resolver.js";
|
|
@@ -12,6 +16,9 @@ import { DistillationJobRepository } from "../store/sqlite/repositories/distilla
|
|
|
12
16
|
import { HybridInvocationTraceRepository } from "../store/sqlite/repositories/hybrid-invocation-trace-repo.js";
|
|
13
17
|
import { InputRecordRepository } from "../store/sqlite/repositories/input-record-repo.js";
|
|
14
18
|
import { InjectionRepository } from "../store/sqlite/repositories/injection-repo.js";
|
|
19
|
+
import { AttributionRecordRepository } from "../store/sqlite/repositories/attribution-record-repo.js";
|
|
20
|
+
import { RepoPolicyRepository } from "../store/sqlite/repositories/repo-policy-repo.js";
|
|
21
|
+
import { EpisodeRepository } from "../store/sqlite/repositories/episode-repo.js";
|
|
15
22
|
import { NodeRepository } from "../store/sqlite/repositories/node-repo.js";
|
|
16
23
|
import { OutcomeRecordRepository } from "../store/sqlite/repositories/outcome-record-repo.js";
|
|
17
24
|
import { ReviewEventRepository } from "../store/sqlite/repositories/review-event-repo.js";
|
|
@@ -20,8 +27,9 @@ import { TaskRunRepository } from "../store/sqlite/repositories/task-run-repo.js
|
|
|
20
27
|
import { applyGovernedNodeFeedback, deriveNodeOriginProfileForNode } from "../experience-management/node-lifecycle-governance.js";
|
|
21
28
|
import { deriveGovernanceSignals, isPotentialMisfire } from "../experience-management/governance-observability.js";
|
|
22
29
|
import { nowIso } from "../utils/clock.js";
|
|
23
|
-
import { createId } from "../utils/ids.js";
|
|
30
|
+
import { createId, stableId } from "../utils/ids.js";
|
|
24
31
|
import { buildRepoSummary } from "./repo-summary.js";
|
|
32
|
+
import { buildRetrievalPolicyInspectionSummary } from "./retrieval-policy-inspection.js";
|
|
25
33
|
const normalizeHybridExplainPrompt = (value) => value
|
|
26
34
|
.toLowerCase()
|
|
27
35
|
.replace(/\s+/g, " ")
|
|
@@ -89,14 +97,41 @@ export const deriveStructuredSilenceReason = (input) => {
|
|
|
89
97
|
}
|
|
90
98
|
return "unknown";
|
|
91
99
|
};
|
|
92
|
-
const toReviewEvent = (nodeId, eventType, source, taskRunId) => ({
|
|
100
|
+
const toReviewEvent = (nodeId, eventType, source, taskRunId, episodeId) => ({
|
|
93
101
|
id: createId("review"),
|
|
102
|
+
episode_id: episodeId,
|
|
94
103
|
node_id: nodeId,
|
|
95
104
|
task_run_id: taskRunId,
|
|
96
105
|
event_type: eventType,
|
|
97
106
|
source,
|
|
98
107
|
created_at: nowIso()
|
|
99
108
|
});
|
|
109
|
+
const toManualOverrideAttributionRecord = (input) => {
|
|
110
|
+
const timestamp = nowIso();
|
|
111
|
+
return {
|
|
112
|
+
id: stableId("attr", `${input.injectionEvent?.injection_id ?? "manual"}:${input.nodeId}:manual_override:${input.feedback}:${timestamp}`),
|
|
113
|
+
injection_id: input.injectionEvent?.injection_id,
|
|
114
|
+
node_id: input.nodeId,
|
|
115
|
+
episode_id: input.episodeId ?? input.injectionEvent?.episode_id,
|
|
116
|
+
intervention_strength: input.injectionEvent?.scorecard?.interventionStrength,
|
|
117
|
+
injection_mode: input.injectionEvent?.mode,
|
|
118
|
+
delivery_mode: input.injectionEvent?.delivery_mode,
|
|
119
|
+
delivered: Boolean(input.injectionEvent?.delivered),
|
|
120
|
+
outcome: input.injectionEvent?.was_successful === true
|
|
121
|
+
? "success"
|
|
122
|
+
: input.injectionEvent?.was_successful === false
|
|
123
|
+
? "failure"
|
|
124
|
+
: "unknown",
|
|
125
|
+
attribution_verdict: input.feedback === "helped" ? "strong_helped" : "strong_harmed",
|
|
126
|
+
confidence: "high",
|
|
127
|
+
evidence_refs: input.evidenceRefs,
|
|
128
|
+
user_override: input.feedback,
|
|
129
|
+
source: "manual_override",
|
|
130
|
+
attribution_reason: "manual_override",
|
|
131
|
+
created_at: timestamp,
|
|
132
|
+
resolved_at: timestamp
|
|
133
|
+
};
|
|
134
|
+
};
|
|
100
135
|
const deriveNodeRisk = (node) => {
|
|
101
136
|
if (node.state === "candidate") {
|
|
102
137
|
return "high";
|
|
@@ -353,6 +388,9 @@ export class ExperienceInteractionService {
|
|
|
353
388
|
hybridWorkerClient;
|
|
354
389
|
inputRepo;
|
|
355
390
|
injectionRepo;
|
|
391
|
+
attributionRecordRepo;
|
|
392
|
+
repoPolicyRepo;
|
|
393
|
+
episodeRepo;
|
|
356
394
|
nodeRepo;
|
|
357
395
|
candidateRepo;
|
|
358
396
|
jobRepo;
|
|
@@ -367,6 +405,9 @@ export class ExperienceInteractionService {
|
|
|
367
405
|
bootstrapDatabase(db);
|
|
368
406
|
this.inputRepo = new InputRecordRepository(db);
|
|
369
407
|
this.injectionRepo = new InjectionRepository(db);
|
|
408
|
+
this.attributionRecordRepo = new AttributionRecordRepository(db);
|
|
409
|
+
this.repoPolicyRepo = new RepoPolicyRepository(db);
|
|
410
|
+
this.episodeRepo = new EpisodeRepository(db);
|
|
370
411
|
this.nodeRepo = new NodeRepository(db);
|
|
371
412
|
this.candidateRepo = new CandidateRepository(db);
|
|
372
413
|
this.jobRepo = new DistillationJobRepository(db);
|
|
@@ -458,15 +499,19 @@ export class ExperienceInteractionService {
|
|
|
458
499
|
if (!record) {
|
|
459
500
|
return undefined;
|
|
460
501
|
}
|
|
461
|
-
const
|
|
502
|
+
const episodeProjection = record.episode_id ? this.episodeRepo.getByEpisodeId(record.episode_id) : undefined;
|
|
503
|
+
const injectionEvent = episodeProjection?.injection_events[0] ?? (record.session_id
|
|
462
504
|
? this.injectionRepo.getLatestBySessionId(record.session_id)
|
|
463
505
|
: record.injected_node_ids.length
|
|
464
506
|
? this.injectionRepo.getLatest()
|
|
465
|
-
: undefined;
|
|
507
|
+
: undefined);
|
|
466
508
|
const selectedNodeIds = injectionEvent?.injected_node_ids?.length
|
|
467
509
|
? injectionEvent.injected_node_ids
|
|
468
510
|
: record.injected_node_ids;
|
|
469
511
|
const injectedNodes = this.nodeRepo.listByIds(selectedNodeIds);
|
|
512
|
+
const attributionRecords = episodeProjection?.attribution_records ?? (injectionEvent
|
|
513
|
+
? this.attributionRecordRepo.listByInjectionId(injectionEvent.injection_id)
|
|
514
|
+
: selectedNodeIds.flatMap((nodeId) => this.attributionRecordRepo.listByNodeId(nodeId)));
|
|
470
515
|
const scorecard = injectionEvent?.scorecard ??
|
|
471
516
|
(selectedNodeIds.length
|
|
472
517
|
? buildInjectionScorecard({
|
|
@@ -479,8 +524,8 @@ export class ExperienceInteractionService {
|
|
|
479
524
|
injected_node_ids: selectedNodeIds
|
|
480
525
|
}, "inject", injectedNodes, record.session_id)
|
|
481
526
|
: undefined);
|
|
482
|
-
const taskRun = record.session_id ? this.taskRunRepo.getLatestBySessionId(record.session_id) : undefined;
|
|
483
|
-
const reviewEvents = taskRun?.id ? this.reviewEventRepo.listByTaskRunId(taskRun.id) : [];
|
|
527
|
+
const taskRun = episodeProjection?.task_run ?? (record.session_id ? this.taskRunRepo.getLatestBySessionId(record.session_id) : undefined);
|
|
528
|
+
const reviewEvents = episodeProjection?.review_events ?? (taskRun?.id ? this.reviewEventRepo.listByTaskRunId(taskRun.id) : []);
|
|
484
529
|
const autoFeedback = summarizeAutomaticFeedback(reviewEvents);
|
|
485
530
|
const intervention = injectionEvent?.mode === "skip"
|
|
486
531
|
? "skip"
|
|
@@ -491,7 +536,7 @@ export class ExperienceInteractionService {
|
|
|
491
536
|
? "holdout"
|
|
492
537
|
: "shadow"
|
|
493
538
|
: "inject";
|
|
494
|
-
const outcomeRecord = taskRun?.id ? this.outcomeRepo.listByTaskRunId(taskRun.id)[0] : undefined;
|
|
539
|
+
const outcomeRecord = episodeProjection?.outcome_records[0] ?? (taskRun?.id ? this.outcomeRepo.listByTaskRunId(taskRun.id)[0] : undefined);
|
|
495
540
|
const latestAutomaticFeedback = reviewEvents.find((event) => event.source === "automatic");
|
|
496
541
|
const autoFeedbackReason = inferAutoFeedbackReason({
|
|
497
542
|
explicitReason: injectionEvent?.attribution_reason,
|
|
@@ -502,6 +547,7 @@ export class ExperienceInteractionService {
|
|
|
502
547
|
const decisionExplanation = buildDecisionExplanation({ intervention, scorecard });
|
|
503
548
|
return {
|
|
504
549
|
sessionId: record.session_id,
|
|
550
|
+
episodeId: record.episode_id,
|
|
505
551
|
scopeId: record.scope_id,
|
|
506
552
|
taskType: record.task_type,
|
|
507
553
|
intervention,
|
|
@@ -509,6 +555,8 @@ export class ExperienceInteractionService {
|
|
|
509
555
|
delivered: injectionEvent?.delivered,
|
|
510
556
|
autoFeedback,
|
|
511
557
|
autoFeedbackReason,
|
|
558
|
+
attributionRecords,
|
|
559
|
+
episodeProjection,
|
|
512
560
|
outcome: record.outcome_signal,
|
|
513
561
|
injectedNodes: injectedNodes.map(toNodeSummary),
|
|
514
562
|
hints: injectedNodes.map((node) => node.compact_hint),
|
|
@@ -517,6 +565,7 @@ export class ExperienceInteractionService {
|
|
|
517
565
|
decisionExplanation,
|
|
518
566
|
trustSummary: buildTrustSummary({ scorecard, injectedNodes: injectedNodes.map(toNodeSummary) }),
|
|
519
567
|
retrievalNotes: buildRetrievalNotes(scorecard),
|
|
568
|
+
retrievalPolicySummary: buildRetrievalPolicyInspectionSummary(scorecard),
|
|
520
569
|
timeline: buildLatestTimeline({
|
|
521
570
|
record,
|
|
522
571
|
taskRunCreatedAt: taskRun?.created_at,
|
|
@@ -539,13 +588,15 @@ export class ExperienceInteractionService {
|
|
|
539
588
|
if (!event) {
|
|
540
589
|
return undefined;
|
|
541
590
|
}
|
|
542
|
-
const
|
|
591
|
+
const episodeProjection = event.episode_id ? this.episodeRepo.getByEpisodeId(event.episode_id) : undefined;
|
|
592
|
+
const taskRun = episodeProjection?.task_run ?? (event.session_id ? this.taskRunRepo.getLatestBySessionId(event.session_id) : undefined);
|
|
543
593
|
const latestRecord = event.session_id ? this.inputRepo.getLatestBySessionId(event.session_id) : undefined;
|
|
544
594
|
if (latestRecord) {
|
|
545
595
|
return this.inspectRecord(latestRecord);
|
|
546
596
|
}
|
|
547
597
|
const injectedNodes = this.nodeRepo.listByIds(event.injected_node_ids);
|
|
548
|
-
const
|
|
598
|
+
const attributionRecords = episodeProjection?.attribution_records ?? this.attributionRecordRepo.listByInjectionId(event.injection_id);
|
|
599
|
+
const reviewEvents = episodeProjection?.review_events ?? (taskRun?.id ? this.reviewEventRepo.listByTaskRunId(taskRun.id) : []);
|
|
549
600
|
const autoFeedback = summarizeAutomaticFeedback(reviewEvents);
|
|
550
601
|
const latestAutomaticFeedback = reviewEvents.find((reviewEvent) => reviewEvent.source === "automatic");
|
|
551
602
|
const intervention = event.mode === "skip"
|
|
@@ -555,13 +606,14 @@ export class ExperienceInteractionService {
|
|
|
555
606
|
? "holdout"
|
|
556
607
|
: "shadow"
|
|
557
608
|
: "inject";
|
|
558
|
-
const outcomeRecord = taskRun?.id ? this.outcomeRepo.listByTaskRunId(taskRun.id)[0] : undefined;
|
|
609
|
+
const outcomeRecord = episodeProjection?.outcome_records[0] ?? (taskRun?.id ? this.outcomeRepo.listByTaskRunId(taskRun.id)[0] : undefined);
|
|
559
610
|
const outcome = outcomeRecord?.outcome_signal ??
|
|
560
611
|
(taskRun?.final_status === "success" ? "success" : taskRun?.final_status === "failure" ? "failure" : "unknown");
|
|
561
612
|
const summary = event.task_summary ?? taskRun?.task_summary ?? "Latest injection event";
|
|
562
613
|
const decisionExplanation = buildDecisionExplanation({ intervention, scorecard: event.scorecard });
|
|
563
614
|
return {
|
|
564
615
|
sessionId: event.session_id,
|
|
616
|
+
episodeId: event.episode_id,
|
|
565
617
|
scopeId: event.scope_id,
|
|
566
618
|
taskType: event.task_type,
|
|
567
619
|
intervention,
|
|
@@ -574,6 +626,8 @@ export class ExperienceInteractionService {
|
|
|
574
626
|
intervention,
|
|
575
627
|
outcome
|
|
576
628
|
}),
|
|
629
|
+
attributionRecords,
|
|
630
|
+
episodeProjection,
|
|
577
631
|
outcome,
|
|
578
632
|
injectedNodes: injectedNodes.map(toNodeSummary),
|
|
579
633
|
hints: injectedNodes.map((node) => node.compact_hint),
|
|
@@ -582,6 +636,7 @@ export class ExperienceInteractionService {
|
|
|
582
636
|
decisionExplanation,
|
|
583
637
|
trustSummary: buildTrustSummary({ scorecard: event.scorecard, injectedNodes: injectedNodes.map(toNodeSummary) }),
|
|
584
638
|
retrievalNotes: buildRetrievalNotes(event.scorecard),
|
|
639
|
+
retrievalPolicySummary: buildRetrievalPolicyInspectionSummary(event.scorecard),
|
|
585
640
|
timeline: buildLatestTimeline({
|
|
586
641
|
record: {
|
|
587
642
|
record_id: `injection:${event.injection_id}`,
|
|
@@ -665,6 +720,77 @@ export class ExperienceInteractionService {
|
|
|
665
720
|
inspectLearningSummary() {
|
|
666
721
|
return this.buildLearningSummary();
|
|
667
722
|
}
|
|
723
|
+
inspectHygiene(cwd = process.cwd(), filters = {}) {
|
|
724
|
+
const scopeId = filters.scopeId ?? resolveScope(cwd).scope_id;
|
|
725
|
+
const candidateStates = ["pending", "distilled", "failed", "discarded"];
|
|
726
|
+
return buildHygieneReviewReport({
|
|
727
|
+
nodes: this.nodeRepo.listByScope(scopeId),
|
|
728
|
+
candidates: candidateStates.flatMap((state) => this.candidateRepo.listByLifecycleState(state)).filter((candidate) => candidate.scope_id === scopeId),
|
|
729
|
+
attributionRecords: this.attributionRecordRepo.listRecentByScope(scopeId, Math.max(50, filters.limit ?? 20)),
|
|
730
|
+
filters: {
|
|
731
|
+
...filters,
|
|
732
|
+
scopeId
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
inspectExportDrafts(cwd = process.cwd(), filters = {}) {
|
|
737
|
+
const scopeId = filters.scopeId ?? resolveScope(cwd).scope_id;
|
|
738
|
+
const candidateStates = ["pending", "distilled", "failed", "discarded"];
|
|
739
|
+
const nodes = this.nodeRepo.listByScope(scopeId);
|
|
740
|
+
const explicitLowReadiness = Boolean(filters.nodeId || filters.risk || filters.state || filters.deliveryState);
|
|
741
|
+
const candidateNodes = nodes
|
|
742
|
+
.filter((node) => !filters.nodeId || node.id === filters.nodeId)
|
|
743
|
+
.filter((node) => !filters.nodeType || node.node_type === filters.nodeType)
|
|
744
|
+
.filter((node) => !filters.taskFamily || node.task_type === filters.taskFamily)
|
|
745
|
+
.filter((node) => !filters.state || node.state === filters.state)
|
|
746
|
+
.filter((node) => !filters.deliveryState || node.delivery_state === filters.deliveryState)
|
|
747
|
+
.filter((node) => explicitLowReadiness || (node.state === "active" && (!node.delivery_state || node.delivery_state === "eligible") && node.harmed_count <= node.helped_count));
|
|
748
|
+
const candidates = candidateStates
|
|
749
|
+
.flatMap((state) => this.candidateRepo.listByLifecycleState(state))
|
|
750
|
+
.filter((candidate) => candidate.scope_id === scopeId);
|
|
751
|
+
const attributionRecordsById = new Map();
|
|
752
|
+
for (const record of this.attributionRecordRepo.listRecentByScope(scopeId, Math.max(50, filters.limit ?? 20))) {
|
|
753
|
+
attributionRecordsById.set(record.id, record);
|
|
754
|
+
}
|
|
755
|
+
for (const node of candidateNodes) {
|
|
756
|
+
for (const record of this.attributionRecordRepo.listByNodeId(node.id)) {
|
|
757
|
+
attributionRecordsById.set(record.id, record);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
const attributionRecords = [...attributionRecordsById.values()];
|
|
761
|
+
const hygiene = buildHygieneReviewReport({
|
|
762
|
+
nodes,
|
|
763
|
+
candidates,
|
|
764
|
+
attributionRecords,
|
|
765
|
+
filters: {
|
|
766
|
+
scopeId,
|
|
767
|
+
limit: Math.max(50, filters.limit ?? 20)
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
return buildExperienceExportDraftReport({
|
|
771
|
+
nodes,
|
|
772
|
+
candidates,
|
|
773
|
+
attributionRecords,
|
|
774
|
+
hygieneFindings: hygiene.findings,
|
|
775
|
+
filters: {
|
|
776
|
+
...filters,
|
|
777
|
+
scopeId
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
inspectReview(cwd = process.cwd(), filters = {}) {
|
|
782
|
+
const scopeId = filters.scopeId ?? resolveScope(cwd).scope_id;
|
|
783
|
+
const limit = filters.limit ?? 5;
|
|
784
|
+
const repo = this.inspectRepoSummary(cwd);
|
|
785
|
+
const hygiene = this.inspectHygiene(cwd, { scopeId, limit });
|
|
786
|
+
const exportDrafts = this.inspectExportDrafts(cwd, { scopeId, limit });
|
|
787
|
+
return buildOperatorReviewFlow({
|
|
788
|
+
repo,
|
|
789
|
+
hygiene,
|
|
790
|
+
exportDrafts,
|
|
791
|
+
limit
|
|
792
|
+
});
|
|
793
|
+
}
|
|
668
794
|
buildLearningSummary(scopeId) {
|
|
669
795
|
const candidateStates = ["pending", "distilled", "failed", "discarded"];
|
|
670
796
|
const jobStates = ["pending", "processing", "succeeded", "failed", "discarded"];
|
|
@@ -728,6 +854,7 @@ export class ExperienceInteractionService {
|
|
|
728
854
|
const latestRecord = this.inputRepo.getLatestByScope(scope.scope_id);
|
|
729
855
|
const latest = latestRecord ? this.inspectRecord(latestRecord) : undefined;
|
|
730
856
|
const learning = this.buildLearningSummary(scope.scope_id);
|
|
857
|
+
const policyInspection = this.inspectRepoPolicy(cwd);
|
|
731
858
|
return buildRepoSummary({
|
|
732
859
|
scope: {
|
|
733
860
|
scopeId: scope.scope_id,
|
|
@@ -735,9 +862,20 @@ export class ExperienceInteractionService {
|
|
|
735
862
|
rootPath: scope.root_path
|
|
736
863
|
},
|
|
737
864
|
latest: latest && latest.scopeId === scope.scope_id ? latest : undefined,
|
|
738
|
-
learning
|
|
865
|
+
learning,
|
|
866
|
+
policyInspection
|
|
739
867
|
});
|
|
740
868
|
}
|
|
869
|
+
inspectRepoPolicy(cwd = process.cwd()) {
|
|
870
|
+
const scope = resolveScope(cwd);
|
|
871
|
+
const policy = this.repoPolicyRepo.get(scope.scope_id) ??
|
|
872
|
+
buildDefaultRepoPolicy(scope.scope_id, this.config.repoExperienceMode);
|
|
873
|
+
return inspectRepoPolicyEvidence(policy, this.attributionRecordRepo.listRecentEligibleByScope(scope.scope_id), this.injectionRepo.listRecentResolvedByScope(scope.scope_id));
|
|
874
|
+
}
|
|
875
|
+
restoreRepoPolicy(cwd = process.cwd()) {
|
|
876
|
+
const scope = resolveScope(cwd);
|
|
877
|
+
return this.repoPolicyRepo.restore(scope.scope_id, this.config.repoExperienceMode);
|
|
878
|
+
}
|
|
741
879
|
inspectFirstValueReadiness(cwd = process.cwd()) {
|
|
742
880
|
const scope = resolveScope(cwd);
|
|
743
881
|
const summary = this.buildLearningSummary(scope.scope_id);
|
|
@@ -873,9 +1011,25 @@ export class ExperienceInteractionService {
|
|
|
873
1011
|
const taskRunId = record.session_id
|
|
874
1012
|
? this.taskRunRepo.getLatestBySessionId(record.session_id)?.id
|
|
875
1013
|
: undefined;
|
|
1014
|
+
const episodeId = record.episode_id;
|
|
1015
|
+
const injectionEvent = record.session_id
|
|
1016
|
+
? this.injectionRepo.getLatestBySessionId(record.session_id)
|
|
1017
|
+
: undefined;
|
|
1018
|
+
const evidenceRefs = [
|
|
1019
|
+
record.record_id,
|
|
1020
|
+
taskRunId,
|
|
1021
|
+
injectionEvent?.injection_id
|
|
1022
|
+
].filter((value) => Boolean(value));
|
|
876
1023
|
for (const node of nodes) {
|
|
877
1024
|
this.nodeRepo.upsert(applyGovernedNodeFeedback(node, feedback, this.deriveOriginProfile(node)));
|
|
878
|
-
this.reviewEventRepo.upsert(toReviewEvent(node.id, feedback === "helped" ? "mark_helped" : "mark_harmed", "user", taskRunId));
|
|
1025
|
+
this.reviewEventRepo.upsert(toReviewEvent(node.id, feedback === "helped" ? "mark_helped" : "mark_harmed", "user", taskRunId, episodeId));
|
|
1026
|
+
this.attributionRecordRepo.insert(toManualOverrideAttributionRecord({
|
|
1027
|
+
nodeId: node.id,
|
|
1028
|
+
feedback,
|
|
1029
|
+
injectionEvent,
|
|
1030
|
+
episodeId,
|
|
1031
|
+
evidenceRefs
|
|
1032
|
+
}));
|
|
879
1033
|
}
|
|
880
1034
|
return {
|
|
881
1035
|
status: "updated",
|
|
@@ -894,6 +1048,11 @@ export class ExperienceInteractionService {
|
|
|
894
1048
|
}
|
|
895
1049
|
this.nodeRepo.upsert(applyGovernedNodeFeedback(node, feedback, this.deriveOriginProfile(node)));
|
|
896
1050
|
this.reviewEventRepo.upsert(toReviewEvent(nodeId, feedback === "helped" ? "mark_helped" : "mark_harmed", "user"));
|
|
1051
|
+
this.attributionRecordRepo.insert(toManualOverrideAttributionRecord({
|
|
1052
|
+
nodeId,
|
|
1053
|
+
feedback,
|
|
1054
|
+
evidenceRefs: [`manual:${nodeId}`]
|
|
1055
|
+
}));
|
|
897
1056
|
return {
|
|
898
1057
|
status: "updated",
|
|
899
1058
|
feedback,
|