Skip to content

Commit d0d9b05

Browse files
committed
feat: surface foundation readiness signal semantics
1 parent 477caef commit d0d9b05

15 files changed

Lines changed: 173 additions & 3 deletions

docs/brainstorms/2026-04-19-mainline-progress-reconciliation-and-post-m7-direction-requirements.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ This document re-baselines current mainline truth on 2026-04-19, records what ch
193193
- readiness now reports `queryBackendDefaultMode`
194194
- readiness now reports `vectorAdapterLinkedIntoQueryBackend`
195195
- operator UI and diagnostics snapshots expose the same linkage evidence, while overall status still remains `in_progress` / `no-go`.
196+
- The next bounded execution slice after that makes current signal semantics explicit without flipping readiness:
197+
- readiness now reports `queryBackendScoreSignals`
198+
- readiness now reports `vectorAdapterSignalKind`
199+
- current mainline truth is now machine-readable as lexical-prefilter semantics rather than an ambiguous "vector" label
200+
- overall status still remains `in_progress` / `no-go`, because lexical overlap evidence is still not ANN evidence.
196201
- Current expected outcome on `main` remains:
197202
- status `in_progress`
198203
- decision `no-go`

docs/diataxis/en/explanation/development-progress-dashboard.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,23 @@ Execution anchor:
258258
- failing references: `24405317254`, `24404975285`,
259259
- recovered run: `24502592419` (`Migration Gates` all green, including runtime/browser/tauri agent-workspace suites).
260260

261+
## Latest Mainline Increment (2026-04-20 M8.9 Foundation Signal-Semantics Evidence)
262+
263+
- Strengthened foundation-readiness evidence without changing the readiness verdict:
264+
- `FoundationReadinessReport.baseline` now includes `queryBackendScoreSignals`,
265+
- `FoundationReadinessReport.baseline` now includes `vectorAdapterSignalKind`.
266+
- Mainline readiness payload now makes current retrieval semantics explicit instead of leaving them implied:
267+
- query backend scoring currently exposes `keyword_matches`, `title_match_bonus`, `vector_prefilter_content_bonus`, and `relation_bonus`,
268+
- vector acceleration currently reports `lexical_token_overlap`, which confirms a lexical prefilter stage rather than embedding-backed ANN retrieval.
269+
- Operator/runtime inspectability stayed aligned with the typed/report layer:
270+
- `scripts/verify-foundation-readiness.js` prints the new signal fields,
271+
- `src/frontend/agent_workspace_runtime.js` persists the same fields in `lastFoundationReadiness`,
272+
- the toolbar summary now includes both the score-signal list and the vector signal kind.
273+
- Guardrail remains unchanged on `main`:
274+
- status stays `in_progress`,
275+
- decision stays `no-go`,
276+
- no ANN readiness claim is permitted from lexical-prefilter evidence alone.
277+
261278
## Latest Mainline Increment (2026-04-16 M7.2 Runtime Evidence Deepening Lane)
262279

263280
- Expanded runtime behavior coverage in `src/agent_workspace.runtime.behavior.test.ts` for pane lifecycle evidence:

docs/diataxis/en/explanation/foundation-reentry-readiness-checklist.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,17 @@ Bundle note:
5858
- rationale: file-backed baseline exists, query-backend and vector-boundary modules are now present, but the vector adapter is still only `prefilter_only`, so independent ANN evidence is still absent.
5959
- The readiness payload now makes that distinction explicit:
6060
- `queryBackendDefaultMode`
61+
- `queryBackendScoreSignals`
6162
- `vectorAdapterLinkedIntoQueryBackend`
6263
- `vectorAdapterStatus`
64+
- `vectorAdapterSignalKind`
6365
- `vectorAdapterIndependent`
66+
- Current expected signal semantics on `main` are:
67+
- `queryBackendScoreSignals = [keyword_matches, title_match_bonus, vector_prefilter_content_bonus, relation_bonus]`
68+
- `vectorAdapterSignalKind = lexical_token_overlap`
69+
- Interpretation rule:
70+
- `lexical_token_overlap` is evidence of lexical prefilter scoring only.
71+
- It is **not** evidence of embedding-backed ANN readiness.
6472

6573
## Non-overclaim Policy
6674

docs/diataxis/zh/explanation/development-progress-dashboard.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,23 @@
258258
- 历史失败参考:`24405317254``24404975285`
259259
- 修复后运行:`24502592419``Migration Gates` 全绿,含 runtime/browser/tauri 三个 agent-workspace 套件)。
260260

