Skip to content

fix: accept native FME flag create aliases and align leftover agent docs - #830

Draft
ravindraharness wants to merge 2 commits into
harness:mainfrom
ravindraharness:fme-v4-remaining-native
Draft

fix: accept native FME flag create aliases and align leftover agent docs#830
ravindraharness wants to merge 2 commits into
harness:mainfrom
ravindraharness:fme-v4-remaining-native

Conversation

@ravindraharness

Copy link
Copy Markdown

Description

Follow-up to #806 (feat: FME dual-mode Harness-native scope migration).

#806 already wired Harness-native fme_feature_flag create / update (JSON Merge Patch) / archive / unarchive, plus kill / restore / reallocate aliases onto /fme/api/v4/feature-flag-definitions/{name}/…. This PR does not re-implement those routes. It takes current main (including the #806 squash) and lands the leftover agent-facing gaps that still produce wrong calls or stale “not yet implemented” guidance after that merge.

Dual-mode routing — current main + this PR

Legend: ✅ wired to a real endpoint · 🚫 throws a clear “not yet implemented” error in that mode · ⛔ rejected outright — deprecated resource, use its replacement · — not applicable · bold = changed in this PR

Resource Legacy (workspace_id) Harness-native (org_id+project_id)
fme_workspace ✅ list — (exists only to discover workspace_id)
fme_environment ✅ list ✅ list
fme_feature_flag ✅ list/get/create/delete/update/kill/restore/reallocate/archive/unarchive ✅ list/get/create/delete/update/kill/restore/reallocate/archive/unarchive — create now accepts traffic_type_id / traffic_type as aliases for body.trafficType, and fails closed if name is missing
fme_feature_flag_definition ✅ get/create/update (PUT) ✅ get/create/update (PATCH, JSON Merge Patch)
fme_rollout_status ✅ list 🚫 list
fme_rule_based_segment (deprecated) ✅ list/get/create/delete ⛔ — use fme_segment
fme_rule_based_segment_definition (deprecated) ✅ list/update/enable/disable/change_request ⛔ — use fme_segment_definition
fme_traffic_type ✅ list 🚫 list
fme_identity ✅ create/update 🚫 create/update
fme_standard_segment (deprecated) ✅ list/get ⛔ — use fme_segment
fme_segment_keys ✅ list/update 🚫 list/update
fme_segment ✅ list/get/create/delete (/fme/api/v4/segments)
fme_segment_definition ✅ list/get/create/update/delete (/fme/api/v4/segment-definitions)

Why this follow-up exists

Agents that already know the legacy create contract pass traffic_type_id at the top level (it is a path param on Split v2). Native v4 requires trafficType in the JSON body, not in the path. After #806, that top-level field was ignored and create failed with “trafficType is required in body”, even though the caller had a traffic type. Native create could also POST { name: undefined } if body.name was omitted.

Separately, feature-flag-rollout and the fme_feature_flag test plan/report still described native update / kill / restore / archive / unarchive as NYI, which is no longer true on main.

Key implementation changes

  • src/registry/toolsets/feature-flags.ts — native create bodyBuilder resolves trafficType from body.trafficType, then traffic_type_id, traffic_type, or body.traffic_type. Missing traffic type or missing name throws a clear error. The wire body is still { name, trafficType, description?, tags?, owners? } on POST /fme/api/v4/feature-flags (no traffic type in the path). Tag wrapping continues to use the existing normalizeFmeTags helper from feat: [FME-17249]: FME dual-mode Harness-native scope migration #806.
  • src/prompts/feature-flag-rollout.ts — native-mode caveat no longer tells agents that definitions or kill/restore are unimplemented. The remaining native gap called out is fme_rollout_status.list.
  • docs/testing/fme_feature_flag/test_plan.md / test_report.md — native update / kill / restore / archive / unarchive cases are success paths against the real v4 URLs (kill/restore → definition routes), not NYI errors. Adds TC-026c for the traffic_type_id alias.
  • tests/registry/feature-flags.test.ts — coverage for traffic_type_idbody.trafficType and missing-name fail-closed. Existing feat: [FME-17249]: FME dual-mode Harness-native scope migration #806 tests for merge-patch update, archive/unarchive, and native kill/restore aliases are unchanged.
  • tests/registry/registry.test.ts — fixture proving ResolvedRoute.headers override EndpointSpec.headers (route wins). Dispatch merge itself shipped in feat: [FME-17249]: FME dual-mode Harness-native scope migration #806; this is the missing unit coverage.

