Skip to content

Add Changesets and GitHub Actions automation - #4

Merged
huangyiirene merged 7 commits into
mainfrom
copilot/add-necessary-automation-work
Jan 18, 2026
Merged

huangyiirene merged 7 commits into
mainfrom
copilot/add-necessary-automation-work

Conversation

Copilot AI commented Jan 18, 2026

Copy link
Copy Markdown
Contributor

Implements version management and CI/CD automation infrastructure.

Changes

Changesets Integration

  • Install @changesets/cli (v2.29.8) for semantic versioning and changelog automation
  • Configure for public npm publishing to @objectstack/spec
  • Add npm scripts: changeset, version, release

GitHub Actions Workflows

  • .github/workflows/ci.yml: Build validation on push/PR (Node 20, TypeScript compilation)
  • .github/workflows/release.yml: Automated npm publishing via Changesets action
  • Minimal GITHUB_TOKEN permissions for security (contents: read for CI, contents: write + pull-requests: write for releases)

Package Metadata

  • Add repository field pointing to objectstack-ai/spec

Usage

Contributors create changesets when making changes:

npm run changeset  # Describe changes interactively

Maintainers merge the auto-generated "Version Packages" PR to trigger npm publish. Requires NPM_TOKEN secret configured in repository settings.

Original prompt

添加必要的自动化工作包括changeset


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits January 18, 2026 09:12
- Install @changesets/cli for version management
- Configure Changesets for public npm publishing
- Add GitHub Actions CI workflow for build and type checking
- Add GitHub Actions Release workflow for automated publishing
- Add changeset npm scripts to package.json
- Add repository field to package.json

Co-authored-by: huangyiirene <[email protected]>
The build step already runs tsc which will fail on errors

Co-authored-by: huangyiirene <[email protected]>
Set minimal permissions (contents: read) to limit GITHUB_TOKEN scope

Co-authored-by: huangyiirene <[email protected]>
Copilot AI changed the title [WIP] Add necessary automation work including changeset Add Changesets and GitHub Actions automation Jan 18, 2026
Copilot AI requested a review from huangyiirene January 18, 2026 09:17
Copilot AI and others added 3 commits January 18, 2026 09:21
Regenerate package-lock.json to fix npm ci failure in CI workflow.
Updates @types/node from 12.20.55 to 25.0.9 and adds missing undici-types dependency.

Co-authored-by: huangyiirene <[email protected]>
@huangyiirene
huangyiirene marked this pull request as ready for review January 18, 2026 09:25
@huangyiirene
huangyiirene merged commit f046f0c into main Jan 18, 2026
1 check passed
os-zhuang pushed a commit that referenced this pull request May 21, 2026
The real moat of metadata-driven development is not 'low-code UI', it
is that the entire business system is small enough to fit in an AI
agent's context window. Make this an explicit, top-level value across
README and the concept docs.

- README.md
  - Add a 'Key Features' bullet on ~100x less code -> AI maintainability
  - Add 'Code footprint' and 'AI maintainability' rows to the
    Retool/Appsmith comparison table
  - Rewrite the 'Why AI-native?' intro to anchor the value on
    'fit in an agent's context window'

- content/docs/index.mdx
  - Add a second callout under the 'not a low-code UI builder' line
    explaining the ~100x code reduction and AI-co-maintenance angle
  - Fix stale 'npx @objectstack/cli init' -> 'npx create-objectstack'
    quick-start command (matches updated README)

- content/docs/concepts/metadata-driven.mdx
  - Rename benefit #4 'Reduced Boilerplate' -> '~100x Less Code -
    Sized for AI Agents' and reframe around context-window fit
  - Clarify that what gets generated is full CRUD + REST + typed SDK
    + MCP tools + validation + permission scaffolding, not just CRUD

- content/docs/concepts/north-star.mdx
  - Add a sixth non-negotiable tenet: 'Compact by Construction'
    -> a typical enterprise app fits in ~1% of a hand-written
    equivalent, small enough for an AI agent to load and refactor
    end-to-end. Explicitly call this out as the real moat.

Co-authored-by: Copilot <[email protected]>
xuyushun441-sys pushed a commit that referenced this pull request May 22, 2026
Introduces an opt-in path in ObjectStackProtocolImplementation.saveMetaItem
that writes overlay metadata through SysMetadataRepository.put instead of
the raw engine, so writes append to the change-log and emit HMR seq events.

Behavioural changes (all behind options.useRepositoryWritePath /
OBJECTSTACK_USE_REPOSITORY_WRITE_PATH=1):
- saveMetaItem request gained optional parentVersion (If-Match) and
  actor fields. ConflictError -> 409 metadata_conflict.
