Commit Graph
3943 Commits
Author SHA1 Message Date
haelyra 131c6186c3 feat: integrate native Copilot skill and agent distribution
Preserve contributor histories for PR #2960 and #2963. Resolve current-main conflicts without dropping OpenCode behavior. Reject traversal source paths, keep volatile inventory counts observational, and apply the shared ownership guard during every adapter repair while retaining adapter-derived roots. RED ownership and traversal regressions now pass, 73 lifecycle tests pass, and native Copilot observes 288 enabled project skills. Disposable install, missing-file repair, and uninstall preserve user-authored agents.
2026-10-09 15:53:38 -04:00
Max BeitanandClaude Sonnet 5 6bf219c33a feat(skills): add conventional-commit-review skill and commit-reviewer agent
Adds a skill + matching delegated agent that draft Conventional
Commits-style messages by reading the repo's own git log norms
(prefix, scope, subject length) instead of assuming a fixed format.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-09 15:50:58 -04:00
Darwin PardaveandCopilot App 5e3863e512 perf: avoid duplicate skill file reads
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-09 15:50:20 -04:00
haelyra 9c21c20744 docs: match Hermes hook examples to installed filenames 2026-10-09 15:49:53 -04:00
haelyra 9e951e266d fix: normalize portable workspace path separators 2026-10-09 15:49:31 -04:00
haelyra aa365f4405 docs: integrate bounded Bun 1.4 runtime guidance
Preserve PR #2968 contributor history, verified upstream claims, and target-specific metadata. Rebind the existing trigger registry metadata after the merge, retaining current trigger phrases and generation provenance. Portable Bun 1.4.2 isolation and parallel-timing examples passed; all five Markdown files and context profiles validated.
2026-10-09 15:47:57 -04:00
haelyra b6262c3665 feat: integrate read-only documentation governance audit
Preserve PR #2943 contributor history and rebind the existing trigger manifest to the 294-skill registry without changing trigger phrases or model provenance. Validated real read-only audit CLI, 66 focused Python tests, 239 full Python tests, five Node surface checks, catalog, install manifests, and context projections.
2026-10-09 15:43:56 -04:00
Dante c29a724bcd fix: declare optional cross-target install dependencies
Carry forward the final scoped delta of PR #3119 at 60e82f95. Keep required dependency closure and select only modules reachable from successful requests; refresh the unchanged 293-skill registry binding.
2026-10-09 15:43:31 -04:00
Yusuf Efe 0f34fdcc14 fix: resolve installed OpenCode skill paths consistently
Carry forward PR #3115 ef475c79 and 780dfb78 onto current main. Preserve the newer hook-consent transforms during install and repair. Main already includes the source import fix from #3167.
2026-10-09 15:40:12 -04:00
montjeffrey 20cd70e06d test: stop Windows developer tooling from leaking into setup, tar, and audit tests
On a Windows machine with Claude Code installed natively, Git for Windows,
and the ECC plugin installed, `node tests/run-all.js` on main fails 44 tests
in 7 files. Linux CI never sees them. Three of the four causes are test
isolation gaps, fixed here (43 tests):

- claude-plugin-setup, claude-scope-migration, setup (38): fixtures put a
  fake claude.cmd first on PATH, but on Windows spawning a bare `claude`
  resolves only .com/.exe, so a native ~/.local/bin/claude.exe ran instead
  of the fake. Fixture PATHs now drop entries holding claude.exe/claude.com.
- ecc-universal-bin, eval-harness-package (4): tar received an absolute
  C:\ archive path, which Git Bash's GNU tar reads as a host:path remote
  spec ("Cannot connect to C: resolve failed"). Extract from inside the
  destination with a relative, forward-slash archive name, which both GNU
  tar and bsdtar accept.
- harness-audit (1): the cache-layout test overrode HOME only, while
  findPluginInstall also reads USERPROFILE and os.homedir(), so the real
  installed plugin won over the fixture. Override USERPROFILE too.

The two helpers live in tests/lib/helpers/windows-test-env.js with a
platform-independent test, so Linux CI holds both invariants too.

