Skip to content

fix(rules): use native formats and scope-specific delivery - #957

Merged
jeff-r2026 merged 22 commits into
Tencent:mainfrom
SaulMoro:fix/946-rules-delivery
Oct 4, 2026
Merged

jeff-r2026 merged 22 commits into
Tencent:mainfrom
SaulMoro:fix/946-rules-delivery

Conversation

@SaulMoro

@SaulMoro SaulMoro commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Team rules
├─ Native files     → Kiro, Qoder/CN, CodeBuddy/WorkBuddy, OMP, JoyCode project
├─ User-scope files → Codex, ZCode, dsh, Pi, JoyCode, Hermes, OpenClaw
├─ Project context  → Codex/ZCode/dsh session hooks; Pi extension
└─ Upgrade pulls    → repair formats, retire unchanged copies, preserve edits

Deliver rules through the files and formats each tool reads. Fix OpenCode namespace globs, OpenClaw event dispatch and hook activation, and diagnostics for missing delivery channels. Push and uninstall respect recorded ownership, flat names and shared files. YAML comments stay outside repaired glob scalars; doctor reports all-colliding flat names and stale activation after the last rule is removed. Scoped inline rules retain Applies to files matching: <globs> as model guidance; the tool does not enforce file filtering.

README capability changes

All five README variants contain the same changes:

Agent Capability Before After
Codex rules ✓ ✓*
OpenCode rules ✓ ✓*
Pi Coding Agent rules ✓ ✓*
Hermes rules — ✓*
OpenClaw rules ✓ ✓*
DeepSeek Harness rules — ✓*
ZCode rules — ✓*

✓* identifies always-on rules without tool-enforced path scoping. Hermes and OpenClaw use their normal user-scope channel. OpenClaw's previous check counted rule files it did not read.

New JoyCode row After
skills, rules, docs, env, agents, learnings, codebase, teamwiki ✓
hooks, mcp, models, usage, sessions, dashboard —

JoyCode scopes project rules natively; its user rules.txt block is always on.

HTTP prompt delivery also creates a missing OpenClaw AGENTS.md in an existing resolved user workspace, preserving personal text.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature causing existing behavior to change)
  • Documentation only
  • Refactor / internal cleanup

Test Plan

OpenClaw HTTP prompt fix at a232064e

Existing resolved user workspace, AGENTS.md absent
Before: prompt skipped, installation ACK = failed
After:  AGENTS.md created with the prompt, installation ACK = success

Resolved the latest P1 review finding by probing the workspace directory instead of requiring its target file. A second regression verifies that personal text in an existing AGENTS.md remains. English/Chinese usage guides and the core troubleshooting reference document the behavior.

  • New public-interface regression via reportAndSyncLocalAgent: npx vitest run src/__tests__/local-agent.test.ts -t 'creates AGENTS.md for an HTTP prompt' failed with expected 'failed' to be 'success' before the fix and passed afterward.
  • npx vitest run --maxWorkers=4 src/__tests__/local-agent.test.ts src/__tests__/instruction-targets.test.ts src/__tests__/openclaw-hooks.test.ts src/__tests__/user-rules-files.test.ts src/__tests__/project-hook-rules.test.ts: 487 passed across 5 files.
  • npx tsc --noEmit
  • npm run lint
  • npm run build
  • git diff --check

E2E and compiled real-CLI verification were not rerun for this follow-up, preserving the user's explicit waiver. Earlier verification records remain below.

Conflict resolution at 204aa650

origin/main e465eec2 + PR head 41854ec4 → merge 204aa650
CHANGELOG.md: retain entries from both branches
  • npx tsc --noEmit
  • npm run lint
  • npm run build
  • npx vitest run --maxWorkers=4 src/__tests__/import-org.test.ts src/__tests__/votes.test.ts src/__tests__/rules.test.ts src/__tests__/rule-render-contracts.test.ts src/__tests__/doctor-rules-delivery.test.ts src/__tests__/user-rules-files.test.ts src/__tests__/project-hook-rules.test.ts src/__tests__/init.test.ts src/__tests__/post-pull.test.ts: 455 passed across 9 files.
  • git diff --check; all 83 PR-only paths and 8 main-only paths preserved byte-for-byte. The four overlapping paths are the changelog and documentation; runtime files have no overlap.