261+
## 主线最新增量(2026-04-20 M8.9 Foundation 信号语义证据)
262+
263+
- 在不改变 readiness 结论的前提下,补强了 foundation-readiness 证据面:
264+
- `FoundationReadinessReport.baseline` 新增 `queryBackendScoreSignals`
265+
- `FoundationReadinessReport.baseline` 新增 `vectorAdapterSignalKind`
266+
- 主线 readiness 载荷现在把当前检索语义显式写出,而不是让执行侧自行猜测:
267+
- query backend 当前打分信号为 `keyword_matches``title_match_bonus``vector_prefilter_content_bonus``relation_bonus`
268+
- vector acceleration 当前信号类型为 `lexical_token_overlap`,这只说明“词法预过滤”阶段存在,不等于 embedding/ANN 检索已经落地。
269+
- 执行侧/运行时可观测性保持与 typed/report 层一致:
270+
- `scripts/verify-foundation-readiness.js` 现在输出新信号字段,
271+
- `src/frontend/agent_workspace_runtime.js` 会在 `lastFoundationReadiness` 中保留同样字段,
272+
- 工具栏摘要消息现在会同时展示打分信号列表与向量信号类型。
273+
- `main` 上的护栏结论保持不变:
274+
- 状态仍为 `in_progress`
275+
- 决策仍为 `no-go`
276+
- 不能把 lexical-prefilter 证据误写成 ANN readiness。
277+
261278
## 主线最新增量(2026-04-16 M7.2 运行时证据加深链路)
262279

263280
- 已在 `src/agent_workspace.runtime.behavior.test.ts` 扩展 pane 生命周期证据覆盖:

docs/diataxis/zh/explanation/foundation-reentry-readiness-checklist.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,17 @@
5858
- 原因:file-backed 基线已存在,query-backend 与 vector 边界都已进入主线,但该 vector adapter 仍只是 `prefilter_only`,独立 ANN 证据仍未进入主线。
5959
- readiness 载荷现在也显式区分这层语义:
6060
- `queryBackendDefaultMode`
61+
- `queryBackendScoreSignals`
6162
- `vectorAdapterLinkedIntoQueryBackend`
6263
- `vectorAdapterStatus`
64+
- `vectorAdapterSignalKind`
6365
- `vectorAdapterIndependent`
66+
- 当前 `main` 的预期信号语义为:
67+
- `queryBackendScoreSignals = [keyword_matches, title_match_bonus, vector_prefilter_content_bonus, relation_bonus]`
68+
- `vectorAdapterSignalKind = lexical_token_overlap`
69+
- 解读规则:
70+
- `lexical_token_overlap` 只表示词法预过滤打分存在。
71+
-**不等于** embedding/ANN readiness 已经成立。
6472

6573
## 防超前宣称策略
6674

scripts/foundation-readiness-utils.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,23 @@ function resolveQueryBackendDefaultMode(queryBackendSource, graphAdapterModulePr
5151
return 'unknown';
5252
}
5353