The 44th failure, plugin-hook-bootstrap's no-bash test, is a production
bug rather than a test leak: System32\bash.exe launches an installed WSL
distro, which passes the bash probe. It gets a separate fix.
2026-10-09 14:32:52 -04:00
Yann Roberto 39796acf2f perf(state-store): reuse unchanged read snapshots
Keep the operation lock while validating bigint file identity and reuse
only snapshots produced by successful trusted static SELECTs. Avoid
reloading and exporting unchanged databases on repeated public reads.

Retain conservative comparison for generic SQL, including RETURNING and
PRAGMA writes, and invalidate reuse after transactions, exports or errors.
Cover cache invalidation, cross-process visibility, Windows device IDs,
reentrant partial writes, lock contention and independent result objects.

Validate 188 focused tests per environment on WSL Node 22.22.3 and native
Windows Node 22.15.0/24.16.0, plus 38 related WSL tests. Paired warm-read
benchmarks show 7.6-18.1x point-query speedup on 160 KiB/1.28 MiB databases.
2026-10-09 17:04:56 +08:00
Yann Roberto a6ce6fbbdb fix(state-store): tolerate missing Windows lock device IDs
Handle Windows Node path stats that report dev=0 for the same file whose
open descriptor reports a volume serial. Keep bigint inode checks strict,
retain device comparisons whenever both are known, and leave POSIX strict.

Cover zero-device identity cases, high inode precision, replacement and
file-type safeguards. Verify 164 focused tests each on native Windows
Node 22.15.0 and 24.16.0, plus WSL Ubuntu Node 22.22.3.
2026-10-09 16:46:19 +08:00
Yann Roberto f76c469fa7 fix(state-store): persist writes from prepared result queries
Compare the completed snapshot after get/all queries so RETURNING and
prepared PRAGMA writes survive reloads and reopening. Export only after
the outer operation or transaction succeeds; unchanged read snapshots
still avoid disk writes. This adds one export/byte comparison per read
snapshot without relying on SQL parsing or private sql.js APIs.

Add 18 regression cases covering multi-row INSERT/UPDATE/DELETE RETURNING,
standalone and transactional get/all, no-row PRAGMA writes, and rollback.
The unfixed adapter fails 16 of these cases. Strengthen read-only checks.

Validation: 148 focused tests pass on WSL Node 22 and Windows Node 24;
the general state-store suite passes 20/20 on WSL and 19/20 on Windows,
where the existing file-symlink fixture is denied by Windows permissions.
Scoped adapter coverage is 90.13% lines, 82.73% branches, 100% functions.
ESLint, Unicode safety, and git diff --check pass.
2026-10-09 16:28:30 +08:00
zakyirsyaad 93e6475420 fix(qwen): publish the adapter, handle CRLF, reject unknown flags
Three review findings, all verified before fixing.

1. Publish surface (blocking). package.json `files` lists
   scripts/gemini-adapt-agents.js but not this script, so the npm tarball
   omitted it and ecc-universal users hit MODULE_NOT_FOUND. Added to `files`
   and to the allowlist in tests/scripts/npm-publish-surface.test.js, which now
   passes 2/2.

2. CRLF agents were silently skipped. The frontmatter regex matched LF only, so
   a Windows-saved agent was reported as 'already compatible' while still
   carrying tools: Read, Bash and color: teal -- a success message with no
   adaptation. Normalize to LF, adapt, then restore the original ending style.
   Reproduced before and after: the same CRLF fixture went from 'Updated 0' with
   Read/teal intact to 'Updated 1' with read_file/cyan and CRLF preserved.

3. Unknown flags were discarded. Because the script rewrites files in place,
   `--dry-run` rewrote every installed agent and exited 0. parseArgs now throws
   on any unrecognized option before a directory is selected.

Tests: 12/12 (added CRLF preservation and no-mutation-on-unknown-flag),
gemini-adapt-agents 4/4 unaffected, npm-publish-surface 2/2. Re-run against all
68 canonical definitions: 68 updated, second run 0 updated, no Claude-shaped
frontmatter remaining, no spurious CRLF introduced.

Note: findings 2 and 3 apply equally to scripts/gemini-adapt-agents.js, which
has the same LF-only regex and the same flag filter. Left unchanged here to keep
this PR scoped to the Qwen adapter; worth a follow-up.
2026-10-09 13:46:34 +07:00
zakyirsyaad 0bb8403249 fix(qwen): correct three claims in the Qwen context file
Review corrections, each verified against an installed Qwen Code 0.25.0:

