refactor: simplify distillation data layout
This commit is contained in:
+4
-19
@@ -29,22 +29,7 @@ text-to-cad/assets/
|
|||||||
text-to-cad/benchmarks/*.gif
|
text-to-cad/benchmarks/*.gif
|
||||||
text-to-cad/models/
|
text-to-cad/models/
|
||||||
|
|
||||||
# DesignIR teacher data and runtime artifacts
|
# Local distillation inputs and run artifacts. Only output/ is versioned.
|
||||||
designir-pipeline/workspace/teacher/inbox/*
|
designir-pipeline/input/*
|
||||||
!designir-pipeline/workspace/teacher/inbox/.gitkeep
|
!designir-pipeline/input/.gitkeep
|
||||||
designir-pipeline/workspace/teacher/evidence/*
|
designir-pipeline/runs/
|
||||||
!designir-pipeline/workspace/teacher/evidence/.gitkeep
|
|
||||||
designir-pipeline/workspace/reconstruction/inbox/*
|
|
||||||
!designir-pipeline/workspace/reconstruction/inbox/.gitkeep
|
|
||||||
designir-pipeline/workspace/reconstruction/designir/*
|
|
||||||
!designir-pipeline/workspace/reconstruction/designir/.gitkeep
|
|
||||||
designir-pipeline/workspace/reconstruction/output/*
|
|
||||||
!designir-pipeline/workspace/reconstruction/output/.gitkeep
|
|
||||||
designir-pipeline/workspace/acceptance/inbox/*
|
|
||||||
!designir-pipeline/workspace/acceptance/inbox/.gitkeep
|
|
||||||
designir-pipeline/workspace/acceptance/reports/*
|
|
||||||
!designir-pipeline/workspace/acceptance/reports/.gitkeep
|
|
||||||
designir-pipeline/workspace/promotion/candidates/*
|
|
||||||
!designir-pipeline/workspace/promotion/candidates/.gitkeep
|
|
||||||
designir-pipeline/workspace/promotion/replay_validated/*
|
|
||||||
!designir-pipeline/workspace/promotion/replay_validated/.gitkeep
|
|
||||||
|
|||||||
@@ -96,33 +96,27 @@ Schema 位于:
|
|||||||
将待处理的 STEP/STP 文件放入:
|
将待处理的 STEP/STP 文件放入:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
designir-pipeline/workspace/teacher/inbox/
|
designir-pipeline/input/
|
||||||
```
|
```
|
||||||
|
|
||||||
完整运行目录:
|
蒸馏目录只保留三层:
|
||||||
|
|
||||||
| 阶段 | 路径 |
|
| 路径 | 用途 | Git |
|
||||||
| --- | --- |
|
| --- | --- | --- |
|
||||||
| 教师 STEP 输入 | `workspace/teacher/inbox/` |
|
| `designir-pipeline/input/` | 原始教师 STEP/STP | 不提交 |
|
||||||
| 私有几何证据 | `workspace/teacher/evidence/` |
|
| `designir-pipeline/runs/` | 证据、DesignIR、重建件、验收、草稿和失败记录 | 不提交 |
|
||||||
| Reconstruction Agent 输入 | `workspace/reconstruction/inbox/` |
|
| `designir-pipeline/output/library.json` | 通过确定性校验的经验库 | 提交 |
|
||||||
| 参数化重建结果 | `workspace/reconstruction/designir/` |
|
|
||||||
| 独立重建 STEP | `workspace/reconstruction/output/` |
|
|
||||||
| Acceptance Agent 输入 | `workspace/acceptance/inbox/` |
|
|
||||||
| 验收报告 | `workspace/acceptance/reports/` |
|
|
||||||
| 经验候选 | `workspace/promotion/candidates/` |
|
|
||||||
| 跨案例回放验证 | `workspace/promotion/replay_validated/` |
|
|
||||||
| 正式经验库 | `workspace/promotion/promoted/library.json` |
|
|
||||||
| 失败与能力缺口 | `workspace/quarantine/` |
|
|
||||||
|
|
||||||
详细说明见 [`designir-pipeline/workspace/README.md`](designir-pipeline/workspace/README.md)。
|
`runs/` 内部由程序按需创建 `evidence`、`designir`、`rebuilt`、
|
||||||
|
`acceptance`、`review` 和 `quarantine`。目录层级只负责整理文件;两个
|
||||||
|
Agent 的读写边界由程序和合同控制。
|
||||||
|
|
||||||
|
详细说明见 [`designir-pipeline/README.md`](designir-pipeline/README.md)。
|
||||||
|
|
||||||
批量提取教师证据:
|
批量提取教师证据:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
designir-pipeline/scripts/cad-experience extract-folder \
|
designir-pipeline/scripts/cad-experience extract-folder
|
||||||
--input designir-pipeline/workspace/teacher/inbox \
|
|
||||||
--output designir-pipeline/workspace/teacher/evidence
|
|
||||||
```
|
```
|
||||||
|
|
||||||
蒸馏得到的经验必须同时通过几何一致性、特征语义、参数可编辑性和修改稳定性验收。两个 Agent 都无权直接发布经验,最终晋升由确定性策略执行。
|
蒸馏得到的经验必须同时通过几何一致性、特征语义、参数可编辑性和修改稳定性验收。两个 Agent 都无权直接发布经验,最终晋升由确定性策略执行。
|
||||||
@@ -187,7 +181,7 @@ text-to-cad/.venv/bin/python -m unittest \
|
|||||||
```bash
|
```bash
|
||||||
text-to-cad/.venv/bin/python \
|
text-to-cad/.venv/bin/python \
|
||||||
designir-pipeline/skills/cad-experience-builder/scripts/cad_experience.py \
|
designir-pipeline/skills/cad-experience-builder/scripts/cad_experience.py \
|
||||||
audit designir-pipeline/workspace/promotion/promoted/library.json
|
audit designir-pipeline/output/library.json
|
||||||
```
|
```
|
||||||
|
|
||||||
## 当前边界
|
## 当前边界
|
||||||
|
|||||||
+29
-20
@@ -26,30 +26,32 @@ removed. `scripts/designir_pipeline.py anti-cheat` rejects source STEP
|
|||||||
references, imported B-Reps, embedded meshes, topology references, and generator
|
references, imported B-Reps, embedded meshes, topology references, and generator
|
||||||
source that calls STEP import APIs.
|
source that calls STEP import APIs.
|
||||||
|
|
||||||
## Workspace
|
## Data layout
|
||||||
|
|
||||||
Runtime data is role-separated under `workspace/`:
|
The operator-facing layout has only three directories:
|
||||||
|
|
||||||
For the exact input, process, acceptance, and output locations, see
|
|
||||||
[`workspace/README.md`](workspace/README.md).
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
workspace/
|
designir-pipeline/
|
||||||
teacher/inbox/ uploaded STEP/STP files
|
input/ drop source STEP/STP files here
|
||||||
teacher/evidence/ private deterministic evidence
|
runs/ all private process artifacts
|
||||||
reconstruction/inbox/ evidence packets for Agent A
|
output/library.json verified experience consumed at runtime
|
||||||
reconstruction/designir/ authored DesignIR 2.0
|
|
||||||
reconstruction/output/ independently rebuilt STEP
|
|
||||||
acceptance/inbox/ manifests visible to Agent B
|
|
||||||
acceptance/reports/ geometry and editability reports
|
|
||||||
promotion/candidates/ untrusted generalized methods
|
|
||||||
promotion/replay_validated/
|
|
||||||
promotion/promoted/ deterministic published experience
|
|
||||||
quarantine/ unsupported vocabulary and failed cases
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Only `.gitkeep` files are versioned in runtime directories. Teacher geometry,
|
`input/` and `runs/` are ignored by Git. Only the deterministic result in
|
||||||
private evidence, generated parts, and reports stay local.
|
`output/` is versioned. The pipeline creates these private run directories as
|
||||||
|
needed:
|
||||||
|
|
||||||
|
| Local path | Purpose |
|
||||||
|
| --- | --- |
|
||||||
|
| `runs/evidence/` | Deterministic evidence extracted from source STEP. |
|
||||||
|
| `runs/designir/` | DesignIR authored by Reconstruction Agent. |
|
||||||
|
| `runs/rebuilt/` | STEP rebuilt without access to source STEP. |
|
||||||
|
| `runs/acceptance/` | Independent geometry and editability reports. |
|
||||||
|
| `runs/review/` | Sanitized semantic batches and untrusted drafts. |
|
||||||
|
| `runs/quarantine/` | Failures and unsupported feature vocabulary. |
|
||||||
|
|
||||||
|
The shallow directory structure is for usability, not authorization. Agent and
|
||||||
|
compiler access is enforced by their contracts and by anti-cheat checks.
|
||||||
|
|
||||||
## DesignIR 2.0
|
## DesignIR 2.0
|
||||||
|
|
||||||
@@ -87,9 +89,16 @@ by deterministic code after several independent cases pass.
|
|||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
Use the CAD Python environment:
|
Drop files into `input/`, then use the CAD Python environment:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
scripts/cad-experience extract-folder
|
||||||
|
scripts/cad-experience prepare
|
||||||
|
# The semantic distiller writes runs/review/experience-draft.json.
|
||||||
|
scripts/cad-experience publish \
|
||||||
|
--draft runs/review/experience-draft.json
|
||||||
|
scripts/cad-experience audit output/library.json
|
||||||
|
|
||||||
../text-to-cad/.venv/bin/python scripts/designir_pipeline.py validate part.designir.json
|
../text-to-cad/.venv/bin/python scripts/designir_pipeline.py validate part.designir.json
|
||||||
../text-to-cad/.venv/bin/python scripts/designir_pipeline.py compile \
|
../text-to-cad/.venv/bin/python scripts/designir_pipeline.py compile \
|
||||||
part.designir.json --output rebuilt.step
|
part.designir.json --output rebuilt.step
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ meaningfully editable.
|
|||||||
|
|
||||||
## Allowed inputs
|
## Allowed inputs
|
||||||
|
|
||||||
- Teacher STEP from the protected teacher vault.
|
- Teacher STEP from protected `input/`.
|
||||||
- Candidate DesignIR.
|
- Candidate DesignIR from `runs/designir/`.
|
||||||
- Reconstructed STEP.
|
- Reconstructed STEP from `runs/rebuilt/`.
|
||||||
- Deterministic compiler version.
|
- Deterministic compiler version.
|
||||||
- Modification test contract.
|
- Modification test contract.
|
||||||
|
|
||||||
@@ -36,10 +36,9 @@ Parametric behavior:
|
|||||||
|
|
||||||
## Required output
|
## Required output
|
||||||
|
|
||||||
Write one machine-readable acceptance report with separate geometry,
|
Write one machine-readable report under `runs/acceptance/` with separate geometry,
|
||||||
feature-semantic, parameter-editability, and stability sections. Never collapse
|
feature-semantic, parameter-editability, and stability sections. Never collapse
|
||||||
the result into an unexplained similarity score.
|
the result into an unexplained similarity score.
|
||||||
|
|
||||||
The agent may recommend pass, fail, or quarantine. Only the deterministic
|
The agent may recommend pass, fail, or quarantine. Only the deterministic
|
||||||
publisher changes promotion state.
|
publisher changes promotion state.
|
||||||
|
|
||||||
|
|||||||
@@ -7,4 +7,7 @@ reconstruction_output_access: read
|
|||||||
acceptance_report_access: write
|
acceptance_report_access: write
|
||||||
publish_access: denied
|
publish_access: denied
|
||||||
instructions: acceptance-agent.md
|
instructions: acceptance-agent.md
|
||||||
|
teacher_input_path: input
|
||||||
|
designir_input_path: runs/designir
|
||||||
|
rebuild_input_path: runs/rebuilt
|
||||||
|
report_output_path: runs/acceptance
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ geometry.
|
|||||||
|
|
||||||
## Allowed inputs
|
## Allowed inputs
|
||||||
|
|
||||||
- One private evidence packet produced by the ingestion service.
|
- One private evidence packet from `runs/evidence/`.
|
||||||
- The user modification request.
|
- The user modification request.
|
||||||
- Promoted generalized experience.
|
- Promoted generalized experience.
|
||||||
- The DesignIR schema and supported operation vocabulary.
|
- The DesignIR schema and supported operation vocabulary.
|
||||||
@@ -24,7 +24,7 @@ geometry.
|
|||||||
|
|
||||||
## Required output
|
## Required output
|
||||||
|
|
||||||
Write one `*.designir.json` containing:
|
Write one `runs/designir/*.designir.json` containing:
|
||||||
|
|
||||||
- family and reconstruction status;
|
- family and reconstruction status;
|
||||||
- coordinate system and datums;
|
- coordinate system and datums;
|
||||||
@@ -46,4 +46,5 @@ If the vocabulary is insufficient, emit
|
|||||||
Request `isolated-rebuild`. Passing means the compiler generated a complete STEP
|
Request `isolated-rebuild`. Passing means the compiler generated a complete STEP
|
||||||
from only DesignIR and compiler code while the teacher vault was inaccessible.
|
from only DesignIR and compiler code while the teacher vault was inaccessible.
|
||||||
The router may choose `build123d` or `simplecadapi`; the latter also produces a
|
The router may choose `build123d` or `simplecadapi`; the latter also produces a
|
||||||
replayable SimpleCAD model JSON as a backend artifact.
|
replayable SimpleCAD model JSON as a backend artifact. Put rebuild artifacts in
|
||||||
|
`runs/rebuilt/`.
|
||||||
|
|||||||
@@ -8,3 +8,6 @@ reconstruction_output_access: request_only
|
|||||||
acceptance_report_access: denied
|
acceptance_report_access: denied
|
||||||
publish_access: denied
|
publish_access: denied
|
||||||
instructions: reconstruction-agent.md
|
instructions: reconstruction-agent.md
|
||||||
|
input_path: runs/evidence
|
||||||
|
designir_output_path: runs/designir
|
||||||
|
rebuild_output_path: runs/rebuilt
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
# STEP reconstruction benchmark
|
|
||||||
|
|
||||||
Each case stores only a protected teacher STEP in Git LFS. DesignIR,
|
|
||||||
reconstructed STEP, acceptance reports, and perturbation artifacts are produced
|
|
||||||
at runtime outside the case directory.
|
|
||||||
|
|
||||||
These two teachers were migrated from the retired Exact Base fixtures. Their old
|
|
||||||
copied-B-Rep specifications and generated outputs were intentionally removed.
|
|
||||||
They are now held-out truth for independent DesignIR reconstruction.
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"schema_version": "1.0",
|
|
||||||
"case_id": "015133",
|
|
||||||
"teacher": "teacher.step",
|
|
||||||
"purpose": "held_out_designir_reconstruction"
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"schema_version": "1.0",
|
|
||||||
"case_id": "015240",
|
|
||||||
"teacher": "teacher.step",
|
|
||||||
"purpose": "held_out_designir_reconstruction"
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -10,11 +10,10 @@ published library and require repeated support before promoting any experience.
|
|||||||
|
|
||||||
## Required workflow
|
## Required workflow
|
||||||
|
|
||||||
1. Put source `.step` or `.stp` files in
|
1. Put source `.step` or `.stp` files directly in `input/`. Git ignores this
|
||||||
`workspace/teacher/inbox/`. Only deterministic ingestion and Agent B may
|
directory; only deterministic ingestion and Agent B may access it.
|
||||||
access this vault.
|
2. Parse every new, content-unique STEP into private JSON under
|
||||||
2. Parse every new, content-unique STEP into visible private JSON under
|
`runs/evidence/`:
|
||||||
`workspace/teacher/evidence/`:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
../../scripts/cad-experience extract-folder
|
../../scripts/cad-experience extract-folder
|
||||||
@@ -26,11 +25,11 @@ published library and require repeated support before promoting any experience.
|
|||||||
../../scripts/cad-experience prepare
|
../../scripts/cad-experience prepare
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Read `workspace/promotion/candidates/semantic-batch.json` completely. Act as the semantic
|
4. Read `runs/review/semantic-batch.json` completely. Act as the semantic
|
||||||
distiller: compare families, parameter roles, datum roles, canonical
|
distiller: compare families, parameter roles, datum roles, canonical
|
||||||
reconstruction stages, feature cardinality classes, relations, prior
|
reconstruction stages, feature cardinality classes, relations, prior
|
||||||
vocabulary, failure rules, and validation targets; then author
|
vocabulary, failure rules, and validation targets; then author
|
||||||
`workspace/promotion/candidates/experience-draft.json` using
|
`runs/review/experience-draft.json` using
|
||||||
`references/llm-review-contract.md`.
|
`references/llm-review-contract.md`.
|
||||||
|
|
||||||
Propose methods, invariants, and family-level `reconstruction_grammar`
|
Propose methods, invariants, and family-level `reconstruction_grammar`
|
||||||
@@ -44,7 +43,7 @@ published library and require repeated support before promoting any experience.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
../../scripts/cad-experience publish \
|
../../scripts/cad-experience publish \
|
||||||
--draft ../../workspace/promotion/candidates/experience-draft.json
|
--draft ../../runs/review/experience-draft.json
|
||||||
```
|
```
|
||||||
|
|
||||||
The publisher recomputes support from the private corpus, rejects numeric
|
The publisher recomputes support from the private corpus, rejects numeric
|
||||||
@@ -55,14 +54,14 @@ published library and require repeated support before promoting any experience.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
python scripts/cad_experience.py audit \
|
python scripts/cad_experience.py audit \
|
||||||
../../workspace/promotion/promoted/library.json
|
../../output/library.json
|
||||||
```
|
```
|
||||||
|
|
||||||
7. Query only the published library for creation, modification, or rebuilding:
|
7. Query only the published library for creation, modification, or rebuilding:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python scripts/cad_experience.py query \
|
python scripts/cad_experience.py query \
|
||||||
../../workspace/promotion/promoted/library.json \
|
../../output/library.json \
|
||||||
--family flanged_hub_adapter \
|
--family flanged_hub_adapter \
|
||||||
--features base_flange,hollow_sleeve,counterbore
|
--features base_flange,hollow_sleeve,counterbore
|
||||||
```
|
```
|
||||||
@@ -88,8 +87,10 @@ required.
|
|||||||
family without publishing any teacher dimensions.
|
family without publishing any teacher dimensions.
|
||||||
- Exact source paths, hashes, dimensions, coordinates, and face references are
|
- Exact source paths, hashes, dimensions, coordinates, and face references are
|
||||||
permitted in private case JSON and forbidden in the published library.
|
permitted in private case JSON and forbidden in the published library.
|
||||||
- Keep input/output as a human-visible staging area and induction corpus. Never
|
- Keep `input/` and `runs/` as a local-only induction corpus. Never use them
|
||||||
use it directly during creation, modification, or reconstruction.
|
directly during ordinary creation, modification, or reconstruction.
|
||||||
|
- Commit only the verified runtime library in `output/`; never commit source
|
||||||
|
STEP files, extracted evidence, review drafts, reports, or rebuilt parts.
|
||||||
- A semantic candidate is not a trusted design method until repeated,
|
- A semantic candidate is not a trusted design method until repeated,
|
||||||
independently sourced cases satisfy the promotion policy.
|
independently sourced cases satisfy the promotion policy.
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
Case JSON is private evidence used only during induction. It may contain exact
|
Case JSON is private evidence used only during induction. It may contain exact
|
||||||
parameters, but the inducer never copies those fields into published experience.
|
parameters, but the inducer never copies those fields into published experience.
|
||||||
Store source STEP files in `workspace/teacher/inbox` and generated private
|
Store source STEP files in `input/` and generated private evidence in
|
||||||
evidence in `workspace/teacher/evidence`.
|
`runs/evidence/`.
|
||||||
|
|
||||||
Do not pass either folder or a case JSON to cad-router or a CAD backend.
|
Do not pass either folder or a case JSON to cad-router or a CAD backend.
|
||||||
Creation, modification, and reconstruction may consume only the promoted public
|
Creation, modification, and reconstruction may consume only the promoted public
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# LLM semantic review contract
|
# LLM semantic review contract
|
||||||
|
|
||||||
Read the sanitized `work/review/semantic-batch.json`, not raw STEP geometry.
|
Read the sanitized `runs/review/semantic-batch.json`, not raw STEP geometry.
|
||||||
Maintain stable proposal identifiers when an existing candidate expresses the
|
Maintain stable proposal identifiers when an existing candidate expresses the
|
||||||
same method.
|
same method.
|
||||||
|
|
||||||
Write `work/review/experience-draft.json` with this shape:
|
Write `runs/review/experience-draft.json` with this shape:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -618,17 +618,15 @@ def plugin_root() -> Path:
|
|||||||
|
|
||||||
|
|
||||||
def default_library_path() -> Path:
|
def default_library_path() -> Path:
|
||||||
return (
|
return plugin_root() / "output" / "library.json"
|
||||||
plugin_root()
|
|
||||||
/ "workspace"
|
|
||||||
/ "promotion"
|
|
||||||
/ "promoted"
|
|
||||||
/ "library.json"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def parser_root() -> Path:
|
def input_root() -> Path:
|
||||||
return plugin_root() / "workspace" / "teacher"
|
return plugin_root() / "input"
|
||||||
|
|
||||||
|
|
||||||
|
def runs_root() -> Path:
|
||||||
|
return plugin_root() / "runs"
|
||||||
|
|
||||||
|
|
||||||
def step_files(root: Path) -> list[Path]:
|
def step_files(root: Path) -> list[Path]:
|
||||||
@@ -684,7 +682,7 @@ def extract_folder(input_dir: Path, output_dir: Path) -> dict[str, Any]:
|
|||||||
|
|
||||||
|
|
||||||
def default_review_dir() -> Path:
|
def default_review_dir() -> Path:
|
||||||
return plugin_root() / "workspace" / "promotion" / "candidates"
|
return runs_root() / "review"
|
||||||
|
|
||||||
|
|
||||||
def prepare_semantic_batch(
|
def prepare_semantic_batch(
|
||||||
@@ -1088,15 +1086,15 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
|
|
||||||
extract_folder_parser = subparsers.add_parser("extract-folder")
|
extract_folder_parser = subparsers.add_parser("extract-folder")
|
||||||
extract_folder_parser.add_argument(
|
extract_folder_parser.add_argument(
|
||||||
"--input", type=Path, default=parser_root() / "inbox"
|
"--input", type=Path, default=input_root()
|
||||||
)
|
)
|
||||||
extract_folder_parser.add_argument(
|
extract_folder_parser.add_argument(
|
||||||
"--output", type=Path, default=parser_root() / "evidence"
|
"--output", type=Path, default=runs_root() / "evidence"
|
||||||
)
|
)
|
||||||
|
|
||||||
prepare_parser = subparsers.add_parser("prepare")
|
prepare_parser = subparsers.add_parser("prepare")
|
||||||
prepare_parser.add_argument(
|
prepare_parser.add_argument(
|
||||||
"--input", type=Path, default=parser_root() / "evidence"
|
"--input", type=Path, default=runs_root() / "evidence"
|
||||||
)
|
)
|
||||||
prepare_parser.add_argument(
|
prepare_parser.add_argument(
|
||||||
"--library", type=Path, default=default_library_path()
|
"--library", type=Path, default=default_library_path()
|
||||||
@@ -1110,7 +1108,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
publish_parser = subparsers.add_parser("publish")
|
publish_parser = subparsers.add_parser("publish")
|
||||||
publish_parser.add_argument("--draft", type=Path, required=True)
|
publish_parser.add_argument("--draft", type=Path, required=True)
|
||||||
publish_parser.add_argument(
|
publish_parser.add_argument(
|
||||||
"--input", type=Path, default=parser_root() / "evidence"
|
"--input", type=Path, default=runs_root() / "evidence"
|
||||||
)
|
)
|
||||||
publish_parser.add_argument(
|
publish_parser.add_argument(
|
||||||
"--library", type=Path, default=default_library_path()
|
"--library", type=Path, default=default_library_path()
|
||||||
@@ -1125,7 +1123,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
help="LLM-authored proposal draft. Without this, publishing is blocked.",
|
help="LLM-authored proposal draft. Without this, publishing is blocked.",
|
||||||
)
|
)
|
||||||
distill_parser.add_argument(
|
distill_parser.add_argument(
|
||||||
"--input", type=Path, default=parser_root() / "evidence"
|
"--input", type=Path, default=runs_root() / "evidence"
|
||||||
)
|
)
|
||||||
distill_parser.add_argument(
|
distill_parser.add_argument(
|
||||||
"--library", type=Path, default=default_library_path()
|
"--library", type=Path, default=default_library_path()
|
||||||
|
|||||||
@@ -107,6 +107,15 @@ def make_case(index: int) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
class CadExperienceTest(unittest.TestCase):
|
class CadExperienceTest(unittest.TestCase):
|
||||||
|
def test_default_data_paths_use_shallow_local_layout(self):
|
||||||
|
pipeline_root = Path(__file__).parents[1].resolve()
|
||||||
|
self.assertEqual(pipeline_root / "input", MODULE.input_root())
|
||||||
|
self.assertEqual(pipeline_root / "runs", MODULE.runs_root())
|
||||||
|
self.assertEqual(
|
||||||
|
pipeline_root / "output" / "library.json",
|
||||||
|
MODULE.default_library_path(),
|
||||||
|
)
|
||||||
|
|
||||||
def reviewed_proposal(self) -> dict:
|
def reviewed_proposal(self) -> dict:
|
||||||
return {
|
return {
|
||||||
"id": "constraint.flanged_hub_adapter.shared_axis",
|
"id": "constraint.flanged_hub_adapter.shared_axis",
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
# Distillation Workspace
|
|
||||||
|
|
||||||
This directory is the runtime boundary for uploaded STEP reconstruction and
|
|
||||||
experience distillation.
|
|
||||||
|
|
||||||
## Where to put target STEP files
|
|
||||||
|
|
||||||
Place STEP or STP files to be reconstructed in:
|
|
||||||
|
|
||||||
```text
|
|
||||||
teacher/inbox/
|
|
||||||
```
|
|
||||||
|
|
||||||
Use unique, stable filenames. Batch inputs are intentionally ignored by Git so
|
|
||||||
large private corpora do not inflate the repository.
|
|
||||||
|
|
||||||
## Where each stage is stored
|
|
||||||
|
|
||||||
| Stage | Directory | Contents |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Source input | `teacher/inbox/` | Original target STEP/STP files. |
|
|
||||||
| Extracted evidence | `teacher/evidence/` | Private geometry facts extracted from each source. |
|
|
||||||
| Agent A input | `reconstruction/inbox/` | Sanitized evidence packets and reconstruction requests. |
|
|
||||||
| Agent A result | `reconstruction/designir/` | Executable `*.designir.json` models. |
|
|
||||||
| Independent rebuild | `reconstruction/output/` | STEP rebuilt without teacher-file access; SimpleCAD jobs may also emit model JSON. |
|
|
||||||
| Agent B input | `acceptance/inbox/` | Acceptance manifests linking teacher, DesignIR, rebuild, and edit contract. |
|
|
||||||
| Acceptance result | `acceptance/reports/` | Geometry, topology, semantic, and parameter-perturbation reports. |
|
|
||||||
| Failed/unsupported | `quarantine/` | Unsupported vocabulary, invalid cases, and failure clusters. |
|
|
||||||
| Experience candidates | `promotion/candidates/` | Generalized methods proposed from validated cases. |
|
|
||||||
| Replay gate | `promotion/replay_validated/` | Methods repeated successfully across independent cases. |
|
|
||||||
| Final distilled result | `promotion/promoted/library.json` | Only deterministic, promoted experience consumed by CAD Router. |
|
|
||||||
|
|
||||||
## Data flow
|
|
||||||
|
|
||||||
```text
|
|
||||||
teacher/inbox/*.step
|
|
||||||
-> teacher/evidence/
|
|
||||||
-> reconstruction/inbox/
|
|
||||||
-> reconstruction/designir/
|
|
||||||
-> reconstruction/output/*.step
|
|
||||||
-> acceptance/inbox/
|
|
||||||
-> acceptance/reports/
|
|
||||||
-> promotion/candidates/
|
|
||||||
-> promotion/replay_validated/
|
|
||||||
-> promotion/promoted/library.json
|
|
||||||
```
|
|
||||||
|
|
||||||
Agent A cannot read `teacher/inbox/`. Agent B may read the teacher STEP and the
|
|
||||||
rebuilt result, but neither agent can directly publish experience. Promotion is
|
|
||||||
performed only by the deterministic policy gate.
|
|
||||||
|
|
||||||
The `.gitkeep` files preserve this layout in Git. Runtime STEP files, evidence,
|
|
||||||
rebuilds, and reports remain local by default.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,494 +0,0 @@
|
|||||||
{
|
|
||||||
"schema_version": "2.0",
|
|
||||||
"library_kind": "generalized_cad_experience",
|
|
||||||
"generated_at": "2026-07-23T08:16:40+00:00",
|
|
||||||
"induction_mode": "llm_proposals_with_deterministic_evidence_verification",
|
|
||||||
"status": "ready",
|
|
||||||
"policy": {
|
|
||||||
"instance_parameters_allowed": false,
|
|
||||||
"absolute_coordinates_allowed": false,
|
|
||||||
"single_case_promotion_allowed": false,
|
|
||||||
"llm_semantic_review_required": true,
|
|
||||||
"draft_evidence_verified": true,
|
|
||||||
"router_consumable": true,
|
|
||||||
"minimum_support": 20,
|
|
||||||
"minimum_confidence": 0.8
|
|
||||||
},
|
|
||||||
"corpus_summary": {
|
|
||||||
"accepted_case_count": 2,
|
|
||||||
"duplicate_case_count": 0,
|
|
||||||
"rejected_case_count": 0,
|
|
||||||
"family_count": 11
|
|
||||||
},
|
|
||||||
"experience_summary": {
|
|
||||||
"llm_proposal_count": 4,
|
|
||||||
"promoted_experience_count": 0,
|
|
||||||
"candidate_experience_count": 4,
|
|
||||||
"by_kind": [],
|
|
||||||
"by_scope": [],
|
|
||||||
"candidate_by_kind": [
|
|
||||||
{
|
|
||||||
"kind": "constraint",
|
|
||||||
"count": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"count": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "validation_rule",
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"experiences": [
|
|
||||||
{
|
|
||||||
"id": "constraint.rotational_part.shared_dominant_axis",
|
|
||||||
"kind": "constraint",
|
|
||||||
"scope": [
|
|
||||||
"rotational_part"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"coaxial_cylindrical_stack",
|
|
||||||
"rotational_body"
|
|
||||||
],
|
|
||||||
"relations": [
|
|
||||||
"dominant_axis_alignment"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"guidance": "Preserve the dominant axis as the organizing datum for rotational feature roles.",
|
|
||||||
"semantic_rationale": "The datum transfers because axis alignment is independent of the individual component dimensions.",
|
|
||||||
"support": 2,
|
|
||||||
"confidence": 1.0,
|
|
||||||
"check": "Confirm that rotational feature roles remain aligned to the same organizing datum.",
|
|
||||||
"promotion_state": "candidate",
|
|
||||||
"required_support": 20,
|
|
||||||
"remaining_support": 18,
|
|
||||||
"required_confidence": 0.8,
|
|
||||||
"consumer_policy": "visible_for_review_but_not_available_to_cad_router"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.rotational_part.coaxial_core_with_center_passage",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"rotational_part"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"circular_equal_radius_pattern"
|
|
||||||
],
|
|
||||||
"relations": [
|
|
||||||
"shared_passage_axis"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"guidance": "Treat the rotational body, coaxial cylindrical stack, and central passage as one shared-axis core.",
|
|
||||||
"semantic_rationale": "The relationship transfers because the participating roles describe axis organization rather than a particular size.",
|
|
||||||
"support": 2,
|
|
||||||
"confidence": 1.0,
|
|
||||||
"check": "Confirm that the rotational body, stacked cylindrical roles, and central passage retain their intended common axis.",
|
|
||||||
"promotion_state": "candidate",
|
|
||||||
"required_support": 20,
|
|
||||||
"remaining_support": 18,
|
|
||||||
"required_confidence": 0.8,
|
|
||||||
"consumer_policy": "visible_for_review_but_not_available_to_cad_router"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.rotational_part.patterned_axial_mounting",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"rotational_part"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"repeated_axial_hole_pattern",
|
|
||||||
"rotational_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 55,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.hollow_or_stepped_shaft.coaxial_cylindrical_stack+stepped_cylindrical_passage",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"hollow_or_stepped_shaft"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"coaxial_cylindrical_stack",
|
|
||||||
"stepped_cylindrical_passage"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 46,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.hollow_or_stepped_shaft.rotational_body+coaxial_cylindrical_stack",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"hollow_or_stepped_shaft"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"coaxial_cylindrical_stack",
|
|
||||||
"rotational_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 46,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.hollow_or_stepped_shaft.shaft_like_body+elongated_body",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"hollow_or_stepped_shaft"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"elongated_body",
|
|
||||||
"shaft_like_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 46,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.multi_axis_manifold.cylindrical_feature_network+multi_axis_passage",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"multi_axis_manifold"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"cylindrical_feature_network",
|
|
||||||
"multi_axis_passage"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 55,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.multi_axis_manifold.planar_dominant_body+multi_level_planar_profile",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"multi_axis_manifold"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"multi_level_planar_profile",
|
|
||||||
"planar_dominant_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 44,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.patterned_plate.cylindrical_feature_network+multi_axis_passage",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"patterned_plate"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"cylindrical_feature_network",
|
|
||||||
"multi_axis_passage"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 76,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.patterned_plate.planar_dominant_body+multi_level_planar_profile",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"patterned_plate"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"multi_level_planar_profile",
|
|
||||||
"planar_dominant_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 202,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.patterned_plate.repeated_axial_hole_pattern+circular_equal_radius_pattern",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"patterned_plate"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"circular_equal_radius_pattern",
|
|
||||||
"repeated_axial_hole_pattern"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 66,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.patterned_prismatic_part.cylindrical_feature_network+multi_axis_passage",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"patterned_prismatic_part"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"cylindrical_feature_network",
|
|
||||||
"multi_axis_passage"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 156,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.patterned_prismatic_part.planar_dominant_body+multi_level_planar_profile",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"patterned_prismatic_part"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"multi_level_planar_profile",
|
|
||||||
"planar_dominant_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 323,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.patterned_prismatic_part.repeated_axial_hole_pattern+circular_equal_radius_pattern",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"patterned_prismatic_part"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"circular_equal_radius_pattern",
|
|
||||||
"repeated_axial_hole_pattern"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 159,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.plate_or_bracket.planar_dominant_body+multi_level_planar_profile",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"plate_or_bracket"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"multi_level_planar_profile",
|
|
||||||
"planar_dominant_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 35,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.prismatic_block.planar_dominant_body+multi_level_planar_profile",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"prismatic_block"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"multi_level_planar_profile",
|
|
||||||
"planar_dominant_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 67,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.rotational_part.coaxial_cylindrical_stack+stepped_cylindrical_passage",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"rotational_part"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"coaxial_cylindrical_stack",
|
|
||||||
"stepped_cylindrical_passage"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 123,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.rotational_part.rotational_body+coaxial_cylindrical_stack",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"rotational_part"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"coaxial_cylindrical_stack",
|
|
||||||
"rotational_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 123,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.shaft.coaxial_cylindrical_stack+stepped_cylindrical_passage",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"shaft"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"coaxial_cylindrical_stack",
|
|
||||||
"stepped_cylindrical_passage"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 40,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.shaft.rotational_body+coaxial_cylindrical_stack",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"shaft"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"coaxial_cylindrical_stack",
|
|
||||||
"rotational_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 40,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "motif.shaft.shaft_like_body+elongated_body",
|
|
||||||
"kind": "feature_motif",
|
|
||||||
"scope": [
|
|
||||||
"shaft"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"elongated_body",
|
|
||||||
"shaft_like_body"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Treat the participating feature roles as one coordinated composition rather than unrelated primitives.",
|
|
||||||
"semantic_rationale": "The composition recurs across independent dimensional variants in the same family.",
|
|
||||||
"support": 40,
|
|
||||||
"confidence": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "reconstruction.flanged_rotational_part.primary",
|
|
||||||
"kind": "reconstruction_grammar",
|
|
||||||
"scope": [
|
|
||||||
"flanged_rotational_part"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"circular_equal_radius_pattern",
|
|
||||||
"coaxial_cylindrical_stack",
|
|
||||||
"cylindrical_feature_network",
|
|
||||||
"multi_level_planar_profile",
|
|
||||||
"repeated_axial_hole_pattern",
|
|
||||||
"rotational_body",
|
|
||||||
"stepped_cylindrical_passage"
|
|
||||||
],
|
|
||||||
"relations": [
|
|
||||||
"repeated_radius_group"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"guidance": "Represent repeated axial holes as a symmetric mounting pattern tied to the rotational body.",
|
|
||||||
"semantic_rationale": "The motif remains useful across variants because it captures repeated functional placement around a rotational form.",
|
|
||||||
"support": 2,
|
|
||||||
"confidence": 1.0,
|
|
||||||
"check": "Confirm that repeated axial holes remain grouped consistently around the rotational body.",
|
|
||||||
"promotion_state": "candidate",
|
|
||||||
"required_support": 20,
|
|
||||||
"remaining_support": 18,
|
|
||||||
"required_confidence": 0.8,
|
|
||||||
"consumer_policy": "visible_for_review_but_not_available_to_cad_router"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "validation.rotational_part.axis_and_pattern_consistency",
|
|
||||||
"kind": "validation_rule",
|
|
||||||
"scope": [
|
|
||||||
"rotational_part"
|
|
||||||
],
|
|
||||||
"when": {
|
|
||||||
"features": [
|
|
||||||
"central_passage",
|
|
||||||
"repeated_axial_hole_pattern"
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
},
|
|
||||||
"guidance": "Validate both the shared rotational axis and the grouped repeated-hole relationship before handoff.",
|
|
||||||
"semantic_rationale": "These checks protect transferable intent without relying on instance geometry.",
|
|
||||||
"support": 2,
|
|
||||||
"confidence": 1.0,
|
|
||||||
"check": "Confirm shared-axis alignment and repeated-hole grouping before treating the model as ready.",
|
|
||||||
"promotion_state": "candidate",
|
|
||||||
"required_support": 20,
|
|
||||||
"remaining_support": 18,
|
|
||||||
"required_confidence": 0.8,
|
|
||||||
"consumer_policy": "visible_for_review_but_not_available_to_cad_router"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -58,7 +58,7 @@ Write `cad-task.json` beside the task artifacts with this minimum shape:
|
|||||||
],
|
],
|
||||||
"parameters": {},
|
"parameters": {},
|
||||||
"experience": {
|
"experience": {
|
||||||
"library": "../../../designir-pipeline/workspace/promotion/promoted/library.json",
|
"library": "../../../designir-pipeline/output/library.json",
|
||||||
"context_kind": "generalized_cad_experience_query",
|
"context_kind": "generalized_cad_experience_query",
|
||||||
"methods_applied": []
|
"methods_applied": []
|
||||||
},
|
},
|
||||||
@@ -74,10 +74,10 @@ have a sibling `*.designir.json` that owns its coordinate system, datums,
|
|||||||
parameters, expressions, features, constraints, edit interface, and validation
|
parameters, expressions, features, constraints, edit interface, and validation
|
||||||
contract. See `designir-2.0.md`.
|
contract. See `designir-2.0.md`.
|
||||||
|
|
||||||
For an uploaded STEP, keep teacher geometry in the protected ingestion and
|
For an uploaded STEP, keep teacher geometry in `designir-pipeline/input/` and
|
||||||
acceptance workspace. The reconstruction task contains private evidence,
|
all private evidence, DesignIR candidates, rebuilds, and acceptance reports in
|
||||||
DesignIR, backend source, and rebuilt STEP but no teacher STEP or imported
|
`designir-pipeline/runs/`. The reconstruction task receives evidence but no
|
||||||
B-Rep.
|
teacher STEP or imported B-Rep.
|
||||||
|
|
||||||
## Backend adapter requirements
|
## Backend adapter requirements
|
||||||
|
|
||||||
|
|||||||
@@ -241,15 +241,13 @@ def default_experience_library() -> Path | None:
|
|||||||
configured = os.environ.get("CAD_EXPERIENCE_LIBRARY", "").strip()
|
configured = os.environ.get("CAD_EXPERIENCE_LIBRARY", "").strip()
|
||||||
if configured:
|
if configured:
|
||||||
return Path(configured).expanduser()
|
return Path(configured).expanduser()
|
||||||
workspace_candidate = (
|
published_candidate = (
|
||||||
SKILL_ROOT.parents[2]
|
SKILL_ROOT.parents[2]
|
||||||
/ "designir-pipeline"
|
/ "designir-pipeline"
|
||||||
/ "workspace"
|
/ "output"
|
||||||
/ "promotion"
|
|
||||||
/ "promoted"
|
|
||||||
/ "library.json"
|
/ "library.json"
|
||||||
)
|
)
|
||||||
return workspace_candidate if workspace_candidate.is_file() else None
|
return published_candidate if published_candidate.is_file() else None
|
||||||
|
|
||||||
|
|
||||||
def classify_edit_context(
|
def classify_edit_context(
|
||||||
@@ -265,20 +263,18 @@ def classify_edit_context(
|
|||||||
(
|
(
|
||||||
SKILL_ROOT.parents[2]
|
SKILL_ROOT.parents[2]
|
||||||
/ "designir-pipeline"
|
/ "designir-pipeline"
|
||||||
/ "workspace"
|
/ "input"
|
||||||
/ "teacher"
|
|
||||||
).resolve(),
|
).resolve(),
|
||||||
(
|
(
|
||||||
SKILL_ROOT.parents[2]
|
SKILL_ROOT.parents[2]
|
||||||
/ "designir-pipeline"
|
/ "designir-pipeline"
|
||||||
/ "workspace"
|
/ "runs"
|
||||||
/ "acceptance"
|
|
||||||
).resolve(),
|
).resolve(),
|
||||||
]
|
]
|
||||||
if any(source == root or root in source.parents for root in protected_roots):
|
if any(source == root or root in source.parents for root in protected_roots):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"cad-router reconstruction cannot read the teacher or acceptance "
|
"cad-router reconstruction cannot read distillation input or run "
|
||||||
"vault; pass the ingestion job reference or an editable DesignIR"
|
"artifacts; pass an editable DesignIR outside the private pipeline"
|
||||||
)
|
)
|
||||||
suffix = source.suffix.lower() if source else ""
|
suffix = source.suffix.lower() if source else ""
|
||||||
text = request.lower()
|
text = request.lower()
|
||||||
|
|||||||
@@ -363,12 +363,10 @@ class CadRouterTests(unittest.TestCase):
|
|||||||
teacher_source = (
|
teacher_source = (
|
||||||
Path(__file__).resolve().parents[5]
|
Path(__file__).resolve().parents[5]
|
||||||
/ "designir-pipeline"
|
/ "designir-pipeline"
|
||||||
/ "workspace"
|
/ "input"
|
||||||
/ "teacher"
|
|
||||||
/ "inbox"
|
|
||||||
/ "part.step"
|
/ "part.step"
|
||||||
)
|
)
|
||||||
with self.assertRaisesRegex(ValueError, "cannot read the teacher"):
|
with self.assertRaisesRegex(ValueError, "cannot read distillation input"):
|
||||||
route_module.route(
|
route_module.route(
|
||||||
self.parse(
|
self.parse(
|
||||||
"修改这个零件",
|
"修改这个零件",
|
||||||
@@ -377,6 +375,23 @@ class CadRouterTests(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_private_run_artifact_is_rejected_as_edit_source(self) -> None:
|
||||||
|
run_source = (
|
||||||
|
Path(__file__).resolve().parents[5]
|
||||||
|
/ "designir-pipeline"
|
||||||
|
/ "runs"
|
||||||
|
/ "designir"
|
||||||
|
/ "part.designir.json"
|
||||||
|
)
|
||||||
|
with self.assertRaisesRegex(ValueError, "cannot read distillation input"):
|
||||||
|
route_module.route(
|
||||||
|
self.parse(
|
||||||
|
"修改这个零件",
|
||||||
|
"--edit-source",
|
||||||
|
str(run_source),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user