E2E and real-CLI verification were not rerun for this conflict resolution, as explicitly waived by the user. Earlier evidence remains below.

Pre-merge verification at 41854ec4, based on main at 6c5949f8:

  • npx tsc --noEmit
  • npm run lint
  • npm run build
  • Node 22.23.3: node node_modules/vitest/vitest.mjs run --coverage --maxWorkers=4: 7,975 passed, 20 skipped
  • Rules/render/doctor regressions: 192 passed. Ten new cases failed before the fixes and pass afterward.
  • GitHub CI at 41854ec4: Node 22/Linux, the previously failing job, passed in run 37132282805. Remaining matrix/build/E2E jobs were still running when this record was added.
  • CI post-pull reproduction: forcing a 20 ms pause between scheduling close and attaching output listeners reproduced the missing tail twice. The corrected fixture passed that scenario 25 times with Node 22 and coverage. Existing assertions are unchanged.
  • Rebase verification at 591dc5eb: init/doctor/hooks tests, 153 passed. Covered again by the current whole unit suite.
  • Current build: npx vitest run --config vitest.e2e.config.ts src/__tests__/e2e/doctor-delivery-cli.test.ts: 12 passed.
  • Rebase verification at 591dc5eb: doctor-delivery and hooks-project-isolation E2E, 14 passed. Shared main-checkout Claude/Codex hooks and project isolation were not changed by this follow-up.
  • Compiled real CLI with git provider and isolated HOME, recorded below
  • Regressions cover full/unchanged pulls, edited and undelivered flat files, deleted OpenCode namespaces, shared ownership, push, uninstall, Hermes cleanup and tolerant glob parsing

The full E2E suite was not rerun, preserving the requested waiver. Its previously recorded run had 492 passed and 26 skipped at f87b4d78. The post-pull CI failure was a test-fixture race: independent timers could emit close before output under worker load. The fake process now emits stream data before close and is created at spawn time; production post-pull code is unchanged. Current runtime fixes were rebuilt and verified through the real CLI.

Evidence

Real CLI after build, git provider, isolated HOME, Kiro/OMP/Pi in user scope:

# rules/fe/style.md has unquoted paths: **/*.ts
# rules/.removed contains fe.style, the flat name of the live namespaced rule
$ teamai pull
✔ [user] Synced 1 rule(s)
$ teamai pull
✔ [user] Already synced at 7597c56, skipping

Both Kiro and OMP fe.style.md copies retain the live rule after both pulls. Pi AGENTS.md contains Applies to files matching: **/*.ts; neither pull prints a frontmatter parse error. Before the fixes, the root tombstone could delete the flat copy and strict YAML parsing dropped the inline scope hint.

A second project-only HOME with Hermes/Claude and an obsolete managed block in global SOUL.md:

$ teamai pull
ℹ Removed the team rules an older project pull wrote to <sandbox>/home-project/.hermes/SOUL.md: Hermes gets no project rules
✔ [project] Synced 1 rule(s)

The obsolete block is absent and personal SOUL.md text remains. Previously the project-only install left the global rules behind. These runs exercise CLI delivery and migration; they do not launch those host applications.

Additional real CLI after build, git provider, isolated HOME:

paths: **/*.ts # TypeScript files
  Kiro/OMP native glob: **/*.ts
  Pi inline hint: Applies to files matching: **/*.ts

Only rules: fe.style/x and fe/style.x
  doctor: Rules delivered to omp = false, both names and rename guidance
  doctor: Rules delivered to kiro = false, both names and rename guidance