Explicitly unchanged (already on main via #806)

  • Native update remains PATCH /fme/api/v4/feature-flags/{name} with Content-Type: application/merge-patch+json on routeResolver.headers, not spec.headers (legacy JSON Patch array is unchanged).
  • Native archive / unarchive remain POST …/archive and …/unarchive.
  • Native kill / restore / reallocate remain aliases onto /fme/api/v4/feature-flag-definitions/{name}/kill|restore|reallocate with environment_id as a query param (POST, not legacy PUT).
  • Legacy workspace_id paths, Split product auth, and JSON Patch update bodies stay as feat: [FME-17249]: FME dual-mode Harness-native scope migration #806 left them.
  • No new server.registerTool(). No fme_environment CRUD beyond list. No native fme_traffic_type / fme_workspace / fme_identity / fme_rollout_status.

Native create body (after this PR)

Field Source Notes
name body.name or input.name required — throws if missing
trafficType body.trafficType | traffic_type_id | traffic_type | body.traffic_type required — in the JSON body, never the path
description body.description optional
tags body.tags optional; strings wrapped as { name }
owners body.owners optional; { type: "USER", id | email } or { type: "GROUP", identifier } — not a string array

Type of Change

  • Bug fix (agent-facing create input + stale docs/prompt)
  • New feature

Checklist

  • pnpm exec vitest run tests/registry/feature-flags.test.ts tests/registry/registry.test.ts — 248 passed
  • pnpm test — full suite not run in this worktree (pnpm typecheck / pnpm build still fail here on missing @huggingface/transformers in the shared node_modules; same as the feat: [FME-17249]: FME dual-mode Harness-native scope migration #806 worktree note)
  • pnpm typecheck — blocked on @huggingface/transformers (pre-existing, not introduced here)
  • pnpm build — same
  • pnpm standards:check
  • pnpm docs:check

Coding Standards (registry-driven MCP model)

  • No new server.registerTool() calls — only toolset definitions in src/registry/toolsets/
  • Toolset registered in ALL_TOOLSETS and ToolsetName union (unchanged — existing feature-flags toolset)
  • operationPolicy on every new/changed endpoint (no new endpoints; create bodyBuilder only)
  • Shared response extractors from src/registry/extractors.ts
  • identifierFields and scope declared on new resources (none added)
  • No console.log() in src/

Test plan

  • Unit: native create with body.trafficType still matches the feat: [FME-17249]: FME dual-mode Harness-native scope migration #806 v4 body shape
  • Unit: native create with top-level traffic_type_id and no body.trafficType POSTs /fme/api/v4/feature-flags with { name, trafficType } and no trafficTypes path segment
  • Unit: native create without name / without traffic type throws and does not call the client
  • Unit: native kill/restore still route to definition URLs (existing feat: [FME-17249]: FME dual-mode Harness-native scope migration #806 tests)
  • Unit: ResolvedRoute.headers win over spec.headers
  • Live QA (optional): harness_create fme_feature_flag with org_id+project_id+traffic_type_id against https://qa.harness.io (Cursor MCP harness-fme-pr1 is HARNESS_READ_ONLY=true; flip that server or use a non-read-only stdio process)

Made with Cursor

Public v4 create already shipped in harness#806, but agents still pass traffic_type_id the way they do for legacy create, and the rollout prompt plus test plan still claimed kill/restore were NYI.

Co-authored-by: Cursor <cursoragent@cursor.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Those markdown files are not part of the create-alias change, and rewriting NYI rows or pass counts without a fresh live run only adds review noise.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants