Repository navigation
Convert to monorepo with scoped packages - #8
Merged
Merged
Conversation
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Upgrade project to multi-package structure
Convert to monorepo with scoped packages
Jan 18, 2026
huangyiirene
marked this pull request as ready for review
January 18, 2026 12:23
xuyushun441-sys
pushed a commit
that referenced
this pull request
May 22, 2026
…invariant)
User feedback: in shared-DB multi-tenant deployments, only render-time
metadata types (views, dashboards, reports) may be overridden per
organization. Anything that affects the physical schema, persisted
contracts, or automation guarantees must be platform-global — otherwise
a per-org overlay on, say, an object would diverge the table schema
that the whole tenant pool depends on.
This invariant is already enforced via MetadataTypeRegistryEntry.allowOrgOverride
in the spec, but two gaps remained:
1. `report` had `allowOrgOverride: false` even though it is pure
presentation — flipped to true to match the principle.
2. The principle itself was not written down. Added a 'Tenant-
customizable type whitelist' section to ADR-0005's amendment block
with a complete table grouped by domain, plus the rule: 'default
for any new metadata type is allowOrgOverride: false; promotion
requires (a) overlay Zod schema, (b) written render-only rationale.'
No code change beyond the report flag — protocol.ts already derives
OVERLAY_ALLOWED_TYPES from the registry (Prime Directive #8).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
xuyushun441-sys
pushed a commit
that referenced
this pull request
May 22, 2026
…PR-10a)
Pins down two invariants that PR-10b/c (LayeredRepository overlay
refactor) must preserve:
1. Whitelist enforcement — only allowOrgOverride:true types may be
saved as per-org overlays in project-kernel mode. Verifies:
- 5 accepted (view, dashboard, report, email_template, plural form)
- 11 denied with code='not_overridable', status=403
(object, field, flow, workflow, agent, permission, role,
profile, datasource, objects, flows)
- Single-kernel mode (no projectId) bypasses the gate
- Registry-as-source-of-truth: every allowed/denied type traces
back to DEFAULT_METADATA_TYPE_REGISTRY.allowOrgOverride
(Prime Directive #8 — no parallel allow-list)
2. Canonical hash stability — precondition for backfilling _hash on
existing sys_metadata rows in PR-10b. Verifies canonicalize/
hashSpec are insensitive to key order, undefined-vs-absent, and
deeply-nested optional fields; positional semantics preserved
for arrays; distinct payloads → distinct hashes.
Adds @objectstack/metadata-core as a workspace dep of @objectstack/
objectql to import canonicalize/hashSpec.
Test count: objectql 258 → 286. All green.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
xuyushun441-sys
pushed a commit
that referenced
this pull request
May 22, 2026
…etadata (ADR-0008 PR-10b)
PR-10b of ADR-0008. Wraps the existing sys_metadata table behind the
canonical MetadataRepository interface from @objectstack/metadata-core.
No production wiring yet — that lands in PR-10c when LayeredRepository
composes [FileSystemRepository, SysMetadataRepository] and the manager
bridge routes overlay PUTs through it.
What's implemented (M0 single-row update semantics):
- get / put / delete against (type, name, organization_id) row
- hashSpec stamping into _hash column (PR-10a guarantees stability)
- optimistic locking: parentVersion must match HEAD _hash
- no-op short-circuit on identical-body put (no event, no seq bump)
- whitelist enforcement: refuses put/delete for types whose registry
entry has allowOrgOverride: false (Prime Directive #8)
- in-process watch() with type/name/org/branch filter
- list() yields MetadataItemHeader (body stripped)
- close() for clean teardown
Deferred to M1:
- append-only metadata_events table + cross-replica seq
- history() — currently yields empty
- branch ops (fork/merge)
- hashSpec backfill for legacy rows missing _hash
Tests: 16 new tests covering CRUD, optimistic locking, whitelist,
list, watch (incl. filter), history no-op, close. objectql 286 → 302.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
4 tasks
xuyushun441-sys
pushed a commit
that referenced
this pull request
May 29, 2026
Repoint email_template's canonical Zod schema from the legacy EmailTemplateSchema (a sub-shape inside Notification) to EmailTemplateDefinitionSchema across both runtime registries: - packages/objectql/src/protocol.ts (TYPE_TO_SCHEMA → used by protocol.getMetaTypes() to emit JSON Schemas for Studio) - packages/spec/src/kernel/metadata-type-schemas.ts (BUILTIN_METADATA_TYPE_SCHEMAS) Resolves Prime Directive #8 (one canonical Zod source per metadata type) for email_template. Studio property panel now renders all canonical fields (name, label, category, locale, subject, bodyHtml, bodyText, variables, fromOverride, replyTo, active, isSystem, description) with no missing-schema warnings. Also wires emailTemplates as a top-level defineStack() collection: - MAP_SUPPORTED_FIELDS + PLURAL_TO_SINGULAR (spec/shared) - ARTIFACT_FIELD_TO_TYPE (metadata plugin) - APP_CATEGORY_KEYS (runtime app-plugin) Rewrites the email-template FormView for the new shape and ships three reference templates in examples/app-crm (crm.deal_won, crm.welcome, crm.lead_followup) wired via emailTemplates: Object.values(emails). Verified end-to-end: list, detail+preview iframe, property panel, and GET /api/v1/meta all return the new schema. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced May 29, 2026
This was referenced Aug 3, 2026
This was referenced Sep 2, 2026
This was referenced Sep 12, 2026
Merged
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Sep 17, 2026
…shared process table (objectstack-ai#17809) Fixes objectstack-ai#17104 The shared-process-table rule is written for SIGNALS only. `guard-process-kill.sh`'s ALLOWED list ends by calling `pgrep -f` a harmless READ — correct about killing, and exactly where the card's measured trap sits. A name-matched WAIT has the same root cause (one process table, text matching, no ownership check) and the same property that makes the kill rule a rule rather than advice: **it reports success.** A `pgrep -f "$PAT"` run from a shell whose own command line contains `$PAT` matches the asker itself, `head -1` takes it, and the wait never returns. Two prose edits, no guard logic and no new refusal — per the grading, a wait that never returns spends only the asker's own budget, so this half is a written rule, not a hook. ## Edit 1 — `AGENTS.md`, Prime Directive objectstack-ai#8 (the kill rule's line) **Before** (lines 533–534, 89 + 113 = 202 bytes): ``` the task is done** (`kill $(lsof -ti tcp:PORT)`). Don't leave orphan servers behind. ⛔ One process table per container: **kill only a PID you recorded, never a name** (`guard-process-kill.sh`). ``` **After** (lines 533–534, 113 + 116 = 229 bytes): ``` the task is done** (`kill $(lsof -ti tcp:PORT)`). ⛔ One process table per container: **kill only a PID you recorded, and wait only on one, never a name** — `pgrep -f` matches the asking shell (`guard-process-kill.sh`). ``` File line count: **1075 before, 1075 after.** No ceiling raise. ### How the line was paid — and why the dispatch's first route is not available The dispatch offered three routes and noted the ratchet "pins a widest-table-row byte count, not prose width". That is true of `MAX_TABLE_ROW_BYTES` (AGENTS.md 768, headroom 0, untouched here), but it is not the whole ratchet: `check-skill-line-ratchet.mjs` also carries a **flat `MAX_LINE_BYTES = 120`** prose rule, and line 534 measured **113 bytes — 7 bytes of headroom** against a clause that needs ~80. **Route (a), riding line 534, is arithmetically impossible.** Route (b) — folding into the paragraph's existing lines — is re-wrapping slack into new content. `os-dev.md` forbids that spelling explicitly (「付行数棘轮的唯一合法货币是删内容:⛔ 不拿 re-wrap (折行合并)当筹行,新增以删减付账」), and the ratchet's own header names widening-to-budget as the defect it was built against. Flagging rather than silently choosing: the dispatch offers a route `os-dev.md` closes, and `os-dev.md` wins. So route (c), **paid by deletion in the same edit**: `Don't leave orphan servers behind.` (34 bytes including its leading space) is deleted. It loses nothing — it is a negative restatement of the bolded **`shut it down yourself when the task is done`** that immediately precedes it in the same sentence pair; the rule's positive form, its prescribed teardown command and its scope all survive untouched. No other content was removed. Both new lines are within the 120-byte budget (113, 116). The wrap falls inside a bold span, which is this file's own established convention — lines 532→533 already wrap inside **`shut it down yourself when the task is done`**. ## Edit 2 — `.claude/hooks/guard-process-kill.sh` (header comment only) Line 60's sentence **keeps its meaning about signals** and gains the caveat (85 → 91 bytes, plus an 88-byte continuation line): ``` # pgrep -f foo / ps aux | grep node — a READ. Nothing dies; look all you like. But a # READ is not a WAIT — see the section below. ``` A new header section then carries the positive form and the spelling detail the AGENTS.md ceiling could not hold (`cmd & pid=$!` then `wait "$pid"`, a pidfile, or a wrapper that prints its own PID), the measured five-hour self-deadlock, and the reason this half is deliberately unguarded. `.claude/hooks/` carries **no ceiling** (the ratchet header states this explicitly), so the detail belongs here — which is also the file's existing division of labour with the kill rule. File: 333 → 361 lines. New comment lines are ≤94 bytes, matching the file's existing widest comment line exactly. `bash -n` clean; hook still wired in `.claude/settings.json` and still `-rwxr-xr-x`. ## Verification Final commit `35a20c6`. **Governed verdict** — `node scripts/pm/check-governed-merges.mjs --test AGENTS.md .claude/hooks/guard-process-kill.sh`, **exit 3**: ``` governed-surface predicate: 2 of 2 path(s) hit the register (5 surfaces, repo-agnostic). ⛔ GOVERNED — a human merge is the review record for this PR (objectstack-ai#9495 regime). No seat flips it ready, enqueues it, or arms auto-merge (AGENTS.md Prime Directive objectstack-ai#14). ``` **Guard self-test** — `.claude/hooks/guard-process-kill.selftest.sh`: **69 passed, 0 failed** both before and after the edit (exit 0). It pins the *refusal* text, not the header comment, so a header-only change leaves it green and no pin needed updating. **Ratchet** — `pnpm check:pm-skill-ratchet`, exit 0: ``` ✓ check-skill-line-ratchet: AGENTS.md: widest table row is 768 bytes (pin 768; headroom 0). ✓ check-skill-line-ratchet: AGENTS.md is 1075 lines (ceiling 1075; headroom 0). ``` **Derived gate set** — `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 18 families from the 2-path change set; all 18 run, all exit 0. Reconciled with `--ran`: ``` Run reconciliation — 18 derived, 18 run, 0 NOT-MEASURED, 0 UNRUN. ✓ dispatch-gates --ran: 18 derived famil(ies) accounted for — 18 run, 0 NOT-MEASURED (a DERIVED zero — all 18 recorded an exit code and none of them is 3). ``` Two gates first returned **exit 3 = PREREQUISITE NOT MET** (not a finding): `node_modules` was absent until `pnpm install`, and `check:doc-formula-expressions` additionally needed `@objectstack/formula` and `@objectstack/lint` built. Both re-ran at exit 0 after the builds (`os-verify-lock.sh`, `VERDICT command-exit 0`). **Control characters** — `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` over both files: no matches. `pnpm check:nul-bytes` exit 0. **objectui pin check** — read from `objectui` `origin/main`:`scripts/upstream-port-pin.json`. It pins **11** upstream paths (the `guard-main-checkout*`, `guard-shared-stash*` and `guard-tree-enum*` families plus `check-half-states.mjs`, `invoked-as.mjs`, `check-bash32-floor.mjs`). `guard-process-kill` appears **zero** times. **No downstream pin moves**, and the objectui parity check has nothing to flag. **changeset**: `skip-changeset` — `AGENTS.md` (repo-root instruction file) and `.claude/**` are both on the fast track; nothing in any package's `files[]` moves. ## 维护者速读(草稿) **改了什么** —— 两处纯文字改动。`AGENTS.md` 第 534 行的「只杀你记录过的 PID,绝不按名字杀」规则, 补上同样正向形式的另一半:**等待也只等你记录过的 PID**;`guard-process-kill.sh` 头部注释里那句 「`pgrep -f` 只是读,随便看」保留它关于「信号」的原意,并补上关于「等待」的告诫。⛔ 没有改任何守卫 逻辑,没有新增拦截。 **为什么改** —— 卡片记录的是一次实测事故:三个后台等待进程死锁了五个小时。原因是 `pgrep -f "$PAT"` 在一个自身命令行就包含 `$PAT` 的 shell 里执行,匹配到了**提问者自己**,于是 `tail --pid` 在等自己的 父进程、父进程在等它。这个错误**会报成功** —— `pgrep` 返回 0,还打印出一个看起来很合理的 PID,所以 没有任何信号提示出错。杀错进程毁的是别人的活、动静很大;等错 PID 静悄悄地烧掉的是你自己的时间,所以 它能跑满五个小时都没人发现。 **风险与代价(含回滚)** —— 风险极低:改的是说明文字,不是可执行逻辑。`bash -n` 通过,守卫自检 69 项全绿(改动前后一致),钩子仍然挂载且可执行。代价是 `AGENTS.md` 行数棘轮在 1075/1075 零余量, 为了不抬上限,删掉了「Don't leave orphan servers behind.」这句话——它只是前面加粗那句「任务做完自己 关掉」的反面重复,规则内容没有任何损失。回滚就是 `git revert` 这一个 commit,无迁移、无依赖。 **席位意见** —— (留空,待 skills 席位定稿) **你要做的** —— 这是受管面(`AGENTS.md` + `.claude/**`),按 Prime Directive objectstack-ai#14 由维护者**手动合并**; ⛔ 不翻 ready、不进合并队列、不开 auto-merge。请确认一点:用「删掉那句重复话」来换这一行,是否认可 ——若您认为那句话应当保留,替代方案是抬 `AGENTS.md` 的行数上限(需要您的裁决),我没有自行抬。 ## Acceptance notes Out of scope, noted and **not** filed (neither is a reproducible defect, a declared-contract violation, nor a metadata trap — the three filing classes): - The dispatch's reading that the ratchet "pins a widest-table-row byte count, not prose width" is incomplete: a flat `MAX_LINE_BYTES = 120` prose rule also applies, and it is what caps line 534. Reported to the PM rather than filed — it is a fact about this dispatch's premise, already corrected above. Carrier: the skills seat, on this PR. - The dispatch's "AGENTS.md prose lines wrap at ~100 columns in that section" does not match the measurement: Prime Directive objectstack-ai#8 wraps at 84–90 bytes, and only the ⛔ line ran to 113. Same carrier, same PR; no separate card. --- _Generated by [Claude Code](https://claude.ai/code/session_01MCLBsUgfykL74aU716rzVK)_ Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Sep 17, 2026
…used to be (objectstack-ai#17838) The Protocol Domains table in `AGENTS.md` still listed a `Cloud` / `cloud/` row after the cloud control-plane contracts left the open-source spec and the package & marketplace format moved to `packages/spec/src/marketplace/`, published as `@objectstack/spec/marketplace`. The row sent a reader to a directory the tree no longer has, and omitted the one that replaced it. This replaces that one row with a `Marketplace` / `marketplace/` row at the same alphabetical position (after `Kernel`), described from the directory's actual modules rather than from the card's proposal. One line in, one line out — 1075 lines before and after. Docs-only, `skip-changeset`. Fixes objectstack-ai#17370 ## Acceptance notes ### The row ``` -| `Cloud` | `cloud/` | Multi-tenant, deployment, environment | +| `Marketplace` | `marketplace/` | Package, Version, Listing, Install, Template | ``` ### Premise findings, re-taken on `origin/main` `51b024a16` (the PM took them on `d79f2499`; `main` advanced by two `docs(pm)` commits, objectstack-ai#17828 and objectstack-ai#17823, neither touching `AGENTS.md`) 1. **Holds.** `AGENTS.md:657` read `| `Cloud` | `cloud/` | Multi-tenant, deployment, environment |` directly after the `Kernel` row at `:656`; the file is 1075 lines. 2. **Holds.** `git ls-tree -d origin/main packages/spec/src/marketplace` answers `040000 tree 3f19482…`; `packages/spec/src/cloud` answers nothing. `packages/spec/package.json` exports `./marketplace`, and has no `./cloud`. 3. **Holds.** `git grep -ln "Multi-tenant, deployment, environment" origin/main` hits only `AGENTS.md`; `git grep -ln "Protocol Domains" origin/main -- scripts .github packages/spec/scripts` hits nothing. No gate reads this table. 4. **Holds, re-measured.** All 22 open PRs' file lists scanned at this commit, fully paginated (PR objectstack-ai#17076 is the standing Version Packages PR at 383 changed files — four pages read). None touches `AGENTS.md`. 5. **FALSIFIED — the dispatch's line-width premise.** The dispatch named "AGENTS.md's own line-width rule, Prime Directive objectstack-ai#8" wrapping at ~84–90 bytes. There is no such rule. Prime Directive objectstack-ai#8 is **North Star alignment**; `AGENTS.md` carries no line-width rule at all. The real 120-byte budget is `MAX_LINE_BYTES` in `scripts/pm/check-skill-line-ratchet.mjs`, and it **exempts a markdown table row by shape** (`EXEMPTION_CLASSES.table`: "a wrapped `|` row is a different table"). What actually binds a table row is that script's **second** ratchet, `MAX_TABLE_ROW_BYTES`, pinned for `AGENTS.md` at **768 bytes**, shrink-only, headroom 0. The new row is far under it, and the gate's own verdict lines confirm both pins are untouched: ``` ✓ check-skill-line-ratchet: AGENTS.md: widest table row is 768 bytes (pin 768; headroom 0). ✓ check-skill-line-ratchet: AGENTS.md is 1075 lines (ceiling 1075; headroom 0). ``` The dispatch's *operative* instruction — stay within the table's own widest row — was honoured anyway; see the width note below. ### Work item B — other `cloud/` references in AGENTS.md `git grep -n "cloud/" origin/main -- AGENTS.md` returns exactly one hit: line 657, the row being replaced. Nothing else in the file to report, and nothing else was touched. ### The description, verified against the directory `git ls-tree -r --name-only origin/main packages/spec/src/marketplace` lists ten files — five modules and five test files: ``` index.ts marketplace.zod.ts marketplace.test.ts package.zod.ts package-namespace.test.ts package-version.zod.ts package-l10n.test.ts package-l10n.ts template-manifest-id.test.ts template-manifest.zod.ts ``` The card proposed 「Package identity & versions, marketplace listing / publish / install format, template manifests」. That description is **accurate** — it does not overstate — but it is 132 bytes as a row, against a table whose widest row is 84, and its `&` / ` / ` punctuation is out of register with its neighbours, which are bare comma-separated noun lists of the domain's principal schemas (`Data` → "Object, Field, FieldType, Query, Filter, Sort"; `Security` → "Permission, Role, Policy"). So it was shortened into that register, one noun per real schema family, each traceable to a module's top-level exports: | Noun | Module | Principal exports | |:---|:---|:---| | `Package` | `package.zod.ts` | `PackageSchema`, `PackageTranslationsSchema`, `CreatePackageRequestSchema` | | `Version` | `package-version.zod.ts` | `PackageVersionSchema`, `PackageManifestSchema`, `PublishPackageVersionRequestSchema` | | `Listing` | `marketplace.zod.ts` | `MarketplaceListingSchema`, `PackageSubmissionSchema`, `MarketplaceSearchRequestSchema` | | `Install` | `marketplace.zod.ts` | `MarketplaceInstallRequestSchema`, `MarketplaceInstallResponseSchema` | | `Template` | `template-manifest.zod.ts` | `TemplateManifestSchema` — the on-disk `objectstack.manifest.json` descriptor | `package-l10n.ts` is the listing-localisation resolver over `PackageTranslations` and folds under `Package`; the neighbouring rows do not enumerate helper resolvers either (`Shared` → "Error maps, normalization utilities"). ### Byte width of the new row versus the table's widest | Row | Bytes | |:---|---:| | New `Marketplace` row | **81** | | Table's widest row — `UI` (`:649`) | 84 | | Old `Cloud` row (replaced) | 62 | | `MAX_TABLE_ROW_BYTES` pin for AGENTS.md (the gate) | 768 | The new row is 3 bytes under the table's own widest and 687 under the enforced pin. ### Gates Derived in this worktree with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths — the tool takes its own change set from the merge base). 14 families derived, **14 run, all exit 0**: ``` 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 ``` Reconciled: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran RANFILE` (exit codes recorded per family) → ``` ✓ dispatch-gates --ran: 14 derived famil(ies) accounted for — 14 run, 0 NOT-MEASURED (a DERIVED zero — all 14 recorded an exit code and none of them is 3). ``` All gate readings above were taken at `f68b09653`, the final commit on this branch. No build or test family is owed: the diff touches no package, so the closure build is empty and no package's `pnpm test` / `pnpm typecheck` is in scope. Control-byte self-scan beyond `check:nul-bytes`: `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' AGENTS.md` exits 1 with zero output. ### Changeset `skip-changeset`. Measured, not assumed: of the 76 tracked package manifests, zero published package lists anything matching `AGENTS` in its `files[]`, against a positive control of 70 published packages that do list `README`. `AGENTS.md` is a repo-root instruction file and ships in no tarball, so this PR publishes nothing. ### Governed surface `AGENTS.md` is a governed surface (Prime Directive objectstack-ai#14). This PR stays a **draft**; it is never flipped ready, never queued, and auto-merge is never armed by this seat. The PM places the four-piece and the maintainer merges. ## 维护者速读(草稿) **改了什么** — `AGENTS.md` 的 Protocol Domains 表里那一行 `Cloud` / `cloud/` 换成了 `Marketplace` / `marketplace/`,位置不变(仍在 `Kernel` 之后,按字母序),描述按目录里实际有的五个模块重写。整个 PR 就这一行,进一行出一行,文件 1075 行前后不变。 **为什么改** — objectstack-ai#16325 把云控制面的协议移出开源 spec(option B「cut by owner」,维护者「同意」),包与市场格式搬到了 `packages/spec/src/marketplace/`。那一行从此指着一个不存在的目录,并且漏掉了顶替它的那个。没有任何门禁读这张表,所以它只会一直烂着,不会变红——这正是要人来修的原因。 **风险与代价(含回滚)** — 风险接近于零:纯文档一行,不触碰任何包,不发布任何东西,14 个派生门禁全绿。回滚就是把这一行改回去,一次 revert 即可,没有任何下游依赖。唯一需要留意的是这是受管面,必须由维护者手工合并。 **席位意见** — (留空,待席位定稿) **你要做的** — 确认 `Marketplace` 行的描述用词是否合你的意:目前是 `Package, Version, Listing, Install, Template`,比卡片原提案短,理由是要和表里其他行同一种写法(裸名词列表)、同一个宽度量级(81 字节,表内最宽 84)。如果你更想保留卡片原来那句更长的描述,告诉我,我改。确认后由你手工合并。 --- _Generated by [Claude Code](https://claude.ai/code/session_01MCLBsUgfykL74aU716rzVK)_ Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Sep 18, 2026
os-zhuang
pushed a commit
that referenced
this pull request
Sep 18, 2026
Fixes #19131 Clause-②: no One new file — `docs/NORTH-STAR.md` — carrying the maintainer's North Star text exactly as finalized in chat on 2026-09-18 (「同意,北极星定稿」 · 「其他同意」). Nothing else moves: the pointers in `AGENTS.md` / `SKILL.md` / `PRIORITIZATION.md` and the governed register belong to #18489, which remains open. Governed by intent — this page is meant to sit above `AGENTS.md` as the fleet's law. Draft on purpose: the maintainer merges it by hand. No seat readies it, queues it, or arms auto-merge on it. ## Byte-for-byte proof The file's content is the fenced markdown block of #19131's body, extracted mechanically and compared byte for byte. Card body read through the REST proxy (4646 bytes); the extracted block is 3271 bytes over 25 lines, with no trailing whitespace on any line and exactly one terminating newline. ````text # 1 — read the card body through the REST proxy curl -sS -H "Authorization: Bearer $GITHUB_TOKEN" \ -H "Accept: application/vnd.github+json" \ https://api.github.com/repos/objectstack-ai/objectstack/issues/19131 > card.json node -e 'process.stdout.write(JSON.parse(require("fs").readFileSync("card.json","utf8")).body)' > card-body.md # 2 — extract the fenced block, dropping both fence lines sed -n '/^```markdown$/,/^```$/p' card-body.md | sed '1d;$d' > card-block.md # 3 — compare $ diff card-block.md docs/NORTH-STAR.md $ echo $? 0 $ sha256sum card-block.md docs/NORTH-STAR.md b94152a07b9fd81aa59e019875aa5a53a00a7c058e53e098bb1b6f65ac6f67a8 card-block.md b94152a07b9fd81aa59e019875aa5a53a00a7c058e53e098bb1b6f65ac6f67a8 docs/NORTH-STAR.md $ git show HEAD:docs/NORTH-STAR.md | sha256sum b94152a07b9fd81aa59e019875aa5a53a00a7c058e53e098bb1b6f65ac6f67a8 - ```` Two independent extractions were run — the `sed` range above and a JSON-side split on the fence lines — and both produce the same sha256, so the proof does not rest on one parser. The card body itself was checked for sanitizer damage first: exactly one opening fence and one closing fence, no image-bracket sequence, complete Markdown. Nothing was reworded, reformatted, translated or annotated: no added heading, date, number, provenance line, status line, table of contents or footer, and no trailing-whitespace "fix". ## Gates Derived, not guessed: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (change set `docs/NORTH-STAR.md`, one path, against merge base `14a762f9f`). All 11 derived families were run at `37f1830fd`; every exit code captured redirect-then-`$?`, never through a pipe. | command | exit | |:---|:---| | `node scripts/check-ci-filter-parity.mjs` | 0 | | `node scripts/check-closing-keyword-parity.mjs` | 0 | | `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 | | `node scripts/check-comment-mask-corpus.mjs` | 0 | | `pnpm --filter @objectstack/lint run check:doc-formula-expressions` | 0 | | `pnpm check:cross-package-test-inputs` | 0 | | `pnpm check:doc-authoring` | 0 | | `pnpm check:driver-memory-census` | 0 | | `pnpm check:nul-bytes` | 0 | | `pnpm check:refd-timer-probe` | 0 | | `pnpm check:watch-hint-literal` | 0 | Reconciled with `dispatch-gates --ran`: *11 derived families accounted for — 11 run, 0 NOT-MEASURED (a DERIVED zero — all 11 recorded an exit code and none of them is 3)*. Two readings worth naming: - `check:doc-authoring` is the gate that actually reads this file: its roots are `.claude`, `docs`, `skills`, `content`, so a hand-written top-level guide under `docs/` is corpus. It reports *402 files clean — no bare metadata literals*. - `check:doc-formula-expressions` first exited **3** (PREREQUISITE NOT MET — `@objectstack/lint` resolves to source but its compiled entry point was absent). That is not a finding and measures nothing. `@objectstack/formula` and `@objectstack/lint` were built through `scripts/pm/os-verify-lock.sh` (VERDICT `command-exit 0`, both runs), after which the gate passed: *22 record-scoped formula examples across 439 files / 1378 TS blocks judged clean*. Outside the derivation, one extra docs audit was run for this doc-only diff: `node scripts/docs-audit/check-affected-docs.mjs` :: exit 0. No package build or package test is owed: `pnpm-workspace.yaml`'s globs cover `packages/*`, its seven nested roots, `apps/*` and `examples/*` — none of them reaches repo-root `docs/`, so this path belongs to no workspace package and there is no affected set to build or test. ## Repo-wide lint, narrowed — with the three readings the narrowing needs Instead of the farm-wide `eslint . --no-inline-config`, this diff's lint obligation is empty, and that is a measurement rather than a skip: 1. **Population, read off eslint's own config, not guessed:** every `files:` entry in `eslint.config.mjs` targets `**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` or a narrower subset of those extensions. No config object matches Markdown. 2. **File count, read off `--format json`:** `pnpm exec eslint --no-inline-config --format json docs/NORTH-STAR.md` returns one entry with `errorCount: 0` and the single message *"File ignored because no matching configuration was supplied."* — the diff contributes **0** linted files. 3. **Invariance for untouched files:** `eslint.config.mjs` is not in this diff, and this repo runs one config that never enables type-aware linting for any file (no `parserOptions.project`, no typed rules — stated in the config's own header comment and true of every `languageOptions` block, each carrying only `ecmaVersion` and `sourceType`). A Markdown file outside the lint population therefore cannot move the verdict on any file this diff does not touch. Readings 1–3 were taken at `37f1830fd`, the final commit. `turbo ls --affected` is deliberately **not** cited: with no base to compare against in a fresh worktree it printed all 81 packages, which is a fallback, not a reading. ## Changeset `skip-changeset`, measured rather than assumed: an npm tarball can only contain files inside its own package directory, and `docs/NORTH-STAR.md` sits outside every workspace package (globs above). Cross-checked from the other side — no package manifest in `packages/**`, `apps/**`, `examples/**` or `skills/**` has a `files[]` entry referencing a `docs/` path — and the repo-root manifest is `private: true`. Nothing published moves, so there is no released surface for a changeset to describe. ## Acceptance notes - *noted, not filed:* `AGENTS.md` Prime Directive #8 still sends readers to `content/docs/concepts/north-star.mdx`, so after this lands two north-star documents coexist until the pointers are rewired. That rewiring — AGENTS.md, the skill files, `PRIORITIZATION.md` and the governed register — is explicitly the other card's scope, and #18489 remains open as its carrier. Not filed as a defect: nothing is broken today, and the successor is already queued. ## 维护者速读(草稿) **改了什么**:新增一个文件 `docs/NORTH-STAR.md`,内容就是你 2026-09-18 在聊天里定稿的那段北极星文本,逐字节照搬(sha256 与卡面 fenced block 一致,diff 为空)。没有第二个文件改动。 **为什么改**:把这段定稿从聊天记录落成仓库里的一页,让它能被引用、被门禁读到、被后续的指针改动挂上。文本本身没有任何加工——没加标题、日期、编号、来源行、状态行、目录或页脚。 **风险与代价(含回滚)**:风险接近零——这是一页文档,不改任何代码或已发布产物,`skip-changeset` 已实测(不在任何包目录内)。回滚就是删这一个文件,无迁移、无依赖。唯一的暂态是:在 #18489 把指针改完之前,`AGENTS.md` 第 8 条仍指向旧的 `content/docs/concepts/north-star.mdx`,两页会并存一段时间。 **席位意见**:(留空,待席位定稿) **你要做的**:读这一页,不同意的地方**直接删行或改行**——这是你的文本,不是我的草案,所以我没有替你改任何一个字。定稿后**由你手动合并**(按设计留作 draft:这页是 `AGENTS.md` 之上的法,没有任何 AI 席位会 ready、入队或武装它)。 --- _Generated by [Claude Code](https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF)_ Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Sep 18, 2026
This was referenced Sep 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Restructure repository from single package to pnpm workspace with 5 scoped packages for granular consumption.
Package Structure
@objectstack/spec-meta- Metamodel types (ObjectEntity, ObjectField, ObjectView)@objectstack/spec-plugin- Plugin runtime interfaces (ObjectStackPlugin, PluginContext)@objectstack/spec-schemas- Zod validation schemas (ManifestSchema)@objectstack/spec-constants- Path conventions (PKG_CONVENTIONS)@objectstack/spec- Aggregator package re-exporting all sub-packagesBackward Compatibility
Existing imports remain unchanged:
Changes
packages/*/src/workspace:*dependenciesfilesfield to package.json for publish controlOriginal prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.