Formly Agent Contracts
Formly Contract
Formly Contract는 Angular Formly 필드 구성을 안정적이고 버전 관리되는 JSON으로 변환하여, E2E 테스트 작성자나 코딩 에이전트가 폼의 구조를 추측하지 않고도 이해할 수 있게 해줍니다.
FormlyFieldConfig[]가 주어지면, 어댑터는 다음을 설명합니다:
폼의 컨트롤, 표시 콘텐츠, 그룹 및 반복 가능한 템플릿;
각 필드의 모델 경로, Formly 타입, 라벨, 제약 조건 및 선택 항목;
알려진 표시 여부, 필수, 읽기 전용, 비활성화 및 동적 옵션 동작;
data-testid,data-test-id,data-cy와 같은 정확하거나 애플리케이션에서 파생된 테스트 로케이터;구성에서 직접 온 것, 제어된 Formly 빌드에서 해석된 것, 아직 알 수 없는 것; 그리고
안전하게 표현할 수 없는 동작에 대한 안정적인 진단 정보.
결과물은 엄격한 런타임 검증, 표준 직렬화 및 콘텐츠 해시를 갖춘 결정론적 Form Contract입니다. 이 계약은 Cypress/Playwright 테스트 계획과 향후 에이전트 도구를 위한 신뢰할 수 있는 입력으로 의도되었습니다. Formly의 실시간 런타임 객체 덤프가 아닙니다.
현재 제공되는 것
이 저장소는 현재 스키마 v0.3과 두 개의 워크스페이스 패키지를 제공합니다:
패키지 | 용도 |
| 계약 DTO, 런타임 검증, 표준 JSON 및 SHA-256 콘텐츠 해싱 |
| Formly 6.1을 위한 안전한 선언적 추출 및 신뢰할 수 있는 시나리오 컴파일 |
또한 다음을 포함합니다:
합성 골든 폼을 사용하는 결정론적 CLI 데모;
12개의 합성 Formly 픽스처를 갖춘 브라우저 렌더링 Angular 테스트 애플리케이션; 그리고
고정된 Angular
20.3.29및 Formly6.1.8조합에 대한 호환성 커버리지.
파서와 계약이 현재 제품입니다. 프로덕션 MCP 서버, 자동 Playwright 생성, 브라우저 관찰 및 애플리케이션 소스 탐지는 향후 계층이며 이 MVP에는 포함되지 않습니다.
Related MCP server: SpecBridge MCP
자신의 Angular/Formly 코드베이스에서 사용하기
이 패키지는 Angular 애플리케이션 옆에서 빌드/테스트 도구로 실행됩니다. 애플리케이션의 브라우저 번들에 추가할 필요는 없습니다. 일반적인 도입 흐름은 다음과 같습니다:
application-owned Formly factories
|
generation script or CI job
|
versioned contract JSON
|
Playwright / Cypress / agent tooling1. 패키지 추가
패키지는 아직 npm에 게시되지 않았습니다. 첫 릴리스 전까지는 이 저장소를 사용하는 애플리케이션 옆에 복제하고 두 패키지를 빌드하세요:
git clone https://github.com/dills122/formly-contract.git
cd formly-contract
pnpm install --frozen-lockfile
pnpm --filter @formly-contract/contract-schema build
pnpm --filter @formly-contract/formly-adapter build그런 다음 사용하는 애플리케이션의 package.json에서 링크하세요(체크아웃 경로에 맞게 상대 경로를 조정하세요):
{
"devDependencies": {
"@formly-contract/contract-schema": "link:../formly-contract/packages/contract-schema",
"@formly-contract/formly-adapter": "link:../formly-contract/packages/formly-adapter"
}
}사용하는 애플리케이션에서 pnpm install을 실행하세요. 애플리케이션은 이미 호환되는 Angular 및 Formly 피어 의존성을 제공해야 합니다. 현재 테스트된 조합은 Angular 20.3.29와 Formly 6.1.8입니다. 패키지가 게시되면 일반적인 버전 관리 pnpm add --save-dev 의존성이 이러한 로컬 링크를 대체합니다.
2. 노출할 폼 선택
애플리케이션 소스 탐지는 의도적으로 자동화되지 않았습니다. 계약 생성기가 검사하기를 원하는 폼 팩토리만 가져오는 작은 애플리케이션 소유 레지스트리를 만드세요:
// tools/contract-forms.ts
import type { FormlyFieldConfig } from '@ngx-formly/core';
import { createClaimFields } from '../src/app/claims/claim.fields';
import { createCustomerFields } from '../src/app/customers/customer.fields';
export interface ContractFormTarget {
id: string;
createFields: () => FormlyFieldConfig[];
}
export const contractForms: ContractFormTarget[] = [
{ id: 'claims.create', createFields: () => createClaimFields() },
{ id: 'customers.edit', createFields: () => createCustomerFields() },
];각 팩토리는 새로운 필드 트리를 반환해야 합니다. 팩토리에 애플리케이션 입력이 필요한 경우, 로컬 개발 및 CI에서 사용하기 안전한 합성 값으로 클로저로 감싸세요.
3. 계약 아티팩트 생성
애플리케이션 저장소에 빌드 타임 스크립트를 추가하세요:
// tools/generate-form-contracts.ts
import { mkdir, writeFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { canonicalStringify } from '@formly-contract/contract-schema';
import { extractFormContract } from '@formly-contract/formly-adapter';
import { contractForms } from './contract-forms';
const outputDirectory = resolve('artifacts/form-contracts');
await mkdir(outputDirectory, { recursive: true });
for (const target of contractForms) {
const { contract, diagnostics } = extractFormContract({
formId: target.id,
fields: target.createFields(),
});
await writeFile(
resolve(outputDirectory, `${target.id}.json`),
`${canonicalStringify(contract)}\n`,
);
console.log(
`${target.id}: ${contract.nodes.length} root nodes, ${diagnostics.length} diagnostics`,
);
}이 파일을 사용하는 저장소에서 이미 사용 중인 TypeScript 러너로 실행하거나 Node 대상 도구 프로젝트의 일부로 컴파일하세요. 결과 JSON은 검토를 위해 커밋하거나, CI 아티팩트로 업로드하거나, 다운스트림 테스트 작성 도구에서 읽을 수 있습니다. 표준 형식이고 콘텐츠 해시가 있으므로 예기치 않은 폼 계약 변경은 소스 제어 또는 CI에서 확인할 수 있습니다.
이 선언적 경로가 가장 좋은 시작점입니다. 임의의 애플리케이션 코드를 실행하지 않고 정적 구조를 캡처하고 표현식 콜백을 동적 메타데이터로 기록합니다.
4. Playwright에서 계약 사용
저장된 JSON을 신뢰하기 전에 검증하고, 필요한 의미론적 노드를 찾은 다음 정확한 로케이터 후보 중 하나를 사용하세요. 표준 data-testid 로케이터의 경우:
import { readFile } from 'node:fs/promises';
import {
parseFormContract,
type ContractNode,
type ModelPathSegment,
} from '@formly-contract/contract-schema';
function findNodeByPath(
nodes: readonly ContractNode[],
modelPath: readonly ModelPathSegment[],
): ContractNode | undefined {
for (const node of nodes) {
if (
node.modelPath.length === modelPath.length &&
node.modelPath.every((segment, index) => segment === modelPath[index])
) {
return node;
}
const nested = findNodeByPath(
node.arrayTemplate
? [...node.children, node.arrayTemplate]
: node.children,
modelPath,
);
if (nested) return nested;
}
}
const contract = parseFormContract(
JSON.parse(
await readFile('artifacts/form-contracts/claims.create.json', 'utf8'),
),
);
const claimantName = findNodeByPath(contract.nodes, ['claimant', 'name']);
const testId = claimantName?.locators.find(
(locator) =>
locator.strategy === 'testId' && locator.attribute === 'data-testid',
);
if (!claimantName || !testId) {
throw new Error('claimant.name has no exact data-testid locator');
}
await page.getByTestId(testId.value).fill('Ada Lovelace');실제 사용자는 일반적으로 재귀적 노드 조회와 로케이터 선택을 공유 Playwright 또는 Cypress 헬퍼에 넣습니다. 복합 컨트롤은 여러 로케이터 대상을 노출할 수 있으므로 헬퍼는 하나의 Formly 노드가 항상 하나의 DOM 요소에 매핑된다고 가정하지 말고 target으로 선택해야 합니다. 빈 로케이터 배열과 진단 정보는 누락된 증거로 처리해야 하며, 임의로 만든 선택자로 대체해서는 안 됩니다.
5. 필요할 때 동적 동작 해석
표현식이 표시 여부, 필수/읽기 전용 상태 또는 옵션 목록을 결정하는 경우 합성 시나리오를 추가하고 compileFormContractScenario를 호출하세요. 애플리케이션의 실제 Formly 모듈과 사용자 정의 타입으로 구성된 신뢰할 수 있는 Angular 테스트/빌드 환경에서 해당 API를 실행하세요. 합성 모델 및 폼 상태 데이터만 사용하여 의미 있는 시나리오마다 하나의 아티팩트를 생성하세요.
합성 호환성 하네스는 FormlyFormBuilder를 얻기 위한 완전한 Angular TestBed 설정을 보여줍니다. 아래의 상세 API 예제는 시나리오 호출을 보여줍니다.
이것이 왜 유용한가
대규모 Formly 폼은 종종 중첩 그룹, 공유 프래그먼트, 사용자 정의 필드 타입, 표현식, 동적 선택 항목 및 애플리케이션 규칙으로 구성됩니다. 해당 소스를 반복적으로 읽는 것은 느리며, 렌더링된 페이지에서 추측하는 것은 취약한 테스트로 이어집니다.
이 프로젝트는 작고 명확한 경계를 만듭니다:
Formly fields + synthetic scenario
|
safe contract projection
|
deterministic versioned JSON
|
E2E planning / agent inspection사용자는 하나의 계약을 검사하여 다음과 같은 질문에 답할 수 있습니다:
어떤 컨트롤이 존재하며, 어떤 순서로 존재하나요?
각 컨트롤은 어떤 모델 값을 편집하나요?
어떤 값과 검증 경계가 알려져 있나요?
선택 목록이 비어 있나요, 정적, 동적 또는 비동기인가요?
어떤 필드가 숨겨지거나, 필수, 읽기 전용 또는 비활성화될 수 있나요?
어떤
data-*, 역할, 라벨, 플레이스홀더 또는 DOM-ID 로케이터 후보를 사용할 수 있나요?어떤 사실이 정확하거나, 파생되었거나, 하나의 시나리오에 대해 해석되었거나, 여전히 알 수 없나요?
이 저장소 사용해 보기
전제 조건:
Node.js
22.22.1pnpm
10.23.0
pnpm install --frozen-lockfile
pnpm demopnpm demo는 패키지 일부를 빌드하고 하나의 표준 JSON 계약을 출력합니다. 전체 저장소 게이트를 실행하려면:
pnpm check이 명령은 린트, 모든 테스트, 패키지 및 Angular 프로덕션 빌드, 데모 스모크 테스트 및 문서 검사를 실행합니다.
선언된 폼 구조 추출
콜백을 실행하지 않고 Formly 구성을 검사하려면 extractFormContract를 사용하세요:
import { extractFormContract } from '@formly-contract/formly-adapter';
import type { FormlyFieldConfig } from '@ngx-formly/core';
const fields: FormlyFieldConfig[] = [
{
key: 'profile.name',
type: 'input',
props: {
label: 'Name',
required: true,
attributes: { 'data-testid': 'profile-name' },
},
},
];
const { contract, diagnostics } = extractFormContract({
formId: 'example.profile',
fields,
});이 경로는 순수하고 비변경적입니다. 표현식 함수를 호출하지 않고, Observable을 구독하지 않으며, 검증기를 실행하지 않고, Angular 컴포넌트를 렌더링하지 않습니다. 인식된 콜백은 동적 규칙 메타데이터가 되고, 지원되지 않는 동작은 명시적 진단 정보가 됩니다. 반환된 노드는 안정적인 ID example.profile::path:s_profile.s_name, 모델 경로 ['profile', 'name'], 필수 제약 조건 및 정확한 data-testid 로케이터를 갖습니다.
합성 시나리오 해석
필수, 읽기 전용, 비활성화, 숨김, 옵션 또는 로케이터 속성이 Formly 표현식 콜백에 의존하는 경우 compileFormContractScenario를 사용하세요:
import { inject } from '@angular/core';
import { FormlyFormBuilder } from '@ngx-formly/core';
import { compileFormContractScenario } from '@formly-contract/formly-adapter';
const builder = inject(FormlyFormBuilder);
const { contract, diagnostics } = compileFormContractScenario({
formId: 'example.profile',
builder,
createFields: () => createProfileFields(),
model: { contactMethod: 'email' },
formState: { readonly: false },
});이것은 신뢰할 수 있는 빌드/CI API입니다. 애플리케이션에 구성된 FormlyFormBuilder를 사용하므로 애플리케이션 및 Formly 콜백이 실행될 수 있습니다. 모델과 폼 상태는 구조적 복제가 가능해야 하며, 필드 팩토리 또는 빌더가 실행되기 전에 둘 다 복제됩니다.
빌드된 필드 트리는 여전히 선언적 추출과 동일한 허용 목록을 통과합니다. 예를 들어, 동적 옵션은 애플리케이션 객체에서 임의의 속성을 복사하는 대신 공개 label/value/disabled 레코드로 축소됩니다.
이 컴파일러를 MCP 또는 기타 신뢰할 수 없는 요청 핸들러에서 직접 노출하지 마세요. 쿼리 계층은 이전에 생성된 계약 아티팩트를 읽어야 합니다.
테스트 로케이터
모든 노드에는 순서가 있는 locators 배열이 있습니다. 어댑터는 props.attributes에서 다음 공통 속성을 자동으로 읽습니다:
data-testiddata-test-iddata-testdata-cydata-pw
명시적 역할, 접근 가능한 이름, 플레이스홀더 및 Formly 필드 ID 후보도 유지할 수 있습니다. 빈 배열은 신뢰할 수 있는 로케이터가 없음을 의미합니다. 어댑터는 CSS나 XPath를 절대 임의로 만들지 않습니다.
자체 명명 규칙을 가진 애플리케이션은 testIdAttributes를 설정하고 결정론적 deriveLocators 콜백을 제공할 수 있습니다. 콜백은 실제 Formly 필드가 아닌 동결된 ID 데이터만 받습니다. 날짜 범위와 같은 복합 위젯에 대해 여러 명명된 대상을 반환할 수 있습니다. 출력은 confidence: "derived"로 표시됩니다. 전체 계약 및 예제는 v0.3 로케이터 사양을 참조하세요.
증거 모델
계약은 세 가지 증거 수준을 분리하여 유지합니다:
증거 | 의미 | 현재 사용 가능 여부 |
| 제공된 Formly 구성에서 안전하게 읽음 | 예 |
| 하나의 합성 시나리오에 대한 제어된 Formly 빌드에서 읽음 | 예 |
| 실제 렌더링된 브라우저 DOM에서 관찰됨 | 스키마 준비 완료; 캡처 계층 미구현 |
해석된 로케이터는 브라우저에서 관찰된 것으로 조용히 제시되지 않습니다. 마찬가지로 불투명하거나 비동기적인 동작은 추측되지 않고 보고됩니다.
지원되는 계약 정보
스키마 v0.3은 다음을 표현할 수 있습니다:
순서가 있는 컨트롤, 그룹, 표시 전용 노드 및 배열 템플릿;
안정적인 의미론적 노드 ID 및 누적 모델 경로;
Formly 및 일반적인 의미론적 컨트롤 타입;
라벨, 설명, 플레이스홀더, JSON 안전 기본값 및 래퍼;
필수, 최소/최대, 길이, 문자열 패턴 및 명명된 제약 조건;
정적 및 해석된 공개 옵션과 동적/비동기 옵션 소스 메타데이터;
문자열/불리언 조건 및 콜백/비동기 동적 규칙 메타데이터;
해석된 숨김, 읽기 전용 및 비활성화 상태;
여러 명명된 대상을 포함한 정확하고 파생된 로케이터 후보; 그리고
결정론적 진단 정보, 표준 JSON 및 콘텐츠 해싱.
의도된 제한 사항
폼은 명시적으로 제공되어야 합니다. 어댑터는 임의의 TypeScript 내보내기나 애플리케이션 경로를 발견하지 않습니다.
선언적 추출은 함수나 함수 소스를 절대 평가하지 않습니다.
시나리오 컴파일러는 초기 제어된 Formly 빌드를 수행하지만 원격 옵션이나 수명 주기 기반 브라우저 동작을 기다리지 않습니다.
Formly
RegExp패턴은 진단됩니다. v0.3은 문자열 패턴만 표현합니다.사용자 정의 위젯 동작과 값 코덱은 아직 모델링되지 않았습니다.
프로젝트는 현재 Cypress/Playwright 테스트를 생성하거나 실행하지 않습니다.
프로덕션 MCP 서버나 브라우저 관찰 계층은 포함되지 않습니다.
호환성은 Angular
20.3.29와 Formly6.1.8조합에 대해 입증되었으며 모든 Angular/Formly 조합에 대해서는 아닙니다.npm 게시 및 릴리스 자동화는 아직 포함되지 않았습니다.
합성 테스트 애플리케이션
Angular 테스트 애플리케이션에는 기본 및 사용자 정의 필드, 래퍼, 검증기, 확장, 사전 설정, 표현식, 검증, 리피터, 불투명 동작 및 레거시 Formly v6 별칭을 다루는 12개의 가상 폼이 포함되어 있습니다.
pnpm app:servehttp://127.0.0.1:4200/를 열고 카탈로그에서 픽스처를 선택하세요.
워크플레이스 폼과 데이터는 비공개 작업 저장소에 남아 있어야 합니다. 비공개 픽스처 모듈은 워크플레이스 라벨, 식별자, 옵션 또는 규칙을 이 공개 프로젝트에 복사하지 않고 TestFormDefinition을 구현하고 TEST_FORM_GROUPS를 통해 그룹을 등록할 수 있습니다.
저장소 구조
packages/
contract-schema/ Versioned DTOs, validation, canonical JSON, and hashing
formly-adapter/ Declared extraction and trusted Formly scenario builds
fixtures/
synthetic-form/ Public golden form and real-builder compatibility fixture
apps/
demo-cli/ Prints the deterministic golden contract
formly-test-app/ Browser-rendered Angular/Formly fixture catalog
docs/ Specifications, ADRs, delivery plans, and evidence로드맵
의도된 전달 경로는 다음과 같습니다:
Form Contract packages (current)
|
read-only MCP queries
|
typed E2E intent
|
deterministic Playwright/Cypress drivers
|
browser observation and parity checks향후 계층은 불변 계약을 사용해야 합니다. Angular 실행, 임의 콜백 평가 또는 선택자 발명을 일상적인 에이전트 요청으로 옮겨서는 안 됩니다.
문서
기여 및 보안
기여를 환영합니다. 참여하기 전에 CONTRIBUTING.md와 행동 강령을 읽어 주세요. 보안 문제는 SECURITY.md에 설명된 비공개 프로세스를 통해 신고해 주세요.
이 프로젝트는 MIT 라이선스에 따라 제공됩니다.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Live React design-system APIs, patterns, and code validation so AI agents build real UI, not slop.
Machine-native capabilities with explicit contracts and machine-readable commerce.
Define, ship & query your analytics tracking from one source of truth, trusted by humans and agents.
API governance for AI agents. Detects breaking changes, scores blast radius, blocks unsafe calls.
Related MCP Servers
- AlicenseBqualityDmaintenanceExposes TypeScript Language Server Protocol functionality to AI agents, enabling them to query types at specific positions, find definitions and references, get diagnostics, run type tests, and type-check inline code just like in an IDE.91463MIT
- FlicenseAqualityDmaintenanceA clone-and-own MCP server that exposes OpenAPI/Huma contract intelligence to AI agents by turning API specifications into deterministic endpoint metadata, schemas, validation facts, and TypeScript declarations.6
- FlicenseAqualityDmaintenanceEnables AI agents to query component governance rules, validate component props, and generate development prompts for questionnaire editors.4
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to browse, read, compare, and validate OpenAPI contracts for providers and consumers.1MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/dills122/formly-contract'
If you have feedback or need assistance with the MCP directory API, please join our Discord server