No rules, team-owned OpenCode glob still in instructions
  doctor: Team rules are active in opencode = false, in user and project scope
  opencode.json remains unchanged by doctor
  removing the glob: no empty-rule activation finding

Before these fixes, the comment became part of the glob, all-colliding tools had no delivery diagnostic, and an empty rule set bypassed stale activation checks. These cases now pass through the compiled CLI.

Related Issues

Fixes #946.

Dependencies #952 and #958 are merged. The branch now includes origin/main at e465eec2 through merge commit 204aa650; their implementation is outside this PR's diff. Conflict resolutions retain #958 automatic Codex trust, main-checkout hook sharing and doctor trust queries alongside #946 delivery notes. The init regression now checks automatic trust reporting without an unconditional manual-trust warning. English/Chinese guides retain both changes.

Notes for Reviewers

Reviewed the whole branch inventory and runtime changes against origin/main, and compared all 17 original commits with git range-diff. The rebase preserves the previous rule ownership fixes and main's read-only votes aggregation from #968. Bilingual guides, design docs and affected skill-data references are updated.

Merge danger

Door: Two-way for code. Migration removes only proven, unchanged team copies and preserves member edits; restoring a legacy layout requires a compatible release and pull. The existing data-directory migration does not support downgrades.

Blast radius: Rules, instruction files, hook configuration and diagnostics across tools.

Earlier verification and retained limits
  • Previously recorded: 54 parser/render checks with Cursor 2026.09.22, CodeBuddy 2.160.0, JoyCode 3.8.71 and OMP 18.2.1; mock-model runs with OMP/OpenCode, Pi across two turns, and OpenClaw startup/new/reset in a live gateway. These were not repeated for this rebase.
  • Only OMP parser tests run in CI. Other extracted parsers require TEAMAI_RULE_PARSER_BUNDLES; they are among the current skips.
  • Kiro CLI ignores path scoping. OMP reads project rules only at the root. Copilot CLI ≥1.0.89 also reads Claude rules; OMP can read namespaced Copilot rules twice.
  • A WorkBuddy-only project creates .codebuddy, which makes CodeBuddy count as installed.
  • ZCode/dsh lose hook text at compaction; dsh requires --patch and may miss the first request. Codex automatic hook trust comes from fix(hooks): trust Codex hooks and share project hooks across worktrees #958, with manual fallback when disabled or unsuccessful.
  • OpenClaw message/auto-reset mappings have fixture coverage only. Qoder Desktop/CN subdirectory discovery remains an accepted assumption.
  • Kiro, Qoder/CN, CodeBuddy, WorkBuddy, JoyCode, ZCode, dsh, Hermes and Cursor IDE were not run live. Additional providers remain with CI.
  • Excluded work: ZCode's 32 KB hook-output cap and dsh skills ignoring DSH_HOME.

