Skip to content

[WIP] Fix error in step four of the action run - #5

Merged
huangyiirene merged 2 commits into
copilot/add-necessary-automation-workfrom
copilot/fix-step-four-error
Jan 18, 2026
Merged

huangyiirene merged 2 commits into
copilot/add-necessary-automation-workfrom
copilot/fix-step-four-error

Conversation

Copilot AI commented Jan 18, 2026

Copy link
Copy Markdown
Contributor

Fix package-lock.json sync issue causing CI failure

Problem: The GitHub Actions CI workflow fails at the "Install dependencies" step because package-lock.json is out of sync with package.json. The lock file contains outdated dependencies (@types/node@12.20.55) that don't match the current requirements.

Plan:

  • Regenerate package-lock.json by running npm install
  • Verify the lock file is properly updated
  • Test that npm ci works correctly
  • Test that the build succeeds
Original prompt

引用: https://github.com/objectstack-ai/spec/actions/runs/21109331090/job/60705711577#step:4:1


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

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 <7665279+huangyiirene@users.noreply.github.com>
@huangyiirene
huangyiirene marked this pull request as ready for review January 18, 2026 09:25
@huangyiirene
huangyiirene merged commit 2d44d3d into copilot/add-necessary-automation-work Jan 18, 2026
Copilot AI requested a review from huangyiirene January 18, 2026 09:25
Copilot stopped work on behalf of huangyiirene due to an error January 18, 2026 09:25
hotlong added a commit that referenced this pull request May 20, 2026
Closes gap #5 from the production-readiness review: zero-dependency
observability hooks that let hosts plug Prometheus / OTel / Sentry
without the framework taking a hard dep on any of them.

Three pluggable primitives (all default to no-op, zero overhead):

  - MetricsRegistry — counter/histogram/gauge contract;
    NoopMetricsRegistry default + InMemoryMetricsRegistry for tests.
    Canonical names exposed via RUNTIME_METRICS constant.
  - ErrorReporter — captureException(err, ctx) contract; called only
    for 5xx responses (4xx are tracked via the metrics counter,
    intentionally NOT reported, to keep APM signal:noise high).
    NoopErrorReporter default + InMemoryErrorReporter for tests.
  - Request correlation — extractRequestId / generateRequestId /
    resolveRequestId; X-Request-Id is validated against
    ^[A-Za-z0-9._:-]+$ ≤200 chars so a malicious caller cannot inject
    headers or pollute logs. Also parseTraceparent / formatTraceparent
    for W3C Trace Context interop.

Wired into createDispatcherPlugin via instrumentRouteHandler() which
wraps every server.get/post/delete handler with:

  - request-id propagation (req.requestId + X-Request-Id response header)
  - http_requests_total{method,route,status} counter
  - http_request_duration_ms{method,route} histogram
  - http_request_errors_total{method,route} on thrown errors
  - error reporter on 5xx, both for thrown errors AND for the common
    case where the handler catches and calls errorResponseBase
    (side-channel via res.__obsRecordedError)
  - reporter failures are swallowed so they never mask the original
    error

The IHttpServer wrapping is a Proxy that intercepts only the three
verb methods — no signature changes on the 50+ existing handlers.

docs/OBSERVABILITY.md ships the full production recipe: Prometheus
prom-client adapter, OTel adapter, Sentry adapter, Datadog adapter,
cardinality caveats, go-live checklist.

52 new tests (21 request-context, 9 metrics, 6 error-reporter,
16 instrument). 280 total runtime tests; 4 pre-existing failures
unrelated. tsc clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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 <223556219+Copilot@users.noreply.github.com>
os-zhuang added a commit that referenced this pull request Jun 19, 2026
…antics

Full hardening of the remaining items from review:

- #5 MySQL/length: key _objectstack_sequences by a single key_hash
  (SHA-256 of object,tenant_id,field,scope) instead of a 4-column natural
  PK. The natural PK exceeded MySQL's utf8mb4 index-length limit (a certain
  CREATE TABLE failure) and bounded how long a {field} scope could be. The
  hash PK keys every dialect uniformly and lets scope be a generous
  non-indexed column. Legacy 3-column and interim {scope}-column tables are
  migrated in place; migration fails safe (fixed-prefix keeps working, a
  per-scope write errors actionably).

- #1 scope ambiguity: confirmed NOT fixable by separating adjacent token
  boundaries — when two records render the same prefix they render the same
  visible number, so they MUST share a counter to stay unique (a separator
  would mint duplicates). Documented the semantics + the remedy (delimiter
  literal in the format), backed by tests. The compile lint already nudges
  authors toward unambiguous formats.

