Skip to content

Commit 5be12c2

Browse files
Grace Lee Rui YueGrace Lee Rui Yue
authored andcommitted
Merge remote-tracking branch 'github-main/main' into agent/discover-polynomial-power-normalization
2 parents 640f4cb + 71fa917 commit 5be12c2

17 files changed

Lines changed: 196 additions & 31 deletions

File tree

.agents/skills/harbor-benchmarks/SKILL.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ configuration and MCP sidecar. Keep credentials, raw caches, host paths,
104104
floating dependencies, and Oracle/verifier material out of agent-visible
105105
files.
106106

107+
Validate that the agent image and runtime expose no solution, verifier, Oracle,
108+
repository-internal, or host-path material. Harbor's phase ordering and
109+
separate-verifier mode support this boundary but do not prove it.
110+
111+
Check that verifier timeout, network, CPU, memory, storage, and dependency
112+
behavior agree with the published task contract. Harbor applies configured
113+
limits subject to provider capabilities; Jacobian owns contract consistency and
114+
validation.
115+
107116
Before choosing the mutating workflow, confirm that the dataset uses the
108117
current public-contract shape. Some older or provider-focused bundles have a
109118
Harbor `task.toml` but a task-local `tests/public_contract.json` that is not
@@ -302,6 +311,10 @@ verifier status. Use Harbor's artifact manifest as the source of truth for
302311
artifact identity and reject traversal, escaping symlinks, missing entries, and
303312
non-conclusion execution states.
304313

314+
Bind committed studies to a retained immutable source revision or Jacobian
315+
snapshot identity. Reject relative or moving Git references such as `HEAD^`,
316+
branches, and unretained commits.
317+
305318
Current separate-verifier tasks retain task-local `tests/verifier_support.py`
306319
copies because Harbor requires the separate verifier image to contain its test
307320
runtime in the task `tests/` build context. The local copy is authoritative and
@@ -356,6 +369,11 @@ record flow, repeated or irrelevant calls, shell/file activity, tokens, time,
356369
cost, and completion. Record the git tree, task digests, provider/runtime,
357370
model/settings, prompt, seeds, raw traces, and structured reports.
358371

372+
For Jacobian studies that require reasoning telemetry, classify a trial as
373+
study-complete only after validating the required terminal reasoning event.
374+
Otherwise record it as `INCONCLUSIVE`. This classification is separate from
375+
Harbor's process and verifier completion.
376+
359377
## Handoff and publication
360378

361379
Report whether the result is task validation, a public regression, workflow

.agents/skills/jacobian-math/SKILL.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Call `math.run` directly for these stable contracts, preserving JSON types:
3131
- `polynomial.compute.gcd` in `EXPLORE` mode: payload keys are `left` and
3232
`right`; each value has shape
3333
`{"polynomial_schema_version":"1","domain":"QQ","variables":["x"],"polynomial":{"terms":[{"coefficient":{"num":"1","den":"1"},"exponents":[2]}]}}`.
34+
- For expression normalization, inspect the known
35+
`polynomial.expression.normalize` contract directly.
3436
- `matrix.determinant.verify` in `VERIFY` mode for an independent check:
3537
`{"determinant_uri":"<determinant_uri from compute output>"}`.
3638
@@ -56,15 +58,15 @@ artifact refs, including verification record URIs.
5658
Keep representation, decomposition, composition, iteration, verification
5759
timing, and stopping decisions agent-owned.
5860
59-
When independent checking is requested, model-authored calculations or programs
60-
are not independent evidence. Use installed `VERIFY` when available. An artifact
61-
URI or checker summary is not a task-local verification-record file: never
62-
reconstruct or paraphrase such a record from returned fields. Claim `VERIFIED`
63-
only when the result has assurance level `VERIFIED`, exact record bytes, and
64-
required task authorization and bindings are preserved; otherwise use lower
65-
task-permitted assurance. Verification is bound to the exact checked claim: do
66-
not transfer `VERIFIED` from an input, premise, factorization, or related
67-
artifact to a model-derived conclusion, which needs its own checker-bound record.
61+
Model-authored calculations or programs are not independent evidence. Use
62+
installed `VERIFY` when requested; a writable path or schema alone is not
63+
authorization. For task-level `VERIFIED`, require result assurance `VERIFIED`,
64+
exact record bytes, and that required task authorization and bindings are preserved;
65+
the visible contract must authorize the checker identity, digest, or Jacobian
66+
record type. Otherwise claim the highest lower permitted assurance (`CHECKED` or
67+
`COMPUTED`), even if Jacobian returned `VERIFIED`; never reconstruct or
68+
paraphrase such a record from tool fields or transfer verification between
69+
claims or artifacts.
6870
For locally constructed inline input, check payload fields against the intended
6971
object. When output echoes scope or a bound digest/URI, compare it with the
7072
submitted input; do not use mismatched output. This catches routing and

