Skip to content

Commit 9f7bd0a

Browse files
Record public input source binding
Signed-off-by: yoshifuminakamura <nakamura@riken.jp>
1 parent d22864c commit 9f7bd0a

8 files changed

Lines changed: 154 additions & 9 deletions

File tree

‎docs/cx/BENCHKIT_SPEC.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,9 @@ Benchkit は、pre-staged input、restart、学習済みモデル、公開 archi
490490
この場合、`source_info` が実際に使った app source と repo 内 input の両方の固定点になる。
491491
`input_info` は省略してもよく、Portal や review で dataset 名を見せたい場合だけ、`kind: "repo-local-input"`、`source: "source_info"`、`repo_relative_path`、`verification_status: "covered_by_source_commit"` などの補助情報を持たせてよい。
492492

493+
入力が別の public input repository や public archive から来る場合は、`input_info` 側に公開URL、ref、resolved commit または digest、取得/生成 recipe を置く。
494+
この場合も、入力が記録済み source commit で固定されるなら `verification_status: "public_source_commit"` として `Covered` に分類できる。
495+
493496
site-local path は所在情報であり、長期的な input identity ではない。
494497
巨大データや共同研究由来データを site-local shared storage に置くことは許容されるが、Result provenance では path より dataset identity、recipe、manifest、digest を優先する。
495498
public surface では、必要がない限り detailed local path を表示しない。
@@ -514,6 +517,9 @@ When the input is already stored in the top-level application repository and is
514517
In that case, `source_info` is the fixed point for both the application source and the repository-local input actually used.
515518
`input_info` may be omitted, or it may carry lightweight helper fields such as `kind: "repo-local-input"`, `source: "source_info"`, `repo_relative_path`, and `verification_status: "covered_by_source_commit"` when the dataset name should be visible in the Portal or during review.
516519

520+
When the input comes from a separate public input repository or public archive, `input_info` should carry the public URL, ref, resolved commit or digest, and acquisition or generation recipe.
521+
If the input is fixed by a recorded source commit, it may use `verification_status: "public_source_commit"` and be classified as `Covered`.
522+
517523
A site-local path is location information, not a durable input identity.
518524
Large datasets and collaboration-derived inputs may still be staged on site-local shared storage, but Result provenance should prefer dataset identity, recipe, manifest, and digest over paths.
519525
Detailed local paths should not be exposed on the public surface unless they are necessary.

‎docs/guides/add-app.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ Portal の `/results/usage` では、通常の benchmark result に対する入
193193

194194
- `None`: `input_info` がない
195195
- `Declared`: `input_info` はあるが、digest 検証や source commit coverage までは示していない
196-
- `Covered`: repo-local input が `source_info.resolved_commit` で固定されることを示している
196+
- `Covered`: repo-local input または public input source が記録済み source commit で固定されることを示している
197197
- `Verified`: manifest / content digest などの証跡と `verification_status: "verified"` がある
198198

199199
`None` や `Declared` はただちに CI failure ではありません。

‎programs/genesis/run.sh‎

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,43 @@ stderr="${resultsdir}/log_${header}_err.txt"
3535
binary="spdyn"
3636
inputdir="../../../inputs/apoa1/"
3737

38+
record_public_input_info() {
39+
local input_source_commit="$1"
40+
{
41+
printf '{\n'
42+
printf ' "schema_version": 1,\n'
43+
printf ' "inputs": [\n'
44+
printf ' {\n'
45+
printf ' "dataset_id": '
46+
bk_json_string "apoa1-p8"
47+
printf ',\n'
48+
printf ' "dataset_version": '
49+
bk_json_string "$BRANCH"
50+
printf ',\n'
51+
printf ' "kind": "public-git",\n'
52+
printf ' "source": "public_url",\n'
53+
printf ' "public_url": '
54+
bk_json_string "$REPO_URL"
55+
printf ',\n'
56+
printf ' "source_ref": '
57+
bk_json_string "$BRANCH"
58+
printf ',\n'
59+
printf ' "resolved_commit": '
60+
bk_json_string "$input_source_commit"
61+
printf ',\n'
62+
printf ' "repo_relative_path": '
63+
bk_json_string "$dir_path"
64+
printf ',\n'
65+
printf ' "recipe": '
66+
bk_json_string "${input}.sub generated from ${input}"
67+
printf ',\n'
68+
printf ' "verification_status": "public_source_commit"\n'
69+
printf ' }\n'
70+
printf ' ]\n'
71+
printf '}\n'
72+
} | bk_record_input_info
73+
}
74+
3875
echo "[${REPO_DIR}] Running on system: $system"
3976

4077
if [[ -d "${REPO_DIR}" ]]; then
@@ -51,14 +88,15 @@ echo "System=$system"
5188
echo "Nodes=$nodes"
5289
echo "numproc=$numproc"
5390
echo "nthreads=$nthreads"
54-
totalcores=$(( numproc * nthreads ))
5591

5692
if [[ ! -d ${REPO_DIR} ]]; then
5793
git clone --branch "${BRANCH}" "${REPO_URL}" "${REPO_DIR}"
5894
else
5995
echo "Reposiotry already exists and looks valid. Skipping clone."
6096
fi
6197

98+
input_source_commit=$(git -C "${REPO_DIR}" rev-parse HEAD)
99+
record_public_input_info "$input_source_commit"
62100

63101
if [[ ! -f "${artifactsdir}/spdyn" ]]; then
64102
echo "Error: spdyn does not exist."
@@ -128,17 +166,19 @@ run_genesis_nvidia_gpu() {
128166
local cuda_visible_devices_var="${env_prefix}_CUDA_VISIBLE_DEVICES"
129167
local profiler_tool_var="${env_prefix}_PROFILER_TOOL"
130168
local profiler_level_var="${env_prefix}_PROFILER_LEVEL"
169+
local -a nvidia_mpi_cmd
170+
local -a nvidia_mpi_args
131171

132172
local module_name="${!module_var:-$default_module}"
133173
if [ "$module_name" != "none" ] && command -v module >/dev/null 2>&1; then
134174
read -r -a module_names <<< "$module_name"
135175
module load "${module_names[@]}"
136176
fi
137177

138-
read -r -a mpi_cmd <<< "${!mpi_cmd_var:-mpirun -np ${numproc}}"
178+
read -r -a nvidia_mpi_cmd <<< "${!mpi_cmd_var:-mpirun -np ${numproc}}"
139179
if [ -n "${!mpi_args_var:-}" ]; then
140180
read -r -a nvidia_mpi_args <<< "${!mpi_args_var}"
141-
mpi_cmd+=("${nvidia_mpi_args[@]}")
181+
nvidia_mpi_cmd+=("${nvidia_mpi_args[@]}")
142182
fi
143183

144184
export OMP_NUM_THREADS=${nthreads}
@@ -150,8 +190,8 @@ run_genesis_nvidia_gpu() {
150190
genesis_configure_ncu_profile "$system_name" "$profiler_tool_var" "$profiler_level_var" "$module_var" || return 1
151191

152192
echo "Running ${system_name} as NVIDIA GPU benchmark run without profiler"
153-
"${mpi_cmd[@]}" ./${binary} ${input}.sub 2>&1 | tee ${output}
154-
genesis_run_configured_ncu_profiles "$system_name" "${mpi_cmd[@]}" ./${binary} ${input}.sub || return 1
193+
"${nvidia_mpi_cmd[@]}" ./${binary} ${input}.sub 2>&1 | tee ${output}
194+
genesis_run_configured_ncu_profiles "$system_name" "${nvidia_mpi_cmd[@]}" ./${binary} ${input}.sub || return 1
155195
}
156196

157197
genesis_rikyu_apptainer_run_prefix() {

‎result_server/templates/_usage_report_evidence_snapshot_section.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ <h2 class="section-title">Evidence Snapshot</h2>
1717
<span><strong>Evidence Snapshot:</strong> the roll-up and CSV export source for configured, executed, profiled, estimated, source, input, and build-cache evidence.</span>
1818
<span><strong>Configured:</strong> yes = enabled and implemented; partial = enabled but script support incomplete; off = configured off; no = not listed.</span>
1919
<span><strong>Result Quality:</strong> missing = no result; basic = core result only; ready = estimation bindings present; rich = source provenance and artifacts present.</span>
20-
<span><strong>Input Status:</strong> None = no input_info; Declared = input_info only; Covered = repo-local input fixed by source_info; Verified = digest-backed input verification.</span>
20+
<span><strong>Input Status:</strong> None = no input_info; Declared = input_info only; Covered = input fixed by a recorded source commit; Verified = digest-backed input verification.</span>
2121
<span><strong>Reuse Package:</strong> complete = public packet eligible with profile and estimate evidence; public packet eligible = source material is ready for a public Markdown reuse packet.</span>
2222
<span><strong>Public Packet:</strong> eligible = public result with public source provenance and public input binding.</span>
2323
<span><strong>Next Action:</strong> the first practical follow-up suggested by the current evidence state.</span>

‎result_server/tests/test_evidence_snapshot.py‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,62 @@ def test_evidence_snapshot_requires_public_source_for_public_packet(tmp_path):
162162
assert row["reuse_package_status"] == "needs public evidence"
163163

164164

165+
def test_evidence_snapshot_accepts_public_input_commit_for_public_packet(tmp_path):
166+
received_dir = tmp_path / "received"
167+
estimated_dir = tmp_path / "estimated"
168+
received_dir.mkdir()
169+
estimated_dir.mkdir()
170+
171+
_write_json(
172+
received_dir / "result_20260901_010101_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee.json",
173+
{
174+
"code": "demoapp",
175+
"system": "DemoSystem",
176+
"Exp": "CASE0",
177+
"FOM": 1.0,
178+
"source_info": {
179+
"source_type": "git",
180+
"repo_url": "https://example.com/demoapp.git",
181+
"ref_name": "main",
182+
"resolved_commit": "abcdef1234567890",
183+
},
184+
"input_info": {
185+
"inputs": [
186+
{
187+
"dataset_id": "apoa1-p8",
188+
"kind": "public-git",
189+
"source": "public_url",
190+
"public_url": "https://example.com/input.git",
191+
"source_ref": "main",
192+
"resolved_commit": "1234567890abcdef",
193+
"repo_relative_path": "npt/apoa1",
194+
"verification_status": "public_source_commit",
195+
}
196+
],
197+
},
198+
},
199+
)
200+
201+
snapshot = build_evidence_snapshot(
202+
str(received_dir),
203+
str(estimated_dir),
204+
generated_at="2026-09-07T00:00:00Z",
205+
app_support_rows=[
206+
{
207+
"app": "demoapp",
208+
"systems": {
209+
"DemoSystem": {"status": "enabled"},
210+
},
211+
}
212+
],
213+
)
214+
215+
row = snapshot["rows"][0]
216+
assert row["input_status"] == "Covered"
217+
assert row["public_packet_status"] == "eligible"
218+
assert row["reuse_package_status"] == "public packet eligible"
219+
220+
165221
def test_evidence_snapshot_uses_estimate_benchmark_systems_without_future_target_rows(tmp_path):
166222
received_dir = tmp_path / "received"
167223
estimated_dir = tmp_path / "estimated"

‎result_server/tests/test_portal_list_templates.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,5 +823,5 @@ def test_usage_report_evidence_snapshot_consolidates_coverage_and_quality():
823823
assert "Maturity Gaps" in html
824824
assert "Input Status" in html
825825
assert "None = no input_info" in html
826-
assert "Covered = repo-local input fixed by source_info" in html
826+
assert "Covered = input fixed by a recorded source commit" in html
827827
assert "no profile; no estimate; source incomplete; input not declared" in html

‎result_server/tests/test_results_loader.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,28 @@ def test_input_info_status_classification(self):
504504
})
505505
assert covered["stats"]["input_info_status"] == "covered"
506506