1. web_search does exist. The mapping table said WebSearch had no Qwen
   equivalent; Qwen Code exposes web_search as a deferred tool backed by a
   DashScope search agent. Now qualified by provider, with web_fetch as the
   fallback, and web_search added to the deferred-tools sentence.

2. docs/QWEN-GUIDE.md is not installed. The installer copies .qwen/QWEN.md to
   ~/.qwen/ but does not copy docs/, so a relative reference to the guide is dead
   in any session outside an ECC checkout. Now states that explicitly and links
   the guide in the repository.

3. The AGENTS.md loading claim is now version-qualified. It is accurate for
   0.25.0 under default settings -- with no context.fileName configured, Qwen's
   own debug log resolves "Final ordered QWEN.md,AGENTS.md paths to read" to
   both files -- but AGENTS.md is not the documented default context filename, so
   the sentence no longer asserts unconditional behaviour and points at
   context.fileName instead.
2026-10-09 13:38:43 +07:00
zakyirsyaad 7695b99348 fix(qwen): map WebSearch to web_search instead of dropping it
Review correction. The original version dropped WebSearch on the claim that Qwen
Code has no web search tool. That claim is wrong: Qwen Code exposes web_search as
a deferred tool, resolving through a DashScope search agent.

web_search is provider-dependent rather than universally present, but mapping is
still the better default than dropping. Where the provider supports it the agent
gains the capability; where it does not, Qwen Code ignores an unresolvable entry
in tools: without warning, so the outcome is the same as dropping. The reasoning
is recorded in a comment at the mapping so the choice is not silently reverted.

Across the 68 canonical definitions this changes two agents from losing a
declared capability to keeping it. Tests updated to assert the mapping; 10/10
pass and gemini-adapt-agents.test.js still passes 4/4.
2026-10-09 13:38:24 +07:00
zakyirsyaad 70940903cc test(commands): guard argument-hint against unquoted flow sequences
The existing frontmatter test only checks that a description is present, so all
three array-valued argument-hint declarations passed CI on main. Harnesses that
type-check the field reject the whole file, which is how the commands went
missing without anyone noticing.

Add an assertion scoped to argument-hint only. A blanket 'no flow sequences in
frontmatter' rule would be wrong: allowed-tools is a legitimate list in
marketing-campaign.md and skill-create.md.

Verified both directions -- on main the new test fails and names exactly
code-review.md, cost-report.md, and orch-review.md; on this branch the suite
passes 96/96.
2026-10-09 12:59:53 +07:00
zakyirsyaad 64eaa7d124 feat(qwen): add qwen-adapt-agents.js to normalize agent frontmatter
--target qwen installs all 68 agent definitions verbatim, so they carry Claude
Code tool names (Read, Write, Edit, Bash, Grep, Glob, WebSearch) and color: teal.
Qwen Code uses different tool ids, and its palette is red/blue/green/yellow/
purple/orange/pink/cyan/auto, so an unlisted value is dropped at load time with a
SUBAGENT_MANAGER warning.

ECC already solves this for Gemini via scripts/gemini-adapt-agents.js; this adds
the Qwen counterpart plus a test mirroring the Gemini one. The canonical agents/
directory is untouched -- each harness adapts its own installed copy.

