Skip to content

Add missing Field.phone() helper and factory methods for Action/Dashboard/Report - #15

Merged
huangyiirene merged 5 commits into
copilot/add-crm-functionality-examplefrom
copilot/fix-action-job-step-error
Jan 19, 2026
Merged

huangyiirene merged 5 commits into
copilot/add-crm-functionality-examplefrom
copilot/fix-action-job-step-error

Conversation

Copilot AI commented Jan 19, 2026 •

Copy link
Copy Markdown
Contributor

Fix CRM Example TypeScript Build Errors ✅

Problem: The CRM example has multiple TypeScript compilation errors preventing CI from passing.

Root Causes:

  1. Field.select() signature mismatch - expects string[] but code passes SelectOption[] objects
  2. Missing phone field type helper in Field factory
  3. Action, Dashboard, and Report are only types, not runtime objects with .create() methods

Solution:

  • Add phone field type helper to Field factory
  • Update Field.select()/Field.multiselect() to support both old and new API signatures (backward compatible)
  • Add factory methods (Action.create, Dashboard.create, Report.create) using z.input for proper default handling
  • Add comprehensive test coverage (12 new tests)
  • Add JSDoc comments documenting the API
  • Fix spread order in select/multiselect to avoid option duplication
  • Security scan: ✅ No vulnerabilities
  • Code review: ✅ Addressed feedback

Backward Compatibility:

// Old API (still works)
Field.select(['High', 'Low'], { label: 'Priority' })

// New API (now supported)
Field.select({ 
  options: [{label: 'High Priority', value: 'high', color: '#FF0000'}], 
  label: 'Priority' 
})

Test Results: ✅ All 279 tests passing
Build Status: ✅ All packages build successfully (CRM, TODO, docs)
Security: ✅ No vulnerabilities detected

Original prompt

引用: https://github.com/objectstack-ai/spec/actions/runs/21135959933/job/60779299734#step:8:1


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@vercel

vercel Bot commented Jan 19, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
spec Ready Ready Preview, Comment Jan 19, 2026 0:12am

Request Review

- Add phone field type helper to Field factory
- Update Field.select/multiselect to support both array and object signatures
- Add factory methods (Action.create, Dashboard.create, Report.create)
- Use z.input and parse for factory methods to support default values

Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes TypeScript compilation errors in the CRM example by enhancing the Field factory API and adding factory helper methods for UI components. The changes enable both legacy string-array syntax and new object-based configuration for select fields, while adding missing field type helpers and runtime factory methods.

Changes:

  • Added phone field type helper and dual-signature support for select/multiselect fields (backward compatible)
  • Added factory helper methods (Action.create, Dashboard.create, Report.create) with proper type inference using z.input
  • Restructured documentation metadata hierarchy by moving root: true from parent to child sections

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/spec/src/data/field.zod.ts Added phone helper and refactored select/multiselect to accept both string arrays and SelectOption objects
packages/spec/src/ui/action.zod.ts Added Action.create() factory method with additional exported types
packages/spec/src/ui/dashboard.zod.ts Added Dashboard.create() factory method with exported widget type
packages/spec/src/ui/report.zod.ts Added Report.create() factory method with additional exported types
content/docs/references/meta.json Removed root: true from parent metadata
content/docs/references/data/meta.json Added root: true to Data Protocol section
content/docs/references/ui/meta.json Added root: true to UI Protocol section
content/docs/references/system/meta.json Added root: true to System Protocol section
content/docs/references/ai/meta.json Added root: true to AI Protocol section

Comment thread packages/spec/src/data/field.zod.ts Outdated
finalConfig = optionsOrConfig;
}

return { type: 'select', ...finalConfig, options } as const;

Copilot AI Jan 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spread order ...finalConfig, options means that if finalConfig contains an options property, it will be overwritten by the options variable. Consider using options, ...finalConfig to ensure the parsed options take precedence, or explicitly handle the options property separately to avoid confusion.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 49030d1. Now extracting options from config object and placing processed options first in spread order to ensure they always take precedence.

Comment thread packages/spec/src/data/field.zod.ts Outdated
finalConfig = optionsOrConfig;
}

return { type: 'multiselect', ...finalConfig, options } as const;

Copilot AI Jan 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spread order ...finalConfig, options means that if finalConfig contains an options property, it will be overwritten by the options variable. Consider using options, ...finalConfig to ensure the parsed options take precedence, or explicitly handle the options property separately to avoid confusion.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 49030d1. Now extracting options from config object and placing processed options first in spread order to ensure they always take precedence.

@huangyiirene

Copy link
Copy Markdown
Collaborator

@copilot fix

- Add tests for Field.phone() helper
- Add tests for Field.select() backward compatibility (old and new API)
- Add tests for Field.multiselect() backward compatibility
- Add tests for Action.create() with default value handling
- Add tests for Dashboard.create() with default value handling
- All 279 tests passing

Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Document backward-compatible API with examples for both old and new signatures

Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix action job step error Add missing Field.phone() helper and factory methods for Action/Dashboard/Report Jan 19, 2026
Copilot AI requested a review from huangyiirene January 19, 2026 12:08
- Extract options from config object to avoid confusion
- Change spread order to options first, then finalConfig
- Ensures processed options always take precedence

Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>

Copilot AI commented Jan 19, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix

Fixed the spread order issue in select/multiselect field helpers (commit 49030d1). The options property is now extracted from the config object and the processed options array always takes precedence.

@huangyiirene
huangyiirene marked this pull request as ready for review January 19, 2026 12:16
@huangyiirene
huangyiirene merged commit 8beab63 into copilot/add-crm-functionality-example Jan 19, 2026
2 checks passed
os-zhuang pushed a commit that referenced this pull request Jun 20, 2026
…table #15)

