fix(explore): shrink a later cluster into the remainder instead of dropping it (CG-36)
A file's ranked clusters were all-or-nothing past the first one: the top-ranked cluster was taken (shrunk to fit when it had to be) and every cluster below it was rendered whole, then either fit the remainder or was dropped entirely. On a file whose top-ranked cluster is TRIVIAL that discards the answer — django's `db/models/sql/query.py` kept a 22-line glue cluster and dropped the 624-line `Query` body, spending 1,923 of a 7,947 reservation; okhttp's `RealInterceptorChain.kt` did the same behind its import header. The response stayed full, which is why this was invisible: the unspent reservation carried forward exactly as designed and a file scoring a fifth as much took the bytes. Two sites, the same rule — hold the remainder while it is still worth a section (CG-26's between-FILES lesson, applied between CLUSTERS): - selection now shrinks a later cluster into what is left of the file's budget, by the same whole-member rule the first cluster already used; - the ceiling trim re-renders the weakest cluster into the room that remains before dropping it. On excalidraw's `typeChecks.ts` the section-cost estimate missed by 13 chars and a 1,512-char cluster — the file's highest-SCORING one — was thrown away to pay for it. Cluster RANKING is untouched: measured, both real cases lost on `maxImportance`, not on the density tiebreak the issue suspected, and density-first is what keeps Alamofire's `Session.swift` from burying its methods under the property list. Suite (6 repos, clean-rebuilt indexes): all 8 starvation flags cleared, +1,012 source chars net. django's `sql/query.py` 1,923 -> 10,082 of 7,947, okhttp's `RealInterceptorChain.kt` 1,474 -> 6,038 of 6,058, gin's `routergroup.go` 3,273 -> 5,632. okhttp trades its rank-6 file (score 21) for +7,196 chars in the two files that answer the question. Ships two fixtures pulling in opposite directions (`starved-cluster-ts` and `dense-header-ts`), a `spendShareAtLeast` gate in probe-allocation, and probe-file-spend.mjs — a standing per-file reservation-vs-delivered sweep.
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import { RequestChain, describeChain } from '../pipeline/chain';
|
||||
import type { PipelineRequest, PipelineResponse } from '../pipeline/types';
|
||||
import { openSocket } from '../transport/socket';
|
||||
|
||||
/**
|
||||
* The entry point a caller reaches for. Everything the chain does happens
|
||||
* underneath this call, which is why a flow question names it.
|
||||
*/
|
||||
export async function sendRequest(request: PipelineRequest): Promise<PipelineResponse> {
|
||||
const socket = openSocket(request.host, request.port);
|
||||
const chain = new RequestChain(request, socket);
|
||||
trace(describeChain(chain));
|
||||
return chain.proceed(request);
|
||||
}
|
||||
|
||||
export function trace(line: string): void {
|
||||
if (process.env.PIPELINE_TRACE) process.stderr.write(`${line}\n`);
|
||||
}
|
||||
|
||||
export async function sendAll(requests: PipelineRequest[]): Promise<PipelineResponse[]> {
|
||||
const out: PipelineResponse[] = [];
|
||||
for (const request of requests) out.push(await sendRequest(request));
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
export interface ClientConfig {
|
||||
host: string;
|
||||
port: number;
|
||||
retries: number;
|
||||
userAgent: string;
|
||||
}
|
||||
|
||||
export function defaultConfig(): ClientConfig {
|
||||
return { host: 'localhost', port: 8080, retries: 3, userAgent: 'pipeline/1.0' };
|
||||
}
|
||||
|
||||
export function withHost(config: ClientConfig, host: string): ClientConfig {
|
||||
return { ...config, host };
|
||||
}
|
||||
Reference in New Issue
Block a user