pluribus-context 0.3.15 → 0.3.16

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.md CHANGED
@@ -4,6 +4,13 @@
4
4
 
5
5
  All notable changes to Pluribus are documented here.
6
6
 
7
+ ## 0.3.16 — audit fidelity evidence
8
+
9
+ ### Added
10
+
11
+ - Add `pluribus audit --fidelity-report` so maintainers can emit target-by-target portability evidence in JSON or human output: represented sections, unsupported sections, activation shape, warnings, and the next step before claiming a rule/skill bundle is universal.
12
+ - Update the portability fidelity report guide to use `audit --json --fidelity-report` as the reproducible evidence artifact for directory reviewers and rule/skill bundle maintainers.
13
+
7
14
  ## 0.3.15 — portability fidelity report demo
8
15
 
9
16
  ### Added
package/bin/pluribus.js CHANGED
@@ -55,6 +55,7 @@ OPTIONS (audit)
55
55
  --json Print machine-readable audit results
56
56
  --output Write --json results to a file instead of stdout
57
57
  --github-annotations Print GitHub Actions annotations for drift/missing outputs
58
+ --fidelity-report Include portability/fidelity evidence for selected targets
58
59
 
59
60
  OPTIONS (watch)
60
61
  --source Path to pluribus.md (default: ./pluribus.md)
@@ -78,6 +79,7 @@ EXAMPLES
78
79
  pluribus audit --json
79
80
  pluribus audit --strict --json --output pluribus-audit.json
80
81
  pluribus audit --strict --github-annotations
82
+ pluribus audit --json --fidelity-report
81
83
  pluribus watch --tools claude,cursor
82
84
 
83
85
  DOCS
@@ -88,7 +90,7 @@ const COMMAND_FLAGS = {
88
90
  init: new Set(['name', 'description', 'tools', 'dry-run']),
89
91
  sync: new Set(['dry-run', 'tools', 'source', 'update-imports']),
90
92
  validate: new Set(['source', 'update-imports']),
91
- audit: new Set(['source', 'tools', 'update-imports', 'strict', 'ci', 'json', 'output', 'github-annotations']),
93
+ audit: new Set(['source', 'tools', 'update-imports', 'strict', 'ci', 'json', 'output', 'github-annotations', 'fidelity-report']),
92
94
  watch: new Set(['source', 'tools', 'update-imports', 'dry-run', 'once', 'debounce']),
93
95
  }
94
96
 
@@ -15,7 +15,7 @@ git clone https://github.com/caioribeiroclw-pixel/pluribus.git
15
15
  cd pluribus/examples/portability-fidelity
16
16
  node ../../bin/pluribus.js validate
17
17
  node ../../bin/pluribus.js sync --dry-run
18
- node ../../bin/pluribus.js audit --json
18
+ node ../../bin/pluribus.js audit --json --fidelity-report
19
19
  ```
20
20
 
21
21
  For the npm release path, copy `examples/portability-fidelity/pluribus.md` into a temporary directory as `pluribus.md`, then run:
@@ -23,7 +23,7 @@ For the npm release path, copy `examples/portability-fidelity/pluribus.md` into
23
23
  ```bash
24
24
  npx --yes pluribus-context@latest validate
25
25
  npx --yes pluribus-context@latest sync --dry-run