The verification table cited permission-evaluator.ts for the role-hierarchy no-op;
the accurate evidence is sharing-rule-service.ts expandRecipient (no role_and_subordinates
branch) + flat team-graph + no Role.parent consumer. Substance (widening unimplemented)
unchanged; citation corrected after re-verification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVdnfUAx85amkerym26vdx
os-zhuang added a commit that referenced this pull request Jun 20, 2026
…del enforce/prove/reconcile) (#2058)

* docs(adr): ADR-0056 permission model landing verification (whole-model enforce/prove/reconcile audit)

A capstone governance ADR that applies the ADR-0049 (enforce-or-remove) and
ADR-0054 (prove-it-runs) gates to the ENTIRE authorization model for the first
time. Based on a four-pass read-only audit (spec inventory, runtime-enforcement
trace, proof-coverage matrix, prior-ADR reconciliation), it presents a per-primitive
declared↔enforced↔proven verification table and makes 10 reconciling decisions:

- D1 collapse the 3-way-mismatched OWD enum to one canonical set + reject unknown
- D2 close the anonymous default-allow fail-open (default-deny)
- D3 OWD baseline must not depend on plugin-sharing being loaded
- D4 RLS compiler must error at authoring time / fail-closed at runtime, never silently drop
- D5 reconcile Sharing Rules spec↔runtime divergence per ADR-0049
- D6 role-hierarchy widening: implement or mark experimental (it is a silent no-op today)
- D7 first-class app-declared default Profile (replaces hardcoded fallback)
- D8 triage compliance/encryption/masking surface per ADR-0049
- D9 bind enforced-but-unproven invariants into the liveness ledger
- D10 (durable) an Authorization Conformance Matrix as a CI-checked artifact

Phased P1 honesty-pass → P2 close fail-open holes → P3 provisioning+proofs → P4 evidence-gated.
Status: Proposed. No code change; design only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVdnfUAx85amkerym26vdx

* docs(adr): ADR-0056 — correct role-hierarchy evidence citation (D6 / table #15)

The verification table cited permission-evaluator.ts for the role-hierarchy no-op;
the accurate evidence is sharing-rule-service.ts expandRecipient (no role_and_subordinates
branch) + flat team-graph + no Role.parent consumer. Substance (widening unimplemented)
unchanged; citation corrected after re-verification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVdnfUAx85amkerym26vdx

---------

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…n alone — over 5,000 changed lines (objectstack-ai#19042)

Fixes objectstack-ai#19037
Clause-②: no

## What changed

`AGENTS.md` Multi-agent discipline §7 said 「Two classes of PR never
enter this path on green alone」 — (a) a governed-surface diff, (b) the
Version Packages / release-performing PR. The maintainer's ruling adds a
third, and the rules layer contradicted the landing rule until it said
so. The paragraph now names three classes:

> (c) a PR whose **changed lines exceed 5,000** (`additions +
deletions`, generated files included) — it lands only by a human merge,
which is its review record.

and the closing instruction reads the size in the same breath as the
file list and the author: 「Read the PR's file list (`get_files`), **its
author and its size** before you arm anything.」

Ruling (verbatim, untranslated), recorded on objectstack-ai#16045 (comment 5729462393)
and carried by objectstack-ai#19012 / PR objectstack-ai#19033:

> 「还有应该完善skills,修改代码量超过某个行数(比如5000)就应该人工审核。」

Read as the landing rule already spells it: `additions + deletions` on
the PR, strictly greater than 5,000, generated files INCLUDED, no
exemption; the terminal is the human's merge. The sentence states the
ruling, not a line number of PR objectstack-ai#19033, so it reads true whether or not
that PR has landed. No new rule beyond the ruling: no exemption, no
lower number, no review that is not the human's merge.

**Why the sentence carries no card number or date.** `AGENTS.md`'s
header: a rule 「carries no incident narrative, no ruling date or
quotation, and no issue-number citation (`pnpm check:pm-skill-id-lint`)
— a rule's provenance lives in the PR that landed it」; that gate's
pattern is `/#[0-9]{3,}/` over `AGENTS.md`, so `objectstack-ai#16045` / `objectstack-ai#19012` in
the sentence would go red. The dispatch's mechanism assumption 1 (name
the ruling by card) is falsified by the gate and by the file's own
header — the provenance is this PR body, and the sentence is
self-contained.

## Line budget — net 0 at the ceiling (1099 / 1099)

The paragraph was wrapped at ~88 bytes with a 27-byte last line;
re-flowed at the file's own 120-byte per-line budget (the Prime
Directives block runs to 120 bytes; §8 beside it to 116) it absorbs the
clause with no new line. Every bold and code span stays whole on its
line, as before.

| line | before (bytes) | after (bytes) |
|---|---|---|
| 495 | 90 | 113 |
| 496 | 88 | 117 |
| 497 | 88 | 109 |
| 498 | 81 | 109 |
| 499 | 86 | 111 |
| 500 | 27 | 75 |
| paragraph | 466 | 640 |
| file | 1099 lines | 1099 lines |

Before:

```text
   ⛔ **Two classes of PR never enter this path on green alone:** (a) a diff touching any
   **governed surface** (**Prime Directive objectstack-ai#14**, which names them and holds the current
   list — **this file and `CLAUDE.md` are on it**, so re-read it rather than recalling
   it); (b) the **Version Packages** PR, or any PR whose merge performs a release
   (**Prime Directive objectstack-ai#15**). Read the PR's file list (`get_files`) **and its author**
   before you arm anything.
```

After:

```text
   ⛔ **Three classes of PR never enter this path on green alone:** (a) a diff touching any **governed surface**
   (**Prime Directive objectstack-ai#14**, which names them and holds the current list — **this file and `CLAUDE.md` are on it**,
   so re-read it rather than recalling it); (b) the **Version Packages** PR, or any PR whose merge performs a
   release (**Prime Directive objectstack-ai#15**); (c) a PR whose **changed lines exceed 5,000** (`additions + deletions`,
   generated files included) — it lands only by a human merge, which is its review record. Read the PR's file
   list (`get_files`), **its author and its size** before you arm anything.
```

## Reader test

A seat about to arm a 6,000-line PR reads §7 and stops: 「Three classes …
(c) a PR whose changed lines exceed 5,000 … lands only by a human
merge」. Before this PR the same seat read two classes, found a
6,000-line diff in neither, and armed.

## Other mentions in `AGENTS.md` (mechanism assumption 3)

`grep -n -i -E 'green alone|two classes|Version Packages'` on
`origin/main` `dbd474431`:

- :291, :299, :307, :309 — Prime Directive objectstack-ai#15's own text (no seat
merges the Version Packages PR; that merge is the release trigger).
Left: it is class (b)'s anchor, not an enumeration of the
never-on-green-alone set.
- :495, :498 — the §7 sentence. Changed (this PR).
- No other line enumerates the set. Two neighbours name class (a) alone
by design and were left: the Skills section's 「Both roots are governed
surfaces — human-merge only, or Prime Directive objectstack-ai#14's pinned-approval
path」 (about governed surfaces only), and Post-Task Checklist step 2's
「⛔ Except a diff touching a governed surface」, which defers to §7 by
reference for the arming rule — see Acceptance notes.