- #6 width overflow: confirmed by-design — the pad width is a MINIMUM, the
  counter grows past it and never wraps (mainstream autonumber semantics).
  Documented + regression test, no throw (throwing would break legitimate
  high-count sequences).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang added a commit that referenced this pull request Jun 19, 2026
…ber formats (#2043)

* feat(autonumber): date, {field} and per-scope counter reset for formats

Tokenize autonumberFormat via a shared pure renderer in @objectstack/spec
(parseAutonumberFormat / renderAutonumber) that both the engine fallback and
the SQL driver call, so they emit byte-identical numbers (#1603 parity):

- date tokens {YYYY}{YY}{MM}{DD}{YYYYMMDD} resolve the calendar day in the
  request's business timezone (ExecutionContext.timezone, ADR-0053; UTC
  fallback), threaded through new DriverOptions.timezone
- {field} interpolation substitutes record values into the prefix
- counter scope = rendered prefix before the sequence slot, so AD{YYYYMMDD}{0000}
  resets daily, {section}{island_zone}{000} numbers per group, {plan_no}{000}
  numbers per parent — one mechanism, no separate reset config

Fixed-prefix formats (CASE-{0000}) render an empty scope and keep their single
global counter. _objectstack_sequences gains a scope column (PK widened to
object,tenant_id,field,scope); legacy 3-column tables migrate in place on first
use, carrying existing counters to scope=''.

* fix(autonumber): drop backtracking lookahead in seed scan (ReDoS)

The empty-prefix legacy branch used /(\d+)(?!.*\d)/ to grab the last digit
run, whose negative lookahead is a polynomial-ReDoS sink on stored values
with many repeated zeros (CodeQL js/polynomial-redos, high). Replace both
branches with the linear /\d+/g, preserving the last-digit-run semantics.

* fix(autonumber): guard {field} interpolation footguns

Add three guardrails on top of the {field}/date/per-scope autonumber work:

- Empty interpolated {field} now throws (shared missingFieldValues helper)
  in both the SQL driver and the engine fallback, instead of silently
  collapsing the record into the wrong counter scope.
- Build-time lint (objectstack compile): unknown / self-referencing {field}
  fails the build; an optional {field} warns to mark it required.
- Legacy _objectstack_sequences PK-widen failure fails safe — fixed-prefix
  sequences keep working and a per-scope write raises an actionable error
  rather than an opaque DB primary-key violation at insert time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(autonumber): hash-keyed sequence table; clarify scope & width semantics

Full hardening of the remaining items from review:

- #5 MySQL/length: key _objectstack_sequences by a single key_hash
  (SHA-256 of object,tenant_id,field,scope) instead of a 4-column natural
  PK. The natural PK exceeded MySQL's utf8mb4 index-length limit (a certain
  CREATE TABLE failure) and bounded how long a {field} scope could be. The
  hash PK keys every dialect uniformly and lets scope be a generous
  non-indexed column. Legacy 3-column and interim {scope}-column tables are
  migrated in place; migration fails safe (fixed-prefix keeps working, a
  per-scope write errors actionably).

- #1 scope ambiguity: confirmed NOT fixable by separating adjacent token
  boundaries — when two records render the same prefix they render the same
  visible number, so they MUST share a counter to stay unique (a separator
  would mint duplicates). Documented the semantics + the remedy (delimiter
  literal in the format), backed by tests. The compile lint already nudges
  authors toward unambiguous formats.

- #6 width overflow: confirmed by-design — the pad width is a MINIMUM, the
  counter grows past it and never wraps (mainstream autonumber semantics).
  Documented + regression test, no throw (throwing would break legitimate
  high-count sequences).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: os-zhuang <jack@objectstack.ai>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang pushed a commit that referenced this pull request Jul 8, 2026
