Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/scripts/verify-packed-retrieval-parity.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@ function assertPackageMeasurement(record, tarballPath) {
const evaluationTooling = manifest.items?.find((item) => item.id === 'evaluation-tooling')
const activePhase = manifest.items?.find((item) => item.id === manifest.current?.active_phase)
const budget = activePhase?.npm_package_budget ?? evaluationTooling?.npm_package_budget
const receipt = manifest.current
const receipt = activePhase?.corrective?.package_candidate ?? manifest.current
const actual = {
npm_files: requiredNumber(record.entryCount, 'npm pack entryCount'),
npm_packed_bytes: requiredNumber(record.size, 'npm pack size'),
npm_unpacked_bytes: requiredNumber(record.unpackedSize, 'npm pack unpackedSize'),
}
for (const [field, value] of Object.entries(actual)) {
if (requiredNumber(receipt?.[field], `current release package receipt ${field}`) !== value) {
if (requiredNumber(receipt?.[field], `active package receipt ${field}`) !== value) {
throw new Error(
`Current release package receipt is stale: ${field}=${receipt?.[field]}, freshly packed artifact=${value}`,
`Active package receipt is stale: ${field}=${receipt?.[field]}, freshly packed artifact=${value}`,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
)
}
}
Expand All @@ -76,13 +76,13 @@ function assertPackageMeasurement(record, tarballPath) {
|| receipt?.npm_integrity !== record.integrity
) {
throw new Error(
'Current release artifact identity is stale for the freshly packed artifact',
'Active package artifact identity is stale for the freshly packed artifact',
)
}
const artifactSha256 = createHash('sha256').update(readFileSync(tarballPath)).digest('hex')
if (receipt?.npm_artifact_sha256 !== artifactSha256) {
throw new Error(
'Current release SHA-256 is stale for the freshly packed artifact',
'Active package SHA-256 is stale for the freshly packed artifact',
)
}
if (
Expand Down
51 changes: 48 additions & 3 deletions docs/core-reset/removal-manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,13 @@ current:
parent_authorization_receipt: https://github.com/mohanagy/madar/issues/629#issuecomment-5155128626
target_branch: next
npm_dist_tag: next
publication_state: authorized_pending_protected_next_release_merge
qualification_state: pending_manual_test_and_formal_631_gate
publication_state: published_from_protected_next
publication_receipt: https://github.com/mohanagy/madar/issues/631#issuecomment-5155719419
release_merge: 81045cc08f1df797ecb86748c9bce09db62aeebd
release_tree: 9d3d90fe7feb3e55042c4f38ac8925abca6e83d1
trusted_publishing_run: https://github.com/mohanagy/madar/actions/runs/30734176943
published_at: 2026-08-02T05:42:52Z
qualification_state: owner_manual_test_found_corrective_defects_formal_631_gate_pending
package_candidate:
npm_files: 102
npm_packed_bytes: 155157
Expand Down Expand Up @@ -2666,7 +2671,47 @@ items:
registry_metadata_publication: forbidden
tag: forbidden
main_target: forbidden
notes: 'Issues #632 and #630 are complete. The owner separately authorized exactly @lubab/madar@0.40.0-beta.5 under npm next from the forthcoming protected-next release merge for manual testing before formal #631 qualification. #631 will compare that installed package with 0.32.0, 0.40.0-beta.4, one pinned Graphify commit and a no-tool control. No comparative claim or provider campaign exists yet; stable/latest, GitHub Release, Registry publication, a tag and main remain forbidden.'
corrective:
authorization_receipt: https://github.com/mohanagy/madar/issues/631#issuecomment-5157008370
parent_receipt: https://github.com/mohanagy/madar/issues/629#issuecomment-5157009594
protected_base: 81045cc08f1df797ecb86748c9bce09db62aeebd
protected_base_tree: 9d3d90fe7feb3e55042c4f38ac8925abca6e83d1
target_branch: next
modified_sources:
- src/adapters/mcp/protocol.ts
- src/domain/query/plan.ts
evaluation_sources:
- tools/eval/lib/infrastructure/compare.ts
production_loc_budget:
added_max: 8
removed_min: 8
net_max: 0
source_measurement:
production_typescript_files: 44
production_typescript_loc: 15871
added: 8
removed: 8
net: 0
diff_sha256: 51a23988d596afd5d060d603ad98f83903ed06c8bf6cf6bcba0bac66a59e12fe
replacement_measurement:
source_loc: 1424
emitted_bytes: 60983
package_candidate:
npm_files: 102
npm_packed_bytes: 155253
npm_unpacked_bytes: 653988
npm_shasum: fe8d482e4bbca13df65a4eb4efd45fde1c35f4a4
npm_integrity: sha512-8vuEuekerfMzLeIky14BCZa0CUBT34vL8eL1D/ees90u04TGnPdHra1dAsV47AnsiEp3UAPiAsnLKUVpEc1FEg==
npm_artifact_sha256: f63056b7bce91beb59dcdbb341092100500234ff859caac6199c1e84706f0b8e
constraints:
new_production_files: forbidden
dependency_or_lock_change: forbidden
graph_or_index_change: forbidden
query_result_schema_change: forbidden
retrieval_budget_change: forbidden
package_ceiling_change: forbidden
publication: forbidden
notes: 'Issues #632 and #630 are complete and beta.5 is immutable published manual-test history. The beta.5 owner test found one generic workflow-bound parser defect and one ready-state client-handoff defect before formal #631 qualification. Corrective receipt 5157008370 authorizes exactly two zero-net production-source modifications plus the zero-fallback evaluator correction from protected next 81045cc08f1df797ecb86748c9bce09db62aeebd. Both exact owner prompts now return ready 7/7 against the same real-GoValidate flow/evidence corridor without changing graph, index, selection, result schema, dependencies, retrieval budgets, or package ceilings. No comparative claim or provider campaign exists yet; publication, stable/latest, GitHub Release, Registry publication, a tag and main remain forbidden.'
exit_gate: The installed exact-head package matches or beats the strongest frozen baseline, scores at least 90 mean with no run below 85 or critical error, makes one Madar retrieval with zero repository-tool fallback in natural-client runs, and passes closed-book, parity, budget, CI, independent-review, and zero-thread gates.

- id: non-core-graph-products
Expand Down
4 changes: 2 additions & 2 deletions src/adapters/mcp/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const MCP_TOOLS: readonly McpToolDefinition[] = Object.freeze([
Object.freeze({
name: 'retrieve',
description:
'Return an authenticated answer dossier or exact gaps.',
'Return an authenticated answer dossier or exact gaps. Call once per repository question. If state is ready, answer only from the dossier; do not use repository tools or read source files. If state is non-ready, report its exact condition and verify only the named gaps.',
inputSchema: Object.freeze({
type: 'object',
additionalProperties: false,
Expand Down Expand Up @@ -135,7 +135,7 @@ export async function handleMcpProtocolRequest(
version: context.version,
},
instructions:
'Call once. Ready is complete; otherwise report its exact condition.',
'Call retrieve once per repository question. If state is ready, answer only from the dossier; do not use repository tools or read source files. If state is non-ready, report its exact condition and verify only the named gaps.',
})
case 'ping':
return success(id, {})
Expand Down
12 changes: 6 additions & 6 deletions src/domain/query/plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@ function flowSubject(text: string): SubjectMatch {
RegExp(`\\bhow (?:does|do|did) (.+?) get (?:${FW})\\b`),
])
if (direct) return [direct, []]
const active = RegExp(
`\\bhow (?:(?:${AUX}) )?(.+?) (${FW}) (.+?)(?= (?:${CLAUSE})\\b| end to end\\b|$)`,
const match = RegExp(
`\\bhow (?:(?:${AUX}) )?(.+?) (${FW}) (.*?)(?=(?:${CLAUSE})\\b|end to end\\b|$)`,
).exec(text)
if (active) {
const object = content(active[3]!, 'workflow').join(' ')
if (object) return [object, content(active[1]!, 'workflow', true)]
if (match) {
const object = content((match[3] || match[1])!, 'workflow').join(' ')
if (object) return [object, content(match[1]!, 'workflow', true)]
}
const topic = pick(text, 'workflow', [
/^follow (?:\S+ )*?(\S+) from .+ until (?:\S+ )*?(\S+) is/,
Expand Down Expand Up @@ -160,7 +160,7 @@ function flowBounds(text: string): FlowBounds {
?? read(/\bfrom .+?\bthrough (?!to\b)(.+?)(?= to\b| how\b|$)/u)
?? (walked ? undefined
: read(/\bthrough (?!to\b)(.+?)(?= to\b| how\b|$)/u)),
terminal: read(/\b(?:through to|to) (.+?)(?= how\b|$)/u),
terminal: read(/(?<!end )\b(?:through )?to (.+?)(?= how\b|$)/u)?.replace(/^save (?=report$)/u, ''),
}
}

Expand Down
37 changes: 37 additions & 0 deletions tests/unit/compare.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,21 @@ describe('compare command contract', () => {
)
})

it('allows neutral tool discovery before the single retrieve', async () => {
const { graphPath } = fixture()
const result = await executeNativeAgentCompare(
{
graphPath,
question: 'Trace login',
outputDir: 'out/compare',
execTemplate: 'runner {prompt_file}',
},
{ runner: runnerFor({ madarTools: ['ToolSearch', 'mcp__madar__retrieve'] }) },
)

expect(result.report.attribution_status).toBe('verified')
})

it('fails attribution when repository exploration precedes retrieve', async () => {
const { graphPath } = fixture()
const result = await executeNativeAgentCompare(
Expand All @@ -175,6 +190,28 @@ describe('compare command contract', () => {
})
})

it.each([
'Read',
'read',
'search',
'list',
'shell-read-only',
'mcp__filesystem__read_file',
])('fails attribution when %s follows retrieve', async (tool) => {
const { graphPath } = fixture()
const result = await executeNativeAgentCompare(
{
graphPath,
question: 'Trace login',
outputDir: 'out/compare',
execTemplate: 'runner {prompt_file}',
},
{ runner: runnerFor({ madarTools: ['mcp__madar__retrieve', tool] }) },
)

expect(result.report.attribution_status).toBe('violated')
})

it.each([
{
label: 'baseline invokes Madar',
Expand Down
125 changes: 120 additions & 5 deletions tests/unit/core-reset-governance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,29 @@ const BETA_5_AUTHORIZATION =
'https://github.com/mohanagy/madar/issues/631#issuecomment-5155128419'
const BETA_5_PARENT_AUTHORIZATION =
'https://github.com/mohanagy/madar/issues/629#issuecomment-5155128626'
const BETA_5_RELEASE_MERGE = '81045cc08f1df797ecb86748c9bce09db62aeebd'
const BETA_5_RELEASE_TREE = '9d3d90fe7feb3e55042c4f38ac8925abca6e83d1'
const BETA_5_PUBLICATION =
'https://github.com/mohanagy/madar/issues/631#issuecomment-5155719419'
const NO_FALLBACK_CORRECTIVE_AUTHORIZATION =
'https://github.com/mohanagy/madar/issues/631#issuecomment-5157008370'
const NO_FALLBACK_CORRECTIVE_PARENT =
'https://github.com/mohanagy/madar/issues/629#issuecomment-5157009594'
const NO_FALLBACK_CORRECTIVE_SOURCES = [
'src/adapters/mcp/protocol.ts',
'src/domain/query/plan.ts',
] as const
const NO_FALLBACK_CORRECTIVE_DIFF_SHA256 =
'51a23988d596afd5d060d603ad98f83903ed06c8bf6cf6bcba0bac66a59e12fe'
const NO_FALLBACK_CORRECTIVE_PACKAGE = {
npm_files: 102,
npm_packed_bytes: 155_253,
npm_unpacked_bytes: 653_988,
npm_shasum: 'fe8d482e4bbca13df65a4eb4efd45fde1c35f4a4',
npm_integrity:
'sha512-8vuEuekerfMzLeIky14BCZa0CUBT34vL8eL1D/ees90u04TGnPdHra1dAsV47AnsiEp3UAPiAsnLKUVpEc1FEg==',
npm_artifact_sha256: 'f63056b7bce91beb59dcdbb341092100500234ff859caac6199c1e84706f0b8e',
} as const
const CAPABILITY_VALIDATION_V2_PROPOSAL_SHA256 =
'4906405cbb806c850c0612305ef460e023e2060b5338734ae0af12303901cbd0'
const CAPABILITY_VALIDATION_V2_ISSUE = 'https://github.com/mohanagy/madar/issues/612'
Expand Down Expand Up @@ -1286,6 +1309,11 @@ describe('core reset governance', () => {
target_branch: string
npm_dist_tag: string
publication_state: string
publication_receipt: string
release_merge: string
release_tree: string
trusted_publishing_run: string
published_at: string
qualification_state: string
package_candidate: {
npm_files: number
Expand Down Expand Up @@ -1480,8 +1508,13 @@ describe('core reset governance', () => {
parent_authorization_receipt: BETA_5_PARENT_AUTHORIZATION,
target_branch: 'next',
npm_dist_tag: 'next',
publication_state: 'authorized_pending_protected_next_release_merge',
qualification_state: 'pending_manual_test_and_formal_631_gate',
publication_state: 'published_from_protected_next',
publication_receipt: BETA_5_PUBLICATION,
release_merge: BETA_5_RELEASE_MERGE,
release_tree: BETA_5_RELEASE_TREE,
trusted_publishing_run: 'https://github.com/mohanagy/madar/actions/runs/30734176943',
published_at: '2026-08-02T05:42:52Z',
qualification_state: 'owner_manual_test_found_corrective_defects_formal_631_gate_pending',
package_candidate: BETA_5_PACKAGE,
stable_or_latest: 'forbidden',
github_release: 'forbidden',
Expand Down Expand Up @@ -2394,12 +2427,48 @@ describe('core reset governance', () => {
tag: 'forbidden',
main_target: 'forbidden',
},
corrective: {
authorization_receipt: NO_FALLBACK_CORRECTIVE_AUTHORIZATION,
parent_receipt: NO_FALLBACK_CORRECTIVE_PARENT,
protected_base: BETA_5_RELEASE_MERGE,
protected_base_tree: BETA_5_RELEASE_TREE,
target_branch: 'next',
modified_sources: [...NO_FALLBACK_CORRECTIVE_SOURCES],
evaluation_sources: ['tools/eval/lib/infrastructure/compare.ts'],
production_loc_budget: { added_max: 8, removed_min: 8, net_max: 0 },
source_measurement: {
production_typescript_files: 44,
production_typescript_loc: 15_871,
added: 8,
removed: 8,
net: 0,
diff_sha256: NO_FALLBACK_CORRECTIVE_DIFF_SHA256,
},
replacement_measurement: { source_loc: 1_424, emitted_bytes: 60_983 },
package_candidate: NO_FALLBACK_CORRECTIVE_PACKAGE,
},
})
expect(execFileSync(
const correctiveSources = execFileSync(
git,
['diff', '--name-only', BETA_5_RELEASE_MERGE, '--', 'src'],
{ encoding: 'utf8' },
).trim().split('\n').filter(Boolean).sort()
expect(correctiveSources).toEqual([...NO_FALLBACK_CORRECTIVE_SOURCES].sort())
const correctiveEvaluatorSources = execFileSync(
git,
['diff', '--name-only', OBLIGATION_RETRIEVAL_MERGE, '--', 'src'],
['diff', '--name-only', BETA_5_RELEASE_MERGE, '--', 'tools/eval/lib'],
{ encoding: 'utf8' },
).trim()).toBe('')
).trim().split('\n').filter(Boolean).sort()
expect(correctiveEvaluatorSources).toEqual(['tools/eval/lib/infrastructure/compare.ts'])
expect(() => execFileSync(
git,
['diff', '--exit-code', BETA_5_RELEASE_MERGE, '--', 'package.json', 'package-lock.json'],
)).not.toThrow()
expect(createHash('sha256').update(execFileSync(
git,
['diff', '--binary', '--full-index', BETA_5_RELEASE_MERGE, '--',
...NO_FALLBACK_CORRECTIVE_SOURCES],
)).digest('hex')).toBe(NO_FALLBACK_CORRECTIVE_DIFF_SHA256)
const changedEvidenceSkeletonProduction = execFileSync(
git,
[
Expand Down Expand Up @@ -6241,6 +6310,19 @@ describe('core reset governance', () => {
diff_sha256: string
}
}
corrective?: {
protected_base: string
modified_sources: string[]
production_loc_budget: { added_max: number; removed_min: number; net_max: number }
source_measurement: {
production_typescript_files: number
production_typescript_loc: number
added: number
removed: number
net: number
diff_sha256: string
}
}
candidate_source?: {
production_typescript_files: number
production_typescript_loc: number
Expand All @@ -6253,6 +6335,39 @@ describe('core reset governance', () => {
const { current } = manifest
const activePhase = manifest.items.find((item) => item.id === current.active_phase)
const completedPhase = manifest.items.find((item) => item.id === current.completed_phase)
const corrective = activePhase?.corrective
if (corrective) {
const baseline = corrective.protected_base
expect(execFileSync(git, ['cat-file', '-t', `${baseline}^{commit}`], {
encoding: 'utf8',
}).trim()).toBe('commit')
expect(() => execFileSync(
git, ['merge-base', '--is-ancestor', baseline, 'HEAD'],
)).not.toThrow()
const inventory = sourceInventory()
const delta = productionSourceDelta(baseline)
expect(inventory.filesystemViolations).toEqual([])
expect(delta.added).toBeLessThanOrEqual(corrective.production_loc_budget.added_max)
expect(delta.removed).toBeGreaterThanOrEqual(corrective.production_loc_budget.removed_min)
expect(delta.net).toBeLessThanOrEqual(corrective.production_loc_budget.net_max)
const { diff_sha256: expectedDiffSha256, ...sourceMeasurement } =
corrective.source_measurement
expect({
production_typescript_files: inventory.files,
production_typescript_loc: inventory.loc,
...delta,
}).toEqual(sourceMeasurement)
const changedProduction = execFileSync(
git, ['diff', '--name-only', baseline, '--', 'src'], { encoding: 'utf8' },
).trim().split('\n').filter(Boolean).sort()
expect(changedProduction).toEqual([...corrective.modified_sources].sort())
const diffSha256 = createHash('sha256').update(execFileSync(
git,
['diff', '--binary', '--full-index', baseline, '--', ...corrective.modified_sources],
)).digest('hex')
expect(diffSha256).toBe(expectedDiffSha256)
return
}
const candidatePhase = activePhase?.candidate?.source_measurement
? activePhase
: completedPhase
Expand Down
9 changes: 9 additions & 0 deletions tests/unit/mcp-schema-budget.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ describe('MCP schema budget', () => {
.toEqual(['question', 'budget'])
})

it('makes ready terminal and scopes non-ready verification to named gaps', () => {
const description = MCP_TOOLS[0]?.description ?? ''

expect(description).toContain('state is ready')
expect(description).toContain('answer only from the dossier')
expect(description).toContain('do not use repository tools')
expect(description).toContain('named gaps')
})

it('seals the public schema against runtime mutation', () => {
expect(Object.isFrozen(MCP_TOOLS)).toBe(true)
expect(Object.isFrozen(MCP_TOOLS[0])).toBe(true)
Expand Down
Loading
Loading