@ouro.bot/cli 0.1.0-alpha.277 → 0.1.0-alpha.278

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/changelog.json CHANGED
@@ -1,6 +1,12 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.278",
6
+ "changes": [
7
+ "fix(identity): spread-with-validation loader eliminates the field-drop bug class that caused #349 (silent `sync` drop). Two distinct structural bugs fixed, one in each agent.json loader: (1) `loadAgentConfig` in `src/heart/identity.ts` previously built the returned `AgentConfig` via a hand-rolled object literal that listed every field explicitly — any new field on `AgentConfig` that wasn't added to this literal got silently dropped. Root cause of #349. Refactored to a spread-then-override pattern: start with `{ ...parsed as AgentConfig }`, then explicitly override `version`, `enabled`, `humanFacing`, `agentFacing`, `senses`, `phrases` which need validation/normalization. The deprecated `provider` field is re-attached from the validated `rawProvider` check. (2) `readAgentConfigForAgent` in `src/heart/auth/auth-flow.ts` previously did `parsed as unknown as AgentConfig` which passed through ALL fields unconditionally (so no silent drops) but ALSO had zero per-field validation — any garbage in agent.json leaked into the returned config. Refactored to apply the same spread-with-validation pattern, reusing `normalizeSenses` (now exported from identity.ts). Both entry points now return equivalent configs for the same agent.json file. New `src/__tests__/heart/identity-fixture.ts` exports `FULL_AGENT_JSON satisfies DeepRequired<AgentConfig>` — a compile-time regression guard that fails to build if any new field is added to `AgentConfig` without updating the fixture. Two new test files: `identity-contract.test.ts` exercises `readAgentConfigForAgent` with `createTmpBundle`; `identity-load-contract.test.ts` exercises `loadAgentConfig` via `vi.mock(\"fs\")` (split to avoid the fs-mock-vs-real-fs conflict). 7 tests total."
8
+ ]
9
+ },
4
10
  {
5
11
  "version": "0.1.0-alpha.277",
6
12
  "changes": [
@@ -159,9 +159,18 @@ function readAgentConfigForAgent(agentName, bundlesRoot = (0, identity_1.getAgen
159
159
  if (!agentFacing || typeof agentFacing !== "object") {
160
160
  throw new Error(`agent.json at ${configPath} has unsupported provider '${String(parsed.provider)}'`);
161
161
  }
162
+ // Spread-with-validation: same pattern as loadAgentConfig to eliminate
163
+ // the unvalidated-pass-through bug class. The spread carries through
164
+ // every field present in parsed; senses goes through the same
165
+ // normalization as loadAgentConfig so the two entry points return
166
+ // equivalent configs for the same file.
167
+ const config = {
168
+ ...parsed,
169
+ senses: (0, identity_1.normalizeSenses)(parsed.senses, configPath),
170
+ };
162
171
  return {
163
172
  configPath,
164
- config: parsed,
173
+ config,
165
174
  };
166
175
  }
167
176
  function writeAgentProviderSelection(agentName, facing, provider, bundlesRoot = (0, identity_1.getAgentBundlesRoot)()) {
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.HARNESS_CANONICAL_REPO_URL = exports.DEFAULT_AGENT_SENSES = exports.DEFAULT_VAULT_SERVER_URL = exports.DEFAULT_AGENT_PHRASES = exports.DEFAULT_AGENT_CONTEXT = exports.PROVIDER_CREDENTIALS = void 0;
37
37
  exports.resolveVaultConfig = resolveVaultConfig;
38
+ exports.normalizeSenses = normalizeSenses;
38
39
  exports.buildDefaultAgentTemplate = buildDefaultAgentTemplate;
39
40
  exports.getAgentName = getAgentName;
40
41
  exports.getRepoRoot = getRepoRoot;
@@ -404,27 +405,27 @@ function loadAgentConfig() {
404
405
  // Tolerate deprecated provider field for backward compatibility
405
406
  const rawProvider = parsed.provider;
406
407
  const provider = isValidProvider(rawProvider) ? rawProvider : undefined;
408
+ // Spread parsed first so any field present in AgentConfig is carried
409
+ // through by default, then explicitly override the fields that need
410
+ // validation or normalization. This eliminates the field-drop bug class
411
+ // that caused the `sync` block (and previously `shell`) to be silently
412
+ // omitted from the returned config. Regression-guarded by the
413
+ // Required<AgentConfig> contract test in identity-contract.test.ts.
407
414
  const config = {
415
+ ...parsed,
408
416
  version,
409
417
  enabled,
410
- ...(provider !== undefined ? { provider } : {}),
411
418
  humanFacing,
412
419
  agentFacing,
413
- context: parsed.context,
414
- logging: parsed.logging,
415
420
  senses: normalizeSenses(parsed.senses, configFile),
416
- mcpServers: parsed.mcpServers,
417
421
  phrases: parsed.phrases,
418
- vault: parsed.vault,
419
- // The sync block was missing from this hand-rolled object literal since
420
- // it was added to AgentConfig. Result: `getSyncConfig()` always read
421
- // `agentConfig.sync?.enabled ?? false` and always saw undefined, so the
422
- // entire sync code path (preTurnPull / postTurnPush in pipeline.ts) was
423
- // dead. The `ouro status` per-agent Git Sync display kept reporting
424
- // "enabled" because it reads agent.json directly via `listBundleSyncRows`,
425
- // not through loadAgentConfig — so the bug hid in plain sight for weeks.
426
- sync: parsed.sync,
427
422
  };
423
+ if (provider !== undefined) {
424
+ config.provider = provider;
425
+ }
426
+ else {
427
+ delete config.provider;
428
+ }
428
429
  (0, runtime_1.emitNervesEvent)({
429
430
  event: "identity.resolve",
430
431
  component: "config/identity",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.277",
3
+ "version": "0.1.0-alpha.278",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",