26
- npx --yes pluribus-context@latest audit --json
26
+ npx --yes pluribus-context@latest audit --json --fidelity-report
27
27
  ```
28
28
 
29
29
  ## What a claim should say
@@ -75,7 +75,7 @@ Pluribus is intentionally narrower than a skill registry or memory layer:
75
75
  - `pluribus.md` keeps the claim in one reviewed source of truth.
76
76
  - `sync --dry-run` previews target-specific outputs before writing files.
77
77
  - generated files carry a warning header so manual edits are visible.
78
- - `audit --json` gives CI/reviewers a machine-readable check for missing or drifted outputs.
78
+ - `audit --json --fidelity-report` gives CI/reviewers a machine-readable check for missing/drifted outputs plus target-by-target section loss, activation shape, and portability warnings.
79
79
  - remote imports are opt-in, locked, cached, and digest-checked before becoming shared context.
80
80
 
81
81
  That does **not** prove runtime behavior. You still need tool-specific smoke tests for load order, path/glob activation, available tools, MCP servers, and permission semantics.
@@ -85,7 +85,7 @@ That does **not** prove runtime behavior. You still need tool-specific smoke tes
85
85
  1. Put the portability claim in the canonical source.
86
86
  2. Generate target outputs with `sync --dry-run` and inspect semantic loss.
87
87
  3. Keep target-native instructions when a semantic cannot be represented everywhere.
88
- 4. Commit a small audit artifact (`pluribus audit --json --output reports/pluribus-audit.json`) when you want CI/review evidence.
88
+ 4. Commit a small audit artifact (`pluribus audit --json --fidelity-report --output reports/pluribus-audit.json`) when you want CI/review evidence.
89
89
  5. Update the claim whenever a new target is added, a tool changes capability names, or a permission/security default changes.
90
90
 
91
91
  ## Feedback wanted
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pluribus-context",
3
- "version": "0.3.15",
3
+ "version": "0.3.16",
4
4
  "description": "AI context/rules sync for CLAUDE.md, Claude Code, Cursor rules, Copilot instructions, OpenClaw, Windsurf, Continue, and Zed.",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/caioribeiroclw-pixel/pluribus#readme",
@@ -68,6 +68,10 @@
68
68
  "type": "string",
69
69
  "format": "uri",
70
70
  "description": "Issue template URL for reporting audit false positives, noisy output, or confusing next steps."
71
+ },
72
+ "fidelityReport": {
73
+ "$ref": "#/$defs/fidelityReport",
74
+ "description": "Optional portability/fidelity evidence emitted by `pluribus audit --fidelity-report`."
71
75
  }
72
76
  },
73
77
  "allOf": [
@@ -92,6 +96,80 @@
92
96
  ],
93
97
  "additionalProperties": false,
94
98
  "$defs": {
99
+ "fidelityReport": {
100
+ "type": "object",
101
+ "required": ["claim", "sourceSections", "targets", "summary", "warnings", "nextStep"],
102
+ "properties": {
103
+ "claim": { "type": "string" },
104
+ "sourceSections": {
105
+ "type": "array",
106
+ "items": { "type": "string" }
107
+ },
108
+ "targets": {
109
+ "type": "array",
110
+ "items": { "$ref": "#/$defs/fidelityTarget" }
111
+ },
112
+ "summary": {
113
+ "type": "object",
114
+ "required": ["targetCount", "targetsWithUnsupportedSections", "warningCount"],
115
+ "properties": {
116
+ "targetCount": { "type": "integer", "minimum": 0 },
117
+ "targetsWithUnsupportedSections": { "type": "integer", "minimum": 0 },
118
+ "warningCount": { "type": "integer", "minimum": 0 }
119
+ },
120
+ "additionalProperties": false
121
+ },
122
+ "warnings": {
123
+ "type": "array",
124
+ "items": { "$ref": "#/$defs/fidelityWarning" }
125
+ },
126
+ "nextStep": { "type": "string" }
127
+ },
128
+ "additionalProperties": false
129
+ },
130
+ "fidelityTarget": {
131
+ "type": "object",
132
+ "required": ["toolId", "files", "activation", "representedSections", "unsupportedSections"],
133
+ "properties": {
134
+ "toolId": { "type": "string" },
135
+ "files": {
136
+ "type": "array",
137
+ "items": { "type": "string" }
138
+ },
139
+ "activation": { "$ref": "#/$defs/fidelityActivation" },
140
+ "representedSections": {
141
+ "type": "array",
142
+ "items": { "type": "string" }
143
+ },
144
+ "unsupportedSections": {
145
+ "type": "array",
146
+ "items": { "type": "string" }
147
+ }
148
+ },
149
+ "additionalProperties": false
150
+ },
151
+ "fidelityActivation": {
152
+ "type": "object",
153
+ "required": ["kind", "evidence"],
154
+ "properties": {
155
+ "kind": { "type": "string" },
156
+ "evidence": {
157
+ "type": "array",
158
+ "items": { "type": "string" }
159
+ }
160
+ },
161
+ "additionalProperties": false
162
+ },
163
+ "fidelityWarning": {
164
+ "type": "object",
165
+ "required": ["code", "target", "message"],
166
+ "properties": {
167
+ "code": { "type": "string" },
168
+ "target": { "type": "string" },
169
+ "message": { "type": "string" }
170
+ },
171
+ "additionalProperties": false
172
+ },
95
173
  "result": {
96
174
  "type": "object",
97
175
  "required": ["toolId", "status", "file"],
@@ -38,6 +38,7 @@ export async function runAudit(args) {
38
38
  const strict = Boolean(args.strict || ci)
39
39
  const json = Boolean(args.json)
40
40
  const githubAnnotations = Boolean(args['github-annotations'] || ci)
41
+ const fidelityReportEnabled = Boolean(args['fidelity-report'])
41
42
  const hasJsonOutput = Object.prototype.hasOwnProperty.call(args, 'output')
42
43
  const jsonOutput = typeof args.output === 'string' && args.output.trim() ? args.output : null
43
44
  const cwd = process.cwd()
@@ -225,12 +226,18 @@ export async function runAudit(args) {
225
226
  }, {})
226
227
 
227
228
  const hasProblem = (summary.drift || 0) + (summary.missing || 0) + (summary.error || 0) > 0
229
+ const fidelityReport = fidelityReportEnabled ? buildFidelityReport({ cwd, sections, tools, loadSkill }) : null
230
+
231
+ if (!json && fidelityReport) {
232
+ printFidelityReport(fidelityReport)
233
+ }
234
+
228
235
  if (githubAnnotations) {
229
236
  writeGitHubAnnotations(results, { strict })
230
237
  }
231
238
 
232
239
  if (json) {
233
- writeJson({
240
+ const payload = {
234
241
  ok: !hasProblem,
235
242
  source: displaySource,
236
243
  sourceFound: true,
@@ -246,7 +253,13 @@ export async function runAudit(args) {
246
253
  ? 'Run pluribus sync --dry-run to preview fixes, then pluribus sync to update generated files.'
247
254
  : 'Generated context files are in sync.',
248
255
  feedback: AUDIT_FEEDBACK_URL,
249
- }, jsonOutput)
256
+ }
257
+
258
+ if (fidelityReport) {
259
+ payload.fidelityReport = fidelityReport
260
+ }
261
+
262
+ writeJson(payload, jsonOutput)
250
263
  } else {
251
264
  console.log('')
252
265
  console.log(`Summary: ${summary.current || 0} current, ${summary.drift || 0} drifted, ${summary.missing || 0} missing, ${summary.error || 0} error(s).`)
@@ -264,6 +277,105 @@ export async function runAudit(args) {
264
277
  }
265
278
  }
266
279
 
280
+ function buildFidelityReport({ cwd, sections, tools, loadSkill }) {
281
+ const presentSections = Object.entries(sections)
282
+ .filter(([, value]) => String(value || '').trim())
283
+ .map(([name]) => name)
284
+ .sort((a, b) => a.localeCompare(b))
285
+
286
+ const lowerPresentSections = new Set(presentSections.map((name) => name.toLowerCase()))
287
+ const targets = tools.map((toolId) => {
288
+ const skill = loadSkill(cwd, toolId)
289
+ const representedSections = new Set([...(skill?.required || []), ...(skill?.optional || [])].map((name) => name.toLowerCase()))
290
+ const unsupportedSections = presentSections.filter((name) => !representedSections.has(name.toLowerCase()))
291
+
292
+ return {
293
+ toolId,
294
+ files: skill?.outputFiles || [],
295
+ activation: inferActivation(toolId, skill?.outputFiles || []),
296
+ representedSections: presentSections.filter((name) => representedSections.has(name.toLowerCase())),
297
+ unsupportedSections,
298
+ }
299
+ })
300
+
301
+ const warnings = []
302
+ for (const target of targets) {
303
+ if (target.unsupportedSections.length > 0) {
304
+ warnings.push({
305
+ code: 'section-not-rendered-by-target',
306
+ target: target.toolId,
307
+ message: `${target.toolId} template does not render section(s): ${target.unsupportedSections.join(', ')}`,
308
+ })
309
+ }
310
+ }
311
+
312
+ if (targets.some((target) => target.activation.kind === 'flat-project-wide')) {
313
+ warnings.push({
314
+ code: 'project-wide-activation-only',
315
+ target: '*',
316
+ message: 'Generated outputs are project-wide/always-on; Pluribus does not currently model path-scoped activation, manual attach, or progressive disclosure semantics.',
317
+ })
318
+ }
319
+
320
+ const advancedSections = ['workflow', 'context', 'examples', 'anti-patterns'].filter((name) => lowerPresentSections.has(name))
321
+ if (advancedSections.length > 0 && warnings.some((warning) => warning.code === 'section-not-rendered-by-target')) {
322
+ warnings.push({
323
+ code: 'portability-claim-needs-evidence',
324
+ target: '*',
325
+ message: `Do not claim universal portability without evidence: advanced section(s) ${advancedSections.join(', ')} are not represented equally by every selected target.`,
326
+ })
327
+ }
328
+
329
+ return {
330
+ claim: 'project-wide instruction portability evidence for selected targets',
331
+ sourceSections: presentSections,
332
+ targets,
333
+ summary: {
334
+ targetCount: targets.length,
335
+ targetsWithUnsupportedSections: targets.filter((target) => target.unsupportedSections.length > 0).length,
336
+ warningCount: warnings.length,
337
+ },
338
+ warnings,
339
+ nextStep: warnings.length > 0
340
+ ? 'Review unsupportedSections/warnings before calling this context universal; narrow the tools list, change the source, or document known lossy targets.'
341
+ : 'Selected targets render the current non-empty source sections with no known Pluribus template loss; still smoke-test behavior in each agent.',
342
+ }
343
+ }
344
+
345
+ function inferActivation(toolId, outputFiles) {
346
+ if (toolId === 'windsurf' || toolId === 'continue') {
347
+ return {
348
+ kind: 'project-wide-rule',
349
+ evidence: outputFiles,
350
+ }
351
+ }
352
+
353
+ return {
354
+ kind: 'flat-project-wide',
355
+ evidence: outputFiles,
356
+ }
357
+ }
358
+
359
+ function printFidelityReport(report) {
360
+ console.log('')
361
+ console.log('Fidelity report:')
362
+ console.log(` Claim: ${report.claim}`)
363
+ console.log(` Targets: ${report.targets.map((target) => target.toolId).join(', ')}`)
364
+
365
+ for (const target of report.targets) {
366
+ const unsupported = target.unsupportedSections.length > 0
367
+ ? `; unsupported sections: ${target.unsupportedSections.join(', ')}`
368
+ : '; no known section loss'
369
+ console.log(` • ${target.toolId}: ${target.activation.kind}${unsupported}`)
370
+ }
371
+
372
+ for (const warning of report.warnings) {
373
+ console.log(` ⚠️ ${warning.code}: ${warning.message}`)
374
+ }
375
+
376
+ console.log(` Next: ${report.nextStep}`)
377
+ }
378
+
267
379
  function getTools(rawContent, toolsArg) {
268
380
  if (toolsArg) {
269
381
  return splitTools(toolsArg)
@@ -1 +1 @@
1
- export const VERSION = '0.3.15'
1
+ export const VERSION = '0.3.16'