- Plural type aliases (views, dashboards, ...) normalized to singular
  before the repo's overlay-allowlist gate (rubber-duck #5).
- Object-registry mutation moved AFTER successful put() so a conflict
  does not leave the in-memory registry stale (rubber-duck #3 invariant
  test added).

Repo/test-fake fixes uncovered by rubber-duck review:
- SysMetadataRepository.put/delete now update/delete by row id because
  the engine's strict .update requires id or multi:true (rubber-duck #1).
- sys_metadata.checksum column widened from 64 -> 71 chars to hold the
  sha256: prefix produced by hashSpec() (rubber-duck #2).
- Three test fake engines extended to support both overlay-tuple and
  id-based where lookups.

333/333 objectql tests pass.

Deferred to PR-10d.4: REST plumbing for parentVersion/actor
(rubber-duck #6), race-window retry for omitted parentVersion
(rubber-duck #4), default flag flip + legacy path removal.

Co-authored-by: Copilot <[email protected]>
xuyushun441-sys pushed a commit that referenced this pull request May 24, 2026
Proposes that every Action opts in to AI exposure via a single `ai:` block
on ActionSchema, and the runtime auto-derives AIToolDefinitions from the
existing ActionRegistry. Eliminates the need to maintain parallel skill /
tool code for every business operation an admin can already perform.

- Adds opt-in `ai: { exposed, description, paramHints, outputSchema, ... }`
  block to @objectstack/spec ui/action.zod.ts
- Adds ActionRegistry.toolsForAi(opts) in @objectstack/runtime
- Wires service-ai/agent-runtime to merge action-tools into availableTools
- Routes LLM tool_calls with meta.kind='action' through ActionRegistry so
  permissions, validation, hooks, audit, and transactions all apply uniformly
- Confirmation defaults derived from existing confirmText / type='delete'

Authored from HotCRM v1.1 planning. HotCRM will be the first consumer:
delete src/skills/, convert each business skill to defineAction with ai
exposed, ship the 'Operational Parity' story as Wow #4.

Refs ADR-0003, ADR-0008, ADR-0009, ADR-0010.

Co-authored-by: Copilot <[email protected]>
xuyushun441-sys added a commit that referenced this pull request Jun 13, 2026
#1821)

Small models (e.g. claude-haiku) sometimes answered a "draw a bar chart"
request with a markdown TABLE — running query_data/aggregate_data and
formatting the numbers — instead of calling visualize_data. This was a
tool-selection problem, not a capability gap: the chart preference was buried
as guideline #7 and competed with guideline #4 ("format with markdown
tables").

- data-explorer-skill.ts: add a prominent "Choosing the right tool" section
  ABOVE the guidelines — chart intent (incl. CN terms 图表/柱状图/折线图/饼图/画图)
  → MUST call visualize_data; never substitute a table; reconcile the
  table-formatting guideline; fix duplicate guideline numbering.
- visualize-data.tool.ts: strengthen the tool description to be imperative
  ("the ONLY tool that draws a chart… you MUST call this, not a table; if you
  already fetched the numbers, still call visualize_data to render them").

Prompt-only tuning — no behavior/contract change. Raises the likelihood the
model reaches for visualize_data on a plain chart request without an explicit
"use visualize_data" nudge.

Co-authored-by: Jack Zhuang <[email protected]>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 17, 2026
…it selected left in this same major (ADR-0049) (objectstack-ai#17638)

Part of objectstack-ai#17157

`CacheWarmup.strategy` no longer accepts `'scheduled'`, and its
`.describe()` stops promising `(cron)`.

objectstack-ai#16320 (PR objectstack-ai#17146) deleted `CacheWarmup.schedule` — the cron key this
enum member selected — and declined the member itself as *"a value, not
a position this ruling names"*. That is a statement about that ruling's
**scope**, not a finding that the value was sound. After the deletion
the member declared a warmup cadence with **no key left to configure it
and no engine that has ever run one**, while its own `.describe()` still
promised `(cron)`. ADR-0049 enforce-or-remove.

## The four prerequisite readings, re-measured on `origin/main` at
`690f083f83` — one is FALSIFIED

| # | claim | reading on `main` | verdict |
|:--|:--|:--|:--|
| 1 | the enum + describe still stand at `cache.zod.ts:199-200` | they
stand, at **`:179-180`** — the card's numbers were taken on PR objectstack-ai#17146's
branch | ✅ (line numbers moved) |
| 2 | `CacheWarmupSchema` has zero consumers outside its declaring file
| **zero runtime consumers**, 6 non-runtime files — see below | ✅ |
| 3 | objectstack-ai#16320 landed; `CacheWarmup.schedule` is gone from `main` | gone;
only the tombstone comment remains in the shape | ✅ |
| 4 | the D3 ledger entry `cache-warmup-schedule-retired` exists and
says what the card quotes | **no such entry exists** — see below | ❌
**falsified** |

**objectstack-ai#4 in full.** `git grep -rn "cache-warmup-schedule-retired"` on `main`
returns **exactly one** hit:
`packages/spec/src/cron-typed-positions-retirement.test.ts:212`, inside
`NEVER_REGISTERED_IDS` — a list of ids that pin test **asserts ABSENT**.
objectstack-ai#16320 landed as a bare deletion (`直接删`, maintainer ruling 2026-09-10)
with *no* `RETIRED_KEYS_BY_MAJOR` entry, *no* D2 conversion and *no* D3
semantic entry. The statements the card quotes are real, but they live
in the **tombstone comment** in `cache.zod.ts` and in the ADR-0058 D7
ledger comment in `packages/qa/dogfood` — not in a D3 ledger entry. The
card's argument survives intact; only its citation was wrong.

**objectstack-ai#2 with its lit control reproduced** (the card's zeros were all taken
beside one, so the control is re-measured too):

```
$ git grep -l -P '\bCacheWarmupSchema\b' -- . ':!packages/spec/src/system/cache.zod.ts' \
      ':!packages/spec/api-surface/**' ':!packages/spec/authorable-surface/**' | wc -l
6
```

…and all six are non-runtime: the generated reference page's import
line, `declaration-map/system.json`, `export-origins/system.json`, the
ADR-0058 D7 ledger comment in `packages/qa/dogfood`, the objectstack-ai#16320 pin
test, and this package's own `system/cache.test.ts`. **Zero runtime
readers.**

```
$ git grep -l -P '\bConnectorSchema\b' -- . ':!…surfaces…' | grep -v connector.zod.ts | wc -l
46          # lit control — the sweep sees consumers when there are any
```

(The card measured 48 for the control on objectstack-ai#17146's branch; 46 on `main`.
It is emphatically lit either way.)

`CacheWarmup` is also bound to **no** metadata type and embedded in
**no** stack collection: `git grep -n
'DistributedCacheConfigSchema|CacheWarmupSchema' --
packages/spec/src/stack.zod.ts packages/spec/src/kernel/` exits **1**.
So there is no authored source and no stored row anywhere that has ever
carried this value, and `os migrate meta` has nothing to list.

## The retirement mechanism — established, not invented

The card is right that there is **no value-level analogue of
`retiredKey()`**, and none is invented here. The repo's established
mechanism for an enum-VALUE retirement is the **enum's own `error` map,
dispatched on `issue.input`** — three precedents on this tree:

| precedent | site |
|:--|:--|
| `object.managedBy: 'system'` | `data/object.zod.ts`
(`MANAGED_BY_SYSTEM_RETIRED`) |
| `HookBodyCapability` `'crypto.hash'` (objectstack-ai#4391) | `data/hook-body.zod.ts`
(`CRYPTO_HASH_RETIRED`) |
| `HotReloadConfig.stateStrategy` `'disk'` / `'distributed'` | D3 entry
`hot-reload-inert-state-strategies-retired` |

`.claude/skills/spec-property-retirement` §2 names it outright as the
only route that applies when the def survives and only its value set
shrinks. Only the value that **used to be legal** gets the "was removed"
sentence; `strategy: 'sheduled'` keeps zod's own enum message.

Registration follows the same precedents: an **ADR-0087 D3 semantic
entry** (`cache-warmup-scheduled-strategy-retired`), *not* a D2
conversion (no source to rewrite) and *nothing* in
`RETIRED_KEYS_BY_MAJOR` (no authorable key changed). The prescription
deliberately carries **no `os migrate meta` sentence** — promising a
listing the tool cannot produce would be the very defect this card is
about; the house pin (`retired-key-migrate-sentence.test.ts`) judges
only prescriptions that name the command.

## ⭐ The instrument — the negative leg, both legs quoted

**An enum-value narrowing is invisible to all four ratchets**, and this
branch confirms it by measurement, not by argument: after `pnpm --filter
@objectstack/spec build`, `git status --porcelain` was **empty** —
`authorable-surface/system.json` still carries
`system/CacheWarmup:strategy` byte-for-byte (it keys on the *position*,
which is untouched), and `api-surface/`, `json-schema.manifest/` and the
D7 ledger likewise. **A green CI run is therefore not evidence this
retirement works.** The pin tests in `system/cache.test.ts` are the only
instrument, so both legs are shown.

Resolution path: `cache.test.ts` imports `./cache.zod` — the **source**,
not `dist/` — so no build interposes between the mutation and the
reading.

```
HEAD blob = 6a5ab59

########## AFTER LEG (retirement in place, HEAD) ##########
AFTER EXIT=0
 Test Files  1 passed (1)
      Tests  36 passed (36)

########## BEFORE LEG (schema reverted to origin/main 690f083) ##########
  occurrences of the retired member in the enum line: 1     ** mutation proven ON DISK
  occurrences of the injected prescription const:    0
  blob now = 813cf78       ** differs from the HEAD blob
BEFORE EXIT=1
 FAIL  |local| src/system/cache.test.ts > CacheWarmupSchema >
        refuses `strategy: 'scheduled'` and answers with the retirement prescription
 AssertionError: expected [Function] to throw an error
 Test Files  1 failed (1)
      Tests  1 failed | 35 passed (36)

########## RESTORE ##########
  blob restored = 6a5ab59  ** identical to the HEAD blob
  git diff HEAD (must be empty):
  [end]
```

**Before: accepted. After: refused.** The mutation is proved on disk by
blob hash *and* by a grep anchored on the exact text that moved (an
editor's exit code is not evidence); the restore is proved by `git diff
HEAD` being empty, not by an exit code; and the script carried `trap …
EXIT INT TERM` throughout.

The two neighbouring assertions pass in **both** legs, deliberately —
they are controls, not the instrument: a typo (`'sheduled'`) must
**not** be told it "was removed" (or the error map matches everything
and the pin above proves nothing), and `'eager'` / `'lazy'` / the
`'lazy'` default must still parse.

## Changeset level

`minor`, on `@objectstack/spec`. Removing a published enum member **is
breaking**; under the launch-window rule it ships as `minor` —
`check-changeset-no-major.mjs` refuses `major`, and breaking-ness is
carried by the **BREAKING** banner plus the ADR-0087 disposition (an
`adr-0087: registered cache-warmup-scheduled-strategy-retired` marker in
the changeset body). The level is **committed**, so the gate — which
reads via `git show HEAD:PATH` — sees it. `node
scripts/check-changeset-no-major.mjs --base origin/main` and `node
scripts/check-adr-0087-registration.mjs --base origin/main` both exit 0
on this branch.

## Verification — all readings at `c170853213`, the final commit

| run | verdict |
|:--|:--|
| `pnpm --filter @objectstack/spec build && … typecheck && … test`
(under the shared verify lock) | `VERDICT command-exit 0`; **473 test
files, 13428 tests passed** |
| `pnpm --filter @objectstack/spec check:generated` | 15/15 green. One
was stale on the first pass — `check:docs` — regenerated with `gen:docs`
(the reference page's enum cell); `check:authorable-surface`,
`check:api-surface`, `check:spec-changes`, `check:upgrade-guide` were
green **without** regeneration, which is the ratchet-invisibility result
above |
| `pnpm lint` (repo-wide, `eslint . --no-inline-config`) | exit 0 — no
narrowing claimed, the full scan ran |
| `node scripts/pm/dispatch-gates.mjs --ran` | **108 derived, 108 run, 0
UNRUN** |

Of the 108, **7 returned `PREREQUISITE NOT MET` (exit 3, or exit 1 with
an explicit "nothing was measured" verdict) and are recorded as NOT
MEASURED, never as green**: `check:doc-formula-expressions`,
`check:doc-security-posture`, `check:skill-examples`,
`check:docs-transcript-drift`, `check:dual-build-cjs-loads`,
`check:lean-entry-closure`, `check:type-check-debt`. Every one refuses
for the same reason — it reads **built sibling packages** that this
worktree has not built — and none reads a file this diff touches. CI
builds the farm and decides them.

**One gate found a real defect in this branch and is fixed in
`c170853213`:** `check:doc-authoring` Rule 3 flagged `objectstack-ai#16320` inside the
customer-facing prescription string. A refusal message is printed
verbatim at an author who has no tracker to resolve `#NNNN` with, so the
id moved to the adjacent `//` comment and the string keeps **ADR-0049**
as its durable reference. Gate now green.

## Sibling repo

`git grep 'CacheWarmup' ../objectui` → no hits. The Console Pin Gate is
not in play.

## Not in scope

The larger family question — whether `CacheWarmup` /
`DistributedCacheConfig.warmup` should exist at all — is the ADR-0049
family-level decision the card names and is deliberately untouched here.
`Part of objectstack-ai#17157` rather than `Fixes`, since this closes the enum member
and not that question.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH

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

---------

Co-authored-by: Claude <[email protected]>
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