54+
function resolveQueryBackendScoreSignals(queryBackendSource, graphAdapterModulePresent) {
55+
if (!graphAdapterModulePresent) {
56+
return [];
57+
}
58+
59+
const signalChecks = [
60+
['keyword_matches', /\bkeywordMatches\b/],
61+
['title_match_bonus', /\btitleMatchBonus\b/],
62+
['vector_prefilter_content_bonus', /\bcontentMatchBonus\b/],
63+
['relation_bonus', /\brelationBonus\b/],
64+
];
65+
66+
return signalChecks
67+
.filter(([, pattern]) => pattern.test(queryBackendSource))
68+
.map(([signal]) => signal);
69+
}
70+
5471
function resolveVectorAdapterLinkedIntoQueryBackend(queryBackendSource, graphAdapterModulePresent) {
5572
if (!graphAdapterModulePresent) {
5673
return false;
@@ -60,6 +77,31 @@ function resolveVectorAdapterLinkedIntoQueryBackend(queryBackendSource, graphAda
6077
&& queryBackendSource.includes('vectorAccelerationAdapter.accelerate');
6178
}
6279

80+
function resolveVectorAdapterSignalKind(vectorAdapterSource, vectorAdapterModulePresent) {
81+
if (!vectorAdapterModulePresent) {
82+
return 'absent';
83+
}
84+
85+
if (
86+
/lexicalTokenMatches/.test(vectorAdapterSource)
87+
|| /lexicalTokenScore/.test(vectorAdapterSource)
88+
) {
89+
return 'lexical_token_overlap';
90+
}
91+
92+
if (
93+
/embedding/i.test(vectorAdapterSource)
94+
|| /\bann\b/i.test(vectorAdapterSource)
95+
|| /approximate nearest/i.test(vectorAdapterSource)
96+
|| /hnsw/i.test(vectorAdapterSource)
97+
|| /faiss/i.test(vectorAdapterSource)
98+
) {
99+
return 'embedding_ann';
100+
}
101+
102+
return 'unknown';
103+
}
104+
63105
function evaluateFoundationReadiness(options = {}) {
64106
const repoRoot = options.repoRoot || path.resolve(__dirname, '..');
65107
const packageJson = readJsonIfExists(path.join(repoRoot, 'package.json'));
@@ -113,8 +155,16 @@ function evaluateFoundationReadiness(options = {}) {
113155
&& storeSource.includes("storeType: 'file'");
114156
const graphAdapterModulePresent = fileExists(graphAdapterPath);
115157
const queryBackendDefaultMode = resolveQueryBackendDefaultMode(queryBackendSource, graphAdapterModulePresent);
158+
const queryBackendScoreSignals = resolveQueryBackendScoreSignals(
159+
queryBackendSource,
160+
graphAdapterModulePresent
161+
);
116162
const vectorAdapterModulePresent = fileExists(vectorAdapterPath);
117163
const vectorAdapterStatus = resolveVectorAdapterStatus(vectorAdapterSource, vectorAdapterModulePresent);
164+
const vectorAdapterSignalKind = resolveVectorAdapterSignalKind(
165+
vectorAdapterSource,
166+
vectorAdapterModulePresent
167+
);
118168
const vectorAdapterIndependent = vectorAdapterStatus === 'independent';
119169
const vectorAdapterLinkedIntoQueryBackend = resolveVectorAdapterLinkedIntoQueryBackend(
120170
queryBackendSource,
@@ -222,8 +272,10 @@ function evaluateFoundationReadiness(options = {}) {
222272
fileBackedStore,
223273
graphAdapterModulePresent,
224274
queryBackendDefaultMode,
275+
queryBackendScoreSignals,
225276
vectorAdapterModulePresent,
226277
vectorAdapterStatus,
278+
vectorAdapterSignalKind,
227279
vectorAdapterIndependent,
228280
vectorAdapterLinkedIntoQueryBackend,
229281
},
@@ -255,8 +307,10 @@ function formatFoundationReadinessMarkdown(result, reportPaths) {
255307
`- File-backed store evidence: ${result.baseline.fileBackedStore ? 'yes' : 'no'}`,
256308
`- Dedicated graph adapter module present: ${result.baseline.graphAdapterModulePresent ? 'yes' : 'no'}`,
257309
`- Query backend default mode: ${result.baseline.queryBackendDefaultMode}`,
310+
`- Query backend score signals: ${result.baseline.queryBackendScoreSignals.join(', ') || 'none'}`,
258311
`- Dedicated vector adapter module present: ${result.baseline.vectorAdapterModulePresent ? 'yes' : 'no'}`,
259312
`- Vector adapter status: ${result.baseline.vectorAdapterStatus}`,
313+
`- Vector adapter signal kind: ${result.baseline.vectorAdapterSignalKind}`,
260314
`- Vector adapter independent: ${result.baseline.vectorAdapterIndependent ? 'yes' : 'no'}`,
261315
`- Vector adapter linked into query backend: ${result.baseline.vectorAdapterLinkedIntoQueryBackend ? 'yes' : 'no'}`,
262316
'',

scripts/verify-foundation-readiness.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@ function printHumanReport(result, reportPaths) {
2121
`[Foundation Readiness] Dedicated graph adapter present: ${result.baseline.graphAdapterModulePresent ? 'yes' : 'no'}`
2222
);
2323
console.log(`[Foundation Readiness] Query backend default mode: ${result.baseline.queryBackendDefaultMode}`);
24+
console.log(
25+
`[Foundation Readiness] Query backend score signals: ${result.baseline.queryBackendScoreSignals.join(', ') || 'none'}`
26+
);
2427
console.log(
2528
`[Foundation Readiness] Dedicated vector adapter present: ${result.baseline.vectorAdapterModulePresent ? 'yes' : 'no'}`
2629
);
2730
console.log(`[Foundation Readiness] Vector adapter status: ${result.baseline.vectorAdapterStatus}`);
31+
console.log(`[Foundation Readiness] Vector adapter signal kind: ${result.baseline.vectorAdapterSignalKind}`);
2832
console.log(
2933
`[Foundation Readiness] Vector adapter independent: ${result.baseline.vectorAdapterIndependent ? 'yes' : 'no'}`
3034
);

src/agent_workspace.runtime.behavior.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,8 +1666,15 @@ describe('agent workspace runtime behavior', () => {
16661666
fileBackedStore: true,
16671667
graphAdapterModulePresent: true,
16681668
queryBackendDefaultMode: 'local_hybrid',
1669+
queryBackendScoreSignals: [
1670+
'keyword_matches',
1671+
'title_match_bonus',
1672+
'vector_prefilter_content_bonus',
1673+
'relation_bonus',
1674+
],
16691675
vectorAdapterModulePresent: true,
16701676
vectorAdapterStatus: 'prefilter_only',
1677+
vectorAdapterSignalKind: 'lexical_token_overlap',
16711678
vectorAdapterIndependent: false,
16721679
vectorAdapterLinkedIntoQueryBackend: true,
16731680
},
@@ -1710,6 +1717,7 @@ describe('agent workspace runtime behavior', () => {
17101717
expect(messages.textContent || '').toContain('Foundation readiness');
17111718
expect(messages.textContent || '').toContain('prefilter_only');
17121719
expect(messages.textContent || '').toContain('local_hybrid');
1720+
expect(messages.textContent || '').toContain('lexical_token_overlap');
17131721

17141722
const snapshot = runtime.getDiagnosticsSnapshot();
17151723
expect(snapshot.lastFoundationReadiness).toEqual(
@@ -1718,7 +1726,14 @@ describe('agent workspace runtime behavior', () => {
17181726
decision: 'no-go',
17191727
storeType: 'file',
17201728
queryBackendDefaultMode: 'local_hybrid',
1729+
queryBackendScoreSignals: [
1730+
'keyword_matches',
1731+
'title_match_bonus',
1732+
'vector_prefilter_content_bonus',
1733+
'relation_bonus',
1734+
],
17211735
vectorAdapterStatus: 'prefilter_only',
1736+
vectorAdapterSignalKind: 'lexical_token_overlap',
17221737
vectorAdapterIndependent: false,
17231738
vectorAdapterLinkedIntoQueryBackend: true,
17241739
recommendationsCount: 1,

src/foundation.readiness.contract.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ type FoundationReadinessResult = {
1616
fileBackedStore: boolean;
1717
graphAdapterModulePresent: boolean;
1818
queryBackendDefaultMode: 'absent' | 'unknown' | 'local_hybrid' | 'keyword_only';
19+
queryBackendScoreSignals: string[];
1920
vectorAdapterModulePresent: boolean;
2021
vectorAdapterStatus: 'absent' | 'prefilter_only' | 'independent';
22+
vectorAdapterSignalKind: 'absent' | 'unknown' | 'lexical_token_overlap' | 'embedding_ann';
2123
vectorAdapterIndependent: boolean;
2224
vectorAdapterLinkedIntoQueryBackend: boolean;
2325
};
@@ -111,8 +113,15 @@ describe('foundation readiness contract', () => {
111113
expect(result.baseline.fileBackedStore).toBe(true);
112114
expect(result.baseline.graphAdapterModulePresent).toBe(true);
113115
expect(result.baseline.queryBackendDefaultMode).toBe('local_hybrid');
116+
expect(result.baseline.queryBackendScoreSignals).toEqual([
117+
'keyword_matches',
118+
'title_match_bonus',
119+
'vector_prefilter_content_bonus',
120+
'relation_bonus',
121+
]);
114122
expect(result.baseline.vectorAdapterModulePresent).toBe(true);
115123
expect(result.baseline.vectorAdapterStatus).toBe('prefilter_only');
124+
expect(result.baseline.vectorAdapterSignalKind).toBe('lexical_token_overlap');
116125
expect(result.baseline.vectorAdapterIndependent).toBe(false);
117126
expect(result.baseline.vectorAdapterLinkedIntoQueryBackend).toBe(true);
118127
expect(result.documents.checklistPagesPresent).toBe(true);
@@ -171,8 +180,10 @@ describe('foundation readiness contract', () => {
171180
expect(result.baseline.fileBackedStore).toBe(true);
172181
expect(result.baseline.graphAdapterModulePresent).toBe(true);
173182
expect(result.baseline.queryBackendDefaultMode).toBe('unknown');
183+
expect(result.baseline.queryBackendScoreSignals).toEqual([]);
174184
expect(result.baseline.vectorAdapterModulePresent).toBe(true);
175185
expect(result.baseline.vectorAdapterStatus).toBe('independent');
186+
expect(result.baseline.vectorAdapterSignalKind).toBe('unknown');
176187
expect(result.baseline.vectorAdapterIndependent).toBe(true);
177188
expect(result.baseline.vectorAdapterLinkedIntoQueryBackend).toBe(false);
178189
expect(result.documents.checklistPagesPresent).toBe(true);

src/frontend/agent_workspace_runtime.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1434,7 +1434,9 @@
14341434
decision: '',
14351435
storeType: '',
14361436
queryBackendDefaultMode: '',
1437+
queryBackendScoreSignals: [],
14371438
vectorAdapterStatus: '',
1439+
vectorAdapterSignalKind: '',
14381440
vectorAdapterIndependent: false,
14391441
vectorAdapterLinkedIntoQueryBackend: false,
14401442
recommendationsCount: 0,
@@ -1463,22 +1465,31 @@
14631465
decision: trimString(readiness && readiness.decision),
14641466
storeType: trimString(baseline.storeType),
14651467
queryBackendDefaultMode: trimString(baseline.queryBackendDefaultMode),
1468+
queryBackendScoreSignals: Array.isArray(baseline.queryBackendScoreSignals)
1469+
? baseline.queryBackendScoreSignals.map((entry) => trimString(entry)).filter(Boolean)
1470+
: [],
14661471
vectorAdapterStatus: trimString(baseline.vectorAdapterStatus),
1472+
vectorAdapterSignalKind: trimString(baseline.vectorAdapterSignalKind),
14671473
vectorAdapterIndependent: Boolean(baseline.vectorAdapterIndependent),
14681474
vectorAdapterLinkedIntoQueryBackend: Boolean(baseline.vectorAdapterLinkedIntoQueryBackend),
14691475
recommendationsCount,
14701476
};
1477+
const queryBackendScoreSignals = Array.isArray(baseline.queryBackendScoreSignals)
1478+
? baseline.queryBackendScoreSignals.map((entry) => trimString(entry)).filter(Boolean)
1479+
: [];
14711480
appendMessage(
14721481
'assistant',
14731482
getI18nText(
14741483
'agentWorkspace.messages.foundationReadinessLoaded',
1475-
`Foundation readiness ${trimString(readiness && readiness.status) || 'unknown'} / ${trimString(readiness && readiness.decision) || 'unknown'} (store ${trimString(baseline.storeType) || 'n/a'}, backend ${trimString(baseline.queryBackendDefaultMode) || 'n/a'}, vector ${trimString(baseline.vectorAdapterStatus) || 'n/a'}, independent ${Boolean(baseline.vectorAdapterIndependent) ? 'yes' : 'no'}, linked ${Boolean(baseline.vectorAdapterLinkedIntoQueryBackend) ? 'yes' : 'no'}).`,
1484+
`Foundation readiness ${trimString(readiness && readiness.status) || 'unknown'} / ${trimString(readiness && readiness.decision) || 'unknown'} (store ${trimString(baseline.storeType) || 'n/a'}, backend ${trimString(baseline.queryBackendDefaultMode) || 'n/a'}, signals ${queryBackendScoreSignals.join(', ') || 'none'}, vector ${trimString(baseline.vectorAdapterStatus) || 'n/a'}, signal-kind ${trimString(baseline.vectorAdapterSignalKind) || 'n/a'}, independent ${Boolean(baseline.vectorAdapterIndependent) ? 'yes' : 'no'}, linked ${Boolean(baseline.vectorAdapterLinkedIntoQueryBackend) ? 'yes' : 'no'}).`,
14761485
{
14771486
status: trimString(readiness && readiness.status) || 'unknown',
14781487
decision: trimString(readiness && readiness.decision) || 'unknown',
14791488
storeType: trimString(baseline.storeType) || 'n/a',
14801489
queryBackendDefaultMode: trimString(baseline.queryBackendDefaultMode) || 'n/a',
1490+
queryBackendScoreSignals: queryBackendScoreSignals.join(', ') || 'none',
14811491
vectorAdapterStatus: trimString(baseline.vectorAdapterStatus) || 'n/a',
1492+
vectorAdapterSignalKind: trimString(baseline.vectorAdapterSignalKind) || 'n/a',
14821493
vectorAdapterIndependent: Boolean(baseline.vectorAdapterIndependent) ? 'yes' : 'no',
14831494
vectorAdapterLinkedIntoQueryBackend: Boolean(baseline.vectorAdapterLinkedIntoQueryBackend)
14841495
? 'yes'
@@ -1495,7 +1506,9 @@
14951506
decision: '',
14961507
storeType: '',
14971508
queryBackendDefaultMode: '',
1509+
queryBackendScoreSignals: [],
14981510
vectorAdapterStatus: '',
1511+
vectorAdapterSignalKind: '',
14991512
vectorAdapterIndependent: false,
15001513
vectorAdapterLinkedIntoQueryBackend: false,
15011514
recommendationsCount: 0,

0 commit comments

Comments
 (0)