…) (#2683)

* feat(spec,lint): allow dropdown userFilters on object list views (#2679)

Airtable-style quick-filter chips (`userFilters`, `element: 'dropdown'`)
were blanket-suppressed on object list views ("views" mode) — omitted
from `ObjectListViewSchema`, errored by the `validate` list-view-mode
rule, and dropped at render. That over-corrected against ADR-0047 TL;DR
#5 (data mode is meant to expose quick filters).

Narrow the rule: an object list view MAY carry a `dropdown` (value-chip)
userFilters; only the `tabs` preset style stays page-only, because the
saved-view ViewTabBar already owns the tab-bar role (need presets on an
object → use `listViews`).

- spec: new `ObjectUserFiltersSchema` (element narrowed to dropdown/
  toggle, tabs/showAllRecords omitted); `ObjectListViewSchema` extends
  `userFilters` back in with it.
- lint: `validate-list-view-mode` flags `quickFilters` always, but
  `userFilters` only when `element: 'tabs'` / carrying `tabs`.
- app-showcase: dropdown userFilters (status + health) on the default
  `showcase_project` list view.
- docs: ADR-0047 amendment note + regenerated view reference.

Companion objectui runtime change: objectstack-ai/objectui#2338.

* docs(skills): note object list views allow dropdown userFilters, tabs page-only (#2679)

* chore(spec): regenerate skill-docs + api-surface for ObjectUserFiltersSchema (#2679)
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 1, 2026
…ss, with the CPU inversion designed out (objectstack-ai#11915)

The guard's only instrument was output flushes, measured at the wrong end of the
pipeline: what it sees is whatever the last buffering layer chose to release.
--log-order=stream closed one spelling of that; any future buffering layer
re-opens it and kills a healthy suite deterministically on an innocent diff.

Second signal: bytes every process in the wrapped group has passed to write(),
read from /proc/<pid>/io (wchar) — the same quantity the guard already trusts,
sampled at the SOURCE, before any buffering layer can hide it.

Measured first, because the card's CPU direction does not survive contact
(node 22, 2.5s sample, one process per shape):

    shape                        state  dCPU(ticks)  dwchar(bytes)
    idle hang (self-test objectstack-ai#4)     S                0              0
    sync-spinning hang (objectstack-ai#5)      R              251              0
    GC-thrash hang               R              272              0
    HEALTHY silent-but-working   S                1         25,542

CPU does not merely fail to separate these shapes, it separates them BACKWARDS:
the genuine hangs peg a core while the healthy suite the probe exists to protect
is nearly idle, because it is I/O-bound — it is busy writing. wchar separates all
four correctly.

The probe is a confirming signal in one direction only. No output and no
source-side bytes still kills at --stall-minutes with no added latency (idle and
spinning hangs write nothing, so neither is ever deferred). No output but bytes
still moving defers the kill, announced loudly — a live suite hidden by a
buffering layer is a bug to fix, not to tolerate — and only as far as
--stall-cap-minutes, after which the group dies under a distinct STALL-CAP
verdict. That cap is what stops the probe turning "kills healthy suites" into
"never fires on spin hangs", which is strictly worse. A cap <= the window is
refused; an unreadable /proc/<pid>/io reports UNAVAILABLE and the guard behaves
exactly as before.

--stall-minutes is untouched.


Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx

Co-authored-by: Claude <noreply@anthropic.com>
github-merge-queue Bot pushed a commit that referenced this pull request Sep 12, 2026
)

Fixes #17366

## The defect: a carrier a seat could write into and not get out of

The clause-② declaration limb had one carrier — the `Clause-②:` line
inside the card's
governing `Claim:` comment — and repairing a line already written there
was not an act every
seat can perform. The MCP GitHub tool set carries no
edit-an-issue-comment call; the claim
protocol forbids a second `Claim:`; and this gate's own refusal forbids
the checker filling
the line in ("the declaration IS the judgement"). Three closed doors,
and a seat that wrote
the line as prose was left waiting for somebody outside the repository
to retype it.

That was measured five times in one shift across two roles, and the
fifth instance was still
holding a PR with 38 checks and 0 failures out of the queue when the
card was filed.

## The fix: one correction comment, read by the same reader

A dedicated comment whose FIRST line is a fixed key naming, in digits,
the claim comment it
corrects:

```text
Clause-②-correction: 5642248126
Clause-②: no
Session: `session_01MCLBsUgfykL74aU716rzVK`
```

The newest correction naming the card's governing claim supersedes that
claim's declaration,
in both directions — so a wrong VALUE is repaired by the same act as an
unreadable one. The
declaration inside it is read by the SAME `CLAUSE2_KEY_LINE` through the
SAME
`readClause2Line`, so what moved is WHICH COMMENT may carry the
declaration, never what counts
as an answer. That is the move #16304 already made when it asked a
sibling CARD.

Attribution is the `Session:` line the claim protocol already makes
mandatory
(SKILL.md 〈模板与表〉, 「session ID 不可省」, and 「`mode:subagent` 的 dev 与 PM 同会话同
ID」 —
so the session is exactly the granularity of "the claiming seat"). A
correction is attributed
when its `Session:` equals the governing claim's. That is a DECLARED
identity, never a verified
one: the value is copyable text and this fleet writes under one GitHub
login, so the comparison
is on what the comments SAY — the same ceiling C4 already works at.

⛔ No branch of it may become a new one-way door, which is the defect
being removed. A
correction naming another comment, declaring a different session,
carrying no `Session:` line,
or carrying a prose declaration is IGNORED WITH A PRINTED REASON that
names an act the claiming
seat can perform. And a governing claim that carries no `Session:` line
at all leaves nothing to
compare: the correction APPLIES, with a note saying attribution could
not be verified and why.
Refusing there would have rebuilt the door one room over.

The C2 remedy text was rewritten to name WHO can act and HOW, in three
parts: the claim template
in SKILL.md 〈模板与表〉 that already carries the literal `Clause-②: yes | no`
line and should be
copied rather than composed; the fact that an already-posted claim
comment is not editable from
every seat; and the one comment that repairs it. It replaces "add the
line to that claim comment",
which named an act the claiming seat may have no tool for.

## What deliberately did not move

- **The accept set.** `CLAUSE2_KEY_LINE`, `readValueToken` and
`CLAUSE2_VALUES` are untouched. The
card's five measured prose spellings are pinned as negatives in the
self-test.
- **The exit register.** The correction is a new INPUT to C2, not a new
verdict family. 0/1/2/3/4
  keep their meanings and their numbers.
- **`check-half-states.mjs`.** `CLAIM_COMMENT_MARKER` is still imported,
not restated, and not
widened. A correction is not a claim comment and never enters the claim
pool.
- **SKILL.md.** The template already carries the fixed line; this PR
points at it and does not
  restate it.
- **The writes.** This script still writes nothing, hangs no label, and
reads no verdict word.

## Acceptance, all four from the card

1. **A seat writing per the template gets a machine-readable
declaration.** Pinned by importing
the reader over the template's own key with each value substituted, plus
the new remedy text
   that sends the seat to the template rather than to a regex.
2. **The negative control holds.** All five measured spellings from the
card's table are pinned
as not-declared, from the line reader and from a claim comment. The `#1`
spelling is reported
as a SPELLING near miss; the `#2`–`#5` spelling reaches no pattern at
all, because 条款② carries
   no `Clause` token — pinned as a measured fact.
3. **Self-solvability is pinned.** A card whose claim declaration is
unreadable earns a C2 finding;
adding ONE correction comment clears it, with the claim comment
byte-identical across the two
threads, no second `Claim:`, and the governing claim unmoved.
Demonstrated end to end through
the offline `--pair-json` path: `--pair` exit 4 with the broken claim,
exit 0 with the one
   comment added.
4. **Ablation.** Deleting the correction reading reds 22 of 465
self-test cases (every criterion-3
case); deleting the template pointer and the who-can-act remedy reds 7
(criterion 1's new half).
Both legs were mutated on disk, proved to have landed, then restored to
a blob hash equal to
   HEAD's.

## Acceptance notes

- ⚠️ Measured and pinned as a CONTROL, not endorsed and not fixed here:
the template line copied
UNFILLED — `Clause-②: yes | no` — reads as a declared `yes`, because
`readValueToken` takes the
first token after the colon and treats the rest as the seat's argument.
That is an instance of
the population #17098 is already open against (a key-INITIAL DESCRIBING
line read as a
declaration), so it is ⛔ not filed again here. The case carries a
pre-registered FLIP TRIGGER:
when #17098 lands, the expectation becomes `kind !== 'declared'` and the
case flips with it in
that PR. ⛔ It is not to be deleted and its green today is not an
endorsement.
- The PR-body carrier of `Clause-②:` is read by
`scripts/check-changeset-no-major.mjs`, not by this
gate: `--pair` reads the PR side for LABELS (C1) only, and no
`readClause2Line` call here takes a
PR body. The card-side correction shape therefore has no PR-side
counterpart to add, and the
PR-body carrier is editable by the seat anyway — which is exactly the
asymmetry the card names.
- `check-scripts-symbol-anchors`, `check-self-test-wired` and
`check-self-test-workflow-commands`
all pass unchanged: the `check:pm-clause2-carriers` step in `lint.yml`
already runs the self-test,
  and no second step was added.

## Gates, on head `dbbfbb596`

`node scripts/pm/dispatch-gates.mjs --commands` derives 35 families for
this one-path diff; all 35
ran and all 35 exited 0 (`--ran` reconciliation: "35 derived famil(ies)
accounted for — 35 run, 0
NOT-MEASURED (a DERIVED zero — all 35 recorded an exit code and none of
them is 3)"). Lint is the
declared narrowing rather than the repo-wide run CI owns: the receiving
population is
`eslint.config.mjs`'s base block (`files:
['**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}']`), `--format
json` reports 1 file linted with 0 errors and 0 warnings, and the config
"never enables type-aware
linting (no `parserOptions.project`, no typed `@typescript-eslint`
rules) for ANY file"
(`eslint.config.mjs`, its own words) — so this diff cannot move the
verdict on any file it does not
touch. `node scripts/pm/check-governed-merges.mjs --test
scripts/pm/check-clause2-carriers.mjs`
prints "✅ NOT governed — ordinary queue landing applies". `--pair 17738`
exits 0.

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


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

---------

Co-authored-by: Claude <noreply@anthropic.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