@SaulMoro
SaulMoro marked this pull request as draft October 2, 2026 00:08
@jeff-r2026 jeff-r2026 self-assigned this Oct 2, 2026
@SaulMoro
SaulMoro force-pushed the fix/946-rules-delivery branch from b9e9378 to daf0817 Compare October 2, 2026 05:21
@SaulMoro SaulMoro changed the title [After #947, #952] fix(rules): deliver team rules through each tool's own channel [After #952] fix(rules): deliver team rules through each tool's own channel Oct 2, 2026
@SaulMoro
SaulMoro force-pushed the fix/946-rules-delivery branch from daf0817 to f87b4d7 Compare October 3, 2026 06:33
@SaulMoro SaulMoro changed the title [After #952] fix(rules): deliver team rules through each tool's own channel fix(rules): deliver team rules through each tool's own channel Oct 3, 2026
@SaulMoro
SaulMoro marked this pull request as ready for review October 3, 2026 06:33
@jeff-r2026

Copy link
Copy Markdown
Collaborator

This branch has merge conflicts with main. Please rebase onto the latest main and resolve the conflicts so review can continue.

@SaulMoro
SaulMoro force-pushed the fix/946-rules-delivery branch from f87b4d7 to 2c70f26 Compare October 3, 2026 07:04
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
  • [P1 blocking] Preserve edited OMP copies during uninstall — src/resources/rules.ts:644 treats any delivery record as proof that the current flat file is owned. If a member edits a delivered fe.style.md and runs teamai uninstall, ownedFlatCopies() schedules it for unconditional deletion, losing the edit. Require the current hash to match the recorded hash, as other uninstall cleanup does.
  • [P1 blocking] Reclaim globs for deleted OpenCode namespaces — src/resources/opencode-config.ts:112 recognizes namespace globs only from currently desired or currently existing team-rule directories. When the last fe/* rule is deleted or renamed, the previously generated absolute .../rules/fe/*.md entry is no longer considered owned, so pull and doctor leave it in opencode.json. An edited copy preserved in that directory therefore remains loaded after the team stops delivering it.

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

Findings

  • [P1 blocking] Preserve a personal flat-name file before deleting supersedes — src/resources/rules.ts:436. With a placement record mapping style to rules/fe/style.md, Kiro/OMP deliver the author’s copy as style.md and set supersedes to fe.style.md. If the member independently created fe.style.md, every pull deletes it without checking the delivery ledger or rendered content. Apply the same ownership/edit verification used for movedFrom before removal.
  • [P1 blocking] Use the tolerant parser when generating inline rule hints — src/resources/rules.ts:1388. inlinedRulesText() uses splitFrontmatter(), while the new native renderers use teamRuleData() specifically to support common unquoted globs such as paths: **/*.ts. For that input, inline channels receive the body without the promised Applies to files matching hint, causing Codex/ZCode/DSH/Pi/Hermes/OpenClaw to treat a scoped rule as globally applicable.

Resolved

  • The earlier OMP uninstall finding is fixed by verifying the recorded hash or rendered content.
  • The earlier OpenCode deleted-namespace glob finding is fixed by considering namespaces from previously pulled revisions.
  • The PR description includes a representative real-CLI verification at head 2428b2cf, so its testing record is sufficient.

@SaulMoro
SaulMoro force-pushed the fix/946-rules-delivery branch from 2474643 to 0ca60db Compare October 3, 2026 10:28
…ets (Tencent#946)

- Keep OpenClaw's default workspace AGENTS.md out of the retired files: its
  default profile still reads it.
- Strip a retired file of a tool with no file and no hook in this scope
  (OpenClaw in a project) without waiting for a replacement.
- Keep doctor's Pi extension check while the project has team rules, even
  with no instruction blocks.
- Adapt the Tencent#945 every-shape test to OpenClaw's workspace install probe and
  its lack of a project file; drop the Tencent#946 uninstall test Tencent#945's recorded
  entry ownership superseded.
- Hold back a hook tool's retired instruction file while its hook is not
  installed; only a tool with no project channel (OpenClaw) releases it.
- Mark Hermes and OpenClaw rules always on (✓*) in every README.
- Pin that a project uninstall keeps a .opencode/opencode.json left with
  only $schema once the recorded instructions entry goes.
- Resolve the team rules once for doctor's hook checks; use one
  RulesHandler in the uninstall plan; return early from ruleChannelNotes
  outside a project; name only the files a project pull touches when the
  team rules cannot be resolved; drop a stray CHANGELOG period.
…namespace globs (Tencent#946)

- A flat copy on record is teamai's only while it holds what was recorded
  or the render; remove and uninstall keep and name an edited one.
- OpenCode's user rules globs own every namespace directory a rule landed
  in at a revision this checkout pulled, so pull and doctor reclaim the
  glob of a namespace the team deleted.
…n inline rules (Tencent#946)

- A superseded flat copy (fe.style.md beside the author's style.md) goes
  only while it holds what was recorded or the render; an edited one is
  kept and named, a member's own file is left alone.
- inlinedRulesText reads paths: through the tolerant team-rule parse, so
  paths: **/*.ts keeps its 'Applies to files matching' line.
…Tencent#946)

parseLearningDoc logged 'Failed to parse frontmatter' at error level on
every pull for a rule with paths: **/*.ts and indexed the frontmatter as
body text. It now retries with the tolerant team-rule parse and logs at
debug.
@SaulMoro SaulMoro changed the title fix(rules): deliver team rules through each tool's own channel fix(rules): use native formats and scope-specific delivery Oct 3, 2026
@SaulMoro
SaulMoro force-pushed the fix/946-rules-delivery branch from 0ca60db to 591dc5e Compare October 3, 2026 14:32
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

Findings

  • [P1 blocking] Preserve YAML comments outside the repaired glob scalar — src/resources/team-rule.ts:39. For paths: **/*.ts # TypeScript files, the retry produces paths: "**/*.ts # TypeScript files", so native renderers and inline channels receive the nonexistent glob **/*.ts # TypeScript files. Quote only the scalar before the YAML comment.
  • [P2 non-blocking] Create flat-tool diagnostics even when every target collides — src/doctor-delivery.ts:306. If the only rules are fe.style/x and fe/style.x, both flatten to the same OMP/Kiro filename and deliveryTargets() skips both; consequently byTool has no entry and doctor reports no collision for that tool.
  • [P2 non-blocking] Check stale activation artifacts when no rules remain — src/doctor-delivery.ts:274. The early return bypasses buildRulesActivationChecks(), so after the last rule is removed, doctor cannot report a team-owned OpenCode glob left in opencode.json after failed cleanup, even though OpenCode may continue loading the stale copies.

Resolved

  • The four previously reported ownership, OpenCode namespace, supersedes, and inline-parser findings are fixed. The PR’s real-CLI testing record is sufficient.

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

One parser edge looks real; I’m confirming expected syntax and impact.

@SaulMoro

SaulMoro commented Oct 3, 2026

Copy link
Copy Markdown
Collaborator Author

@jeff-r2026 The previous automated comment published an intermediate progress message instead of the final review result. The completed Codex CI review of 41854ec4 states:

Review Result

  • No findings in the current diff.
  • All seven findings from earlier passes are resolved, including YAML comments, flat-name collisions, and empty-rule stale activation diagnostics.
  • The PR description includes representative compiled real-CLI verification at head 41854ec4, so the runtime-change testing record is sufficient.

The parser concern mentioned in the posted progress message did not become a finding in the final result.

Preserve both changelog entries while integrating current main.
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown

Finding

  • [P1 blocking] Allow delivery to a fresh server-sent OpenClaw workspace — src/local-agent.ts:2162 checks whether <workspace>/AGENTS.md already exists. When the server supplies an existing OpenClaw workspace without that file, the new fallback resolves correctly but then skips delivery instead of creating AGENTS.md, so the prompt installation fails. Probe the workspace directory rather than the target file.

Resolved

  • All findings from earlier review passes are fixed in the current diff.

Testing

  • The PR description’s representative compiled real-CLI runs satisfy the required end-to-end verification; their older commit references are non-blocking.

Probe the resolved workspace directory instead of requiring AGENTS.md before delivering an HTTP prompt. Cover creation, successful acknowledgement and preservation of personal text.
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown

Review

  • No new findings in the current diff.
  • All previously raised findings are resolved, including the OpenClaw HTTP prompt fix at src/local-agent.ts:2162.

Testing

  • The PR description includes representative compiled real-CLI verification. The records predate the current head, but the review rules explicitly treat that as non-blocking.
  • No tests or builds were run, per the request.

@jeff-r2026
jeff-r2026 merged commit a8957a8 into Tencent:main Oct 4, 2026
13 checks passed
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.

[bug] Team rules miss most tools: each tool's own rules format, else a file only it reads, else a hook or extension in project scope

2 participants