iop/agent-task/m-oto-bootstrap-command-issue/02+01_agent_register_command/CODE_REVIEW-cloud-G07.md

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 write USER_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-node bootstrap의 필드명, 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] 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.

각 항목의 구현을 실제 소스 파일과 대조하고, 검증 결과 섹션의 출력이 코드와 일치하는지 확인하세요. 리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.

  1. 판정을 append한다.
  2. CODE_REVIEW-{review_lane}-GNN.md -> code_review_{review_lane}_GNN_N.log, PLAN-{build_lane}-GNN.md -> plan_{build_lane}_GNN_M.log로 아카이브한다.
  3. 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 이동한다.
  4. PASS이고 task group이 m-<milestone-slug>이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 update-roadmap 호출은 런타임 책임이다.
  5. 적용 가능한 코드리뷰 전용 체크리스트 항목을 최종 .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??.mdcode_review_{review_lane}_GNN_N.log로 아카이브한다.
  • active PLAN-*-G??.mdplan_{build_lane}_GNN_M.log로 아카이브한다.
  • .gitignore의 Agent-Ops 관리 block이 agent-task/**/*.mdagent-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.mdCODE_REVIEW-{review_lane}-GNN.md를 작성하고 complete.log를 작성하지 않는다.
  • USER_REVIEW이면 agent-ops/skills/common/code-review/templates/user-review-template.md 기준으로 USER_REVIEW.md를 작성하고 active PLAN-*.md, CODE_REVIEW-*.md, complete.log를 남기지 않는다.
  • USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 USER_REVIEW.md를 해소 상태로 갱신하고 complete.log를 작성한 뒤 task directory를 archive로 이동한다.

계획 대비 변경 사항

계획에 명시된 모든 설계와 기능을 준수하여 구현하였으며, 특이 사항이나 계획 대비 변경 사항은 없습니다.

주요 설계 결정

  • URL 스키마 검증 강제화: release-base-urlhttps://로 시작하지 않을 시 에러를 유발하여 보안 정책을 고수했습니다. bootstrap-script-url은 기본으로 https://를 사용하되, 로컬/개발 편의성을 고려해 --allow-insecure-bootstrap-url 플래그가 수동으로 지정되었을 경우에만 http://도 사용 가능하게 통제하였습니다.
  • OTO Node 구조 통일: OTO agent record가 upsert될 때, agent_kindoto-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.