## Gates (local, at `845470659`)

`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 14 families from the changeset (1
path vs merge base `dbd474431`); all 14 ran, exit codes captured
redirect-then-`$?`, plus the two the dispatch named:

```text
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
pnpm check:agent-test-spelling :: exit 0
pnpm check:docs-audit-scope :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-governed-prose :: exit 0
pnpm check:pm-skill-id-lint :: exit 0
pnpm check:pm-skill-ratchet :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:required-contexts :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:skill-frame-sync :: exit 0
pnpm check:doc-authoring :: exit 0
```

Reconciliation: `✓ dispatch-gates --ran: 14 derived famil(ies) accounted
for — 14 run, 0 NOT-MEASURED`. Ratchet: `✓ check-skill-line-ratchet:
AGENTS.md is 1099 lines (ceiling 1099; headroom 0).` and `widest table
row is 768 bytes (pin 768; headroom 0)`. Id-lint: 0 citations in
`AGENTS.md`. Control-byte scan of the file: no match.

Not measured locally: `check:doc-formula-expressions` (a CEL gate over
fenced formula examples in the docs/skills corpus; this diff adds no
fenced block and the family is outside the derivation; CI runs it).
`check:pm-dispatch-gates` ran detached — its verdict is in the report
comment on objectstack-ai#19037.

## Changeset

`skip-changeset`: `AGENTS.md` is a repo-root instruction file; the root
package is private and no package `files[]` ships it — nothing published
moves.

## Acceptance notes

- noted, not filed: Post-Task Checklist step 2 names only the governed
class in its 「⛔ Except」 clause; the size class reaches a dev's own PR
too. It defers to §7 by reference, and the file header's
one-statement-per-rule principle argues against restating; a fold there
is one line of re-flow if the seat wants it. 承接者: skills seat.
- noted, not filed: the size class has no Prime Directive of its own (it
is a ruling, not a directive); a numbered home would be a new directive
beside objectstack-ai#14 / objectstack-ai#15 — a separate decision, not taken here.

## 维护者速读(草稿)

- **改了什么**:`AGENTS.md` 多 agent 纪律 §7 那句「两类 PR 绿了也不能自动进合并队列」改成三类:新增 (c)
改动行数(additions + deletions,含生成文件)超过 5,000 行的 PR,只能由人工合并。文件行数不变(1099 /
1099),只是把那一段按文件自身的行宽重排。
- **为什么改**:您 09-18 的裁决「修改代码量超过某个行数(比如5000)就应该人工审核」已经落进了 PM
的落地规则与门禁脚本,但规则层 `AGENTS.md` 还写着两类,座席读到的规则与落地规则互相矛盾。
- **风险与代价(含回滚)**:纯文本改动,不动任何脚本或门禁;本地 16 项门禁全绿。回滚 = revert 这一个 commit。
- **席位意见**:(留空,由席位定稿)
- **你要做的**:确认这句话与您的裁决一致(尤其「含生成文件、无豁免」与「人工合并即审核记录」两点),然后由您合并。

---
_Generated by [Claude
Code](https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF)_

Co-authored-by: os-dev <elon@objectstack.ai>
Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Oct 6, 2026
os-justin pushed a commit that referenced this pull request Nov 3, 2026
…ecurity finding, with its charter, the Notify: security doorbell and the seat signature

The maintainer set a `security#1` seat and amended it to a lane. This lands:
the lane charter `references/lanes/security.md` (pointers only, the never-public
rules stay in `security-findings.md`), the owner section in `security-findings.md`,
the triage hand-over in `lanes/triage.md`, the `Notify: security · GHSA-ID` doorbell
(`MAILBOX_KEYS` row, reader, self-test rows, protocol text), one 域车道 row in
SKILL.md paid by deleting a 红线 that restated AGENTS.md Prime Directive #15, and
`security` admitted to the seat signature's lane alternation in both of its
copies, with a self-test row for `security#1 · …` and a non-lane word kept refused.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QSeKYn5CmmdShCJifm6WYj

This branch was successfully deployed

1 active deployment
Preview — 49030d18 Deployed Jan 19, 2026 by vercel[bot]
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.

3 participants