igce-builder-cr
Trigger for: cost-reimbursement IGCE, CR cost estimate, CPFF, CPAF, CPIF, cost-plus estimate, BAA estimate, fixed-fee analysis, award-fee analysis, incentive-fee analysis, proposed CR rate validation, cost-pool buildup, share-ratio scenario, price-reasonableness memo, or fair-and
Install
npx skills add https://github.com/1102tools-dev/federal-contracting-skills/tree/main/skills/igce-builder-cr
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install 1102tools-dev-federal-contracting-skills@llmmart
git clone https://github.com/1102tools-dev/federal-contracting-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole 1102tools-dev/federal-contracting-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
IGCE Builder: Cost-Reimbursement
Overview
Build an auditable CPFF, CPAF, or CPIF Independent Government Cost Estimate. Estimate allowable-cost layers and fee separately. Preserve the distinction between fee-bearing and non-fee-bearing cost, and never substitute CALC+ ceiling-rate comparisons for cost analysis.
Regulatory anchors: FAR 15.404-1, FAR 15.404-4, FAR 16.301 through 16.307, 10 U.S.C. 3322, and 41 U.S.C. 3905. Apply the current regulation, solicitation, and agency supplement. This skill does not make legal determinations.
Load supporting files only when needed:
- wrap-rate-presets.md for indirect-cost and fee structures.
- data-source-operations.md before mapping labor or calling BLS, CALC+, or Per Diem.
- workbook-specification.md before creating the workbook.
- professional-product-standard.md before creating the workbook.
- validation-gates.md before and after workbook generation.
- runtime-adaptation.md for questions, tools, formula engines, and delivery.
Operating principle
Product quality default
Build a cost-and-fee model that lets the acquisition team see what changes the estimate. The summary begins with the requirement, CR subtype and form when confirmed, decision supported, estimated cost, fee treatment, material assumptions, scenario range, limitations, and next human action. Use a specific title such as CPFF Independent Government Cost Estimate — [Requirement]. Keep rate evidence and source inputs in dedicated sheets, retain a clear fee-bearing versus pass-through distinction, and never use the workbook to originate a fee objective or a fair-and-reasonable conclusion.
This skill assembles data and formats analysis. The Contracting Officer owns cost-realism judgments, fair-and-reasonable determinations, fee objectives, negotiation positions, and approval documents.
- Use neutral positional language such as
at CALC+ P77 (n=42)orabove CALC+ P50 by 18%. - Never originate a determination, negotiation target, evaluation notice, or contractor-responsibility conclusion.
- Never invent a clearance, SCIF, OCONUS, specialty-labor, cost-risk, or performance premium.
- When the user supplies rationale or a determination, preserve it verbatim and label the resulting document
DRAFT.
Permanent correctness gates
These gates prevent documented silent wrong answers. Keep them in the front-loaded core.
- Workflow B boundary: On every Workflow B entry, emit the Option A/Option B boundary below before analysis or tool use, then wait.
- CALC+ query signature: Use
/v3/api/ceilingrates/withkeyword=. Never useq=; it silently returns the full corpus. - Fee basis: Fee applies only to the user-confirmed fee-bearing cost base. Never apply fee automatically to pass-through ODCs or travel.
- CPFF caps: Under FAR 15.404-4(c)(4)(i), cap CPFF at 15% for experimental, developmental, or research work, 10% for other CPFF work, and apply the separate 6% architect-engineer limitation when relevant. Treat caps as ceilings, not defaults.
- CPFF form: Declare Completion or Term under FAR 16.306(d). Prefer Completion when a definite goal or end product can be estimated; use Term only with a specified level of effort and definite time period.
- CPIF shares: Keep contractor overrun and underrun shares as separate assumptions. Apply min and max fee bounds, and show where a bound stops the share formula.
- CPAF range: Show base-only, assumed-earned, and full-pool fee outcomes. Never hide the award-fee range behind one 85%-earned point.
- Aging formula: Store BLS vintage and contract start as assumptions. Calculate month gap with
VALUE(LEFT(...))andVALUE(MID(...))when dates are stored asYYYY-MMtext. Do not useYEARon text or rely onDATEDIFportability. - Shift coverage: Derive coverage FTE from required coverage hours and productive hours. At 1,880 hours, one 24x7x365 seat is 4.6596 FTE. Do not multiply 4.2 by 1,880.
- Staged questions: Stage A is decomposition confirmation only. Its response must end immediately after that question, with no Stage B preview. Ask Stage B only after Stage A approval.
- Step 8.5: Run formula-structure audit and independent recomputation. Use a real spreadsheet engine when available; disclose exactly when formula execution was not independently verified.
- Credentialed API pacing: Serialize credentialed federal API calls and leave at least three seconds after one completes before starting the next. Never parallelize keyed calls. Honor longer retry intervals and stop instead of rapid retrying.
Workflow selection
Select the workflow before capability tests.
Workflow A: structured CR build
Use when the user supplies labor, location, staffing, period, and fee type. Execute Steps 1 through 9.
Workflow A+: SOW/PWS or BAA build
Use when the user supplies an unstructured requirement or an approved staffing handoff. For raw requirements, run Step 0 and both staged confirmations. For an approved handoff, consume it without repeating decomposition or Stage A.
If a BAA does not declare contract type, explain that CR may fit uncertain research but require the user to select the contract type. Do not self-select CPFF.
Workflow B: CR rate positioning or memo request
Use when the user asks to validate proposed rates, judge cost pools, draft a price-reasonableness memo, or decide whether rates are fair and reasonable.
The entire first response must be exactly the boundary block below. Begin with I can provide and add no heading, workflow label, preamble, capability note, analysis, or tool call before it. End at Which option do you choose? and add nothing after that question.
I can provide positioning data showing where proposed rates sit against CALC+ ceiling rates and BLS market wages. I cannot originate a price-reasonableness memo, fair-and-reasonable determination, cost-realism judgment, or negotiation position. Those are Contracting Officer decisions.
Option A: Positioning data only. I provide per-category CALC+ percentiles and sample size, BLS metro cost buildup, and neutral arithmetic. No verdict or recommendation.
Option B: Draft template using your conclusion. You provide your rationale and determination. I place that text verbatim into a DRAFT template and add benchmark tables. I do not add conclusions or negotiation advice.
Which option do you choose?
After Option A, run the applicable BLS and CALC+ steps and stop at neutral positioning. After Option B, require both rationale and determination before building the draft. Never paraphrase the user's conclusion.
Pre-flight capabilities
When this skill is entered immediately after a numbered Pre-Award Agent pricing selection and the current assistant response has not already shown the orchestrator's outcome preview, emit these exact four lines before intake or a capability check:
Begin line 1 with Recommended outcome:. Do not precede the block with a heading, acknowledgement, selection recap, routing narration, or code fence.
Recommended outcome: Routed IGCE `.xlsx`, separated by confirmed pricing method or hybrid CLIN
Includes: auditable labor, indirect, escalation, travel and other-cost build-up, benchmarks, assumptions, formulas, and validation
Boundary/default: no contract type is inferred; the user or Contracting Officer must confirm FFP, LH, T&M, a CR subtype, or hybrid routing
Next: collect the approved handoff or requirements and the confirmed pricing method
This is a routing fallback, not a second preview. Do not repeat it when the orchestrator already rendered the four lines in the current assistant response. If a CR subtype has not been supplied or confirmed, stop after the bounded pricing-method question and return routing control to the orchestrator; the presence of this component skill never selects a CR subtype for the user.
Begin useful intake after workflow selection; do not make workbook authoring or provider availability the first response. A read-only or artifact-limited session may still reuse supplied facts, identify missing inputs, and review an approved handoff. Run only the relevant portions of this pre-flight immediately before the first dependent MCP call or before promising or beginning workbook generation. For Workflow B, run it only after the user chooses an option.
- Call
bls-oews.get_access_statusbefore any BLS data call. Forlimited_fallback, tell the userBLS_API_KEYis not configured and v1 is limited to 25 requests per day and 10 years per query; continue only when the workload fits. A missing status operation means an outdated or incomplete MCP or shared host profile. - When travel is in scope, call
gsa-perdiem.get_access_statusbefore Per Diem data. Forlimited_fallback, tell the userPERDIEM_API_KEYis not configured andDEMO_KEYis limited to approximately 10 requests per hour. A missing status operation means an outdated or incomplete MCP or host profile. - Treat
configured_unverifiedas presence only. Classify a later 401/403 as rejected credentials and 429 as rate limiting, not an outage. Never retry automatically or ask for a key in chat. Direct setup tohttps://1102tools.com/setup#credentialsand require a restart. - Inspect the operations actually available in the session. Match by server and operation schema, not host-generated namespace.
- Workflows A and A+ require
bls-oewswage, vintage, SOC, and metro operations plusgsa-calcsuggestion and benchmark operations. Addgsa-perdiemonly when travel is in scope. - Workflow B requires only the benchmark operations needed for the chosen analysis. Option B also requires a document-authoring capability if the user requests a file.
- Before workbook creation, require
.xlsxauthoring, Python 3.10+, openpyxl, and the bundled validators. A real spreadsheet engine is preferred but optional when its absence is disclosed. - Test only capabilities the active workflow will use. For a build, confirm the BLS vintage at runtime. Test Per Diem only when travel is in scope. Apply the pacing gate to every keyed call.
- If a capability is missing, look for an equivalent operation from the declared server. Do not bypass the MCP with a hand-built public API call.
- If still missing, stop at that dependent-work boundary and report whether it appears uninstalled, unauthenticated, unavailable, or outdated/incomplete in the host. Preserve completed intake so it is not requested again after the capability is restored.
Information to collect
Required for a build:
- Labor category or task discipline, SOC when known, seniority, FTE or coverage basis, and productive hours.
- Performance location and any staffing split by location.
- Base and option periods, contract start month, and any partial-year duration.
- CR type: CPFF, CPAF, or CPIF. For CPFF, Completion or Term form.
- Indirect-rate basis: disclosed estimate or CO-supplied FPRA/FPRR/DCAA-audited rates with date and authority.
- Fee structure and fee-bearing classification for labor, travel, subcontracts, and every ODC.
Optional with disclosed defaults:
- Productive hours 1,880; escalation 2.5%; fringe 32%; overhead 80%; G&A 12%; FCCM 0%.
- CPFF fee 8%; CPAF base 3%, pool 7%, assumed earned 85%; CPIF target 8%, contractor overrun and underrun shares 20%, min 3%, max 12%.
- No travel or ODCs. Treat missing travel as zero and record that travel was considered.
Do not override CO-supplied audited rates with generic defaults. Use audited rates as point estimates, record their effective date and authority, and do not manufacture low/high offsets around them.
Approved SOW/PWS handoff
Treat a user-reviewed table labeled STAFFING HANDOFF TABLE as approved input regardless of heading punctuation.
- Confirm that the declared contract type is CR. For a hybrid, consume only CR CLINs.
- Preserve approved labor category, SOC, FTE, phase, hours, notes, derivation, and overrides.
- Use the CLIN handoff for period and deliverable mapping when present.
- Present contradictions among handoff, requirement, and current instruction in a short table and wait for the user to choose the controlling value.
- Ask all missing Stage B inputs in one response. Do not rerun decomposition or Stage A unless the user asks to revise staffing.
Orchestration
Step 0: decompose raw requirements
Run only when no approved handoff is present.
- Check labor disciplines, staffing basis, location, period, deliverables, and travel. Performance location is a hard stop before data calls. If three or more elements are missing from a short requirement, ask whether to continue with labeled assumptions or obtain clarification.
- Separate the requirement into task areas with discipline, complexity, cadence, deliverable, and staffing basis.
- Perform agency and technical-domain triage before SOC mapping.
- Map each task to candidate labor categories and SOCs using data-source-operations.md. Use multiple candidates when mapping is ambiguous.
- Estimate FTE ranges only when the scope supplies a defensible basis. Otherwise list the missing sizing facts.
- Stage A: Present the decomposition, then ask only whether the user confirms or amends the task areas, labor categories, and SOC mappings. This must be the response's only question. Do not ask whether to proceed on assumptions, select a contract or fee type, provide a location, or supply any other Stage B input, even when those items are hard stops. Do not preview Stage B. The final sentence must be the decomposition-confirmation question. Stop immediately after its question mark.
- Stage B: After approval, batch fee type, CPFF form if applicable, indirect-rate basis, performance metro, start, period, NAICS/PSC, coverage, travel, ODCs, and fee-bearing classifications. End at the question and wait.
Skip both stages only when the user supplied the full structured build input.
Step 0.5: convert coverage to staffing
annual coverage hours = covered seats * hours per day * coverage days per year
coverage FTE = annual coverage hours / productive hours per FTE
At 1,880 productive hours, one 24x7x365 seat is 8,760 / 1,880 = 4.6596 FTE; two seats are 9.3191. One 8x5x52 seat is 1.1064. Keep four decimals in calculations and disclose rounding. Add overlap, leave-backfill, training, or turnover reserves only with a separate user-approved basis.
Step 1: map labor categories to SOCs
Use the mapping and fallbacks in data-source-operations.md. Map program managers by domain. Use BLS P25/P50/P75 for junior/mid/senior. Preserve user-approved mappings and label fallbacks.
Step 2: pull and age BLS wages
- Call
detect_latest_yearand record the returned vintage. - Resolve the current metro code before wage queries. Query metro, then state, then national only when the more specific level is unavailable.
- Pull the full wage distribution. Flag cap proximity and flat P75/P90 tails.
- Calculate aging from the returned vintage to contract start, store every assumption in the workbook, and avoid double-counting option-year escalation.
Step 3: build cost pools and fee
For each scenario and labor line:
aged annual wage = BLS wage * aging factor
direct hourly = aged annual wage / 2,080
fringe = direct hourly * fringe rate
labor plus fringe = direct hourly + fringe
overhead = labor plus fringe * overhead rate
subtotal = labor plus fringe + overhead
G&A = subtotal * G&A rate
FCCM = (subtotal + G&A) * FCCM rate
estimated cost rate = subtotal + G&A + FCCM
Classify each non-labor item before fee:
total estimated cost = fee-bearing cost + non-fee-bearing cost
fee = fee formula applied only to fee-bearing cost
total estimated price = total estimated cost + fee
Use wrap-rate-presets.md for CPFF, CPAF, and CPIF formulas and scenario rules. Do not convert CPFF fixed fee into a cost-reimbursement percentage that changes with actual cost; workbook scenarios are estimating outcomes, not contract payment mechanics.
Step 4: position rates against CALC+
Use igce_benchmark for statistics-only queries. Use keyword_search only when category buckets are needed. For thin or ambiguous pools, use title-match and experience-match pools and report each sample size. Compare CR estimated-cost-plus-fee separately from the underlying cost rate. Use neutral arithmetic only.
Step 5: calculate travel
Use data-source-operations.md for locality, fiscal-year, and first/last-day rules. A zero-night trip uses one already-discounted first/last-day M&IE amount. Confirm whether travel is fee-bearing; default pass-through travel to non-fee-bearing when the user does not direct otherwise, and disclose that assumption.
Step 6: handle multiple locations
- Use separate rows when headcount by location is known.
- Use a weighted wage when percentages are supplied.
- Use the highest applicable median only as a conservative disclosed fallback when no allocation exists.
Step 7: calculate periods and scenarios
Prorate partial periods by months. Escalate labor and travel from the aged base-year amount. Show low, mid, and high cost-pool cases. For CPAF, show three earned-fee outcomes. For CPIF, show the cost-scenario by fee-outcome matrix and bound crossings. Never classify pass-through cost differently across scenarios.
Step 8: build the workbook
Follow professional-product-standard.md and workbook-specification.md. Use formulas for calculated values, numeric zero for placeholders, and explicit source and assumption cells. Keep editable assumptions visually distinct. Keep formal controls intact while making the default summary and print experience concise and decision-centered.
Step 8.5: validate
Follow validation-gates.md.
- Save a raw-input JSON sidecar.
- Run
scripts/validate_workbook.py <workbook> --expected <sidecar> --engine auto. - Fix every formula-structure or recomputation failure and rerun.
- If LibreOffice or another real engine is available, execute formulas and compare cached values with the independent Python result.
- If no engine is available, say:
Formula structure and independent calculations passed. Formula execution was not independently verified in Excel or LibreOffice. - Visually inspect all sheets for clipping, broken formats, unreadable notes, and empty or misleading tables.
Never call openpyxl-only inspection recalculation or proof of formula execution.
Step 9: deliver
Use the host's artifact-delivery capability when available. Otherwise save to the requested or current working directory and report the absolute path. Do not invent host-specific paths or commands. See runtime-adaptation.md.
Out of scope
- DCAA proposal audits, incurred-cost audits, or validation of contractor accounting systems.
- Contractor responsibility, source selection, negotiation objectives, or cost-realism determinations.
- OCONUS per diem without the appropriate Department of State or DoD source.
- FFP, LH/T&M, grants, and cooperative agreements.
MIT © James Jenrette / 1102tools. Source: github.com/1102tools-dev/federal-contracting-skills
Files (federal-contracting-skills)
-
agents
-
openai.yaml 285 B
interface: display_name: "IGCE Builder: CR" short_description: "Build auditable cost-reimbursement estimates" default_prompt: "Use $igce-builder-cr to build an auditable CPFF, CPAF, or CPIF IGCE from my staffing inputs or requirement." policy: allow_implicit_invocation: true
-
-
references
-
data-source-operations.md 13.4 KB
# CR Data Source Operations and Mapping Reference Use this reference for SOC selection, BLS wage retrieval, CALC+ positioning, and GSA Per Diem. Keep operation names stable and let the host supply any runtime namespace. ## Contents 1. Constants and runtime checks 2. SOC mapping 3. BLS OEWS operations 4. CALC+ operations 5. GSA Per Diem operations 6. Raw-data recording ## 1. Constants and runtime checks | Item | Current baseline | Required handling | |---|---:|---| | Standard work year | 2,080 hours | Convert annual wage to hourly direct labor | | Default productive hours | 1,880 hours | Editable workbook assumption; derive shift-coverage FTE from this value | | BLS wage cap | $239,200 annual or $115 hourly | Reconfirm each release and treat capped values as lower bounds | | BLS vintage | May 2025 | Call `detect_latest_year` before every estimate | | First and last day M&IE | 75% | Use the MCP's discounted result once | | City Pair fare | YCA when available | Use only when origin and destination are known | Treat published constants as baselines. Runtime data controls the estimate. ### Request pacing Serialize credentialed federal API calls and leave at least three seconds between them, including capability checks. Do not parallelize keyed BLS or Per Diem calls. Honor any longer server-provided retry interval. If a service reports a rate limit, stop and report it instead of issuing rapid retries. Unkeyed services must still follow their advertised limits and must not be queried in uncontrolled loops. ## 2. SOC mapping Classify the requirement domain before mapping job titles. ### IT and software | Common title | SOC | BLS title | |---|---|---| | IT Program Manager | 11-3021 | Computer and Information Systems Managers | | Management Analyst | 13-1111 | Management Analysts | | Project Manager | 13-1082 | Project Management Specialists | | Systems Engineer or Analyst, IT | 15-1211 | Computer Systems Analysts | | Cybersecurity or InfoSec Analyst | 15-1212 | Information Security Analysts | | Network Architect | 15-1241 | Computer Network Architects | | Database Administrator | 15-1242 | Database Administrators | | Systems Administrator | 15-1244 | Network and Computer Systems Administrators | | Software Developer | 15-1252 | Software Developers | | QA Tester | 15-1253 | Software QA Analysts and Testers | | Help Desk or User Support | 15-1232 | Computer User Support Specialists | | Data Scientist | 15-2051 | Data Scientists | ### Physical and non-IT engineering Use these codes for physical systems, reactors, aerospace, infrastructure, chemical, mechanical, and hardware integration. | Common title | SOC | BLS title | |---|---|---| | Aerospace Engineer | 17-2011 | Aerospace Engineers | | Biomedical Engineer | 17-2031 | Bioengineers and Biomedical Engineers | | Chemical Engineer | 17-2041 | Chemical Engineers | | Civil Engineer | 17-2051 | Civil Engineers | | Electrical Engineer | 17-2071 | Electrical Engineers | | Electronics Engineer | 17-2072 | Electronics Engineers, Except Computer | | Environmental Engineer | 17-2081 | Environmental Engineers | | Industrial Engineer | 17-2112 | Industrial Engineers | | Mechanical Engineer | 17-2141 | Mechanical Engineers | | Nuclear Engineer | 17-2161 | Nuclear Engineers | | Petroleum Engineer | 17-2171 | Petroleum Engineers | | Systems Engineer, non-IT | 17-2199 | Engineers, All Other | Use 17-2199 when an integration role spans engineering disciplines. Query a specific engineering SOC beside it when useful. ### Science, research, medical, and support | Common title | SOC | BLS title | |---|---|---| | Physicist | 19-2012 | Physicists | | Chemist | 19-2031 | Chemists | | Medical Scientist | 19-1042 | Medical Scientists, Except Epidemiologists | | Registered Nurse | 29-1141 | Registered Nurses | | Physician Assistant | 29-1071 | Physician Assistants | | Technical Writer | 27-3042 | Technical Writers | | Contracting Specialist | 13-1020 | Buyers and Purchasing Agents | ### Program management context Use the contract domain to map Program Manager: - Operations or administration: 11-1021, General and Operations Managers - Physical engineering or R&D: 11-9041, Architectural and Engineering Managers - IT or software: 11-3021, Computer and Information Systems Managers Document the choice. Do not default every technical Program Manager to 11-3021. ## 3. BLS OEWS operations ### Runtime vintage Call `detect_latest_year` before wage retrieval. Record the returned year and use it in Raw Data, the Summary assumption block, and the aging calculation. If it differs from May 2025, use the runtime result. ### Wage retrieval Call: ```text get_wage_data( occ_code=<six-character SOC>, scope=<metro|state|national>, area_code=<five-digit MSA or two-digit state FIPS>, datatypes=["04", "11", "12", "13", "14", "15"] ) ``` The requested datatypes provide mean plus P10, P25, P50, P75, and P90. Valid operation datatypes include `01`, `03`, `04`, `08`, `11`, `12`, `13`, `14`, and `15`. Do not send `02` or `05`. Use `list_common_metros` to resolve common MSAs and renumbering notes. If a metro is absent, resolve its current code from BLS before falling back. Fallback ladder: 1. Metro 2. State, only after the metro series and current MSA code are checked 3. National Record each fallback and its reason. Do not treat suppressed or unavailable metro data as evidence about market quality. For a single-category sanity check, `igce_wage_benchmark` may return compact wage and burden information. Use `get_wage_data` for the full workbook so the percentile basis remains visible. ### Seniority convention When BLS does not distinguish job levels: - Junior or entry: P25 - Mid or journeyman: P50 - Senior: P50 to P75 based on scope - Principal, director, or SME: P75 to P90 If no levels are supplied, price all members at P50 and disclose that convention. Do not invent a junior/mid/senior staffing mix. ### Capped and compressed distributions If a selected percentile hits the BLS cap, treat it as a lower bound. If a selected value is within 10% of the current cap, note that the local market may exceed the reported value and flag the proximity for Contracting Officer review. If P75 is capped: 1. Use the uncapped mean as a senior anchor when appropriate. 2. Cross-reference a separate commercial source if available. 3. Consider national P75 divided by national P50, applied to local P50, and label it as a derivation. 4. Never present the cap as an exact point estimate. If P75 equals P90 below the cap, disclose a flat upper tail. If P25 equals P10, do not use P25 for a junior anchor without review. A possible derived junior value is national P25 multiplied by local P50 divided by national P50. Label every derived value. ## 4. CALC+ operations ### Silent-wrong-answer signature The CALC+ keyword route is: ```text /v3/api/ceilingrates/?keyword=<term> ``` The parameter is `keyword=`. Never use `q=`. The wrong parameter can be accepted while returning the unfiltered corpus. The labor-category discovery response path is: ```text aggregations.labor_category.buckets[*].key aggregations.labor_category.buckets[*].doc_count ``` Record enough of the selected buckets and counts to reproduce the pool. ### Discovery-first flow 1. Call `suggest_contains(field="labor_category", term=<LCAT term>)`. 2. If the top exact buckets form an adequate pool, call `exact_search(field="labor_category", value=<bucket>)` for each selected bucket. 3. If buckets are fragmented, call `keyword_search(keyword=<term>)` and document that keyword matching can include other fields. 4. Use `igce_benchmark(labor_category=<title>, experience_min=<years>, education_level=<level>)` for compact percentile statistics. 5. Do not send `page_size=0`. Use at least 1 when an operation requires the parameter. Expected benchmark fields include count, minimum, maximum, mean, standard deviation, P10, P25, P50, P75, and P90. Use the returned canonical fields instead of probing large raw payloads. ### Tier matching and dual pools Match the actual level. For a mid-level developer, prefer `Software Developer II` over an all-level Software Developer pool. For senior categories, present both: - Title-match pool, discovered through `suggest_contains` and `exact_search` - Experience-match pool, returned by `igce_benchmark` with an appropriate minimum experience filter Report both sample sizes and medians. Do not merge them without disclosure. Useful fragmented-title alternatives: - SOC Analyst or Cyber Analyst: Information Security Analyst I, II, and III - Software Engineer: Software Developer I, II, and III - Data Engineer with a thin pool: Data Scientist with experience filter, clearly labeled as a proxy ### Workflow B shortcut Call: ```text price_reasonableness_check( labor_category=<title>, proposed_rate=<rate>, education_level=<level if known>, experience_min=<years if known> ) ``` Use the returned count, bounds, z-score, and percentile only as positioning data. Label a pool under about 25 records as directional. ### CR positioning bands - Within 10% of P50: expected comparison range - Between 10% and 25% from P50: identify cost-pool, fee, seniority, geography, and pool-composition arithmetic - More than 25% from P50: show the complete stacked-factor bridge and direct the result to Contracting Officer review - Below P25: report the position and ask the Contracting Officer to review the input or pool alignment CALC+ represents awarded MAS ceiling rates with profit embedded. A CR comparison must show both estimated cost and cost plus fee, and must label the structural difference. Do not force a CR rate into an FFP premium band. Do not translate a band into a fair-and-reasonable conclusion. ## 5. GSA Per Diem operations ### Travel estimate For one or more nights, call: ```text estimate_travel_cost( city=<civilian locality>, state=<state>, num_nights=<integer>, travel_month=<optional month>, fiscal_year=<optional FY> ) ``` Expected fields include nightly lodging, lodging total, daily M&IE, first/last-day M&IE, M&IE total, grand total, and travel days. Calculate annual travel as: ```text grand total per trip * trips per year * travelers ``` Use the operation's first/last-day amount once. `get_mie_breakdown` already returns a 75% value. Do not multiply it by 0.75 again. `estimate_travel_cost` requires at least one night. For a 0-night day trip, do not pass zero to that operation. Call `lookup_city_perdiem` for the locality and fiscal year, use `mie_first_last_day` once, and set lodging to zero. Record one travel day in the workbook. ### Installation to locality crosswalk GSA uses civilian localities. Translate installations before lookup. | Installation or site | GSA locality | |---|---| | Fort Meade, MD | Annapolis or Anne Arundel County, MD | | Fort Belvoir, VA | Fairfax or Alexandria, VA | | Pentagon, VA | Arlington, VA or DC rate | | Joint Base Andrews, MD | District of Columbia | | NSA Bethesda or Walter Reed, MD | District of Columbia composite locality | | Fort Liberty, NC | Fayetteville, NC | | Peterson SFB, Schriever SFB, or Fort Carson, CO | Colorado Springs, CO | | Wright-Patterson AFB, OH | Dayton, OH | | Eglin AFB, FL | Fort Walton Beach, FL | | JB San Antonio, Randolph, or Lackland, TX | San Antonio, TX | | Hanscom AFB, MA | Bedford or Boston, MA | | Redstone Arsenal, AL | Huntsville, AL | | Offutt AFB, NE | Omaha or Bellevue, NE | | Cape Canaveral or Patrick SFB, FL | Cocoa Beach or Cape Canaveral, FL | | Joint Base Lewis-McChord, WA | Tacoma or Pierce County, WA | | Oak Ridge National Laboratory or Y-12, TN | Knoxville, TN | | Los Alamos National Laboratory, NM | Santa Fe or Los Alamos County, NM | | Hanford or PNNL, WA | Richland, WA | | Sandia National Laboratories, NM | Albuquerque, NM | | Lawrence Livermore National Laboratory, CA | Livermore or Oakland, CA | | Idaho National Laboratory, ID | Idaho Falls, ID | | White Sands Missile Range, NM | Las Cruces, NM | | NAWS China Lake, CA | Ridgecrest or Kern County, CA | | Edwards AFB, CA | Lancaster or Palmdale, CA | | Dugway Proving Ground, UT | Salt Lake City metro standard rate | | Nellis AFB or Creech AFB, NV | Las Vegas, NV | | Point Mugu or NBVC, CA | Oxnard or Ventura County, CA | For another site, call `lookup_city_perdiem` with the nearest civilian locality and verify the returned county. ### Fiscal-year fallback If the requested fiscal year returns an empty rate list or an error containing `No rates found for FY`, retry the prior fiscal year. Record the requested and fallback years in Methodology. If contract start is within six months of a new fiscal year, query the new year when published or disclose that the current-year baseline must be refreshed. ### Travel interpretation "Quarterly travel between sites" means four total trips split across destinations unless the user says each way or per destination. Ask when the interpretation materially changes cost. If origin and destination are in the same metro or within ordinary local-travel distance, flag that lodging per diem may not apply. Use mileage or another user-supplied local-travel basis instead. ## 6. Raw-data recording Record compact, reproducible inputs and outputs on the Raw Data sheet: - BLS operation, SOC, scope, area code, datatypes, returned vintage, and selected percentiles - CALC+ operation, exact buckets or keyword, count, percentiles, and contamination caveat if applicable - Per Diem locality, state, fiscal year, month, nights, returned lodging, and returned M&IE - Every fallback, proxy, or derived value Do not paste full JSON payloads. Record the parameters and summary fields needed to reproduce each call. -
professional-product-standard.md 5.5 KB
# Professional product standard This file is the canonical source for the copy packaged with each 1102tools skill. The packaged copies must remain identical to this file. ## Product judgment Produce a finished professional work product, not a record of the process used to create it. Write for the person who must understand, use, approve, or act on the result. Exercise editorial judgment. Include material that improves the reader's understanding or decision. Omit material merely because it was collected, available, or easy to generate. Every page, section, table, and visual must earn its place. Match the structure, length, voice, and visual treatment to the assignment. Do not reuse a universal report outline. A short decision card, formal contract-file document, analytical workbook, landscape, timeline, or longer consulting report may all be correct products for different requests. Lead with the useful output. Research mechanics, process narration, methodology, limitations, and compliance controls are secondary unless the reader's purpose makes one of them the product. ## Controlled freedom Route rules define the substantive outcome and genuine formal boundaries. They do not prescribe identical headings, page counts, layouts, or section order unless a law, supplied template, calculation model, or downstream interface requires it. Choose the clearest form for each idea: - prose for explanation and judgment; - tables for real comparison or repeated fields; - cards, profiles, matrices, timelines, charts, and callouts when they improve comprehension; - appendices only for material the intended reader may reasonably need. Do not put paragraph-length narrative in narrow table cells. Do not repeat the same information as a callout, table, and prose section unless each form serves a different reader need. Use a restrained, coherent design with clear hierarchy, readable typography, comfortable spacing, and accessible contrast. Treat examples as quality references, not templates to copy. ## Paid-value standard The primary artifact should contain the analysis, comparison, requirements, model, or operating guidance the customer is paying to receive. Audit material must remain subordinate. Before delivery, remove: - generic background the intended reader already knows; - duplicated findings or actions; - query logs, tool operations, sanitized parameters, and internal record mechanics; - generic owners, gates, scenarios, or warnings invented to fill a template; - boilerplate disclaimers repeated in multiple sections; - empty sections and tables that merely announce missing content. When evidence is insufficient for the promised product, say so plainly and provide the useful narrower result or acquisition plan for the missing evidence. Do not pad an evidence gap into a document that resembles a completed analysis. ## Reader-facing source citations Internal evidence identifiers such as `E001` may remain in a private research record for backward compatibility, but they never appear in a customer-facing artifact. Assign each distinct reader-visible source an identifier in order of first appearance: `S1`, `S2`, `S3`, with no leading zeros. Reuse the same identifier wherever that source supports another claim. Cite sources beside the supported claim using forms such as `[S1]`, `[S1, S4]`, or `[S1-S3]`. End a sourced report with a concise `Source Register`. Each entry uses the corresponding identifier and provides enough information to verify the source: publisher or organization, title or record identity, relevant date, and a clickable public URL or supplied-document locator. Deduplicate sources. Do not display internal source-class tokens or a query-by-query research log. Native legal and acquisition citations such as `FAR 10.001`, a docket number, PIID, UEI, or document section remain in their ordinary form. Add an `S` citation when the artifact also needs a link to the supporting source; do not replace the native citation with an opaque source number. For workbooks, source notes and benchmark rows may use `S` identifiers that resolve to a Sources or Raw Data register. Formula cells and internal validation IDs are not reader-facing source citations. ## Proportionate boundaries Accuracy, authority boundaries, unresolved decisions, and limitations remain mandatory when material. Present them once, in the least intrusive form that keeps the product honest. A concise note or callout is preferable to a recurring legalistic section when the reader needs the answer more than a compliance lecture. Do not weaken a formal SOW/PWS, OT project description, acquisition-policy status analysis, or auditable cost model for stylistic reasons. Formal and mathematical requirements remain hard constraints. Apply taste to hierarchy, selection, explanation, and delivery view, not to the removal of necessary substance. ## Final editorial review After technical validation and rendering, review the complete artifact as a demanding customer: - Is the useful result apparent immediately? - Did the author select and synthesize rather than dump everything collected? - Does each section materially advance the reader's work? - Are sources integrated credibly without dominating the product? - Are limitations accurate and proportionate? - Does the artifact feel composed for this assignment rather than populated from a universal template? - Is this work product an experienced professional could confidently sell? Revise until the answer to every applicable question is yes. Structural validation is a technical floor, not the release decision. -
runtime-adaptation.md 2.7 KB
# Runtime Adaptation Use host capabilities instead of hardcoded client names. ## Questions If the host exposes a structured question tool, use it for short mutually exclusive choices. Otherwise present a numbered list in chat and accept a number, label, or free-text answer. Do not refer to a tool name in user-facing prose. For Stage A, ask only for decomposition confirmation and stop. For Stage B, batch independent missing fields into one response. Ask one field at a time only when an answer changes the next available choices. ## MCP operations Inspect the available operations and match their server, operation name, description, and schema. Host prefixes and separators are implementation details. For example, look for the `detect_latest_year` operation from the BLS OEWS server rather than a literal generated namespace. Declared MCP dependencies do not prove that a server is installed, authenticated, or reachable. Keep the pre-flight check. ## Files and Python Use the host's file-reading, file-writing, and Python capabilities. Follow any authoritative host spreadsheet workflow and its hard stops. Use Python and openpyxl for workbook authoring only when no governing host spreadsheet workflow prohibits that substitute; never guess dependency paths or bypass a host hard stop. Resolve referenced files relative to this skill directory when possible. If the host does not expose the skill directory, report which reference or script cannot be loaded and stop before a step that depends on it. Before the first artifact-specific approval, state whether full workbook mode is available. If it is not, preserve all approved inputs and offer the workbook specification as structured JSON plus Markdown or CSV tables, or ask the user to continue in a maintained client surface that supports workbook generation. Do not label the fallback as a completed workbook. ## Formula verification openpyxl writes formulas and reads cached values; it does not calculate Excel formulas. Validation has three layers: 1. Formula-structure audit with openpyxl. 2. Independent recomputation from raw inputs in Python. 3. Formula execution in a real spreadsheet engine when available. On macOS and Linux, detect `soffice` and use LibreOffice headless for layer 3. Do not automate desktop Excel on macOS. When no engine is available, use the exact disclosure in Step 8.5. ## Delivery Use the host's artifact presentation capability when available. Otherwise save to the user-supplied directory or current working directory and report the absolute path. Do not assume `/mnt`, `present_files`, shell launch commands, or a particular desktop application exists. Never claim that saving a workbook caused formulas to execute. Never call a workbook validated unless the claimed validation layers actually ran. -
validation-gates.md 4.7 KB
# CR Workbook Validation Gates Run all applicable gates after workbook creation and before delivery. ## Layer 1: formula-structure audit The bundled validator checks: - All seven required sheets exist. - `IGCE Summary!B11` computes the month gap from `YYYY-MM` text using `VALUE`, `LEFT`, and `MID`, without `DATEDIF` or `YEAR`. - `IGCE Summary!B12` computes the aging factor from escalation and month gap. - Every Cost Buildup block follows the 23-row layout. - Direct labor is the fifth row of each block and cross-sheet formulas do not use the aged-wage row by mistake. - Fringe, overhead, G&A, FCCM, fee, and price formulas preserve the required bases. - The workbook contains formulas and no formula-error tokens in formula text. - Text beginning with formula-trigger characters is escaped. - Any summary total labeled as a price equals estimated cost plus fee; a price-labeled total that equals the cost subtotal fails. - The current-assumptions Scenario Analysis row reproduces the summary estimated price within one dollar, proving the scenario sheet uses the same fee-base rule. - For a multi-period requirement (`assumptions.periods` greater than 1, reconciled with `IGCE Summary!B19`), the summary shows a per-period breakdown of cost, fee, and price for the base and each option period. - Optional custom formula assertions in the JSON sidecar pass. ## Layer 2: independent recomputation Create a JSON sidecar from the raw inputs, not from workbook formula results. Minimum shape: ```json { "assumptions": { "fee_type": "CPFF", "primary_fee_rate": 0.08, "fringe_rate": 0.32, "overhead_rate": 0.80, "ga_rate": 0.12, "fccm_rate": 0.0, "aging_factor": 1.025, "productive_hours": 1880, "periods": 3 }, "labor_lines": [ { "name": "Research Scientist", "annual_wage": 140000, "fte": 3, "months": 12, "workbook_cost_rate_cell": "'Cost Buildup'!B17", "workbook_price_rate_cell": "'Cost Buildup'!B21" } ], "non_labor_lines": [ { "name": "Travel", "amount": 12000, "fee_bearing": false, "workbook_total_cell": "'Travel Detail'!B14" } ], "workbook_fee_bearing_cost_cell": "'IGCE Summary'!B28", "workbook_total_cost_cell": "'IGCE Summary'!B29", "workbook_total_fee_cell": "'IGCE Summary'!B30", "workbook_total_price_cell": "'IGCE Summary'!B31" } ``` For CPAF, add `award_pool_rate` and `assumed_earned`. For CPIF, the primary recomputation verifies the target case; add formula assertions for overrun and underrun shares and bounds in `Scenario Analysis`. If continuous coverage is present, put `annual_coverage_hours` on the relevant labor line. The recomputation rejects an FTE and productive-hours combination that does not reconcile within 0.5% or one hour. Run: ```text python scripts/recompute_expected_values.py validation-input.json python scripts/validate_workbook.py output.xlsx --expected validation-input.json --engine auto ``` ## Layer 3: real spreadsheet engine With `--engine auto`, the validator looks for LibreOffice. When found, it performs a headless conversion cycle, reopens the calculated workbook with `data_only=True`, checks cached errors, and compares named workbook values against the independent Python result. If formula execution cannot run, do not call the workbook fully recalculated. Use the exact disclosure required by the core skill. ## CR-specific manual gates Confirm each item even when a script passes: - Fee-bearing and non-fee-bearing amounts are visibly separate. - CPFF form is Completion or Term and the rationale follows FAR 16.306(d). - CPFF fee does not exceed the applicable ceiling. - CPAF shows base-only, assumed-earned, and full-pool outcomes. - CPIF uses separate contractor overrun and underrun shares and applies min/max bounds. - Audited indirect rates are point estimates with date and authority, not scenario midpoints. - CALC+ results are neutral positioning and distinguish estimated cost from cost plus fee. - Day-trip M&IE is discounted once, not twice. - BLS vintage is runtime-confirmed and aging is cell-referenced. - No formula range contains text `TBD`. ## Fault injection At minimum, test copies with these deliberate defects and confirm rejection: 1. Replace `keyword=` with `q=` in a recorded CALC+ query. 2. Change the month-gap formula to `DATEDIF` or `YEAR` on text. 3. Point a summary rate to the aged-annual-wage row instead of Direct Labor. 4. Apply fee to total estimated cost when a non-fee pass-through is present. 5. Remove the FCCM layer or apply it to the wrong base. 6. Change a CPIF underrun formula to use the overrun share. 7. Multiply 4.2 FTE by 1,880 hours against an 8,760-hour coverage requirement. Document which faults were automated and which were manually inspected in `test.md`. -
workbook-specification.md 12.2 KB
# CR Workbook Specification Build one `.xlsx` workbook with seven sheets in this order: 1. `IGCE Summary` 2. `Cost Buildup` 3. `Scenario Analysis` 4. `Rate Validation` 5. `Travel Detail` 6. `Methodology` 7. `Raw Data` Include `Travel Detail` even when travel is zero. Put `Travel Not Applicable` and numeric zero in the total cell so summary formulas retain a valid target. ### First-view decision dashboard The first visible area of `IGCE Summary` must state the requirement, estimate purpose, period, fee structure, point estimate and useful range, major cost and fee drivers, the assumptions most likely to move the result, live-source status, and the next acquisition-team action. Keep the dashboard readable without horizontal scrolling and clearly distinguish estimated cost, fee, and estimated price. Do not make a price-reasonableness determination. Do not deliver a workbook whose sheets merely exist. Populate the summary, cost buildup, fee logic, scenarios, source limitations, and next actions so a reviewer can understand and challenge the estimate without reverse-engineering formulas. ## 1. IGCE Summary ### Assumption block Use these exact cells so the validator can inspect the aging formula: | Cell | Label or value | |---|---| | A1:B1 | `IGCE Assumptions (Cost-Reimbursement)` | | A2 / B2 | Fringe Rate / decimal input | | A3 / B3 | Overhead Rate / decimal input | | A4 / B4 | G&A Rate / decimal input | | A5 / B5 | FCCM Rate / decimal input | | A6 / B6 | Escalation Rate / decimal input | | A7 / B7 | Productive Hours per Year / numeric input | | A8 / B8 | Base Year Months / numeric input | | A9 / B9 | BLS Vintage / `YYYY-MM` text input | | A10 / B10 | Contract Start / `YYYY-MM` text input | | A11 / B11 | Months Gap / formula below | | A12 / B12 | Aging Factor / formula below | | A13 / B13 | Fee Type / `CPFF`, `CPAF`, or `CPIF` | | A14 / B14 | Primary Fee Rate / CPFF fixed, CPAF base, or CPIF target | | A15 / B15 | Award Pool Rate or Contractor Overrun Share | | A16 / B16 | Assumed Earned Percentage or Contractor Underrun Share | | A17 / B17 | Minimum Fee Rate, blank when not applicable | | A18 / B18 | Maximum Fee Rate, blank when not applicable | | A19 / B19 | Total Periods (Base plus Options) / whole-number input, 1 for a single-period requirement | Use these formulas: ```excel B11 =MAX(0,(VALUE(LEFT(B10,4))-VALUE(LEFT(B9,4)))*12+VALUE(MID(B10,6,2))-VALUE(MID(B9,6,2))) B12 =(1+B6)^(B11/12) ``` Format B12 as `0.0000`. Never use `YEAR(B9)`, `YEAR(B10)`, or `DATEDIF` on text. ### Summary table Start at row 20. Show each labor category, SOC, location, FTE, hours, base and option-period estimated cost, fee-bearing cost, non-fee-bearing cost, fee, and estimated price. Label every amount as `Estimated Cost`, `Fee`, or `Estimated Price` correctly. Keep separate rows for: - Labor and allocable indirects - Travel - Fee-bearing ODCs or managed subcontracts - Non-fee-bearing pass-through ODCs - Total estimated cost - Fee-bearing base - Fee - Total estimated price Never apply a fee formula directly to total estimated cost unless that total equals the confirmed fee-bearing base. Any total whose label contains the word `price` must equal estimated cost plus fee. Never label a cost-only subtotal as a price; a reviewer reading a price-labeled row must see the full Government obligation, not the cost component alone. The validator recomputes and rejects a price-labeled total that equals the cost subtotal instead of cost plus fee. When the period of performance includes option periods (`Total Periods` greater than 1), the summary must show per-period estimated cost, fee, and estimated price for the base period and each option period, plus the all-periods total. Label the periods explicitly (`Base Year`, `Option Year 1`, and so on). A single compressed multi-year multiplier formula does not satisfy year-by-year Government exposure and the validator rejects it. ## 2. Cost Buildup Use a fixed 23-row block for every labor category. Block `N` begins at: ```text base row = 1 + (N - 1) * 23 ``` | Offset | Label | Formula or input | |---:|---|---| | 0 | `Cost Buildup: <LCAT>` | header | | 1 | BLS Base Annual Wage | source input | | 2 | Aging Factor | `='IGCE Summary'!$B$12` | | 3 | Aged Annual Wage | base wage times aging factor | | 4 | Direct Labor Rate Hourly | aged wage divided by 2,080 | | 5 | blank | separator | | 6 | Fringe Rate | `='IGCE Summary'!$B$2` | | 7 | Fringe Amount | direct rate times fringe | | 8 | Labor plus Fringe | direct plus fringe | | 9 | Overhead Rate | `='IGCE Summary'!$B$3` | | 10 | Overhead Amount | labor plus fringe times overhead | | 11 | Subtotal | labor plus fringe plus overhead | | 12 | G&A Rate | `='IGCE Summary'!$B$4` | | 13 | G&A Amount | subtotal times G&A | | 14 | FCCM Rate | `='IGCE Summary'!$B$5` | | 15 | FCCM Amount | subtotal plus G&A, times FCCM | | 16 | Estimated Cost Rate | subtotal plus G&A plus FCCM | | 17 | Fee Type | `='IGCE Summary'!$B$13` | | 18 | Primary Fee Rate | `='IGCE Summary'!$B$14` | | 19 | Estimated Fee Rate | fee-type formula | | 20 | Estimated Price Rate | estimated cost plus estimated fee | | 21 | Implied Multiplier | estimated price divided by direct hourly | | 22 | blank | block separator | For the first block, Direct Labor Rate Hourly is row 5. Cross-sheet formulas must reference row 5, not row 4, which is Aged Annual Wage. Fee-rate formulas by type: - CPFF: estimated cost rate times B14. - CPAF: estimated cost rate times `(B14 + B15 * B16)`. - CPIF target: estimated cost rate times B14. Put overrun, underrun, and bound mechanics on `Scenario Analysis` rather than hiding them in the labor block. ## 3. Scenario Analysis Show low, mid, and high indirect-rate cases. Include component assumptions at the top, cost, fee-bearing base, non-fee cost, fee, and estimated price. Every scenario must apply the same fee-base rule as the summary: fee applies only to the fee-bearing base, never to non-fee-bearing travel or pass-through ODCs the summary excludes from fee. The scenario row that represents current assumptions must reproduce the summary estimated price exactly; the validator cross-checks that row against the summary and rejects any mismatch beyond one dollar. For CPAF, show within every cost scenario: - Base fee only - Base plus assumed-earned award pool - Base plus full award pool For CPIF, show a matrix with cost scenarios as columns and underrun, target, and overrun outcomes as rows. Include separate overrun and underrun contractor shares, min and max fee, and the first outcome where a bound applies. For CPFF, label the scenarios as alternative Government estimate cases. Do not imply the negotiated fixed fee later floats with actual incurred cost. ## 4. Rate Validation Use columns for labor category, BLS estimated cost rate, BLS estimated cost plus fee, CALC+ P25, P50, P75, P90, sample size, arithmetic divergence, and neutral note. When a comparison pool is thin or contaminated, add title-match and experience-match columns with separate sample sizes. Do not write `reasonable`, `acceptable`, `competitive`, `outlier`, or a negotiation recommendation. ## 5. Travel Detail Use a 17-row block per destination and sum each block into the Summary. For a day trip, use zero lodging and one already-discounted first/last-day M&IE amount. For overnight trips, calculate first and last day at 75% and intervening days at the full rate. Include a `Fee-Bearing?` input for each destination. Default pass-through travel to `No` when the user has not directed otherwise, and disclose the assumption. ## 6. Methodology Keep the narrative concise and auditable. Include: - CR type and, for CPFF, Completion or Term form - Regulatory sources and applicable fee ceiling - Labor/SOC mapping and seniority convention - BLS vintage, metro, series inputs, aging, and escalation - Indirect-rate source, including audited-rate authority and effective date - FCCM basis or explicit zero - Fee-bearing classifications - CPAF or CPIF scenario mechanics when applicable - CALC+ pool construction and limitations - Travel assumptions and fiscal year - Coverage math, if applicable - Exclusions and user-approved overrides - Formula-validation layers actually run Do not state that the workbook proves cost realism, fair and reasonable pricing, or contractor accounting-system adequacy. ## 7. Raw Data Record compact reproducible parameters and result summaries, not full JSON dumps. Include BLS series inputs and selected percentiles, CALC+ query and pool statistics, Per Diem locality and rates, every fallback, and the source of user-supplied rates. ## Formatting and safety - Blue font for user-editable inputs; black for formulas. - Currency: `$#,##0.00` or `$#,##0` consistently. - Percentage: `0.0%`; aging factor: `0.0000`. - Freeze panes below assumption and header blocks. - Escape text beginning with `=`, `+`, `-`, or `@` so Excel does not parse it as a formula. - Use numeric zero, never text `TBD`, in formula ranges. - Autosize columns within readable limits and wrap long notes. ### Column widths and text clipping Excel and LibreOffice let a text cell overflow into the next cell **only when that neighbour is empty**. The moment the cell to the right of a label carries a value or a formula, the label is cut off at its own column boundary in the printed and rendered output, however much white space appears to follow it on screen. Setting a column width without accounting for this is what produces labels such as `Government sh`, `0047900 Washington-Arlin`, and `Scenario Analysis: Senior Software En` in a delivered workbook. Every populated text cell must therefore satisfy at least one of the following, and `validate_workbook.py` fails the workbook when none of them holds: - **Fit.** The label fits inside its own column width. - **Wrap.** The cell sets `wrap_text=True` and the row height is tall enough to show every wrapped line. - **Free overflow.** Every cell on the label's overflow side in the same row is empty. That is the right-hand neighbour for left-aligned and general text, the left-hand neighbour for right-aligned text, and both neighbours for centred text. - **Merge.** The label is merged across the columns it needs. The merged span, not the anchor column alone, is what has to fit. Section headers and block titles are the common failure. A title such as `Scenario Analysis: Senior Software Engineer` must be merged across the block it introduces, placed on a row whose neighbouring cells are left empty, or shortened until it fits. Never rely on visual overflow for a block title that sits beside a populated cell. Concrete generator guidance: - Compute each column width from the **longest label actually written to that column**, not from the header text or a fixed guess. Walk the column after the data is written, take the widest populated string, and set `width = min(cap, needed + 2)`. - Estimate a label in column-width units rather than characters. One unit is about one digit at Calibri 11. Lowercase letters run about 0.96 units, uppercase about 1.05, `i`/`l`/`j` and spaces and most punctuation about 0.45, `m` and `w` about 1.66, and bold text is about 14 percent wider overall. - Prefer a merged header cell for every block title, and reserve narrow columns for short codes, dates, and numbers. - Where a column must stay narrow, move the long text into a wrapped narrative column with an explicit width and an adequate row height. Cap runaway widths in the 60 to 90 unit range and wrap instead of widening past that. - The audit allows roughly one column-width unit of slack, so a label that is genuinely borderline will not fail. Do not aim for the tolerance; aim for the fit. ### Delivery-view gate Before delivery, recalculate and save the final workbook through a calculation engine. The delivered file must retain cached values for formula cells on `IGCE Summary`, including fee-bearing cost, total cost, fee, and total price. Render the summary and correct blank formula outputs, clipped limitations, unreadable assumptions, or a summary that requires horizontal scrolling to understand. Configure the populated print area on every sheet to fit one page wide with no fixed page-height limit. Use landscape orientation for wide tables. The complete `IGCE Summary` title, decision dashboard, cost and fee totals, assumptions, and next action must remain on one page wide when printed or exported; never split the dashboard horizontally. -
wrap-rate-presets.md 4 KB
# Cost Pool and Fee Reference Use this reference only after the user confirms the indirect-rate basis and CR type. These are estimating assumptions, not approved contractor rates. ## Indirect-cost scenarios | Component | Low | Mid | High | Application base | |---|---:|---:|---:|---| | Fringe | 25% | 32% | 40% | Direct labor | | Overhead | 60% | 80% | 120% | Direct labor plus fringe | | G&A | 8% | 12% | 18% | Labor plus fringe plus overhead | | FCCM | 0% | 0% | 0.5% | Subtotal plus G&A | Use FCCM only with a CO-supplied basis tied to FAR 31.205-10 and CAS 414. If the user supplies an FPRA, FPRR, or audited indirect rates, use those rates as the point estimate and document the effective date and approving authority. Do not create artificial low and high offsets around audited rates. ## Fee-bearing classification Classify every cost element before calculating fee. | Cost element | Default estimating treatment | Required action | |---|---|---| | Contractor labor and allocable indirects | Fee-bearing | Confirm with the selected fee structure | | Contractor-developed deliverable or managed subcontract | Undetermined | Ask the user | | Travel reimbursed at government rates | Non-fee-bearing pass-through | Disclose and allow the user to override | | Commercial license or third-party hardware at cost | Non-fee-bearing pass-through | Disclose and allow the user to override | | Government-furnished-equivalent material | Non-fee-bearing | Keep outside the fee base | Never infer that all ODCs bear fee. Keep fee-bearing cost, non-fee-bearing cost, total estimated cost, fee, and total estimated price as separate workbook lines. ## CPFF Record Completion or Term form. ```text fixed fee = confirmed fee-bearing estimated cost * fixed-fee rate total estimated price = total estimated cost + fixed fee ``` The fixed fee is set at award and does not vary with actual incurred cost, except for changes in the work. Workbook low, mid, and high calculations are alternative Government estimate scenarios, not a formula for paying fee as actual cost changes. Apply the current FAR 15.404-4(c)(4)(i) ceilings: - 15% for experimental, developmental, or research CPFF work. - 10% for other CPFF work. - The separate 6% architect-engineer limitation when applicable. Do not treat any ceiling as a recommended rate. ## CPAF ```text base fee = fee-bearing estimated cost * base-fee rate award pool = fee-bearing estimated cost * award-pool rate assumed earned award fee = award pool * assumed-earned percentage estimated fee = base fee + assumed earned award fee ``` Show all three outcomes: 1. Base fee only. 2. Base fee plus assumed-earned pool, default 85% when the user accepts it. 3. Base fee plus full award pool. Describe the 85% case as an estimating assumption, never as an expected performance judgment. ## CPIF Keep overrun and underrun contractor shares separate. ```text target fee = target fee-bearing cost * target-fee rate overrun fee = target fee - (actual fee-bearing cost - target fee-bearing cost) * contractor overrun share overrun fee = max(overrun fee, target fee-bearing cost * minimum-fee rate) underrun fee = target fee + (target fee-bearing cost - actual fee-bearing cost) * contractor underrun share underrun fee = min(underrun fee, target fee-bearing cost * maximum-fee rate) ``` Run at least target, 10% overrun, and 10% underrun. Also run a wide-enough case, often 25%, to show each fee bound if the inputs permit. State the exact cost at which each bound takes effect. ## Scenario rules - Use low, mid, and high indirect-cost scenarios only when the rates are estimating assumptions. - When audited rates control, use the audited point estimate across the primary workbook and show sensitivity only if the user requests it. - Keep travel and pass-through classifications constant across scenarios. - Recompute fee on each Government estimate scenario using that scenario's confirmed fee-bearing base. - In every scenario, show both estimated cost and estimated price. Do not call estimated price `cost`.
-
-
scripts
-
recompute_expected_values.py 9.5 KB
#!/usr/bin/env python3 """Independently recompute CR cost, fee, and estimated price from raw inputs.""" from __future__ import annotations import argparse import json import math import sys from pathlib import Path from typing import Any class InputError(ValueError): """Raised when validation inputs are missing or invalid.""" def _number(value: Any, label: str, *, minimum: float | None = None) -> float: if isinstance(value, bool) or not isinstance(value, (int, float)): raise InputError(f"{label} must be a number") result = float(value) if not math.isfinite(result): raise InputError(f"{label} must be finite") if minimum is not None and result < minimum: raise InputError(f"{label} must be at least {minimum}") return result def _setting( line: dict[str, Any], assumptions: dict[str, Any], key: str, *, minimum: float = 0 ) -> float: if key in line: value = line[key] elif key in assumptions: value = assumptions[key] else: raise InputError(f"missing {key} for {line.get('name', '<unnamed>')}") return _number(value, f"{line.get('name', '<unnamed>')}.{key}", minimum=minimum) def _period_count(assumptions: dict[str, Any]) -> int: """Validate assumptions.periods, the total period count (base plus options).""" periods = assumptions.get("periods", 1) if isinstance(periods, bool) or not isinstance(periods, int) or periods < 1: raise InputError("assumptions.periods must be a whole number of at least 1") return periods def _fee_rate(assumptions: dict[str, Any]) -> tuple[str, float]: raw_type = assumptions.get("fee_type") if not isinstance(raw_type, str): raise InputError("assumptions.fee_type must be CPFF, CPAF, or CPIF") fee_type = raw_type.upper() primary = _number(assumptions.get("primary_fee_rate"), "primary_fee_rate", minimum=0) if fee_type == "CPFF" or fee_type == "CPIF": return fee_type, primary if fee_type == "CPAF": pool = _number(assumptions.get("award_pool_rate"), "award_pool_rate", minimum=0) earned = _number(assumptions.get("assumed_earned"), "assumed_earned", minimum=0) if earned > 1: raise InputError("assumed_earned must not exceed 1") return fee_type, primary + pool * earned raise InputError("assumptions.fee_type must be CPFF, CPAF, or CPIF") def _copy_reference(raw: dict[str, Any], result: dict[str, Any], key: str) -> None: if key not in raw: return value = raw[key] if not isinstance(value, str) or not value.strip(): raise InputError(f"{raw.get('name', '<unnamed>')}.{key} must be a non-empty string") result[key] = value def calculate(payload: dict[str, Any]) -> dict[str, Any]: assumptions = payload.get("assumptions") labor_lines = payload.get("labor_lines") non_labor_lines = payload.get("non_labor_lines", []) if not isinstance(assumptions, dict): raise InputError("assumptions must be an object") if not isinstance(labor_lines, list) or not labor_lines: raise InputError("labor_lines must be a non-empty array") if not isinstance(non_labor_lines, list): raise InputError("non_labor_lines must be an array") periods = _period_count(assumptions) fee_type, effective_fee_rate = _fee_rate(assumptions) calculated_labor: list[dict[str, Any]] = [] fee_bearing_cost = 0.0 for index, raw in enumerate(labor_lines): if not isinstance(raw, dict): raise InputError(f"labor_lines[{index}] must be an object") name = raw.get("name") if not isinstance(name, str) or not name.strip(): raise InputError(f"labor_lines[{index}].name must be a non-empty string") annual_wage = _number(raw.get("annual_wage"), f"{name}.annual_wage", minimum=0) aging = _setting(raw, assumptions, "aging_factor") fringe = _setting(raw, assumptions, "fringe_rate") overhead = _setting(raw, assumptions, "overhead_rate") ga = _setting(raw, assumptions, "ga_rate") fccm = _setting(raw, assumptions, "fccm_rate") hours = _setting(raw, assumptions, "productive_hours") fte = _number(raw.get("fte"), f"{name}.fte", minimum=0) months = _number(raw.get("months", 12), f"{name}.months", minimum=0) period_multiplier = _number( raw.get("period_multiplier", 1), f"{name}.period_multiplier", minimum=0 ) priced_hours = hours * fte if "annual_coverage_hours" in raw: coverage = _number( raw["annual_coverage_hours"], f"{name}.annual_coverage_hours", minimum=0 ) if not math.isclose(priced_hours, coverage, rel_tol=0.005, abs_tol=1.0): raise InputError( f"{name}.productive_hours * fte is {priced_hours:.4f}, " f"which does not reconcile to annual_coverage_hours {coverage:.4f}" ) aged_wage = annual_wage * aging direct = aged_wage / 2080.0 fringe_amount = direct * fringe labor_fringe = direct + fringe_amount overhead_amount = labor_fringe * overhead subtotal = labor_fringe + overhead_amount ga_amount = subtotal * ga fccm_amount = (subtotal + ga_amount) * fccm cost_rate = subtotal + ga_amount + fccm_amount fee_rate = cost_rate * effective_fee_rate price_rate = cost_rate + fee_rate period_cost = cost_rate * hours * fte * (months / 12.0) * period_multiplier period_fee = period_cost * effective_fee_rate period_price = period_cost + period_fee fee_bearing_cost += period_cost result: dict[str, Any] = { "name": name, "aged_annual_wage": aged_wage, "direct_hourly_rate": direct, "estimated_cost_rate": cost_rate, "estimated_fee_rate": fee_rate, "estimated_price_rate": price_rate, "period_cost": period_cost, "period_fee": period_fee, "period_price": period_price, } for key in ( "workbook_cost_rate_cell", "workbook_price_rate_cell", "workbook_total_cost_cell", "workbook_total_price_cell", ): _copy_reference(raw, result, key) calculated_labor.append(result) non_fee_cost = 0.0 calculated_non_labor: list[dict[str, Any]] = [] for index, raw in enumerate(non_labor_lines): if not isinstance(raw, dict): raise InputError(f"non_labor_lines[{index}] must be an object") name = raw.get("name") if not isinstance(name, str) or not name.strip(): raise InputError(f"non_labor_lines[{index}].name must be a non-empty string") amount = _number(raw.get("amount"), f"{name}.amount", minimum=0) fee_bearing = raw.get("fee_bearing", False) if not isinstance(fee_bearing, bool): raise InputError(f"{name}.fee_bearing must be true or false") if fee_bearing: fee_bearing_cost += amount else: non_fee_cost += amount result = {"name": name, "amount": amount, "fee_bearing": fee_bearing} _copy_reference(raw, result, "workbook_total_cell") calculated_non_labor.append(result) total_cost = fee_bearing_cost + non_fee_cost total_fee = fee_bearing_cost * effective_fee_rate total_price = total_cost + total_fee output: dict[str, Any] = { "periods": periods, "fee_type": fee_type, "effective_fee_rate": effective_fee_rate, "labor_lines": calculated_labor, "non_labor_lines": calculated_non_labor, "fee_bearing_cost": fee_bearing_cost, "non_fee_bearing_cost": non_fee_cost, "total_estimated_cost": total_cost, "total_fee": total_fee, "total_estimated_price": total_price, } for key in ( "workbook_fee_bearing_cost_cell", "workbook_total_cost_cell", "workbook_total_fee_cell", "workbook_total_price_cell", ): if key in payload: value = payload[key] if not isinstance(value, str) or not value.strip(): raise InputError(f"{key} must be a non-empty string") output[key] = value return output def load_payload(path: Path) -> dict[str, Any]: try: payload = json.loads(path.read_text(encoding="utf-8")) except OSError as exc: raise InputError(f"cannot read {path}: {exc}") from exc except json.JSONDecodeError as exc: raise InputError(f"invalid JSON in {path}: {exc}") from exc if not isinstance(payload, dict): raise InputError("top-level JSON value must be an object") return payload def main() -> int: parser = argparse.ArgumentParser(description="Recompute expected CR cost and fee totals.") parser.add_argument("input", type=Path, help="Validation-input JSON file") parser.add_argument("--output", type=Path, help="Optional JSON output path") args = parser.parse_args() try: result = calculate(load_payload(args.input)) except InputError as exc: print(f"ERROR: {exc}", file=sys.stderr) return 2 rendered = json.dumps(result, indent=2, sort_keys=True) + "\n" if args.output: try: args.output.write_text(rendered, encoding="utf-8") except OSError as exc: print(f"ERROR: cannot write {args.output}: {exc}", file=sys.stderr) return 2 else: print(rendered, end="") return 0 if __name__ == "__main__": raise SystemExit(main()) -
validate_workbook.py 33.3 KB
#!/usr/bin/env python3 """Validate a CR workbook structurally and with optional engine execution.""" from __future__ import annotations import argparse import json import math import re import shutil import subprocess import sys import tempfile from pathlib import Path from typing import Any from openpyxl import load_workbook from openpyxl.utils import column_index_from_string, get_column_letter from recompute_expected_values import InputError, calculate, load_payload DEFAULT_SHEETS = [ "IGCE Summary", "Cost Buildup", "Scenario Analysis", "Rate Validation", "Travel Detail", "Methodology", "Raw Data", ] CELL_REF = re.compile( r"^(?:'((?:[^']|'')+)'|([^!]+))!\$?([A-Za-z]{1,3})\$?([1-9][0-9]*)$" ) COST_B_REF = re.compile( r"(?:'Cost Buildup'|Cost Buildup)!\$?B\$?([1-9][0-9]*)", re.IGNORECASE, ) BASE_PERIOD_LABEL = re.compile(r"\bBASE[\s-]*(?:YEAR|PERIOD)\b") OPTION_PERIOD_LABEL = re.compile( r"\bOPTION\s*(?:YEAR|PERIOD)?\s*0*([1-9][0-9]*)\b|\bO[YP]\s*0*([1-9][0-9]*)\b" ) TOTAL_PERIODS_CELL = "B19" PRICE_TOLERANCE = 1.0 def normalize_formula(value: Any) -> str: return re.sub(r"\s+", "", str(value)).upper() def parse_cell_ref(reference: str) -> tuple[str, str]: match = CELL_REF.fullmatch(reference.strip()) if not match: raise InputError(f"invalid workbook cell reference: {reference}") sheet = (match.group(1) or match.group(2)).replace("''", "'") coordinate = f"{match.group(3).upper()}{match.group(4)}" return sheet, coordinate def cell_value(workbook: Any, reference: str) -> Any: sheet, coordinate = parse_cell_ref(reference) if sheet not in workbook.sheetnames: raise InputError(f"cell reference uses missing sheet: {reference}") return workbook[sheet][coordinate].value def check_formula( failures: list[str], sheet: Any, coordinate: str, *, expected: str | None = None, contains: list[str] | None = None, not_contains: list[str] | None = None, ) -> None: value = sheet[coordinate].value if not isinstance(value, str) or not value.startswith("="): failures.append(f"{sheet.title}!{coordinate} is not a formula") return normalized = normalize_formula(value) if expected is not None and normalized != normalize_formula(expected): failures.append(f"{sheet.title}!{coordinate} formula does not match expected structure") for item in contains or []: if normalize_formula(item) not in normalized: failures.append(f"{sheet.title}!{coordinate} formula is missing {item}") for item in not_contains or []: if normalize_formula(item) in normalized: failures.append(f"{sheet.title}!{coordinate} formula contains forbidden text {item}") def _is_number(value: Any) -> bool: return not isinstance(value, bool) and isinstance(value, (int, float)) def _nearest_header(sheet: Any, row: int, column: int, limit: int = 40) -> str: """Return the closest non-formula text above a cell in the same column.""" for row_index in range(row - 1, max(0, row - limit), -1): value = sheet.cell(row_index, column).value if isinstance(value, str) and value.strip() and not value.startswith("="): return value.upper() return "" def _is_price_label(value: Any) -> bool: if not isinstance(value, str): return False text = value.strip() if not text or len(text) > 45 or text.endswith(".") or text.startswith("="): return False return "PRICE" in text.upper() def effective_periods(workbook: Any, payload_periods: int, failures: list[str]) -> int: """Reconcile the Total Periods assumption cell with the validation input.""" if "IGCE Summary" not in workbook.sheetnames: return payload_periods value = workbook["IGCE Summary"][TOTAL_PERIODS_CELL].value if value is None: if payload_periods > 1: failures.append( f"IGCE Summary!{TOTAL_PERIODS_CELL} must record Total Periods (Base plus " f"Options) for a {payload_periods}-period requirement" ) return payload_periods if not _is_number(value) or float(value) != int(value) or int(value) < 1: failures.append( f"IGCE Summary!{TOTAL_PERIODS_CELL} Total Periods (Base plus Options) must be " "a whole number of at least 1" ) return payload_periods declared = int(value) if payload_periods > 1 and declared != payload_periods: failures.append( f"IGCE Summary!{TOTAL_PERIODS_CELL} Total Periods is {declared} but the " f"validation input states {payload_periods} periods" ) return max(declared, payload_periods) def period_coverage_audit(workbook: Any, periods: int) -> list[str]: """Require per-period labels on IGCE Summary for a multi-period requirement.""" failures: list[str] = [] if periods <= 1 or "IGCE Summary" not in workbook.sheetnames: return failures base_found = False option_numbers: set[int] = set() for row in workbook["IGCE Summary"].iter_rows(): for cell in row: value = cell.value if not isinstance(value, str): continue upper = value.upper() if BASE_PERIOD_LABEL.search(upper): base_found = True for match in OPTION_PERIOD_LABEL.finditer(upper): option_numbers.add(int(match.group(1) or match.group(2))) if not base_found or len(option_numbers) < periods - 1: found = ", ".join(f"Option {n}" for n in sorted(option_numbers)) or "none" failures.append( f"the stated period of performance has {periods} periods (base plus " f"{periods - 1} options) but IGCE Summary shows no per-period breakdown of " f"estimated cost, fee, and estimated price (base label found: " f"{'yes' if base_found else 'no'}; option-period labels found: {found}); a " "single compressed multi-year multiplier row does not show year-by-year " "Government exposure" ) return failures def price_integrity_audit(cached: Any) -> list[str]: """Reject price-labeled totals that omit fee, and scenario fee-base drift. Works on the cached-value view of the workbook: any total labeled as a price must equal estimated cost plus fee, and the Scenario Analysis row built on current assumptions must reproduce the summary estimated price. """ failures: list[str] = [] if "IGCE Summary" not in cached.sheetnames: return failures summary = cached["IGCE Summary"] label_cost: float | None = None label_fee: float | None = None for row in summary.iter_rows(): label = next((c.value for c in row if isinstance(c.value, str) and c.value.strip()), None) numbers = [float(c.value) for c in row if _is_number(c.value)] if label is None or not numbers or len(label) > 45: continue upper = label.upper() if "PRICE" in upper: continue if "COST" in upper and "TOTAL" in upper and "RATE" not in upper: label_cost = numbers[-1] elif "FEE" in upper and not any( word in upper for word in ("BASE", "BEARING", "RATE", "TYPE") ): label_fee = numbers[-1] summary_cost: float | None = None summary_fee: float | None = None for row in summary.iter_rows(): price_label = next((c.value for c in row if _is_price_label(c.value)), None) if price_label is None: continue numeric_cells = [c for c in row if _is_number(c.value)] if not numeric_cells: continue row_cost: float | None = None row_fee: float | None = None for cell in numeric_cells: header = _nearest_header(summary, cell.row, cell.column) if "FEE" in header and "PRICE" not in header: row_fee = float(cell.value) elif "COST" in header and "PRICE" not in header: row_cost = float(cell.value) cost = row_cost if row_cost is not None else label_cost fee = row_fee if row_fee is not None else label_fee if cost is None or fee is None or fee <= PRICE_TOLERANCE: continue summary_cost, summary_fee = cost, fee expected_price = cost + fee values = [float(c.value) for c in numeric_cells] if not any(abs(value - expected_price) <= PRICE_TOLERANCE for value in values): detail = ( " and equals the cost subtotal" if any(abs(value - cost) <= PRICE_TOLERANCE for value in values) else "" ) failures.append( f"IGCE Summary row {numeric_cells[0].row} is labeled " f"{price_label.strip()!r} but its total omits the fee{detail}: any total " f"labeled as a price must equal estimated cost ({cost:,.2f}) plus fee " f"({fee:,.2f}) = {expected_price:,.2f}" ) if summary_cost is None or summary_fee is None or "Scenario Analysis" not in cached.sheetnames: return failures scenario = cached["Scenario Analysis"] header_row = cost_column = price_column = None for row in scenario.iter_rows(): columns = { "cost": None, "price": None, } for cell in row: value = cell.value if not isinstance(value, str): continue upper = value.upper() if "PRICE" in upper: columns["price"] = cell.column elif "COST" in upper: columns["cost"] = cell.column if columns["cost"] and columns["price"]: header_row, cost_column, price_column = row[0].row, columns["cost"], columns["price"] break if header_row is None: return failures expected_price = summary_cost + summary_fee for row_index in range(header_row + 1, scenario.max_row + 1): cost_value = scenario.cell(row_index, cost_column).value price_value = scenario.cell(row_index, price_column).value if not _is_number(cost_value) or abs(float(cost_value) - summary_cost) > PRICE_TOLERANCE: continue if _is_number(price_value) and abs(float(price_value) - expected_price) > PRICE_TOLERANCE: failures.append( f"Scenario Analysis row {row_index} prices the current-assumptions case at " f"{float(price_value):,.2f} but the IGCE Summary estimated price is " f"{expected_price:,.2f} (cost {summary_cost:,.2f} plus fee " f"{summary_fee:,.2f}); the scenario sheet must apply the same fee-base " "rule as the summary" ) break return failures # --- Rendered-text clipping audit ------------------------------------------- # A text cell overflows into the next cell only when that neighbour is empty. # When the neighbour is occupied the label is cut off in the printed workbook, # so every such label must fit its column, wrap, or be merged across the block. CLIPPING_GLYPH_WIDTHS = { " ": 0.45, ".": 0.45, ",": 0.45, ";": 0.45, ":": 0.45, "'": 0.35, "`": 0.45, "!": 0.45, "|": 0.45, "(": 0.55, ")": 0.55, "[": 0.55, "]": 0.55, "{": 0.60, "}": 0.60, "-": 0.60, "/": 0.55, "\\": 0.55, '"': 0.60, "%": 1.50, "@": 1.70, "$": 1.00, } CLIPPING_LOWER_NARROW = "ijl" CLIPPING_LOWER_SEMI = "frt" CLIPPING_LOWER_WIDE = "mw" CLIPPING_UPPER_NARROW = "I" CLIPPING_UPPER_WIDE = "MW" CLIPPING_BOLD_FACTOR = 1.14 CLIPPING_ABSOLUTE_TOLERANCE = 0.75 CLIPPING_RELATIVE_TOLERANCE = 0.04 CLIPPING_DEFAULT_WIDTH = 8.43 CLIPPING_MESSAGE_TEXT_LIMIT = 120 def glyph_width(character: str) -> float: """Width of one glyph in Excel column-width units (1.0 = one digit).""" if character in CLIPPING_GLYPH_WIDTHS: return CLIPPING_GLYPH_WIDTHS[character] if character in CLIPPING_LOWER_NARROW: return 0.48 if character in CLIPPING_LOWER_SEMI: return 0.59 if character in CLIPPING_LOWER_WIDE: return 1.66 if character in CLIPPING_UPPER_NARROW: return 0.45 if character in CLIPPING_UPPER_WIDE: return 1.55 if character.islower(): return 0.96 if character.isupper(): return 1.05 return 1.0 def estimated_text_width(text: str, font: Any = None) -> float: """Estimated rendered width of a label in column-width units.""" lines = str(text).split("\n") units = max((sum(glyph_width(character) for character in line) for line in lines), default=0.0) size = getattr(font, "size", None) or 11.0 if float(size) != 11.0: units *= float(size) / 11.0 if getattr(font, "bold", False): units *= CLIPPING_BOLD_FACTOR return units def column_width_map(sheet: Any) -> tuple[dict[int, float], float]: """Explicit column widths by index plus the sheet default width.""" widths: dict[int, float] = {} for letter, dimension in sheet.column_dimensions.items(): if dimension.width is None: continue # In-memory dimensions created by a generator carry no min/max, so fall # back to the column the dimension is keyed under. try: own = column_index_from_string(letter) except ValueError: own = None first = dimension.min or own or 1 last = dimension.max or own or first for index in range(first, last + 1): widths[index] = float(dimension.width) default = sheet.sheet_format.defaultColWidth or CLIPPING_DEFAULT_WIDTH return widths, float(default) def merged_ranges_by_anchor(sheet: Any) -> tuple[dict[tuple[int, int], Any], set[tuple[int, int]]]: """Merged-range lookup keyed by anchor cell, plus every covered cell.""" anchors: dict[tuple[int, int], Any] = {} covered: set[tuple[int, int]] = set() for merged in sheet.merged_cells.ranges: anchors[(merged.min_row, merged.min_col)] = merged for row in range(merged.min_row, merged.max_row + 1): for column in range(merged.min_col, merged.max_col + 1): covered.add((row, column)) return anchors, covered def _is_blank(value: Any) -> bool: if value is None: return True return isinstance(value, str) and not value.strip() def text_clipping_audit( workbook: Any, *, sheets: list[str] | None = None, exempt: set[str] | None = None, ) -> list[str]: """Flag text that is cut off in print because an occupied neighbour blocks overflow.""" failures: list[str] = [] skipped = exempt or set() for sheet in workbook.worksheets: if sheets is not None and sheet.title not in sheets: continue widths, default_width = column_width_map(sheet) anchors, covered = merged_ranges_by_anchor(sheet) max_column = sheet.max_column for row in sheet.iter_rows(): for cell in row: value = cell.value if not isinstance(value, str) or not value.strip() or value.startswith("="): continue position = (cell.row, cell.column) if position in covered and position not in anchors: continue alignment = cell.alignment if alignment.wrap_text or alignment.horizontal in {"fill", "distributed"}: continue if f"{sheet.title}!{cell.coordinate}" in skipped: continue merged = anchors.get(position) first_column = cell.column last_column = merged.max_col if merged is not None else cell.column available = sum( widths.get(index, default_width) for index in range(first_column, last_column + 1) ) needed = estimated_text_width(value, cell.font) tolerance = max( CLIPPING_ABSOLUTE_TOLERANCE, CLIPPING_RELATIVE_TOLERANCE * available, ) if needed <= available + tolerance: continue blockers = [] if alignment.horizontal in {"right", "center", "centerContinuous"}: left = first_column - 1 if left < 1: blockers.append("the left sheet edge") elif not _is_blank(sheet.cell(row=cell.row, column=left).value): blockers.append(sheet.cell(row=cell.row, column=left).coordinate) if alignment.horizontal != "right": right = last_column + 1 if right <= max_column and not _is_blank( sheet.cell(row=cell.row, column=right).value ): blockers.append(sheet.cell(row=cell.row, column=right).coordinate) if not blockers: continue shown = value.strip() if len(shown) > CLIPPING_MESSAGE_TEXT_LIMIT: shown = shown[: CLIPPING_MESSAGE_TEXT_LIMIT - 3] + "..." span = ( cell.column_letter if merged is None else f"{cell.column_letter}:{get_column_letter(last_column)}" ) failures.append( f"{sheet.title}!{cell.coordinate} is clipped in print: '{shown}' needs about " f"{needed:.1f} column-width units but column {span} gives {available:g} and " f"{', '.join(blockers)} blocks the overflow; widen the column to at least " f"{math.ceil(needed):g}, enable wrap text with adequate row height, merge the " f"label across the block, or shorten it" ) return failures def structural_audit(workbook: Any, payload: dict[str, Any]) -> list[str]: failures: list[str] = [] required_sheets = payload.get("required_sheets", DEFAULT_SHEETS) if not isinstance(required_sheets, list) or not all( isinstance(item, str) for item in required_sheets ): raise InputError("required_sheets must be an array of strings") for sheet_name in required_sheets: if sheet_name not in workbook.sheetnames: failures.append(f"missing required sheet: {sheet_name}") if "IGCE Summary" in workbook.sheetnames: summary = workbook["IGCE Summary"] check_formula( failures, summary, "B11", contains=[ "VALUE(LEFT(B10,4))", "VALUE(MID(B10,6,2))", "VALUE(LEFT(B9,4))", "VALUE(MID(B9,6,2))", ], not_contains=["DATEDIF", "YEAR("], ) check_formula( failures, summary, "B12", contains=["B6", "B11", "^"], ) if summary["B12"].number_format != "0.0000": failures.append("IGCE Summary!B12 must display the aging factor as 0.0000") formula_count = 0 formula_error_tokens = ("#REF!", "#NAME?", "#VALUE!", "#DIV/0!") for sheet in workbook.worksheets: for row in sheet.iter_rows(): for cell in row: value = cell.value if isinstance(value, str) and value.startswith("="): formula_count += 1 upper = value.upper() if any(token in upper for token in formula_error_tokens): failures.append(f"{sheet.title}!{cell.coordinate} contains a formula error token") elif isinstance(value, str) and value[:1] in {"+", "-", "@"}: failures.append( f"{sheet.title}!{cell.coordinate} starts with a formula-trigger character" ) if formula_count == 0: failures.append("workbook contains no formulas") if "Cost Buildup" in workbook.sheetnames: buildup = workbook["Cost Buildup"] starts: list[int] = [] for row_index in range(1, buildup.max_row + 1): label = buildup.cell(row_index, 1).value if isinstance(label, str) and label.startswith("Cost Buildup:"): starts.append(row_index) if not starts: failures.append("Cost Buildup contains no recognized labor blocks") for block_index, base in enumerate(starts): expected_base = 1 + block_index * 23 if base != expected_base: failures.append( f"Cost Buildup block {block_index + 1} starts at row {base}, expected {expected_base}" ) if buildup[f"B{base + 5}"].value is not None: failures.append(f"Cost Buildup!B{base + 5} must be the blank separator row") if buildup[f"B{base + 22}"].value is not None: failures.append(f"Cost Buildup!B{base + 22} must be the blank block separator") check_formula( failures, buildup, f"B{base + 2}", contains=["'IGCE SUMMARY'!$B$12"], ) if buildup[f"B{base + 2}"].number_format != "0.0000": failures.append( f"Cost Buildup!B{base + 2} must display the aging factor as 0.0000" ) assumptions = payload.get("assumptions", {}) fee_type = str(assumptions.get("fee_type", "")).upper() if fee_type == "CPAF": fee_formula = ( f"=B{base + 16}*('IGCE Summary'!$B$14+" "'IGCE Summary'!$B$15*'IGCE Summary'!$B$16)" ) else: fee_formula = f"=B{base + 16}*'IGCE Summary'!$B$14" formulas = { base + 3: f"=B{base + 1}*B{base + 2}", base + 4: f"=B{base + 3}/2080", base + 6: "='IGCE Summary'!$B$2", base + 7: f"=B{base + 4}*B{base + 6}", base + 8: f"=B{base + 4}+B{base + 7}", base + 9: "='IGCE Summary'!$B$3", base + 10: f"=B{base + 8}*B{base + 9}", base + 11: f"=B{base + 8}+B{base + 10}", base + 12: "='IGCE Summary'!$B$4", base + 13: f"=B{base + 11}*B{base + 12}", base + 14: "='IGCE Summary'!$B$5", base + 15: f"=(B{base + 11}+B{base + 13})*B{base + 14}", base + 16: f"=B{base + 11}+B{base + 13}+B{base + 15}", base + 17: "='IGCE Summary'!$B$13", base + 18: "='IGCE Summary'!$B$14", base + 19: fee_formula, base + 20: f"=B{base + 16}+B{base + 19}", base + 21: f"=B{base + 20}/B{base + 4}", } for row_number, expected_formula in formulas.items(): check_formula( failures, buildup, f"B{row_number}", expected=expected_formula, ) for sheet_name in ("IGCE Summary", "Scenario Analysis", "Rate Validation"): if sheet_name not in workbook.sheetnames: continue sheet = workbook[sheet_name] for row in sheet.iter_rows(): for cell in row: value = cell.value if not isinstance(value, str) or not value.startswith("="): continue for match in COST_B_REF.finditer(value): referenced_row = int(match.group(1)) if (referenced_row - 4) % 23 == 0: failures.append( f"{sheet_name}!{cell.coordinate} uses Cost Buildup row {referenced_row} " "as a cross-sheet input; that row is Aged Annual Wage, not Direct Labor" ) assertions = payload.get("formula_assertions", []) if not isinstance(assertions, list): raise InputError("formula_assertions must be an array") for index, assertion in enumerate(assertions): if not isinstance(assertion, dict) or not isinstance(assertion.get("cell"), str): raise InputError(f"formula_assertions[{index}] must contain a cell string") sheet_name, coordinate = parse_cell_ref(assertion["cell"]) if sheet_name not in workbook.sheetnames: failures.append(f"formula assertion references missing sheet: {sheet_name}") continue contains = assertion.get("contains", []) not_contains = assertion.get("not_contains", []) if not isinstance(contains, list) or not all(isinstance(item, str) for item in contains): raise InputError(f"formula_assertions[{index}].contains must be an array of strings") if not isinstance(not_contains, list) or not all( isinstance(item, str) for item in not_contains ): raise InputError( f"formula_assertions[{index}].not_contains must be an array of strings" ) equals = assertion.get("equals") if equals is not None and not isinstance(equals, str): raise InputError(f"formula_assertions[{index}].equals must be a string") check_formula( failures, workbook[sheet_name], coordinate, expected=equals, contains=contains, not_contains=not_contains, ) failures.extend(text_clipping_audit(workbook)) return failures def find_soffice() -> Path | None: discovered = shutil.which("soffice") if discovered: return Path(discovered) mac_path = Path("/Applications/LibreOffice.app/Contents/MacOS/soffice") return mac_path if mac_path.is_file() else None def recalculate_with_libreoffice(source: Path, executable: Path) -> tuple[tempfile.TemporaryDirectory[str], Path]: temp = tempfile.TemporaryDirectory(prefix="cr-workbook-validation-") temp_root = Path(temp.name) input_dir = temp_root / "input" output_dir = temp_root / "output" input_dir.mkdir() output_dir.mkdir() copied = input_dir / source.name shutil.copy2(source, copied) command = [ str(executable), "--headless", "--convert-to", "xlsx", "--outdir", str(output_dir), str(copied), ] completed = subprocess.run(command, capture_output=True, text=True, timeout=120, check=False) recalculated = output_dir / source.name if completed.returncode != 0 or not recalculated.is_file(): temp.cleanup() detail = (completed.stderr or completed.stdout).strip() raise InputError(f"LibreOffice recalculation failed: {detail or 'no output file'}") return temp, recalculated def close_enough(actual: float, expected: float, tolerance: float) -> bool: return math.isclose(actual, expected, rel_tol=tolerance, abs_tol=max(0.01, tolerance)) def compare_results( workbook: Any, expected: dict[str, Any], tolerance: float, ) -> list[str]: failures: list[str] = [] def compare(reference: str, target: float, label: str) -> None: try: value = cell_value(workbook, reference) except InputError as exc: failures.append(str(exc)) return if isinstance(value, bool) or not isinstance(value, (int, float)): failures.append(f"{label} at {reference} has no calculated numeric value") return if not close_enough(float(value), target, tolerance): failures.append( f"{label} at {reference} is {float(value):.6f}, expected {target:.6f}" ) for line in expected["labor_lines"]: mappings = ( ("workbook_cost_rate_cell", "estimated_cost_rate", "cost rate"), ("workbook_price_rate_cell", "estimated_price_rate", "price rate"), ("workbook_total_cost_cell", "period_cost", "period cost"), ("workbook_total_price_cell", "period_price", "period price"), ) for reference_key, expected_key, label in mappings: if reference_key in line: compare( line[reference_key], line[expected_key], f"{line['name']} {label}", ) for line in expected["non_labor_lines"]: if "workbook_total_cell" in line: compare( line["workbook_total_cell"], line["amount"], f"{line['name']} amount", ) totals = ( ("workbook_fee_bearing_cost_cell", "fee_bearing_cost", "fee-bearing cost"), ("workbook_total_cost_cell", "total_estimated_cost", "total estimated cost"), ("workbook_total_fee_cell", "total_fee", "total fee"), ("workbook_total_price_cell", "total_estimated_price", "total estimated price"), ) for reference_key, expected_key, label in totals: if reference_key in expected: compare(expected[reference_key], expected[expected_key], label) return failures def cached_error_audit(workbook: Any) -> list[str]: failures: list[str] = [] for sheet in workbook.worksheets: for row in sheet.iter_rows(): for cell in row: value = cell.value if isinstance(value, str) and value.startswith("#"): failures.append(f"{sheet.title}!{cell.coordinate} has cached error {value}") return failures def main() -> int: parser = argparse.ArgumentParser( description="Audit a CR workbook and optionally verify formula execution with LibreOffice." ) parser.add_argument("workbook", type=Path, help="Workbook to validate") parser.add_argument("--expected", required=True, type=Path, help="Validation-input JSON") parser.add_argument( "--engine", choices=("auto", "none", "libreoffice"), default="auto", help="Formula execution engine policy", ) parser.add_argument("--tolerance", type=float, default=0.01, help="Relative comparison tolerance") parser.add_argument("--json", action="store_true", help="Emit a JSON result") args = parser.parse_args() if not math.isfinite(args.tolerance) or args.tolerance < 0: print("ERROR: tolerance must be finite and non-negative", file=sys.stderr) return 2 if not args.workbook.is_file(): print(f"ERROR: workbook not found: {args.workbook}", file=sys.stderr) return 2 try: payload = load_payload(args.expected) expected = calculate(payload) formula_workbook = load_workbook(args.workbook, data_only=False) structural_failures = structural_audit(formula_workbook, payload) periods = effective_periods(formula_workbook, expected["periods"], structural_failures) structural_failures.extend(period_coverage_audit(formula_workbook, periods)) cached_view = load_workbook(args.workbook, data_only=True) structural_failures.extend(price_integrity_audit(cached_view)) failures = list(structural_failures) except (InputError, OSError, ValueError) as exc: print(f"ERROR: {exc}", file=sys.stderr) return 2 engine_used: str | None = None engine_note: str temp: tempfile.TemporaryDirectory[str] | None = None try: if args.engine == "none": engine_note = "Formula execution was not requested." else: soffice = find_soffice() if soffice is None: if args.engine == "libreoffice": failures.append("LibreOffice was required but soffice was not found") engine_note = "LibreOffice was required but unavailable." else: engine_note = "Formula execution was not independently verified in Excel or LibreOffice." else: temp, recalculated = recalculate_with_libreoffice(args.workbook, soffice) calculated_workbook = load_workbook(recalculated, data_only=True) failures.extend(cached_error_audit(calculated_workbook)) failures.extend(compare_results(calculated_workbook, expected, args.tolerance)) engine_used = "LibreOffice" engine_note = "LibreOffice formula execution and cached-value comparison ran." except (InputError, OSError, subprocess.SubprocessError, ValueError) as exc: failures.append(str(exc)) engine_note = "LibreOffice execution failed." finally: if temp is not None: temp.cleanup() result = { "status": "pass" if not failures else "fail", "formula_structure": "pass" if not structural_failures else "fail", "independent_recomputation": "pass", "independent_total_estimated_price": expected["total_estimated_price"], "engine": engine_used, "engine_note": engine_note, "failures": failures, } if args.json: print(json.dumps(result, indent=2, sort_keys=True)) else: if failures: print("VALIDATION FAILED") for failure in failures: print(f"- {failure}") elif engine_used: print("Formula structure, independent calculations, and LibreOffice formula execution passed.") else: print( "Formula structure and independent calculations passed. " "Formula execution was not independently verified in Excel or LibreOffice." ) print(f"Independent total estimated price: {expected['total_estimated_price']:.2f}") print(engine_note) return 0 if not failures else 1 if __name__ == "__main__": raise SystemExit(main())
-
-
SKILL.md 19.9 KB
--- name: igce-builder-cr description: > Trigger for: cost-reimbursement IGCE, CR cost estimate, CPFF, CPAF, CPIF, cost-plus estimate, BAA estimate, fixed-fee analysis, award-fee analysis, incentive-fee analysis, proposed CR rate validation, cost-pool buildup, share-ratio scenario, price-reasonableness memo, or fair-and-reasonable analysis. Build auditable CR estimates using BLS OEWS wages, fringe/overhead/G&A/FCCM pools, contract-type-specific fee, GSA CALC+ positioning, and GSA Per Diem travel. Do NOT use for FFP, LH/T&M, grants, or cooperative agreements. Requires the bls-oews, gsa-calc, and gsa-perdiem MCP servers. --- # IGCE Builder: Cost-Reimbursement ## Overview Build an auditable CPFF, CPAF, or CPIF Independent Government Cost Estimate. Estimate allowable-cost layers and fee separately. Preserve the distinction between fee-bearing and non-fee-bearing cost, and never substitute CALC+ ceiling-rate comparisons for cost analysis. Regulatory anchors: FAR 15.404-1, FAR 15.404-4, FAR 16.301 through 16.307, 10 U.S.C. 3322, and 41 U.S.C. 3905. Apply the current regulation, solicitation, and agency supplement. This skill does not make legal determinations. Load supporting files only when needed: - [wrap-rate-presets.md](references/wrap-rate-presets.md) for indirect-cost and fee structures. - [data-source-operations.md](references/data-source-operations.md) before mapping labor or calling BLS, CALC+, or Per Diem. - [workbook-specification.md](references/workbook-specification.md) before creating the workbook. - [professional-product-standard.md](references/professional-product-standard.md) before creating the workbook. - [validation-gates.md](references/validation-gates.md) before and after workbook generation. - [runtime-adaptation.md](references/runtime-adaptation.md) for questions, tools, formula engines, and delivery. ## Operating principle ## Product quality default Build a cost-and-fee model that lets the acquisition team see what changes the estimate. The summary begins with the requirement, CR subtype and form when confirmed, decision supported, estimated cost, fee treatment, material assumptions, scenario range, limitations, and next human action. Use a specific title such as `CPFF Independent Government Cost Estimate — [Requirement]`. Keep rate evidence and source inputs in dedicated sheets, retain a clear fee-bearing versus pass-through distinction, and never use the workbook to originate a fee objective or a fair-and-reasonable conclusion. This skill assembles data and formats analysis. The Contracting Officer owns cost-realism judgments, fair-and-reasonable determinations, fee objectives, negotiation positions, and approval documents. - Use neutral positional language such as `at CALC+ P77 (n=42)` or `above CALC+ P50 by 18%`. - Never originate a determination, negotiation target, evaluation notice, or contractor-responsibility conclusion. - Never invent a clearance, SCIF, OCONUS, specialty-labor, cost-risk, or performance premium. - When the user supplies rationale or a determination, preserve it verbatim and label the resulting document `DRAFT`. ## Permanent correctness gates These gates prevent documented silent wrong answers. Keep them in the front-loaded core. 1. **Workflow B boundary:** On every Workflow B entry, emit the Option A/Option B boundary below before analysis or tool use, then wait. 2. **CALC+ query signature:** Use `/v3/api/ceilingrates/` with `keyword=`. Never use `q=`; it silently returns the full corpus. 3. **Fee basis:** Fee applies only to the user-confirmed fee-bearing cost base. Never apply fee automatically to pass-through ODCs or travel. 4. **CPFF caps:** Under FAR 15.404-4(c)(4)(i), cap CPFF at 15% for experimental, developmental, or research work, 10% for other CPFF work, and apply the separate 6% architect-engineer limitation when relevant. Treat caps as ceilings, not defaults. 5. **CPFF form:** Declare Completion or Term under FAR 16.306(d). Prefer Completion when a definite goal or end product can be estimated; use Term only with a specified level of effort and definite time period. 6. **CPIF shares:** Keep contractor overrun and underrun shares as separate assumptions. Apply min and max fee bounds, and show where a bound stops the share formula. 7. **CPAF range:** Show base-only, assumed-earned, and full-pool fee outcomes. Never hide the award-fee range behind one 85%-earned point. 8. **Aging formula:** Store BLS vintage and contract start as assumptions. Calculate month gap with `VALUE(LEFT(...))` and `VALUE(MID(...))` when dates are stored as `YYYY-MM` text. Do not use `YEAR` on text or rely on `DATEDIF` portability. 9. **Shift coverage:** Derive coverage FTE from required coverage hours and productive hours. At 1,880 hours, one 24x7x365 seat is 4.6596 FTE. Do not multiply 4.2 by 1,880. 10. **Staged questions:** Stage A is decomposition confirmation only. Its response must end immediately after that question, with no Stage B preview. Ask Stage B only after Stage A approval. 11. **Step 8.5:** Run formula-structure audit and independent recomputation. Use a real spreadsheet engine when available; disclose exactly when formula execution was not independently verified. 12. **Credentialed API pacing:** Serialize credentialed federal API calls and leave at least three seconds after one completes before starting the next. Never parallelize keyed calls. Honor longer retry intervals and stop instead of rapid retrying. ## Workflow selection Select the workflow before capability tests. ### Workflow A: structured CR build Use when the user supplies labor, location, staffing, period, and fee type. Execute Steps 1 through 9. ### Workflow A+: SOW/PWS or BAA build Use when the user supplies an unstructured requirement or an approved staffing handoff. For raw requirements, run Step 0 and both staged confirmations. For an approved handoff, consume it without repeating decomposition or Stage A. If a BAA does not declare contract type, explain that CR may fit uncertain research but require the user to select the contract type. Do not self-select CPFF. ### Workflow B: CR rate positioning or memo request Use when the user asks to validate proposed rates, judge cost pools, draft a price-reasonableness memo, or decide whether rates are fair and reasonable. The entire first response must be exactly the boundary block below. Begin with `I can provide` and add no heading, workflow label, preamble, capability note, analysis, or tool call before it. End at `Which option do you choose?` and add nothing after that question. > I can provide positioning data showing where proposed rates sit against CALC+ ceiling rates and BLS market wages. I cannot originate a price-reasonableness memo, fair-and-reasonable determination, cost-realism judgment, or negotiation position. Those are Contracting Officer decisions. > > **Option A: Positioning data only.** I provide per-category CALC+ percentiles and sample size, BLS metro cost buildup, and neutral arithmetic. No verdict or recommendation. > > **Option B: Draft template using your conclusion.** You provide your rationale and determination. I place that text verbatim into a DRAFT template and add benchmark tables. I do not add conclusions or negotiation advice. > > Which option do you choose? After Option A, run the applicable BLS and CALC+ steps and stop at neutral positioning. After Option B, require both rationale and determination before building the draft. Never paraphrase the user's conclusion. ## Pre-flight capabilities When this skill is entered immediately after a numbered Pre-Award Agent pricing selection and the current assistant response has not already shown the orchestrator's outcome preview, emit these exact four lines before intake or a capability check: Begin line 1 with `Recommended outcome:`. Do not precede the block with a heading, acknowledgement, selection recap, routing narration, or code fence. ```text Recommended outcome: Routed IGCE `.xlsx`, separated by confirmed pricing method or hybrid CLIN Includes: auditable labor, indirect, escalation, travel and other-cost build-up, benchmarks, assumptions, formulas, and validation Boundary/default: no contract type is inferred; the user or Contracting Officer must confirm FFP, LH, T&M, a CR subtype, or hybrid routing Next: collect the approved handoff or requirements and the confirmed pricing method ``` This is a routing fallback, not a second preview. Do not repeat it when the orchestrator already rendered the four lines in the current assistant response. If a CR subtype has not been supplied or confirmed, stop after the bounded pricing-method question and return routing control to the orchestrator; the presence of this component skill never selects a CR subtype for the user. Begin useful intake after workflow selection; do not make workbook authoring or provider availability the first response. A read-only or artifact-limited session may still reuse supplied facts, identify missing inputs, and review an approved handoff. Run only the relevant portions of this pre-flight immediately before the first dependent MCP call or before promising or beginning workbook generation. For Workflow B, run it only after the user chooses an option. 1. Call `bls-oews.get_access_status` before any BLS data call. For `limited_fallback`, tell the user `BLS_API_KEY` is not configured and v1 is limited to 25 requests per day and 10 years per query; continue only when the workload fits. A missing status operation means an outdated or incomplete MCP or shared host profile. 2. When travel is in scope, call `gsa-perdiem.get_access_status` before Per Diem data. For `limited_fallback`, tell the user `PERDIEM_API_KEY` is not configured and `DEMO_KEY` is limited to approximately 10 requests per hour. A missing status operation means an outdated or incomplete MCP or host profile. 3. Treat `configured_unverified` as presence only. Classify a later 401/403 as rejected credentials and 429 as rate limiting, not an outage. Never retry automatically or ask for a key in chat. Direct setup to `https://1102tools.com/setup#credentials` and require a restart. 4. Inspect the operations actually available in the session. Match by server and operation schema, not host-generated namespace. 5. Workflows A and A+ require `bls-oews` wage, vintage, SOC, and metro operations plus `gsa-calc` suggestion and benchmark operations. Add `gsa-perdiem` only when travel is in scope. 6. Workflow B requires only the benchmark operations needed for the chosen analysis. Option B also requires a document-authoring capability if the user requests a file. 7. Before workbook creation, require `.xlsx` authoring, Python 3.10+, openpyxl, and the bundled validators. A real spreadsheet engine is preferred but optional when its absence is disclosed. 8. Test only capabilities the active workflow will use. For a build, confirm the BLS vintage at runtime. Test Per Diem only when travel is in scope. Apply the pacing gate to every keyed call. 9. If a capability is missing, look for an equivalent operation from the declared server. Do not bypass the MCP with a hand-built public API call. 10. If still missing, stop at that dependent-work boundary and report whether it appears uninstalled, unauthenticated, unavailable, or outdated/incomplete in the host. Preserve completed intake so it is not requested again after the capability is restored. ## Information to collect Required for a build: - Labor category or task discipline, SOC when known, seniority, FTE or coverage basis, and productive hours. - Performance location and any staffing split by location. - Base and option periods, contract start month, and any partial-year duration. - CR type: CPFF, CPAF, or CPIF. For CPFF, Completion or Term form. - Indirect-rate basis: disclosed estimate or CO-supplied FPRA/FPRR/DCAA-audited rates with date and authority. - Fee structure and fee-bearing classification for labor, travel, subcontracts, and every ODC. Optional with disclosed defaults: - Productive hours 1,880; escalation 2.5%; fringe 32%; overhead 80%; G&A 12%; FCCM 0%. - CPFF fee 8%; CPAF base 3%, pool 7%, assumed earned 85%; CPIF target 8%, contractor overrun and underrun shares 20%, min 3%, max 12%. - No travel or ODCs. Treat missing travel as zero and record that travel was considered. Do not override CO-supplied audited rates with generic defaults. Use audited rates as point estimates, record their effective date and authority, and do not manufacture low/high offsets around them. ## Approved SOW/PWS handoff Treat a user-reviewed table labeled `STAFFING HANDOFF TABLE` as approved input regardless of heading punctuation. 1. Confirm that the declared contract type is CR. For a hybrid, consume only CR CLINs. 2. Preserve approved labor category, SOC, FTE, phase, hours, notes, derivation, and overrides. 3. Use the CLIN handoff for period and deliverable mapping when present. 4. Present contradictions among handoff, requirement, and current instruction in a short table and wait for the user to choose the controlling value. 5. Ask all missing Stage B inputs in one response. Do not rerun decomposition or Stage A unless the user asks to revise staffing. ## Orchestration ### Step 0: decompose raw requirements Run only when no approved handoff is present. 1. Check labor disciplines, staffing basis, location, period, deliverables, and travel. Performance location is a hard stop before data calls. If three or more elements are missing from a short requirement, ask whether to continue with labeled assumptions or obtain clarification. 2. Separate the requirement into task areas with discipline, complexity, cadence, deliverable, and staffing basis. 3. Perform agency and technical-domain triage before SOC mapping. 4. Map each task to candidate labor categories and SOCs using [data-source-operations.md](references/data-source-operations.md). Use multiple candidates when mapping is ambiguous. 5. Estimate FTE ranges only when the scope supplies a defensible basis. Otherwise list the missing sizing facts. 6. **Stage A:** Present the decomposition, then ask only whether the user confirms or amends the task areas, labor categories, and SOC mappings. This must be the response's only question. Do not ask whether to proceed on assumptions, select a contract or fee type, provide a location, or supply any other Stage B input, even when those items are hard stops. Do not preview Stage B. The final sentence must be the decomposition-confirmation question. Stop immediately after its question mark. 7. **Stage B:** After approval, batch fee type, CPFF form if applicable, indirect-rate basis, performance metro, start, period, NAICS/PSC, coverage, travel, ODCs, and fee-bearing classifications. End at the question and wait. Skip both stages only when the user supplied the full structured build input. ### Step 0.5: convert coverage to staffing ```text annual coverage hours = covered seats * hours per day * coverage days per year coverage FTE = annual coverage hours / productive hours per FTE ``` At 1,880 productive hours, one 24x7x365 seat is `8,760 / 1,880 = 4.6596 FTE`; two seats are 9.3191. One 8x5x52 seat is 1.1064. Keep four decimals in calculations and disclose rounding. Add overlap, leave-backfill, training, or turnover reserves only with a separate user-approved basis. ### Step 1: map labor categories to SOCs Use the mapping and fallbacks in [data-source-operations.md](references/data-source-operations.md). Map program managers by domain. Use BLS P25/P50/P75 for junior/mid/senior. Preserve user-approved mappings and label fallbacks. ### Step 2: pull and age BLS wages 1. Call `detect_latest_year` and record the returned vintage. 2. Resolve the current metro code before wage queries. Query metro, then state, then national only when the more specific level is unavailable. 3. Pull the full wage distribution. Flag cap proximity and flat P75/P90 tails. 4. Calculate aging from the returned vintage to contract start, store every assumption in the workbook, and avoid double-counting option-year escalation. ### Step 3: build cost pools and fee For each scenario and labor line: ```text aged annual wage = BLS wage * aging factor direct hourly = aged annual wage / 2,080 fringe = direct hourly * fringe rate labor plus fringe = direct hourly + fringe overhead = labor plus fringe * overhead rate subtotal = labor plus fringe + overhead G&A = subtotal * G&A rate FCCM = (subtotal + G&A) * FCCM rate estimated cost rate = subtotal + G&A + FCCM ``` Classify each non-labor item before fee: ```text total estimated cost = fee-bearing cost + non-fee-bearing cost fee = fee formula applied only to fee-bearing cost total estimated price = total estimated cost + fee ``` Use [wrap-rate-presets.md](references/wrap-rate-presets.md) for CPFF, CPAF, and CPIF formulas and scenario rules. Do not convert CPFF fixed fee into a cost-reimbursement percentage that changes with actual cost; workbook scenarios are estimating outcomes, not contract payment mechanics. ### Step 4: position rates against CALC+ Use `igce_benchmark` for statistics-only queries. Use `keyword_search` only when category buckets are needed. For thin or ambiguous pools, use title-match and experience-match pools and report each sample size. Compare CR estimated-cost-plus-fee separately from the underlying cost rate. Use neutral arithmetic only. ### Step 5: calculate travel Use [data-source-operations.md](references/data-source-operations.md) for locality, fiscal-year, and first/last-day rules. A zero-night trip uses one already-discounted first/last-day M&IE amount. Confirm whether travel is fee-bearing; default pass-through travel to non-fee-bearing when the user does not direct otherwise, and disclose that assumption. ### Step 6: handle multiple locations - Use separate rows when headcount by location is known. - Use a weighted wage when percentages are supplied. - Use the highest applicable median only as a conservative disclosed fallback when no allocation exists. ### Step 7: calculate periods and scenarios Prorate partial periods by months. Escalate labor and travel from the aged base-year amount. Show low, mid, and high cost-pool cases. For CPAF, show three earned-fee outcomes. For CPIF, show the cost-scenario by fee-outcome matrix and bound crossings. Never classify pass-through cost differently across scenarios. ### Step 8: build the workbook Follow [professional-product-standard.md](references/professional-product-standard.md) and [workbook-specification.md](references/workbook-specification.md). Use formulas for calculated values, numeric zero for placeholders, and explicit source and assumption cells. Keep editable assumptions visually distinct. Keep formal controls intact while making the default summary and print experience concise and decision-centered. ### Step 8.5: validate Follow [validation-gates.md](references/validation-gates.md). 1. Save a raw-input JSON sidecar. 2. Run `scripts/validate_workbook.py <workbook> --expected <sidecar> --engine auto`. 3. Fix every formula-structure or recomputation failure and rerun. 4. If LibreOffice or another real engine is available, execute formulas and compare cached values with the independent Python result. 5. If no engine is available, say: `Formula structure and independent calculations passed. Formula execution was not independently verified in Excel or LibreOffice.` 6. Visually inspect all sheets for clipping, broken formats, unreadable notes, and empty or misleading tables. Never call openpyxl-only inspection recalculation or proof of formula execution. ### Step 9: deliver Use the host's artifact-delivery capability when available. Otherwise save to the requested or current working directory and report the absolute path. Do not invent host-specific paths or commands. See [runtime-adaptation.md](references/runtime-adaptation.md). ## Out of scope - DCAA proposal audits, incurred-cost audits, or validation of contractor accounting systems. - Contractor responsibility, source selection, negotiation objectives, or cost-realism determinations. - OCONUS per diem without the appropriate Department of State or DoD source. - FFP, LH/T&M, grants, and cooperative agreements. --- *MIT © James Jenrette / 1102tools. Source: github.com/1102tools-dev/federal-contracting-skills* -
test.md 2.6 KB
# August 2026 Modernization Test Record Date: 2026-08-21 Historical April tests remain in [testing.md](testing.md). This file records tests against the portable, progressive-disclosure version. ## Clients and models - Claude Code CLI 2.1.126, canonical `claude-opus-5`, high effort, explicit `/igce-builder-cr` invocation. - Codex CLI 0.149.0-alpha.4, GPT-5.6 Sol, xhigh, explicit `$igce-builder-cr` invocation. - Local Python 3 with openpyxl and LibreOffice headless. ## Behavior results | Test | Expected | First run | Final result | |---|---|---|---| | CPFF fair-and-reasonable memo request | Exact Option A/Option B boundary and no data call | Claude added one workflow-label sentence | Instruction strengthened; exact Claude rerun and Codex run passed | | Raw exploratory-research BAA with no contract type | Do not self-select CPFF; decompose; Stage A only | Claude bundled an assumptions-or-hold choice into Stage A | Instruction strengthened; exact rerun ended at decomposition confirmation and passed | | Keyed federal APIs | No calls in boundary or Stage A tests | None | Pass | ## August 23 host-capability correction Runtime adaptation now follows a governing host spreadsheet workflow and its hard stops before choosing Python/openpyxl. When the supported workbook path is unavailable, the skill must disclose structured fallback mode before artifact-specific approval and may deliver only a structured JSON specification plus Markdown or CSV tables. Installed-client degradation replay remains an agent-package gate. ## Workbook fixture A one-labor-category CPFF fixture with non-fee-bearing travel was generated outside the repository. Results: - Formula-structure audit: pass - Independent cost, fee, and estimated-price recomputation: pass - LibreOffice formula execution and cached-value comparison: pass - Independent total estimated price: matched within validator tolerance Fault injection: - Replacing the month-gap formula with `DATEDIF` was rejected. - Referencing the aged-annual-wage row as a cross-sheet rate was rejected. ## Static checks - Skill frontmatter validator: pass - Core length: 238 lines at test time - Python compile and command-line help: pass - Core-to-reference links: pass ## Open coverage - A full multi-period CPAF workbook and CPIF 3-by-3 scenario workbook were not generated in this modernization pass. - Formula assertions for CPAF pool outcomes and CPIF min/max bound crossings remain required in each build's validation sidecar. - Claude Code implicit activation and post-compaction replay were not treated as deterministic test surfaces; use explicit invocation for CLI evaluation. -
testing.md 21.6 KB
# IGCE Builder CR: Testing Record # Part 1: For Federal Acquisition Users ## The bottom line Four rounds of testing for the Cost-Reimbursement skill across April 2026: Wave 1 inherited the full patch set from FFP Wave 5 and LH/T&M Wave 2 without direct CR scenarios. Wave 2 ran six scenarios on Claude Opus 4.7 across two rounds (three lazy-prompt, three detailed-prompt), shipping 14 patches plus 11 universal-principle patches ported across all 3 IGCE skills (Wave 3). Wave 4 ran 4 cold tests targeting untested territory (CO-supplied DCAA rates, FCCM layer, pass-through ODCs with fee implications, CPFF Completion vs Term Form), shipping 4 universal patches including one critical correctness fix. 4 regression agents validated all patches hold with zero regressions. The skill now produces auditable CPFF (Completion or Term Form), CPAF, and CPIF workbooks end-to-end with layered cost pool buildup, Fee-Bearing vs Non-Fee Cost separation, DCAA-rate override support, FCCM treatment, fee structure analysis, and ai-boundaries-compliant narrative. - **Wave 1** (inherited): six universal patches from FFP Wave 5 and LH/T&M Wave 2 applied without direct CR scenarios. ai-boundaries v2 gate, pre-flight MCP check, Step 0 two-stage validation gate (with fee type as a Stage B parameter), DoD installation to GSA per diem crosswalk, multi-destination travel sheet, CLI recalc fallback, CALC+ query optimizations, FY rollover guidance. - **Wave 2** (six scenarios validated, Claude Code CLI, Opus 4.7): three lazy-prompt scenarios plus three detailed-prompt scenarios run with realistic user framing to exercise decomposition, parameter prompting, and fee-type selection across all three fee types. Lazy round: 22 findings, 14 patches shipped. Detailed round: 31 additional findings, 11 triaged as universal patches shipped to all 3 IGCE skills (see Wave 3). - **Wave 3** (universal patches derived from CR Wave 2 detailed round): 11 universal-principle patches shipped identically to FFP, LH/T&M, and CR. Inherited across all 3 skills; not re-tested per-skill. - **Wave 4** (4 cold tests on post-Wave-3 skill, 4 patches shipped, 4 regression tests passed): targeted untested territory from "What has NOT been tested" list. Fee-on-ODCs critical correctness fix (CPAF test showed $959K over-fee avoided across 5 years; CPIF test showed $120K avoided across 4 years; CPFF test showed $29K avoided across 3 years). CPFF Completion vs Term Form prescription with FAR 16.306(d)(1) vs (d)(2) citation and decision heuristic. CO-supplied DCAA rates override rule (use FPRA rates instead of 32/80/12 defaults when CO supplies). FCCM (FAR 31.205-10 / CAS 414) as distinct cost pool layer between G&A and Total Estimated Cost. Regression agents validated all 4 patches held across CPFF / CPAF / CPIF with FPRA rates, FCCM > 0, and pass-through ODCs. ## Scenarios tested and how reliably they work | Scenario | Fee type | Prompt style | Result | |---|---|---|---| | CPFF biomedical research at NIH Bethesda (PhD biomedical scientists, no travel, base + 3 OYs) | CPFF | Lazy: "price an NIH research contract, 4 PhDs, base plus options" | Reliable after Wave 2 patches. Medical Scientist SOC (19-1042) added. Cost pool buildup at research-lab defaults. 85% assumed earned gated. | | CPAF managed services at civilian agency (10-person team, CALC+ rate validation, base + 2 OYs) | CPAF | Lazy: "build a CR IGCE for a managed services contract with award fee" | Reliable after Wave 2 patches. 3-scenario fee view (base only, target with 85% earned, ceiling with full pool) shown in Summary. | | CPIF Oak Ridge DOE engineering (asymmetric share ratio, bound-crossing variance, 6 LCATs, base + 4 OYs) | CPIF | Lazy: "CPIF IGCE at Oak Ridge, 80/20 over and 50/50 under, complex work" | Reliable after Wave 2 patches. Asymmetric share ratios split into contractor_share_over and contractor_share_under. ±25% bound-crossing variance documented. | | CPFF AFRL BAA (Dayton) | CPFF 8% | Detailed prompt: "cpff for a BAA with AFRL out of Wright-Patt. R&D advanced materials characterization..." | Valid workbook, $5.61M 5-yr. Workflow A+ clean. FY rollover patch worked. Wright-Patt → Dayton crosswalk confirmed. 9 findings. | | CPAF HHS Claims (DC+Baltimore) | CPAF 3%+7% | Detailed prompt: "cpaf igce for HHS O&M claims processing..." | Valid workbook, $24.6M 5-yr. Multi-metro labor split (8 DC / 4 Baltimore). 3-scenario fee view confirmed. 10 findings. | | CPIF Sandia RF (Albuquerque) | CPIF 7.5% target, 80/20 over, 70/30 under | Detailed prompt: "cpif for Sandia, 8 RF hardware engineers..." | Valid workbook, $12.27M 3-yr. Asymmetric share ratio confirmed. DOE crosswalk confirmed. 12 findings. | ## Manual-verification checklist Scan every CR IGCE output for these before using in a contract file: **1. Fee type declared in Summary row 5.** CPFF, CPAF, or CPIF label is mandatory. Fee math downstream cascades from this cell. **2. Cost pool buildup is layered, not collapsed.** Direct Labor → Fringe → Labor+Fringe → Overhead → Subtotal → G&A → Total Cost → Fee → Total Price. Methodology must explain each layer. **3. Statutory fee caps enforced.** R&D fee cannot exceed 15% of estimated cost per 10 USC 3322(a). Non-R&D practical ceiling is 10%. If fee exceeds these, flag and reduce. **4. CPIF share ratios asymmetric by default.** Most real CPIF agreements have different over and under share ratios (e.g., 80/20 over, 50/50 under). The assumption block exposes both as separate variables. **5. CPIF bound-crossing documented.** When the overrun variance is wide enough that fee hits the min bound, or underrun variance hits the max bound, Methodology must explicitly say "share ratio stops applying at this cost level." **6. CPAF shows 3 fee scenarios, not 1.** Summary must show: (a) base fee only (worst earned), (b) base + 85% pool (target), (c) base + full pool (ceiling). Single-point assumption hides range from CO. **7. ai-boundaries gate held.** First response to "is this CR rate reasonable" must emit the refusal template, not a determination. ## What the skill does not do - **It does not produce FFP or LH/T&M estimates.** Use IGCE Builder FFP or IGCE Builder LH/T&M. - **It does not substitute for a contracting officer's price reasonableness determination.** IGCE is an estimate; the CO makes the determination per FAR 15.404. - **It does not enforce agency-specific fee policies.** Some agencies cap CR fee below 10 USC statutory limits; skill flags the statutory cap only. - **It does not produce a formal DCAA-compliant cost proposal review.** IGCE is the government-side estimate; DCAA audits the contractor's proposed rates separately. - **It has not been tested on:** BAA cooperative agreements under FAR 35.016 with non-standard fee structures, Termination for Convenience cost estimation, CR-to-FFP conversion modeling, or OCONUS CR builds. --- # Part 2: For Developers and Technical Reviewers ## Testing methodology ### Scenarios Three scenarios designed to exercise distinct CR mechanics across fee types: - **S1 (CPFF, biomedical research):** NIH Bethesda, 4 PhD medical scientists, no travel, base + 3 OYs. Lazy prompt: "price an NIH research contract, 4 PhDs, base plus options." Exercises Medical Scientist SOC mapping (19-1042 vs 19-1099 Life Scientists All Other), NIH-domain cost pool defaults, CPFF 8% fixed fee, statutory 15% R&D cap awareness, no-travel Sheet 5 handling. - **S2 (CPAF, managed services):** Civilian agency, 10-person team, 4 travel destinations, CALC+ rate validation, base + 2 OYs. Lazy prompt: "build a CR IGCE for a managed services contract with award fee." Exercises CPAF 3-scenario fee view (base/target/ceiling), assumed-earned gating, civilian-agency cost pool defaults, multi-destination Sheet 5 parameterization. - **S3 (CPIF, Oak Ridge DOE engineering):** 6 LCATs (Mechanical, Electrical, Chemical, Nuclear Engineers, PM, Admin), asymmetric 80/20 over and 50/50 under share ratios, ±10% baseline and ±25% bound-crossing variance, base + 4 OYs. Lazy prompt: "CPIF IGCE at Oak Ridge, 80/20 over and 50/50 under, complex work." Exercises CPIF asymmetric share ratio support, bound-crossing documentation, DOE M&O cost pool defaults, DOE lab per diem crosswalk (Oak Ridge → Knoxville TN). Each scenario had a 14-point binary assertion matrix covering skill activation, fee type selection, cost pool layering, rate validation, FAR citation completeness, workbook structural integrity, methodology completeness, and lazy-prompt recovery (did the skill prompt for missing inputs rather than guess). ### Environment - Claude Code CLI, fresh conversation per scenario, Opus 4.7 - Local `~/.claude/skills/igce-builder-cr/SKILL.md` post-Wave 1 inheritance - All three scenarios completed in a single worker pass without "continue" (post-inheritance skill was slim enough) ### Grading Grader read worker's final response plus produced xlsx. Workers not coached. Assertions graded binary pass/fail. Worker self-critiques incorporated when corroborated by direct observation. ## Wave 1 (inherited, not directly tested on CR) All universal patches derived from FFP Wave 5 and LH/T&M Wave 2 testing applied to CR at Wave 1: - **ai-boundaries positioning (v2 gate):** Workflow B Step 0 token-scan + verbatim refusal template. Skill does not originate "fair and reasonable" determinations, price reasonableness memos, or negotiation recommendations. - **Pre-flight MCP dependency check:** validates bls-oews, gsa-calc, gsa-perdiem tools and API keys before any workflow runs. - **Step 0 two-stage validation gate:** Stage A (decomposition) + Stage B (build parameters including fee type CPFF/CPAF/CPIF) as separate AskUserQuestion calls. Skip for Workflow A with structured inputs. - **DoD installation to GSA per diem crosswalk:** 15-row table mapping military installations to GSA civilian localities. - **Multi-destination travel sheet:** Sheet 5 parameterized for M destinations, Sheet 1 Travel SUMs across blocks. - **CLI recalc fallback:** Python expected-total check when LibreOffice recalc.py unavailable. - **Step 9 environment fork:** delivery path varies by environment (claude.ai / Claude Code CLI / macOS Desktop with Numbers). - **CALC+ query optimizations:** keyword_search to igce_benchmark for stats-only; tier-matched keywords to avoid false divergence flags. - **FY rollover guidance:** if contract PoP start within 6 months of next FY, query both and document refresh on publication. - **Raw Data sheet granularity:** summary tables with query parameters, not raw JSON dumps. ## Wave 2 results (lazy-prompt validated) | Scenario | Score | Fee type | |---|---|---| | S1 CPFF biomedical research | 14/14 | CPFF | | S2 CPAF managed services | 14/14 | CPAF | | S3 CPIF Oak Ridge engineering | 14/14 | CPIF | | **Total** | **42/42 (100%)** | — | ## Wave 2 findings: 22 surfaced, 14 patched ### Universal patches (horizontal, ported to FFP and LH/T&M) 1. **Installation to GSA locality crosswalk expanded with 6 DOE labs.** Oak Ridge/Y-12 to Knoxville, LANL to Santa Fe, Hanford/PNNL to Richland, Sandia to Albuquerque, LLNL to Oakland-Fremont, INL to Idaho Falls. Prevents empty per diem lookups for DOE R&D scope. 2. **BLS MSA URL fallback for metros outside list_common_metros.** Worker hit this in S1 when the NIH Bethesda metro wasn't in the common-metros list. Skill now directs worker to resolve MSA code via https://www.bls.gov/oes/current/msa_def.htm rather than silently falling back to state wages. 3. **Workflow A ambiguous-input rule.** Lazy prompts like "4 PhDs" without discipline triggered worker guessing. Skill now requires AskUserQuestion for ambiguous required inputs before pulling data. 4. **Step 9 env fork with macOS Excel/Numbers branch.** Claude Code CLI with Excel or Numbers installed can skip the Python-side expected-total check; open triggers recalc via system handler. 5. **BLS wage-cap 10% proximity rule.** When chosen percentile lands within 10% of the $239,200 cap (at or above $215,280 annual or $103.50 hourly), Methodology must flag for CO review. 6. **Shift coverage upfront in Information to Collect.** Added as Optional Input row so worker asks about 24x7/16x7/12x5 before Step 0.5 is needed. 7. **Methodology depth guidance.** Target 8-12 sections, 2-4 sentences each, readable in 3 minutes. Longer than 14 sections usually means restating Sheet 1-4 data. ### CR-specific patches 8. **SOC 19-1042 Medical Scientist added to Research/Science table.** S1 worker had to improvise between 19-1099 (Life Scientists All Other) and no-match for PhD biomedical. Medical Scientists, Except Epidemiologists is the correct SOC for NIH/pharma PhD biomedical researchers. 9. **Block layout parameterized by fee type.** Sheet 2 block size varies: CPFF = 19 rows, CPAF = 21 rows (adds Base Fee Rate + Award Pool Rate + Assumed Earned %), CPIF = 23 rows (adds Target Fee Rate + Share Ratio Over + Share Ratio Under + Min Fee + Max Fee). Assumption block row ranges: CPFF rows 2-13, CPAF rows 2-15, CPIF rows 2-17. 10. **Asymmetric CPIF share ratio.** Single share_ratio variable split into contractor_share_over and contractor_share_under. Real CPIF agreements frequently asymmetric (80/20 over, 50/50 under); exposing both directions separately lets the CO see each leg independently. 11. **CPIF bound-crossing variance.** Baseline ±10% variance supplemented with ±25% or wider variance that crosses the min/max fee bounds. Methodology now documents when share ratio stops applying. 12. **CPAF 3-scenario fee view.** Summary shows (a) base only 3% worst, (b) base + 85% pool 8.95% target, (c) base + full pool 10% ceiling. Prevents single-point 85%-earned estimate hiding the range. ### Editorial fixes 13. **Rate Validation status text neutralized.** "Needs explicit justification" replaced with "Position outside ±25% band; document stacked factors in Methodology" (preserving the ±25% CR threshold). 14. **Sheet 5 travel skip-or-include contradiction resolved.** Prior copy said "skip if no travel" in one place and "include stub" in another. Now consistent: always include sheet, show 'Travel Not Applicable' text when no travel. 15. **Stage A/B skip condition sharpened.** Skip when user provides all four: LCATs with discipline, location with metro, FTE counts, PoP. If any ambiguous or missing, run the gate. 16. **igce_benchmark promoted to default.** `mcp__gsa-calc__igce_benchmark` is now the default tool for Workflow A rate validation; keyword_search reserved for example-rate or labor-category bucket needs. 17. **NAICS/PSC proactive ask.** Step 0 Stage B parameter question list now explicitly includes NAICS/PSC alongside fee type, metro, contract start. ### Dropped (too scenario-specific, not worth horizontal ship) - BAA cooperative-agreement fee rules (agency-specific, not generalizable) - OCONUS cost pool adjustments (single OCONUS scenario insufficient data) - Subcontractor fee-on-fee prohibition edge case (vendor-side rule, not IGCE) - Termination for Convenience cost estimation (separate activity) - DCAA forward-pricing rate proposal templates (not IGCE scope) - Modular budget patterns from NIH R01 (belongs to Grants Budget Builder) - Limitation on Subcontracting for small business set-asides (pre-award check, not IGCE) - Award Fee Evaluation Factor weighting (performance monitoring, not IGCE) ## What has NOT been tested on CR - BAA cooperative agreements under FAR 35.016 with non-standard fee structures - Termination for Convenience cost estimation - CR-to-FFP conversion modeling (pricing legacy cost-plus scopes as FFP) - OCONUS CR builds (per diem covers CONUS only) - 24x7 shift coverage with CR fee math (Step 0.5 untouched since inheritance) - Custom cost pool rates supplied by CO (skill has rule; no direct test) - Sonnet 4.6 parity on Wave 2 patches (all runs Opus 4.7) ## Wave 3 (universal patches derived from CR Wave 2 detailed-prompt round) **Wave 3** (Universal patches derived from CR Wave 2 detailed-prompt round): The detailed-prompt scenarios surfaced 31 additional evaluator findings beyond the lazy round. 11 were triaged as universal-principle patches worth shipping to all 3 IGCE skills; the rest were scenario-specific or architectural (deferred). Patches applied: page_size=0 deprecation, 24x7 math contradiction resolved, DATEDIF on text cells fixed, day-trip M&IE double-discount corrected (correctness bug shipping 25% low), aged-wage row placement explicit, Sheet 2 hourly vs Sheet 1 annual clarified, BLS flat-tail detection rule, installation crosswalk expanded with 6 DoD/DOE test ranges, SOC 17-2199 fallback documented, same-metro TDY proximity check, stacked factors term enumerated. Status: inherited patches across FFP / LH-TM / CR identically. ## Wave 4 (4 cold tests targeting untested territory, 4 patches shipped, 4 regression tests) Fourth wave ran 4 cold sub-agent tests on post-Wave-3 skill, then ran 4 regression agents after patches landed. Scenarios were deliberately chosen to exercise items from the Wave 2/3 "not tested" list: CO-supplied DCAA rates, FCCM layer, heavy pass-through ODCs with fee implications, and the CPFF Completion vs Term Form distinction. ### Cold-test scenarios | Scenario | Fee type | Trigger | Finding | |---|---|---|---| | GTRI DARPA neuromorphic R&D, $180K chip samples + $240K cloud as pass-through | CPFF | CPFF Completion vs Term Form ambiguity + fee-on-ODCs trap | Skill was silent on (d)(1) vs (d)(2); skill implicitly fee'd all ODCs | | FEMA Booz Allen CPFF with FPRA (37.8/52.1/11.3/0.22) | CPFF | CO supplies DCAA-audited rates; FCCM non-zero | Skill reverted to 32/80/12 defaults; no FCCM layer | | IRS GDIT modernization with $10.9M 5-year pass-through ODCs (Azure, Snowflake, Splunk, security tools) | CPAF | Fee-on-ODCs trap at scale | Skill would have over-fee'd by ~$1M across 5 years if fee applied to TEC | | NASA KSC Jacobs CPIF with FPRA + FCCM + $415K/yr pass-through ODCs + asymmetric 75/25 over, 55/45 under | CPIF | All 4 patches in one scenario | Every patch fired correctly | ### Patches shipped (Wave 4) | # | Patch | Section affected | Trigger | Severity | |---|---|---|---|---| | 1 | **Fee-Bearing Cost vs Non-Fee Cost split** with explicit fee formula applying only to Fee-Bearing | Step 3 cost pool buildup | Every CR build with pass-through ODCs was silently over-fee'd if fee applied to TEC | **Critical correctness fix** | | 2 | **CPFF Completion Form (FAR 16.306(d)(1)) vs Term Form (FAR 16.306(d)(2))** prescription with decision heuristic and mandatory citation | Step 3 fee structure, Stage B gate | Skill cited FAR 16.306 without subparagraph; models guessed inconsistently between Completion and Term | Universal structural gap | | 3 | **CO-supplied DCAA rates override rule** (use FPRA when CO supplies, do not revert to defaults) | Optional Inputs row | Skill had default 32/80/12 but no rule for when CO supplies audited rates | Universal structural gap | | 4 | **FCCM (FAR 31.205-10 / CAS 414) as distinct cost pool layer** applied to (Subtotal + G&A) | Step 3 buildup, scenario analysis, Optional Inputs | Skill missing this layer entirely; DCAA-audited contractors with CASB Disclosure Statements routinely have non-zero FCCM | Universal structural gap | ### Regression validation (4 agents, zero new gaps) All 4 regression agents ran cold against the post-patch skill on scenarios designed to stress the 4 patches: - **GTRI DARPA neuromorphic CPFF Term Form, fee-on-ODCs at $420K pass-through:** Term Form declared in Summary cell B5 with full rationale. Fee = 7% × $8.88M Fee-Bearing = $621,922. If fee had been on TEC, would have been $651,322. Over-fee avoided: $29,400 across 3 years. Both patches fired. - **FEMA Booz Allen CPFF with FPRA (37.8/52.1/11.3/0.22):** All 4 FPRA layers applied in order. FCCM visible as distinct layer between G&A and TEC. Methodology Section 4 titled "Cost Pool Basis: CO-Supplied DCAA Rates per FPRA." Zero reversion to 32/80/12. Both patches fired. - **IRS GDIT CPAF with $10.9M 5-year pass-through ODCs:** Fee-Bearing Cost $42.6M, Non-Fee Cost $10.9M separated in Summary. Fee at 8.8% target on Fee-Bearing only = $3.75M. Naive fee on full TEC would have been $4.71M. Over-fee avoided: $959,200 across 5 years (lands within 4% of the test spec's ~$1M benchmark). All 3 CPAF fee scenarios (base/target/ceiling) correctly applied to Fee-Bearing only. Patch fired. - **NASA KSC Jacobs CPIF with FPRA + FCCM + pass-through ODCs + asymmetric share ratios:** All 4 patches fired simultaneously. FPRA rates (35.2/78.4/9.6/0.31) used. FCCM layered. Fee on Fee-Bearing only, over-fee avoided $120K across 4 years. Term Form prompt correctly did NOT fire (CPIF, not CPFF). Asymmetric share ratios 75/25 over, 55/45 under held. Bound-crossing variance documented. No regressions. No new universal structural gaps surfaced. Two minor editorial observations (FCCM-adds-1-row footnote on Sheet 2 block-size table, Stage B gate-skipping criteria could specify "fee form also required") deliberately skipped per universal-only discipline; both are documentation polish that the model handled correctly in practice. ### Bottom line: fee-on-ODCs was the largest silent correctness bug in the CR skill Across the 4 regression scenarios, the Fee-Bearing vs Non-Fee Cost split prevented a combined $1.1M of silent over-fee ($29K + $959K + $120K, excluding the FPRA scenario which had no ODCs). Before the patch, any CR IGCE with pass-through ODCs was applying fee to the full Total Estimated Cost, which contradicts standard CR fee practice where fee bears only on contractor execution (labor, burdens, travel) and not on pass-through items. The patch codifies this explicitly with a formula prescription and a CRITICAL call-out. --- *Testing record prepared April 2026 by James Jenrette / 1102tools. Four waves documented: Wave 1 inherited, Wave 2 six scenarios (lazy plus detailed prompts), Wave 3 universal patches, Wave 4 targeted untested territory with 4 patches including critical fee-on-ODCs correctness fix. MIT licensed. Source: github.com/1102tools-dev/federal-contracting-skills.*
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.