Deliberate differences from the Gemini adapter, each a real Qwen behaviour:

  Edit              -> edit          (Gemini maps to replace)
  WebSearch         -> dropped       (Qwen has web_fetch only, no web search)
  mcp__server__tool -> unchanged     (Gemini lowercases to mcp_server_tool)
  color:            -> remapped      (Gemini removes it; teal becomes cyan)
  tools: output     -> comma scalar  (the form Qwen's own examples use)

model: is left alone, matching the Gemini adapter. 58 files say sonnet, 6 haiku,
4 opus and none are Qwen model ids, but Qwen logs no warning for them, so whether
they are ignored or resolved at dispatch time is unverified and changing 68 files
on an assumption seemed worse than flagging it as a follow-up.

Tested: 10/10 new cases pass and gemini-adapt-agents.test.js still passes 4/4.
Run against a copy of all 68 real definitions: 68 updated, 0 bodies changed,
0 invalid frontmatters, second run reports 0 updated. The result was installed
into ~/.qwen/agents and a headless Qwen session loaded all 68 with no errors and
no color warnings.
2026-10-09 12:55:36 +07:00
Beksultan Pirmatov 11a970e11e fix: detect Dart/Flutter projects in project-detect.js
LANGUAGE_RULES had no entry for Dart, and FRAMEWORK_RULES had no way to
detect Flutter, so any Flutter app (pubspec.yaml, lib/*.dart, android/,
ios/) was reported as primary: "unknown" by the SessionStart project-type
banner, despite ECC shipping a dart-flutter-patterns skill and a
dart-build-resolver agent for this exact stack.

Adds a 'dart' language rule (pubspec.yaml/pubspec.lock markers, .dart
extension) and a 'flutter' framework rule that checks pubspec.yaml for
the standard `flutter: / sdk: flutter` dependency shape, via a new
customCheck hook on FRAMEWORK_RULES entries. This distinguishes Flutter
apps from plain Dart packages, which don't depend on the Flutter SDK.

Closes #3469
2026-10-09 11:16:44 +06:00
zakyirsyaad e60dbbc769 fix(qwen): ship agent context in .qwen/QWEN.md instead of installer docs
`.qwen/QWEN.md` is copied to `~/.qwen/QWEN.md`, which Qwen Code loads as
home-level agent context in every session. Its current content describes the
install template itself -- 'This directory contains ECC's Qwen CLI install
template', the `./install.sh` invocation, and the managed-module list -- so
every Qwen session spends its context budget on installer documentation while
getting none of the baseline workflow, coding standards, or security checklist.

Every other harness target ships real agent context here: `.gemini/GEMINI.md`
('provides Gemini CLI with the baseline ECC workflow, review standards, and
security checks') and `.codex/AGENTS.md` ('supplements the root AGENTS.md with
Codex-specific guidance'). Qwen was the only target whose context file described
the installer.

Rewrite it against the GEMINI.md structure and add two Qwen-specific sections:

- A Claude-tool-name to Qwen-tool-id mapping. ECC skills, rules, and agent
  prompts are authored for Claude Code, so a Qwen agent following them needs the
  translation to act correctly.
- An explicit 'Not Available On This Target' note. Hook runtime files are not
  selected for Qwen, so an agent must not report a hook-enforced guard or
  cost-tracking metric as active. Also records that mcp-configs/ is a baseline
  catalog rather than a merged settings file.

The displaced install documentation is not lost: docs/QWEN-GUIDE.md already
covers install, layout, ecc-install-state.json, updating, uninstalling, and the
hook scope decision, so QWEN.md now points there instead of duplicating it.

Counts in the Overview (68 agents / 293 skills / 94 commands) are verified
against the repo and match the figure GEMINI.md already states.
2026-10-09 10:56:43 +07:00
zakyirsyaad d3ad8b524c fix: quote argument-hint values that YAML parses as arrays
Three command files declared argument-hint with an unquoted flow sequence, so a
strict YAML parse yields an array instead of a string. Harnesses that validate
the field reject the whole file: Qwen Code drops the command with
'frontmatter: Expected string, received array' and the slash command silently
disappears from the catalog.

Quote all three to match the convention already used by plan-canvas.md, pr.md,
prp-pr.md, plan-prd.md and the other argument-hint declarations in commands/.
2026-10-09 10:54:29 +07:00
dusseau-dev 849456d57e feat(skills): add agent runtime gateway smoke test 2026-10-08 22:59:42 -04:00
Eneko Ruiz 684c971173 fix(hooks): resolve session IDs from hook payloads 2026-10-08 23:46:56 +02:00
taljeri 6d15a1272e docs(i18n): add Arabic localization scout
Add Arabic (ar) localization guide and glossary, register the locale:ar component and docs-ar module across install manifests, and wire test coverage.

Contributed-by: @taljeri (taljeri)
Signed-off-by: taljeri <318237806+taljeri@users.noreply.github.com>
2026-10-08 21:50:04 +03:00
montjeffrey a973e33134 fix(context): recover retired routing indexes, validate entries and match advice to mode 2026-10-08 16:59:10 +00:00
montjeffrey f4c9b05e54 test(context): pin routing index recovery, entry validation, bounds and mode-aware advice 2026-10-08 16:56:09 +00:00
montjeffrey aec97150d8 docs(carriers): record the closure review follow-up 2026-10-08 16:49:30 +00:00
montjeffrey d00b379f70 fix(carriers): keep keyword patterns from spanning an interpolation 2026-10-08 16:49:08 +00:00
montjeffrey e85c529eaf test(carriers): an interpolated from identifier is not an import 2026-10-08 16:48:47 +00:00
montjeffrey 0d3c85bd54 fix(carriers): match spaced calls, cook escapes, treat Windows and file URLs as absolute 2026-10-08 16:48:33 +00:00
montjeffrey 333e755f50 test(carriers): cover spaced calls, escaped specifiers, Windows paths and index.json 2026-10-08 16:47:54 +00:00
montjeffrey 928baaf26d fix(context): require well-formed Claude validation entries 2026-10-08 16:46:41 +00:00
montjeffrey 03b8f6849f test(context): reject malformed Claude validation entries 2026-10-08 16:46:32 +00:00
montjeffrey 6abf02bb49 feat(carriers): flag absolute and package imports a carrier cannot ship 2026-10-08 15:47:34 +00:00
montjeffrey 5f7c2e9d7a test(carriers): flag absolute and package imports a carrier cannot ship 2026-10-08 15:47:10 +00:00
montjeffrey 3c8042fb33 test(carriers): pin scanner edge cases and share one registry run 2026-10-08 15:46:49 +00:00
montjeffrey 4d8e3cfac0 docs(carriers): record the runtime-closure gate slice 2026-10-08 15:36:04 +00:00
montjeffrey 840a72b6c1 feat(carriers): validate carrier runtime closure in CI 2026-10-08 15:35:03 +00:00
montjeffrey 722f2193cb test(carriers): pin runtime closure checks 2026-10-08 15:30:58 +00:00
Varun Gore 38b8c07f26 Merge branch 'affaan-m:main' into main 2026-10-08 19:36:33 +05:30
serhattayaz-ai ab606759d9 test(install): cover namespace stripping in the Claude manual install 2026-10-08 16:33:23 +03:00
serhattayaz-ai bb95734f4e fix(install): keep namespace stripping when link rewriting is skipped 2026-10-08 16:19:57 +03:00
serhattayaz-ai 27d58e589a fix(install): strip ecc: plugin namespace from manual Claude installs
The ecc@ecc plugin namespaces agents, commands and skills as `ecc:<name>`.
A manual install (install-apply --target claude|claude-project) places the
same files at bare names under ~/.claude, so plugin-prefixed references in
copied markdown point at agents and commands that do not exist in that
layout (e.g. subagent_type "ecc:planner", frontmatter agent: ecc:...).

- Add plugin-namespace.js with stripPluginNamespace(), which removes the
  `ecc:` prefix before an identifier and leaves `ecc@ecc`, URLs and words
  ending in "ecc" alone.
- Apply it to markdown copy operations when the target is claude or
  claude-project. Non-markdown files and other targets are unchanged.
- Reword the agents rule so it describes both install modes instead of
  stating that agents only ship with the plugin.
- Cover the transform with tests/lib/install-plugin-namespace.test.js.
2026-10-08 16:10:35 +03:00
David HeandClaude Opus 5.5 9c21aaa681 fix(skills): set pipefail before piped gates in verification-loop
Phase 1 pipes the build into `tail -20`. Without pipefail the pipeline's
exit status is tail's, so a failed build exits 0. Phase 2 already sets
pipefail, but only after Phase 1 has run, and each phase is its own code
block. Set it at the top of the Phase 1, 3 and 4 blocks, which pipe a gate
into head or tail. Mirrored in pi/core.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 08:07:00 -04:00
kenima-arcandClaude Opus 5.5 04b60e42d7 feat(astra-review): let Astra apply fixes when Fable hits its usage limit
/astra-review now runs on Opus (model: opus). Opus verifies findings,
checks every diff, and runs the tests; fixes go to a Fable subagent.
When that Agent call fails with a rate_limit / HTTP 429 API error, the
command switches to Astra for the rest of the session:

- astra-review.js --fix-findings <file> sends confirmed findings to
  Codex in a workspace-write sandbox with the review isolation intact
  (no web search, MCP disabled, user config ignored, no API keys) and
  /tmp, $TMPDIR, and the network excluded from the writable roots.
- New scripts/lib/astra-review/fix.js builds the fix prompt, validates
  the structured fix result, and formats the report.
- codex.js shares one exec runner between review and fix; the sandbox
  is allowlisted (danger-full-access is refused).
- The command snapshots git diff and untracked files before any writer
  runs, so Opus reverts only the writer's hunks and never the user's
  uncommitted work.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 11:44:07 +09:00
YogurDungeon b4943a5e4b fix: record skill runs under OpenCode and report unmeasured skills honestly
Under OpenCode the skill-health dashboard had no writer and no honest
fallback, so it reported every discovered skill as healthy (#2463).

Root cause: `post:skill:track` is only wired for Claude Code, where
`posttooluse-dispatcher.js` fans the event out to `skill-run-tracker.js`.
The OpenCode plugin re-implements the harness events instead of reusing that
dispatcher, so nothing ever wrote `skill-runs.jsonl` — and the tracker's
matcher only accepted the exact Claude Code tool name `Skill`, while OpenCode
calls the tool `skill`, so even wiring it would have dropped every event.
Commands that locate ECC through the inlined resolver in
`scripts/lib/resolve-ecc-root.js` also fell back to `~/.claude`, which does
not contain ECC, so they could not find their scripts.

Changes:

- `.opencode/plugins/ecc-hooks.ts`: dispatch `post:skill:track` from
  `tool.execute.after`. The tracker module is imported lazily and behind
  try/catch, matching the existing `changed-files-store` pattern: this file is
  OpenCode's startup entry point, so a static import failure would crash the
  session before any hook runs (#2530). The module is reused rather than
  reimplemented, keeping its identifier validation, length bounds and
  "never persist prompt text" guarantees.
- `scripts/hooks/skill-run-tracker.js`: match the tool name case-insensitively
  so `Skill` and `skill` are both accepted.
- `scripts/lib/skill-evolution/health.js`: split the summary into
  measured/healthy/declining/unmeasured instead of deriving `healthy = total -
  declining`, which turned "no telemetry" into "everything is fine" for every
  skill.
- `scripts/lib/skill-evolution/dashboard.js`: show the breakdown and warn
  explicitly when skills have no recorded runs, since absence of telemetry is
  not a health signal.

Under OpenCode the resolver also needs `CLAUDE_PLUGIN_ROOT`, which only the
plugin can supply: `shell.env` exports it when a root is found, without
replacing a root the user set or one an earlier plugin already put in
`output.env`.

Root discovery is per capability and probes required runtime files — never
optional content. Probing for `skills/continuous-learning-v2` (the
`workflow-quality` module) rejected supported modular installs that ship the
plugin and tracker without that optional module, disabling telemetry and the
root export for exactly those users.

Also fixes an incidental bug: the compiled plugin bundle is ESM, where
`__dirname` is undefined, so the ECC version lookup silently fell back to its
default. The module directory is now derived from `import.meta.url`.

Tests: `tests/opencode-plugin-hooks.test.js` covers the telemetry dispatch
(skill tool recorded, other tools ignored, minimal profile respected), a
modular install without the optional skills module, the root export and both
override paths; `tests/hooks/skill-run-tracker.test.js` covers the
case-insensitive matcher; `tests/lib/skill-evolution.test.js` and
`tests/lib/skill-dashboard.test.js` cover the unmeasured bucket, the warning
and the aged-out-coverage wording.

Refs #2463, #2530
2026-10-07 19:45:21 -05:00
montjeffrey 8df78d934e perf(context): store routing vectors in a compact encoding 2026-10-07 18:42:09 +00:00
montjeffrey b4f7b7708f test(context): require compact stored retrieval vectors 2026-10-07 18:40:45 +00:00
montjeffrey 3ff4937f1f fix(context): admit later Claude Code 2.1 patches 2026-10-07 18:39:58 +00:00
montjeffrey fafcdc8991 test(context): admit later Claude Code 2.1 patches 2026-10-07 18:38:40 +00:00