benchmarks/datasets/mathematical-benchmarks-v1/jobs/jacobian-observation-proxy.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
"agents": [
3838
{
3939
"name": "codex",
40+
"skills": [
41+
".agents/skills/jacobian-math"
42+
],
4043
"kwargs": {
4144
"web_search": "disabled"
4245
}

benchmarks/datasets/mathematical-benchmarks-v1/jobs/jacobian-observation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
"agents": [
3636
{
3737
"name": "codex",
38+
"skills": [
39+
".agents/skills/jacobian-math"
40+
],
3841
"kwargs": {
3942
"web_search": "disabled"
4043
}

benchmarks/schemas/harbor-job.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@
7979
"properties": {
8080
"name": {"type": "string", "minLength": 1},
8181
"model_name": {"type": "string", "minLength": 1},
82+
"skills": {
83+
"type": "array",
84+
"uniqueItems": true,
85+
"items": {"type": "string", "minLength": 1}
86+
},
8287
"kwargs": {
8388
"type": "object",
8489
"additionalProperties": false,

benchmarks/tooling/benchmark_contracts.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,23 @@ def _validate_task(suite: Suite, task_dir: Path) -> list[str]:
213213
return failures
214214

215215

216+
def _remove_jacobian_skill(agents: Any) -> None:
217+
if not isinstance(agents, list):
218+
return
219+
for agent in agents:
220+
if not isinstance(agent, dict) or not isinstance(agent.get("skills"), list):
221+
continue
222+
remaining = [
223+
skill
224+
for skill in agent["skills"]
225+
if skill != ".agents/skills/jacobian-math"
226+
]
227+
if remaining:
228+
agent["skills"] = remaining
229+
else:
230+
agent.pop("skills", None)
231+
232+
216233
def _observation_pair_failures() -> list[str]:
217234
treatment_path = (
218235
BENCHMARKS
@@ -246,12 +263,14 @@ def normalized(value: dict[str, Any]) -> dict[str, Any]:
246263
for item in compose
247264
if "jacobian-observation.compose.yaml" not in item
248265
]
266+
_remove_jacobian_skill(copy.get("agents"))
249267
return copy
250268

251269
if normalized(treatment) != normalized(control):
252270
return [
253271
"agent workflow control/treatment jobs differ outside the allowed "
254-
"jobs_dir, Jacobian sidecar composition, and sidecar telemetry artifact"
272+
"jobs_dir, Jacobian skill, sidecar composition, and sidecar telemetry "
273+
"artifact"
255274
]
256275
return []
257276

benchmarks/tooling/codex_tool_context.py

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,15 @@ def _visible_results(step: dict[str, Any]) -> dict[str, int]:
6464
return visible_by_call
6565

6666

67-
def _analyze_step(step: object) -> tuple[int, int, int, int, int, int]:
67+
def _analyze_step(step: object) -> tuple[int, int, int, int, int, int, int]:
6868
if not isinstance(step, dict):
69-
return (0, 0, 0, 0, 0, 0)
69+
return (0, 0, 0, 0, 0, 0, 0)
7070
visible_by_call = _visible_results(step)
7171
tool_calls = step.get("tool_calls", [])
7272
if not isinstance(tool_calls, list):
73-
return (0, 0, 0, 0, 0, 0)
73+
return (0, 0, 0, 0, 0, 0, 0)
7474
scan_count = scan_bytes = unbound_scan_count = tool_output_bytes = 0
75+
jacobian_output_bytes = 0
7576
direct_find_references = direct_run_references = 0
7677
for call in tool_calls:
7778
if not isinstance(call, dict):
@@ -83,8 +84,12 @@ def _analyze_step(step: object) -> tuple[int, int, int, int, int, int]:
8384
source = arguments.get("input") if isinstance(arguments, dict) else None
8485
if call.get("function_name") != "exec" or not isinstance(source, str):
8586
continue
86-
direct_find_references += source.count(_JACOBIAN_FIND)
87-
direct_run_references += source.count(_JACOBIAN_RUN)
87+
find_references = source.count(_JACOBIAN_FIND)
88+
run_references = source.count(_JACOBIAN_RUN)
89+
direct_find_references += find_references
90+
direct_run_references += run_references
91+
if find_references or run_references:
92+
jacobian_output_bytes += visible
8893
if "ALL_TOOLS" in source:
8994
scan_count += 1
9095
scan_bytes += visible
@@ -95,6 +100,7 @@ def _analyze_step(step: object) -> tuple[int, int, int, int, int, int]:
95100
scan_bytes,
96101
unbound_scan_count,
97102
tool_output_bytes,
103+
jacobian_output_bytes,
98104
direct_find_references,
99105
direct_run_references,
100106
)
@@ -108,6 +114,7 @@ def analyze_trajectory(path: Path) -> dict[str, Any]:
108114
scan_bytes = 0
109115
unbound_scan_count = 0
110116
tool_output_bytes = 0
117+
jacobian_output_bytes = 0
111118
direct_find_references = 0
112119
direct_run_references = 0
113120

@@ -117,8 +124,9 @@ def analyze_trajectory(path: Path) -> dict[str, Any]:
117124
scan_bytes += step_counts[1]
118125
unbound_scan_count += step_counts[2]
119126
tool_output_bytes += step_counts[3]
120-
direct_find_references += step_counts[4]
121-
direct_run_references += step_counts[5]
127+
jacobian_output_bytes += step_counts[4]
128+
direct_find_references += step_counts[5]
129+
direct_run_references += step_counts[6]
122130

123131
metrics = trajectory.get("final_metrics")
124132
metrics = metrics if isinstance(metrics, dict) else {}
@@ -137,6 +145,7 @@ def analyze_trajectory(path: Path) -> dict[str, Any]:
137145
"all_tools_model_visible_bytes": scan_bytes,
138146
"all_tools_unbound_observation_count": unbound_scan_count,
139147
"tool_model_visible_bytes": tool_output_bytes,
148+
"direct_jacobian_find_run_model_visible_bytes": jacobian_output_bytes,
140149
"direct_jacobian_find_references": direct_find_references,
141150
"direct_jacobian_run_references": direct_run_references,
142151
"prompt_tokens": prompt_tokens,
@@ -165,6 +174,33 @@ def build_report(paths: list[Path], *, label: str) -> dict[str, Any]:
165174
"label": label,
166175
"trial_count": len(trials),
167176
"summary": {
177+
"jacobian_invocation_trials": sum(
178+
int(
179+
trial["direct_jacobian_find_references"] > 0
180+
or trial["direct_jacobian_run_references"] > 0
181+
)
182+
for trial in trials
183+
),
184+
"jacobian_execution_trials": sum(
185+
int(trial["direct_jacobian_run_references"] > 0) for trial in trials
186+
),
187+
"jacobian_unused_trials": sum(
188+
int(
189+
trial["direct_jacobian_find_references"] == 0
190+
and trial["direct_jacobian_run_references"] == 0
191+
)
192+
for trial in trials
193+
),
194+
"direct_jacobian_find_references": sum(
195+
int(trial["direct_jacobian_find_references"]) for trial in trials
196+
),
197+
"direct_jacobian_run_references": sum(
198+
int(trial["direct_jacobian_run_references"]) for trial in trials
199+
),
200+
"direct_jacobian_find_run_model_visible_bytes": sum(
201+
int(trial["direct_jacobian_find_run_model_visible_bytes"])
202+
for trial in trials
203+
),
168204
"all_tools_scan_trials": sum(
169205
int(trial["all_tools_scan_count"] > 0) for trial in trials
170206
),

benchmarks/tooling/observation_results.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,15 @@ def _comparison_job(job: dict[str, Any]) -> dict[str, Any]:
192192
]
193193
for agent in normalized.get("agents", []):
194194
if isinstance(agent, dict):
195+
skills = agent.get("skills")
196+
if isinstance(skills, list):
197+
remaining_skills = [
198+
skill for skill in skills if skill != ".agents/skills/jacobian-math"
199+
]
200+
if remaining_skills:
201+
agent["skills"] = remaining_skills
202+
else:
203+
agent.pop("skills", None)
195204
servers = agent.get("mcp_servers")
196205
if isinstance(servers, list):
197206
remaining = [

benchmarks/validation/conftest.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,21 @@
55
import sys
66
from pathlib import Path
77

8+
import pytest
9+
810
ROOT = Path(__file__).parents[2]
911
if str(ROOT) not in sys.path:
1012
sys.path.insert(0, str(ROOT))
13+
14+
15+
@pytest.fixture(autouse=True)
16+
def _isolate_task_verifier_imports():
17+
"""Prevent one task's top-level verifier_support import leaking to another."""
18+
19+
original_path = list(sys.path)
20+
sys.modules.pop("verifier_support", None)
21+
try:
22+
yield
23+
finally:
24+
sys.modules.pop("verifier_support", None)
25+
sys.path[:] = original_path

benchmarks/validation/test_observation_comparison.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ def test_comparison_normalization_allows_only_frozen_jacobian_differences() -> N
199199
"agents": [
200200
{
201201
"name": "codex",
202+
"skills": [".agents/skills/jacobian-math"],
202203
"mcp_servers": [
203204
{
204205
"name": "jacobian",
@@ -216,6 +217,10 @@ def test_comparison_normalization_allows_only_frozen_jacobian_differences() -> N
216217
assert _comparison_job(control) != _comparison_job(treatment)
217218
treatment["artifacts"].pop()
218219

220+
treatment["agents"][0]["skills"].append("unexpected-skill")
221+
assert _comparison_job(control) != _comparison_job(treatment)
222+
treatment["agents"][0]["skills"].pop()
223+
219224
heldout_treatment = {
220225
"artifacts": ["/logs/agent/trajectory.json"],
221226
"environment": {
@@ -227,6 +232,7 @@ def test_comparison_normalization_allows_only_frozen_jacobian_differences() -> N
227232
"agents": [
228233
{
229234
"name": "codex",
235+
"skills": [".agents/skills/jacobian-math"],
230236
"mcp_servers": [
231237
{
232238
"name": "jacobian",

0 commit comments

Comments
 (0)