test(explore): #1500 regression fixtures for budget allocation (CG-6)
Two permanent fixtures pinning the failure mode from issue #1500 — explore spending its byte envelope on files that merely name-collide with the query. BOTH FAIL TODAY, by design: they document the bug and become the pass gate for CG-10 (scoring) + CG-12 (proportional allocation). __tests__/fixtures/payroll-go/ — a synthetic Go service mirroring the reporter's shape: generated FKIT CRUD beside a hand-written payroll use-case, entered from an HTTP route. Half the generated tree carries ORDINARY names detectable only by their `// Code generated ... DO NOT EDIT.` header (the #1500 case, and end-to-end cover for CG-5); `payrollpb/*.pb.go` covers the path-detectable channel. BuildPayslip, Upsert and Store each exist twice, generated and hand-written. cycle.go sits above the whole-file window so it clips; the generated files sit below it so they ship whole. Asking "how does payroll cycle create and calculate payslips?" — naming none of the answering symbols — the generated CRUD delivers 57.4% of the envelope against the hand-written layer's 25.6%, all of the latter domain types. cycle.go is allocated the single largest slice (30.6%) and delivers ZERO: the hard ceiling drops its whole section. runPayrollCycleAll, the hand-written BuildPayslip and the real Upsert never reach the agent. The second fixture is this repo, "how does explore allocate its output budget across files", where scripts/agent-eval/*.mjs take 71.8% against tools.ts's 18.5% despite scoring 4.6x lower. It reads the live index, so its assertions are relative rather than fixed percentages. - scripts/agent-eval/probe-allocation.mjs — per-file budget-share probe, driving the CG-4 diagnostic through a JSONL sidecar so it measures the shipping allocator. Fixture entries are hermetic (copy + re-index per run, verified byte-identical across runs); exits 1 while any assertion fails. - scripts/agent-eval/allocation-fixtures.json — both fixtures declared, with the 2026-08-03 baselines. - __tests__/explore-allocation-1500.test.ts — fixture-shape assertions green today; the allocation assertions held as `it.fails` so the suite stays green while the bug is open and goes RED the moment it is fixed. Also documented and deliberately left unfixed: runPayrollCycleAll's `s.store.Upsert` edge resolves to the GENERATED Store.Upsert, not the hand-written one — same-name method resolution across two packages picks the wrong receiver. It is upstream of the allocation bug, so it belongs with CG-10's scoring work. Refs #1500 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
16e17495f4
commit
bd86ad2061
@@ -0,0 +1,84 @@
|
||||
// Code generated by fkit v3.11.0. DO NOT EDIT.
|
||||
//
|
||||
// Source: schema/employee/contract.fkit
|
||||
// Regenerate with: go run ./tools/fkitgen ./schema/employee
|
||||
|
||||
package employee
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ContractRow is the generated row type for table contract.
|
||||
type ContractRow struct {
|
||||
ID string
|
||||
EmployeeID string
|
||||
Kind string
|
||||
Currency string
|
||||
RateCents int64
|
||||
PeriodRateCents int64
|
||||
StartsOn time.Time
|
||||
EndsOn time.Time
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// ContractCreateRequest is the generated create payload for table contract.
|
||||
type ContractCreateRequest struct {
|
||||
EmployeeID string `json:"employeeId"`
|
||||
Kind string `json:"kind"`
|
||||
Currency string `json:"currency"`
|
||||
RateCents int64 `json:"rateCents"`
|
||||
PeriodRateCents int64 `json:"periodRateCents"`
|
||||
StartsOn time.Time `json:"startsOn"`
|
||||
}
|
||||
|
||||
// CreateContract inserts one contract row.
|
||||
func CreateContract(ctx context.Context, db *sql.DB, req ContractCreateRequest) (ContractRow, error) {
|
||||
const q = `INSERT INTO contract (employee_id, kind, currency, rate_cents, period_rate_cents, starts_on)
|
||||
VALUES ($1, $2, $3, $4, $5, $6) RETURNING *`
|
||||
return scanContract(db.QueryRowContext(ctx, q, req.EmployeeID, req.Kind, req.Currency,
|
||||
req.RateCents, req.PeriodRateCents, req.StartsOn))
|
||||
}
|
||||
|
||||
// GetContract selects one contract row by primary key.
|
||||
func GetContract(ctx context.Context, db *sql.DB, id string) (ContractRow, error) {
|
||||
const q = `SELECT * FROM contract WHERE id = $1`
|
||||
return scanContract(db.QueryRowContext(ctx, q, id))
|
||||
}
|
||||
|
||||
// DeleteContract removes one contract row.
|
||||
func DeleteContract(ctx context.Context, db *sql.DB, id string) error {
|
||||
const q = `DELETE FROM contract WHERE id = $1`
|
||||
_, err := db.ExecContext(ctx, q, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// ListContractsForEmployee selects contract rows for one employee.
|
||||
func ListContractsForEmployee(ctx context.Context, db *sql.DB, employeeID string) ([]ContractRow, error) {
|
||||
const q = `SELECT * FROM contract WHERE employee_id = $1 ORDER BY starts_on DESC`
|
||||
rows, err := db.QueryContext(ctx, q, employeeID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []ContractRow
|
||||
for rows.Next() {
|
||||
var r ContractRow
|
||||
if err := rows.Scan(&r.ID, &r.EmployeeID, &r.Kind, &r.Currency, &r.RateCents,
|
||||
&r.PeriodRateCents, &r.StartsOn, &r.EndsOn, &r.CreatedAt, &r.UpdatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func scanContract(row *sql.Row) (ContractRow, error) {
|
||||
var r ContractRow
|
||||
err := row.Scan(&r.ID, &r.EmployeeID, &r.Kind, &r.Currency, &r.RateCents,
|
||||
&r.PeriodRateCents, &r.StartsOn, &r.EndsOn, &r.CreatedAt, &r.UpdatedAt)
|
||||
return r, err
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// Code generated by fkit v3.11.0. DO NOT EDIT.
|
||||
//
|
||||
// Source: schema/employee/employee.fkit
|
||||
// Regenerate with: go run ./tools/fkitgen ./schema/employee
|
||||
|
||||
package employee
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
// EmployeeRow is the generated row type for table employee.
|
||||
type EmployeeRow struct {
|
||||
ID string
|
||||
Email string
|
||||
FullName string
|
||||
Status string
|
||||
HiredOn time.Time
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// EmployeeCreateRequest is the generated create payload for table employee.
|
||||
type EmployeeCreateRequest struct {
|
||||
Email string `json:"email"`
|
||||
FullName string `json:"fullName"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// EmployeeUpdateRequest is the generated update payload for table employee.
|
||||
type EmployeeUpdateRequest struct {
|
||||
FullName *string `json:"fullName,omitempty"`
|
||||
Status *string `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// CreateEmployee inserts one employee row.
|
||||
func CreateEmployee(ctx context.Context, db *sql.DB, req EmployeeCreateRequest) (EmployeeRow, error) {
|
||||
const q = `INSERT INTO employee (email, full_name, status) VALUES ($1, $2, $3) RETURNING *`
|
||||
return scanEmployee(db.QueryRowContext(ctx, q, req.Email, req.FullName, req.Status))
|
||||
}
|
||||
|
||||
// GetEmployee selects one employee row by primary key.
|
||||
func GetEmployee(ctx context.Context, db *sql.DB, id string) (EmployeeRow, error) {
|
||||
const q = `SELECT * FROM employee WHERE id = $1`
|
||||
return scanEmployee(db.QueryRowContext(ctx, q, id))
|
||||
}
|
||||
|
||||
// UpdateEmployee patches one employee row.
|
||||
func UpdateEmployee(ctx context.Context, db *sql.DB, id string, req EmployeeUpdateRequest) (EmployeeRow, error) {
|
||||
const q = `UPDATE employee SET full_name = COALESCE($2, full_name), status = COALESCE($3, status),
|
||||
updated_at = now() WHERE id = $1 RETURNING *`
|
||||
return scanEmployee(db.QueryRowContext(ctx, q, id, req.FullName, req.Status))
|
||||
}
|
||||
|
||||
// DeleteEmployee removes one employee row.
|
||||
func DeleteEmployee(ctx context.Context, db *sql.DB, id string) error {
|
||||
const q = `DELETE FROM employee WHERE id = $1`
|
||||
_, err := db.ExecContext(ctx, q, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// ListEmployeesByStatus selects employee rows in one status.
|
||||
func ListEmployeesByStatus(ctx context.Context, db *sql.DB, status string) ([]EmployeeRow, error) {
|
||||
const q = `SELECT * FROM employee WHERE status = $1 ORDER BY full_name`
|
||||
rows, err := db.QueryContext(ctx, q, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []EmployeeRow
|
||||
for rows.Next() {
|
||||
var r EmployeeRow
|
||||
if err := rows.Scan(&r.ID, &r.Email, &r.FullName, &r.Status, &r.HiredOn,
|
||||
&r.CreatedAt, &r.UpdatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func scanEmployee(row *sql.Row) (EmployeeRow, error) {
|
||||
var r EmployeeRow
|
||||
err := row.Scan(&r.ID, &r.Email, &r.FullName, &r.Status, &r.HiredOn, &r.CreatedAt, &r.UpdatedAt)
|
||||
return r, err
|
||||
}
|
||||
Reference in New Issue
Block a user