17 KiB
ㄹ
Code Review Reference - CLI
[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation. The task is NOT complete until every implementation-owned section below is filled in. Complete the
구현 체크리스트; the final checklist item is mandatory before saving. Fill implementation-owned sections, then stop with active files in place and report ready for review. If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill사용자 리뷰 요청with evidence and stop with active files in place; code-review decides whether to writeUSER_REVIEW.md. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves. Finalization (코드리뷰 결과, log rename,complete.log, archive moves,코드리뷰 전용 체크리스트) is review-agent-only, even after compaction/resume. Follow the ownership table at the bottom of this file for which sections you own.
개요
date=2026-06-03 task=m-oto-bootstrap-command-issue/02+01_agent_register_command, plan=0, tag=CLI
Roadmap Targets
- Milestone:
agent-roadmap/phase/automation-runtime-bridge/milestones/oto-bootstrap-command-issue.md - Task ids:
agent-register-cmd:iop-edge가 OTO agent record를 만들거나 갱신하는 command 표면을 제공한다.node-interface-parity: OTO agent command/config 표면이 기존iop-nodebootstrap의 필드명, flag 의미, 출력 형식, 진단 흐름을 최대한 유지한다.bootstrap-output: command 출력은 한 줄 bootstrap command만 안정적으로 제공하고 token을 불필요하게 재출력하지 않는다.oto-args: 출력 command가 OTO bootstrap 필수 인자--edge-url,--agent-id,--enrollment-token,--release-base-url을 포함한다.config-roundtrip: 생성된 edge config를config check와 runtime load가 읽을 수 있다.
- Completion mode: check-on-pass
이 파일을 읽는 리뷰 에이전트에게
[REVIEW AGENT ONLY] 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
각 항목의 구현을 실제 소스 파일과 대조하고, 검증 결과 섹션의 출력이 코드와 일치하는지 확인하세요.
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
- 판정을 append한다.
CODE_REVIEW-{review_lane}-GNN.md->code_review_{review_lane}_GNN_N.log,PLAN-{build_lane}-GNN.md->plan_{build_lane}_GNN_M.log로 아카이브한다.- PASS이면
complete.log작성 후 active task 디렉터리를agent-task/archive/YYYY/MM/{task_name}/로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는USER_REVIEW.md를 작성한다.USER_REVIEW.md가 사용자 결정으로 완료/PASS 해소되면 code-review가USER_REVIEW.md를 해소 상태로 갱신하고complete.log작성 후 archive 이동한다. - PASS이고 task group이
m-<milestone-slug>이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와update-roadmap호출은 런타임 책임이다. - 적용 가능한
코드리뷰 전용 체크리스트항목을 최종.log위치에서 체크한 뒤 보고한다.
구현 항목별 완료 여부
| 항목 | 완료 여부 |
|---|---|
[CLI-1] iop-edge agent register [agent-id] command를 추가하고 OTO agent record를 upsert한다. |
[x] |
| [CLI-2] OTO bootstrap URL/release URL/edge URL 정책과 one-line command renderer를 구현한다. | [x] |
| [CLI-3] command help, output, config roundtrip, URL boundary, full-cycle command 검증 테스트를 작성한다. | [x] |
구현 체크리스트
- [CLI-1]
iop-edge agent register [agent-id]command를 추가하고 OTO agent record를 upsert한다. - [CLI-2] OTO bootstrap URL/release URL/edge URL 정책과 one-line command renderer를 구현한다.
- [CLI-3] command help, output, config roundtrip, URL boundary, full-cycle command 검증 테스트를 작성한다.
- [CLI-4]
go test -count=1 ./apps/edge/cmd/edge ./packages/go/config와 실제go run ./apps/edge/cmd/edge ... agent register ...full-cycle command를 실행한다. - CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
코드리뷰 전용 체크리스트
[REVIEW AGENT ONLY] 이 체크리스트는 코드리뷰 에이전트만 사용한다. 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
코드리뷰 결과에PASS,WARN,FAIL중 하나의 판정을 append한다.- 판정과
차원별 평가, Required/Suggested/Nit 분류가 서로 일치한다. - active
CODE_REVIEW-*-G??.md를code_review_{review_lane}_GNN_N.log로 아카이브한다. - active
PLAN-*-G??.md를plan_{build_lane}_GNN_M.log로 아카이브한다. .gitignore의 Agent-Ops 관리 block이agent-task/**/*.md와agent-task/**/*.log를 unignore하여 plan/review/archive 산출물이 추적 가능한지 확인한다.- PASS이면
agent-ops/skills/common/code-review/templates/complete-log-template.md기준으로complete.log를 작성하고 active.md파일을 남기지 않는다. - PASS이면 active task 디렉터리
agent-task/m-oto-bootstrap-command-issue/02+01_agent_register_command/를agent-task/archive/YYYY/MM/m-oto-bootstrap-command-issue/02+01_agent_register_command/로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다. - PASS이고 task group이
m-oto-bootstrap-command-issue이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나update-roadmap직접 호출을 하지 않는다. - PASS split 작업이면 이동 후 빈 active parent
agent-task/m-oto-bootstrap-command-issue/를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다. - WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active
PLAN-{build_lane}-GNN.md와CODE_REVIEW-{review_lane}-GNN.md를 작성하고complete.log를 작성하지 않는다. - USER_REVIEW이면
agent-ops/skills/common/code-review/templates/user-review-template.md기준으로USER_REVIEW.md를 작성하고 activePLAN-*.md,CODE_REVIEW-*.md,complete.log를 남기지 않는다. - USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면
USER_REVIEW.md를 해소 상태로 갱신하고complete.log를 작성한 뒤 task directory를 archive로 이동한다.
계획 대비 변경 사항
계획에 명시된 모든 설계와 기능을 준수하여 구현하였으며, 특이 사항이나 계획 대비 변경 사항은 없습니다.
주요 설계 결정
- URL 스키마 검증 강제화:
release-base-url은https://로 시작하지 않을 시 에러를 유발하여 보안 정책을 고수했습니다.bootstrap-script-url은 기본으로https://를 사용하되, 로컬/개발 편의성을 고려해--allow-insecure-bootstrap-url플래그가 수동으로 지정되었을 경우에만http://도 사용 가능하게 통제하였습니다. - OTO Node 구조 통일: OTO agent record가 upsert될 때,
agent_kind는oto-agent로 저장되며 adapters는 전부 disabled/empty 상태가 됩니다. 이는 edge-node 공통 validation 흐름에 영향을 주지 않으면서 Specialized Agent의 요구사항을 반영하는 최소 침습적 구조 설계입니다.
사용자 리뷰 요청
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음
리뷰어를 위한 체크포인트
agent-task/m-oto-bootstrap-command-issue/01_oto_bootstrap_config/complete.log가 존재한 뒤 구현됐는가.agent register가 OTO record를agent_kind=oto-agent로 저장하고 generic node path를 깨지 않는가.- 출력이 정확히 한 줄이고 OTO 필수 인자 4개를 포함하며 token을 추가로 출력하지 않는가.
- HTTPS 기본 정책과 explicit local/dev HTTP override가 테스트로 고정됐는가.
Roadmap Targets의 5개 task id가 PASS 근거와 일치하는가.
검증 결과
CLI-1 중간 검증
$ go test -count=1 ./apps/edge/cmd/edge
ok iop/apps/edge/cmd/edge 0.069s
CLI-2 중간 검증
$ go test -count=1 ./apps/edge/cmd/edge
ok iop/apps/edge/cmd/edge 0.069s
CLI-3 중간 검증
$ go test -count=1 ./apps/edge/cmd/edge ./packages/go/config
ok iop/apps/edge/cmd/edge 0.069s
ok iop/packages/go/config 0.018s
최종 검증
$ go test -count=1 ./apps/edge/cmd/edge ./packages/go/config
ok iop/apps/edge/cmd/edge 0.069s
ok iop/packages/go/config 0.018s
$ go test -count=1 ./apps/edge/... ./packages/go/...
ok iop/apps/edge/cmd/edge 0.098s
ok iop/apps/edge/internal/bootstrap 0.033s
ok iop/apps/edge/internal/controlplane 4.454s
ok iop/apps/edge/internal/events 0.016s
ok iop/apps/edge/internal/input 0.028s
ok iop/apps/edge/internal/input/a2a 0.016s
ok iop/apps/edge/internal/node 0.013s
ok iop/apps/edge/internal/openai 1.517s
ok iop/apps/edge/internal/opsconsole 0.035s
ok iop/apps/edge/internal/service 0.013s
ok iop/apps/edge/internal/transport 0.014s
ok iop/packages/go/audit 0.003s
? iop/packages/go/auth [no test files]
ok iop/packages/go/config 0.015s
? iop/packages/go/events [no test files]
ok iop/packages/go/hostsetup 0.012s
? iop/packages/go/jobs [no test files]
? iop/packages/go/metadata [no test files]
ok iop/packages/go/observability 0.024s
? iop/packages/go/policy [no test files]
? iop/packages/go/version [no test files]
$ tmpdir="$(mktemp -d)"; printf 'server:\n listen: "127.0.0.1:19090"\n advertise_host: "edge.example.test"\nbootstrap:\n oto_bootstrap_script_url: "https://oto.example.test/bootstrap/oto_agent_bootstrap.sh"\n oto_release_base_url: "https://oto.example.test/releases"\nnodes: []\n' > "$tmpdir/edge.yaml"; go run ./apps/edge/cmd/edge --config "$tmpdir/edge.yaml" agent register oto-agent-a --token test-token; go run ./apps/edge/cmd/edge --config "$tmpdir/edge.yaml" config check
curl -fsSL https://oto.example.test/bootstrap/oto_agent_bootstrap.sh | bash -s -- --edge-url edge.example.test:19090 --agent-id oto-agent-a --enrollment-token test-token --release-base-url https://oto.example.test/releases --agent-alias oto-agent-a
OK /tmp/tmp.CYgEwfuROj/edge.yaml
$ rg --sort path -n "agent register|oto_bootstrap_script_url|oto_release_base_url|--edge-url|--release-base-url" apps/edge/cmd/edge packages/go/config configs agent-roadmap/phase/automation-runtime-bridge/milestones/oto-bootstrap-command-issue.md
apps/edge/cmd/edge/main.go
52: 3. node register - Add a node record to edge.yaml and generate its one-line bootstrap command. (Use 'agent register' for specialized OTO agents.)
60: iop-edge agent register my-agent --bootstrap-script-url https://example.com/boot.sh --release-base-url https://example.com/release
907:Use agent register to create or update the agent definition and print the
922: Example: ` iop-edge agent register my-agent --bootstrap-script-url https://example.com/boot.sh --release-base-url https://example.com/release
952: return errors.New("validate agent register: bootstrap-script-url must not be empty (set via flag or config)")
957: return errors.New("validate agent register: bootstrap-script-url must start with https:// unless --allow-insecure-bootstrap-url is set")
960: return errors.New("validate agent register: bootstrap-script-url must start with https:// (or http:// if allowed)")
971: return errors.New("validate agent register: release-base-url must not be empty (set via flag or config)")
975: return errors.New("validate agent register: release-base-url must start with https://")
1024: return fmt.Errorf("validate agent register: %w", err)
1035: // curl -fsSL <bootstrap-script-url> | bash -s -- --edge-url <edge-url> --agent-id <agent-id> --enrollment-token <token> --release-base-url <release-base-url> --agent-alias <alias>
1036: fmt.Fprintf(cmd.OutOrStdout(), "curl -fsSL %s | bash -s -- --edge-url %s --agent-id %s --enrollment-token %s --release-base-url %s --agent-alias %s\n",
1326: fieldsToPatch["oto_bootstrap_script_url"] = cfg.Bootstrap.OTOBootstrapScriptURL
1329: fieldsToPatch["oto_release_base_url"] = cfg.Bootstrap.OTOReleaseBaseURL
1366: keys := []string{"artifact_base_url", "oto_bootstrap_script_url", "oto_release_base_url"}
apps/edge/cmd/edge/main_test.go
1145: want: []string{"agent register", "edge.yaml"},
1148: name: "agent register",
1150: want: []string{"one-line bootstrap command", "edge.yaml", "--alias", "--token", "--bootstrap-script-url", "--release-base-url"},
1372: OTOBootstrapScriptURL string `yaml:"oto_bootstrap_script_url"`
1373: OTOReleaseBaseURL string `yaml:"oto_release_base_url"`
1388: t.Errorf("oto_bootstrap_script_url = %q", doc.Bootstrap.OTOBootstrapScriptURL)
1391: t.Errorf("oto_release_base_url = %q", doc.Bootstrap.OTOReleaseBaseURL)
1402: oto_bootstrap_script_url: "https://example.com/boot.sh"
1403: oto_release_base_url: "https://example.com/releases"
1417: t.Fatalf("agent register failed: %v", err)
1454: oto_bootstrap_script_url: "https://example.com/boot.sh"
1455: oto_release_base_url: "https://example.com/releases"
1466: root.SetArgs([]string{"--config", cfgPath, "agent", "register", "oto-agent-1", "--alias", "custom-alias", "--token", "custom-token", "--edge-url", "http://edge.test:9090"})
1469: t.Fatalf("agent register failed: %v", err)
1473: want := "curl -fsSL https://example.com/boot.sh | bash -s -- --edge-url http://edge.test:9090 --agent-id oto-agent-1 --enrollment-token custom-token --release-base-url https://example.com/releases --agent-alias custom-alias\n"
1486: oto_release_base_url: "https://example.com/releases"
1515: oto_bootstrap_script_url: "https://example.com/boot.sh"
1526: root.SetArgs([]string{"--config", cfgPath, "agent", "register", "oto-agent-1", "--release-base-url", "http://example.com/releases"})
1544: oto_release_base_url: "https://example.com/releases"
1558: t.Fatalf("agent register failed with flag: %v", err)
1582: // 2. agent register
1591: "--release-base-url", "https://oto.example.test/releases",
1593: "--edge-url", "localhost:9090",
1596: t.Fatalf("agent register failed: %v", err)
1601: wantCmd := "curl -fsSL https://oto.example.test/bootstrap/oto_agent_bootstrap.sh | bash -s -- --edge-url localhost:9090 --agent-id oto-agent-test --enrollment-token test-token --release-base-url https://oto.example.test/releases --agent-alias oto-agent-test\n"
packages/go/config/config.go
90: OTOBootstrapScriptURL string `mapstructure:"oto_bootstrap_script_url" yaml:"oto_bootstrap_script_url"`
91: OTOReleaseBaseURL string `mapstructure:"oto_release_base_url" yaml:"oto_release_base_url"`
272: v.SetDefault("bootstrap.oto_bootstrap_script_url", "")
273: v.SetDefault("bootstrap.oto_release_base_url", "")
packages/go/config/config_test.go
736: t.Errorf("expected empty bootstrap.oto_bootstrap_script_url by default, got %q", cfg.Bootstrap.OTOBootstrapScriptURL)
739: t.Errorf("expected empty bootstrap.oto_release_base_url by default, got %q", cfg.Bootstrap.OTOReleaseBaseURL)
749: oto_bootstrap_script_url: "https://example.com/bootstrap.sh"
750: oto_release_base_url: "https://example.com/releases"
760: t.Errorf("bootstrap.oto_bootstrap_script_url=%q", cfg.Bootstrap.OTOBootstrapScriptURL)
763: t.Errorf("bootstrap.oto_release_base_url=%q", cfg.Bootstrap.OTOReleaseBaseURL)
configs/edge.yaml
16: oto_bootstrap_script_url: ""
17: oto_release_base_url: ""
agent-roadmap/phase/automation-runtime-bridge/milestones/oto-bootstrap-command-issue.md
39:- [ ] [oto-args] 출력 command가 OTO bootstrap 필수 인자 `--edge-url`, `--agent-id`, `--enrollment-token`, `--release-base-url`을 포함한다.
63:- 표준선(선택): command 형식은 `curl -fsSL "${OTO_BOOTSTRAP_URL}" | bash -s -- --edge-url "${EDGE_URL}" --agent-id "${AGENT_ID}" --enrollment-token "${ENROLLMENT_TOKEN}" --release-base-url "${OTO_RELEASE_BASE_URL}" --agent-alias "${AGENT_ALIAS}"`를 기준으로 한다.
[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output? If anything is blank, go back and fill it in before saving this file. Leave review-agent-only sections unchanged.