Consolidation Upstream NciBusiness & Domain Workflows
Working environment structure
environment/How the environment is built and run5 filesVisibletests/Tests and grading material the agent never sees5 files
FROM python:3.11-slim
WORKDIR /app
ENV PYTHONUNBUFFERED=1
RUN mkdir -p /logs/artifacts
COPY consolidation/ /app/consolidation/
COPY run_engine.py /app/run_engine.py
VOLUME ["/logs/artifacts"]
# Consolidation engine package
def consolidate(scenario):
'''
Consolidate parent and subsidiary balances.
The engine applies standard intercompany elimination entries:
- Revenue and COGS are reduced by the total intercompany sale amount.
- Unrealized profit in ending inventory is deferred.
- Prior-period unrealized profits that have been sold externally are
recognized by reducing COGS and increasing retained earnings.
'''
parent = scenario['parent']
sub = scenario['subsidiary']
ownership = scenario['ownership']
sales = scenario.get('intercompany_sales', [])
beginning = scenario.get('beginning_unrealized_profits', [])
total_intercompany_revenue = sum(s['sale_amount'] for s in sales)
total_unrealized_profit = 0.0
nci_adjustment = 0.0
for s in sales:
profit = s['gross_profit'] * s['remaining_in_inventory']
total_unrealized_profit += profit
if s['direction'] == 'upstream':
nci_adjustment += profit * (1.0 - ownership)
parent_re_adjustment = total_unrealized_profit
# Recognize prior-period deferred profits that have now been sold
# externally. This reduces current COGS and restores retained earnings.
beginning_realized = 0.0
beginning_re_credit = 0.0
for b in beginning:
amount = b['amount']
beginning_realized += amount
beginning_re_credit += amount
revenue = parent['revenue'] + sub['revenue'] - total_intercompany_revenue
cogs = (
parent['cogs']
+ sub['cogs']
- total_intercompany_revenue
+ total_unrealized_profit
- beginning_realized
)
inventory = parent['inventory'] + sub['inventory'] - total_unrealized_profit
retained_earnings = (
parent['retained_earnings']
+ sub['retained_earnings'] * ownership
- parent_re_adjustment
+ beginning_re_credit
)
nci = sub['retained_earnings'] * (1.0 - ownership) - nci_adjustment
return {
'retained_earnings': retained_earnings,
'nci': nci,
'inventory': inventory,
'revenue': revenue,
'cogs': cogs,
}
VISIBLE_SCENARIOS = [
{
'name': 'no_intercompany',
'parent': {
'revenue': 1000.0,
'cogs': 600.0,
'inventory': 200.0,
'retained_earnings': 500.0,
},
'subsidiary': {
'revenue': 500.0,
'cogs': 300.0,
'inventory': 100.0,
'retained_earnings': 200.0,
},
'ownership': 0.8,
'intercompany_sales': [],
},
{
'name': 'downstream_full',
'parent': {
'revenue': 1000.0,
'cogs': 600.0,
'inventory': 200.0,
'retained_earnings': 500.0,
},
'subsidiary': {
'revenue': 500.0,
'cogs': 300.0,
'inventory': 100.0,
'retained_earnings': 200.0,
},
'ownership': 0.8,
'intercompany_sales': [
{
'direction': 'downstream',
'sale_amount': 100.0,
'gross_profit': 40.0,
'remaining_in_inventory': 1.0,
}
],
},
{
'name': 'upstream_full_wholly_owned',
'parent': {
'revenue': 1000.0,
'cogs': 600.0,
'inventory': 200.0,
'retained_earnings': 500.0,
},
'subsidiary': {
'revenue': 500.0,
'cogs': 300.0,
'inventory': 100.0,
'retained_earnings': 200.0,
},
'ownership': 1.0,
'intercompany_sales': [
{
'direction': 'upstream',
'sale_amount': 100.0,
'gross_profit': 40.0,
'remaining_in_inventory': 1.0,
}
],
},
]
#!/usr/bin/env python3
import json
import sys
from pathlib import Path
sys.path.insert(0, "/app")
from consolidation.engine import consolidate
from consolidation.scenarios import VISIBLE_SCENARIOS
def main():
results = []
for scenario in VISIBLE_SCENARIOS:
result = consolidate(scenario)
results.append({"name": scenario["name"], "result": result})
print(f"{scenario['name']}: {result}")
out_dir = Path("/logs/artifacts")
out_dir.mkdir(parents=True, exist_ok=True)
with open(out_dir / "results.json", "w") as f:
json.dump(results, f, indent=2)
if __name__ == "__main__":
main()
# Consolidation Upstream NCI
You are given a consolidation accounting engine in `/app/consolidation/engine.py`. The engine combines a parent and subsidiary and attempts to eliminate intercompany inventory sales and unrealized profit.
The engine passes the example scenarios in the repository, but it does not produce correct consolidated balances for every valid scenario. The verifier will test it against a broader set of cases, including intercompany inventory sales in both directions, non-controlling interests at various ownership percentages, and prior-period intercompany inventory profits that are realized in the current period.
## Your task
Inspect the engine and the scenario format, fix the consolidation logic so that it handles all valid scenarios correctly, and write the corrected, self-contained `engine.py` to `/logs/artifacts/engine.py`. The verifier will import it as a Python module and call `engine.consolidate(scenario)`.
## Scenario format
```python
{
'parent': {
'revenue': float,
'cogs': float,
'inventory': float,
'retained_earnings': float,
},
'subsidiary': {
'revenue': float,
'cogs': float,
'inventory': float,
'retained_earnings': float,
},
'ownership': float, # 0.0 to 1.0
'intercompany_sales': [
{
'direction': 'downstream' | 'upstream',
'sale_amount': float,
'gross_profit': float,
'remaining_in_inventory': float, # 0.0 to 1.0
},
...
],
'beginning_unrealized_profits': [ # optional
{
'direction': 'downstream' | 'upstream',
'amount': float, # profit deferred in prior periods and realized now
},
...
],
}
```
## Return value
`consolidate(scenario)` must return a dict with exactly these keys:
```python
{
'retained_earnings': float,
'nci': float,
'inventory': float,
'revenue': float,
'cogs': float,
}
```
All values are consolidated balances. The verifier checks them against the correct accounting rules with a small tolerance.
schema_version = '1.2'
artifacts = [
'/logs/artifacts/engine.py',
]
[metadata]
flags = []
sub_category = "finance_accounting_workflows"
author_name = 'Terminal Bench'
author_email = 'bench@example.com'
author_organization = 'Terminal Bench'
difficulty_explanation = 'The task requires implementing consolidation accounting for intercompany inventory profits, including both current-period sales and prior-period deferred profits. The visible scenarios are insufficient to expose the direction-dependence of profit attribution or the need to reverse prior-period deferrals, so a solver must infer the full accounting rule rather than patch to the examples. In practice, this work would be done by a financial reporting accountant, CPA, or consolidation specialist preparing group financial statements under IFRS or U.S. GAAP. The scenario data is synthetically generated for this exercise and is not drawn from real company financial statements.'
solution_explanation = "[withheld to keep the benchmark uncontaminated]"
verification_explanation = "[withheld to keep the benchmark uncontaminated]"
category = "business"
tags = ['accounting', 'consolidation', 'intercompany', 'nci', 'inventory']
expert_time_estimate_hours = 3.0
[verifier]
environment_mode = 'separate'
timeout_sec = 300
[agent]
timeout_sec = 7200
[environment]
build_timeout_sec = 600
FROM python:3.11-slim
WORKDIR /tests
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
RUN mkdir -p /logs/artifacts /logs/verifier
COPY scenarios.py /tests/scenarios.py
COPY test_outputs.py /tests/test_outputs.py
COPY test.sh /tests/test.sh
COPY entrypoint.sh /tests/entrypoint.sh
RUN chmod +x /tests/test.sh /tests/entrypoint.sh
VOLUME ["/logs/artifacts", "/logs/verifier"]
ENTRYPOINT ["/tests/entrypoint.sh"]
#!/bin/bash
# Run the verifier once and then keep the container alive so the harness can
# read /logs/verifier/reward.txt from the shared log volume.
set +e
/tests/test.sh
exec tail -f /dev/null
HIDDEN_SCENARIOS = [
{
'name': 'no_intercompany',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.8,
'intercompany_sales': [],
'beginning_unrealized_profits': [],
},
{
'name': 'downstream_full_80',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.8,
'intercompany_sales': [
{'direction': 'downstream', 'sale_amount': 100.0, 'gross_profit': 40.0, 'remaining_in_inventory': 1.0}
],
'beginning_unrealized_profits': [],
},
{
'name': 'downstream_partial_60',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.6,
'intercompany_sales': [
{'direction': 'downstream', 'sale_amount': 100.0, 'gross_profit': 40.0, 'remaining_in_inventory': 0.5}
],
'beginning_unrealized_profits': [],
},
{
'name': 'upstream_full_80',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.8,
'intercompany_sales': [
{'direction': 'upstream', 'sale_amount': 100.0, 'gross_profit': 40.0, 'remaining_in_inventory': 1.0}
],
'beginning_unrealized_profits': [],
},
{
'name': 'upstream_partial_60',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.6,
'intercompany_sales': [
{'direction': 'upstream', 'sale_amount': 100.0, 'gross_profit': 40.0, 'remaining_in_inventory': 0.5}
],
'beginning_unrealized_profits': [],
},
{
'name': 'upstream_full_100',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 1.0,
'intercompany_sales': [
{'direction': 'upstream', 'sale_amount': 100.0, 'gross_profit': 40.0, 'remaining_in_inventory': 1.0}
],
'beginning_unrealized_profits': [],
},
{
'name': 'mixed_70',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.7,
'intercompany_sales': [
{'direction': 'downstream', 'sale_amount': 100.0, 'gross_profit': 40.0, 'remaining_in_inventory': 0.5},
{'direction': 'upstream', 'sale_amount': 200.0, 'gross_profit': 80.0, 'remaining_in_inventory': 0.3},
],
'beginning_unrealized_profits': [],
},
{
'name': 'multiple_upstream_80',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.8,
'intercompany_sales': [
{'direction': 'upstream', 'sale_amount': 50.0, 'gross_profit': 20.0, 'remaining_in_inventory': 1.0},
{'direction': 'upstream', 'sale_amount': 150.0, 'gross_profit': 60.0, 'remaining_in_inventory': 0.4},
],
'beginning_unrealized_profits': [],
},
{
'name': 'beginning_downstream_80',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.8,
'intercompany_sales': [],
'beginning_unrealized_profits': [
{'direction': 'downstream', 'amount': 40.0},
],
},
{
'name': 'beginning_upstream_60',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.6,
'intercompany_sales': [],
'beginning_unrealized_profits': [
{'direction': 'upstream', 'amount': 40.0},
],
},
{
'name': 'mixed_with_beginning_70',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.7,
'intercompany_sales': [
{'direction': 'downstream', 'sale_amount': 100.0, 'gross_profit': 40.0, 'remaining_in_inventory': 0.5},
{'direction': 'upstream', 'sale_amount': 200.0, 'gross_profit': 80.0, 'remaining_in_inventory': 0.3},
],
'beginning_unrealized_profits': [
{'direction': 'upstream', 'amount': 30.0},
],
},
{
'name': 'mixed_beginning_downstream_upstream_80',
'parent': {'revenue': 1000.0, 'cogs': 600.0, 'inventory': 200.0, 'retained_earnings': 500.0},
'subsidiary': {'revenue': 500.0, 'cogs': 300.0, 'inventory': 100.0, 'retained_earnings': 200.0},
'ownership': 0.8,
'intercompany_sales': [],
'beginning_unrealized_profits': [
{'direction': 'downstream', 'amount': 20.0},
{'direction': 'upstream', 'amount': 50.0},
],
},
]
#!/bin/bash
set +e
mkdir -p /logs/verifier
python3 /tests/test_outputs.py > /logs/verifier/test-stdout.txt 2>&1
TEST_EXIT=$?
cat /logs/verifier/test-stdout.txt
if [ $TEST_EXIT -eq 0 ]; then
echo "1" > /logs/verifier/reward.txt
else
echo "0" > /logs/verifier/reward.txt
fi
# Always exit 0; the reward file is the source of truth.
exit 0
#!/usr/bin/env python3
import ast
import copy
import math
import os
import sys
sys.dont_write_bytecode = True
# Load hidden scenarios from /tests/scenarios.py
import importlib.util
spec = importlib.util.spec_from_file_location('scenarios', '/tests/scenarios.py')
scenarios_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(scenarios_module)
TOLERANCE = 1e-6
REQUIRED_KEYS = {'retained_earnings', 'nci', 'inventory', 'revenue', 'cogs'}
ENGINE_PATH = '/logs/artifacts/engine.py'
# AST node types that are forbidden in the submitted engine.
DANGEROUS_NODES = (
ast.Import,
ast.ImportFrom,
ast.With,
ast.Try,
ast.TryStar,
ast.Lambda,
ast.ClassDef,
ast.Global,
ast.Nonlocal,
ast.Delete,
ast.Starred,
ast.NamedExpr,
ast.Match,
ast.AsyncFunctionDef,
ast.Await,
ast.Yield,
ast.YieldFrom,
ast.AsyncFor,
ast.AsyncWith,
)
# Attribute names that can be used to escape a restricted namespace.
DANGEROUS_ATTRIBUTES = {
'__class__', '__classes__', '__base__', '__bases__', '__mro__',
'__subclasses__', '__globals__', '__builtins__', '__builtin__',
'__import__', '__loader__', '__spec__', '__cached__', '__file__',
'__name__', '__doc__', '__package__', '__all__', '__qualname__',
'__module__', '__dict__', '__weakref__', '__slots__', '__getattribute__',
'__getattr__', '__setattr__', '__delattr__', '__dir__', '__call__',
'__new__', '__init__', '__metaclass__', '__code__', '__closure__',
'__defaults__', '__kwdefaults__',
}
# Names that must not appear as bare identifiers.
DANGEROUS_NAMES = {
'__builtins__', '__import__', '__loader__', '__spec__', '__cached__',
'__file__', '__name__', '__doc__', '__package__',
}
# Functions that must not be called.
DANGEROUS_CALL_NAMES = {
'open', 'file', 'exec', 'eval', 'compile', 'input', 'raw_input', 'vars',
'locals', 'globals', 'getattr', 'setattr', 'delattr', 'hasattr', 'dir',
'type', 'object', 'classmethod', 'staticmethod', 'property', 'super',
'breakpoint', 'help', 'copyright', 'credits', 'license', 'exit', 'quit',
'__import__',
}
# Builtins available to the submitted engine.
SAFE_BUILTINS = {
'abs': abs,
'all': all,
'any': any,
'bool': bool,
'dict': dict,
'divmod': divmod,
'enumerate': enumerate,
'filter': filter,
'float': float,
'frozenset': frozenset,
'int': int,
'len': len,
'list': list,
'map': map,
'max': max,
'min': min,
'pow': pow,
'range': range,
'reversed': reversed,
'round': round,
'set': set,
'slice': slice,
'sorted': sorted,
'str': str,
'sum': sum,
'tuple': tuple,
'zip': zip,
'ArithmeticError': ArithmeticError,
'AssertionError': AssertionError,
'AttributeError': AttributeError,
'Exception': Exception,
'KeyError': KeyError,
'TypeError': TypeError,
'ValueError': ValueError,
'ZeroDivisionError': ZeroDivisionError,
'isinstance': isinstance,
'issubclass': issubclass,
'print': print,
}
def validate_engine_source(source):
'''Validate that the engine source does not contain dangerous constructs.'''
try:
tree = ast.parse(source)
except SyntaxError as e:
raise SyntaxError(f'Engine source has syntax error: {e}')
for node in ast.walk(tree):
if isinstance(node, DANGEROUS_NODES):
raise ValueError(
f'Engine source contains forbidden construct: {type(node).__name__}'
)
if isinstance(node, ast.Attribute):
if node.attr in DANGEROUS_ATTRIBUTES:
raise ValueError(
f'Engine source uses forbidden attribute: {node.attr}'
)
if isinstance(node, ast.Name):
if node.id in DANGEROUS_NAMES:
raise ValueError(
f'Engine source uses forbidden name: {node.id}'
)
if isinstance(node, ast.Call):
if isinstance(node.func, ast.Name) and node.func.id in DANGEROUS_CALL_NAMES:
raise ValueError(
f'Engine source calls forbidden function: {node.func.id}'
)
return tree
def load_submitted_engine():
'''Load the submitted engine from /logs/artifacts/engine.py in a restricted namespace.'''
if not os.path.exists(ENGINE_PATH):
raise FileNotFoundError(f'Submitted engine not found at {ENGINE_PATH}')
with open(ENGINE_PATH, 'r') as f:
source = f.read()
validate_engine_source(source)
namespace = {'__builtins__': SAFE_BUILTINS}
code = compile(source, ENGINE_PATH, 'exec')
exec(code, namespace)
if 'consolidate' not in namespace:
raise AttributeError('Submitted engine does not define consolidate')
return namespace['consolidate']
def expected_consolidated(scenario):
'''Compute expected consolidated balances from first principles.'''
parent = scenario['parent']
sub = scenario['subsidiary']
ownership = scenario['ownership']
sales = scenario.get('intercompany_sales', [])
beginning = scenario.get('beginning_unrealized_profits', [])
total_ic_revenue = sum(s['sale_amount'] for s in sales)
total_unrealized = 0.0
parent_re_adj = 0.0
nci_adj = 0.0
for s in sales:
profit = s['gross_profit'] * s['remaining_in_inventory']
total_unrealized += profit
if s['direction'] == 'upstream':
parent_re_adj += profit * ownership
nci_adj += profit * (1.0 - ownership)
else:
parent_re_adj += profit
beginning_realized = 0.0
beginning_re_credit = 0.0
beginning_nci_credit = 0.0
for b in beginning:
amount = b['amount']
beginning_realized += amount
if b['direction'] == 'upstream':
beginning_re_credit += amount * ownership
beginning_nci_credit += amount * (1.0 - ownership)
else:
beginning_re_credit += amount
revenue = parent['revenue'] + sub['revenue'] - total_ic_revenue
cogs = parent['cogs'] + sub['cogs'] - total_ic_revenue + total_unrealized - beginning_realized
inventory = parent['inventory'] + sub['inventory'] - total_unrealized
retained_earnings = (
parent['retained_earnings']
+ sub['retained_earnings'] * ownership
- parent_re_adj
+ beginning_re_credit
)
nci = sub['retained_earnings'] * (1.0 - ownership) - nci_adj + beginning_nci_credit
return {
'retained_earnings': retained_earnings,
'nci': nci,
'inventory': inventory,
'revenue': revenue,
'cogs': cogs,
}
def close_enough(a, b):
return math.isclose(a, b, abs_tol=TOLERANCE, rel_tol=0.0)
def write_reward(value):
os.makedirs('/logs/verifier', exist_ok=True)
with open('/logs/verifier/reward.txt', 'w') as f:
f.write(str(value))
def snapshot(scenario):
return copy.deepcopy(scenario)
def main():
try:
consolidate = load_submitted_engine()
except Exception as e:
print(f'Failed to load submitted engine: {e}')
write_reward(0)
sys.exit(1)
scenarios = scenarios_module.HIDDEN_SCENARIOS
all_pass = True
failures = []
for scenario in scenarios:
name = scenario['name']
before = snapshot(scenario)
try:
result = consolidate(scenario)
except Exception as e:
all_pass = False
failures.append((name, f'exception: {e}'))
continue
if scenario != before:
all_pass = False
failures.append((name, 'input scenario was mutated'))
continue
if not isinstance(result, dict):
all_pass = False
failures.append((name, f'returned non-dict: {type(result)}'))
continue
missing = REQUIRED_KEYS - set(result.keys())
if missing:
all_pass = False
failures.append((name, f'missing keys: {missing}'))
continue
extra = set(result.keys()) - REQUIRED_KEYS
if extra:
all_pass = False
failures.append((name, f'extra keys: {extra}'))
continue
exp = expected_consolidated(scenario)
for key in REQUIRED_KEYS:
if not close_enough(result[key], exp[key]):
all_pass = False
failures.append((name, f'{key}: got {result[key]}, expected {exp[key]}'))
if all_pass:
print('All scenarios passed.')
else:
print('Failures:')
for name, reason in failures:
print(f' {name}: {reason}')
write_reward(1 if all_pass else 0)
sys.exit(0 if all_pass else 1)
if __name__ == '__main__':
main()