507+
public_source_covered = summarize_result_quality({
508+
"code": "test",
509+
"system": "sys",
510+
"FOM": 1.0,
511+
"input_info": {
512+
"schema_version": 1,
513+
"inputs": [
514+
{
515+
"dataset_id": "case0",
516+
"kind": "public-git",
517+
"source": "public_url",
518+
"public_url": "https://example.com/input.git",
519+
"source_ref": "main",
520+
"resolved_commit": "abcdef1234567890",
521+
"repo_relative_path": "benchmarks/case0",
522+
"verification_status": "public_source_commit",
523+
}
524+
],
525+
},
526+
})
527+
assert public_source_covered["stats"]["input_info_status"] == "covered"
528+
507529
missing_source_commit = summarize_result_quality({
508530
"code": "test",
509531
"system": "sys",

‎result_server/utils/result_records.py‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ def summarize_input_info(data):
252252
}
253253
summaries = {
254254
"declared": "input_info is present, but digest or source-commit coverage is not declared as verified.",
255-
"covered": "input_info declares repository-local input covered by source_info.resolved_commit.",
255+
"covered": "input_info declares input covered by a recorded source commit.",
256256
"verified": "input_info declares verified input with digest evidence.",
257257
}
258258
return {
@@ -277,6 +277,14 @@ def _classify_input_info_item(item, has_source_commit):
277277
"digest",
278278
)
279279
has_digest = any(item.get(field) for field in digest_fields)
280+
revision_fields = (
281+
"resolved_commit",
282+
"commit_hash",
283+
"source_commit",
284+
"revision",
285+
"dataset_revision",
286+
)
287+
has_input_revision = any(item.get(field) for field in revision_fields)
280288

281289
if verification_status == "verified" and has_digest:
282290
return "verified"
@@ -289,6 +297,19 @@ def _classify_input_info_item(item, has_source_commit):
289297
if repo_local_covered:
290298
return "covered"
291299

300+
public_source_covered = (
301+
has_input_revision
302+
and verification_status in {"public_source_commit", "covered_by_public_source_commit"}
303+
and (
304+
source in {"public_url", "public_git", "public-git"}
305+
or item.get("public_url")
306+
or item.get("source_url")
307+
or item.get("archive_url")
308+
)
309+
)
310+
if public_source_covered:
311+
return "covered"
312+
292313
return "declared"
293314

294315

0 commit comments

Comments
 (0)