humanish 0.17.0 → 0.19.0

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.
Files changed (63) hide show
  1. package/README.md +53 -21
  2. package/dist/actor-contract.d.ts +11 -1
  3. package/dist/actor-contract.js.map +1 -1
  4. package/dist/computer-use-actor.d.ts +4 -0
  5. package/dist/computer-use-actor.js +3 -1
  6. package/dist/computer-use-actor.js.map +1 -1
  7. package/dist/computer-use.d.ts +16 -0
  8. package/dist/computer-use.js +59 -6
  9. package/dist/computer-use.js.map +1 -1
  10. package/dist/concurrent-shared-world-lab.js +1 -0
  11. package/dist/concurrent-shared-world-lab.js.map +1 -1
  12. package/dist/cua-actor-lab.d.ts +33 -3
  13. package/dist/cua-actor-lab.js +169 -2
  14. package/dist/cua-actor-lab.js.map +1 -1
  15. package/dist/index.d.ts +3 -1
  16. package/dist/index.js +1 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/lab-config.d.ts +12 -0
  19. package/dist/lab-config.js +12 -0
  20. package/dist/lab-config.js.map +1 -1
  21. package/dist/observer-assets.js +37 -3
  22. package/dist/observer-assets.js.map +1 -1
  23. package/dist/observer-data.d.ts +7 -1
  24. package/dist/observer-data.js +1 -0
  25. package/dist/observer-data.js.map +1 -1
  26. package/dist/observer-library.d.ts +5 -1
  27. package/dist/observer-library.js +9 -7
  28. package/dist/observer-library.js.map +1 -1
  29. package/dist/observer-serve.d.ts +11 -23
  30. package/dist/observer-serve.js +12 -92
  31. package/dist/observer-serve.js.map +1 -1
  32. package/dist/observer.d.ts +6 -0
  33. package/dist/observer.js +52 -1
  34. package/dist/observer.js.map +1 -1
  35. package/dist/pricing.d.ts +78 -0
  36. package/dist/pricing.js +100 -0
  37. package/dist/pricing.js.map +1 -0
  38. package/dist/program.js +294 -122
  39. package/dist/program.js.map +1 -1
  40. package/dist/run.d.ts +54 -0
  41. package/dist/run.js +86 -0
  42. package/dist/run.js.map +1 -1
  43. package/dist/serve-exposure.d.ts +62 -0
  44. package/dist/serve-exposure.js +129 -0
  45. package/dist/serve-exposure.js.map +1 -0
  46. package/dist/serve-http.d.ts +8 -0
  47. package/dist/serve-http.js +37 -0
  48. package/dist/serve-http.js.map +1 -0
  49. package/dist/serve-tunnel.d.ts +6 -2
  50. package/dist/serve-tunnel.js +9 -0
  51. package/dist/serve-tunnel.js.map +1 -1
  52. package/docs/architecture/actor-contract.md +41 -3
  53. package/docs/architecture/observer.md +30 -0
  54. package/docs/architecture/serve.md +138 -82
  55. package/docs/contracts/run-bundle.md +23 -0
  56. package/docs/contracts/schemas.md +111 -15
  57. package/docs/goals/current.md +1 -1
  58. package/docs/principles/invariants-and-defaults.md +2 -1
  59. package/docs/ramp/README.md +1 -1
  60. package/package.json +1 -1
  61. package/dist/observer-auth.d.ts +0 -21
  62. package/dist/observer-auth.js +0 -92
  63. package/dist/observer-auth.js.map +0 -1
package/dist/run.js CHANGED
@@ -18,6 +18,7 @@ import { mapWithConcurrency } from "./concurrency.js";
18
18
  import { screenshotEvidenceError } from "./image-evidence.js";
19
19
  import { buildObserverData } from "./observer-data.js";
20
20
  import { parseResolvedPersona, personaToDirectives, renderPersonaPromptSection } from "./persona.js";
21
+ import { round6 } from "./pricing.js";
21
22
  import { containsSensitive, digestText, redactText, redactToSecretLabel, tailText } from "./redaction.js";
22
23
  import { bindExistingRunArtifactPaths, RUNS_RELATIVE_ROOT, isSafeRunIdSegment, prepareRunArtifactPaths, resolveExistingRunDirectory, resolveLatestRunDirectory, resolveRunsRoot, validatePreparedRunArtifactPaths } from "./run-paths.js";
23
24
  import { assertPreparedSelectedOutputDirectory, assertSafeOutputPathSegment, bindExistingManagedHumanishOutputDirectory, prepareContainedOutputDirectory, prepareContainedOutputDirectoryRoot, prepareContainedOutputFile, prepareSelectedOutputDirectory, readContainedRegularFile, writeContainedOutputFile, writePreparedRunLatestPointer } from "./selected-output-paths.js";
@@ -2460,6 +2461,18 @@ async function verifyPreparedRun(cwd, runInput, runPaths) {
2460
2461
  ? "rerun bundles either are absent or link selected lanes to prior lane status and a fan-out rerun event"
2461
2462
  : `rerun lineage findings: ${rerunFindings.join(", ")}`
2462
2463
  });
2464
+ // Cost is ADVISORY on magnitude, FAIL-CLOSED on labeling/provenance (claims match mechanism).
2465
+ // Absence PASSES (fail-open on display); a claimed dollar figure without its ratesAsOf date +
2466
+ // source, or a total that does not match its known lines, FAILS. Magnitude is never inspected —
2467
+ // a correctly-labeled huge estimate still passes.
2468
+ const costFindings = isRunBundle(bundle) ? costLabelingFindings(bundle) : [];
2469
+ checks.push({
2470
+ name: "cost estimate labeling",
2471
+ ok: costFindings.length === 0,
2472
+ message: costFindings.length === 0
2473
+ ? "cost figures are absent, or every claimed estimate carries its ratesAsOf date + source and the total matches its known lines (estimates never presented as exact)"
2474
+ : `cost labeling findings: ${costFindings.join(", ")}`
2475
+ });
2463
2476
  const ok = checks.every((check) => check.ok);
2464
2477
  const warnings = isRunBundle(bundle)
2465
2478
  ? [...rawScreenshotPostureWarnings(bundle), ...undeclaredSubjectStateWarnings(bundle), ...desktopGeometryWarnings(bundle)]
@@ -3809,6 +3822,79 @@ function rerunLineageFindings(bundle) {
3809
3822
  }
3810
3823
  return findings;
3811
3824
  }
3825
+ /**
3826
+ * Verify the LABELING/provenance of any cost figure a bundle CLAIMS — never its magnitude. Returns
3827
+ * [] (pass) unless a dollar claim lacks its provenance (invariant 6) or a total misreports its
3828
+ * known lines. ABSENCE always passes (fail-open on display, discipline #3): a bundle with no cost,
3829
+ * a null estimate, or a lane without estimatedCost is fine. A NON-NULL figure must carry its
3830
+ * ratesAsOf date + source; a NUMBER total must equal round6(sum of ONLY the non-null lines) and a
3831
+ * null line may never be coerced to 0. A null estimate must be declared honestly (a reason + null
3832
+ * ratesAsOf), mirroring the terminal no-spend proof's null-discipline.
3833
+ */
3834
+ function costLabelingFindings(bundle) {
3835
+ const findings = [];
3836
+ const cost = bundle.cost;
3837
+ if (cost) {
3838
+ if (cost.schema !== "humanish.run-cost-summary.v1") {
3839
+ findings.push(`run cost summary schema is ${String(cost.schema)}, expected humanish.run-cost-summary.v1`);
3840
+ }
3841
+ let knownSum = 0;
3842
+ let anyKnown = false;
3843
+ for (const [index, line] of (cost.breakdown ?? []).entries()) {
3844
+ if (line.estimatedCostUsd === null) {
3845
+ continue;
3846
+ }
3847
+ anyKnown = true;
3848
+ knownSum += line.estimatedCostUsd;
3849
+ if (typeof line.ratesAsOf !== "string" || line.ratesAsOf.length === 0) {
3850
+ findings.push(`cost breakdown line ${index} (${line.kind}) claims $${line.estimatedCostUsd} without a ratesAsOf date`);
3851
+ }
3852
+ if (typeof line.source !== "string" || line.source.length === 0) {
3853
+ findings.push(`cost breakdown line ${index} (${line.kind}) claims $${line.estimatedCostUsd} without a pricing source`);
3854
+ }
3855
+ }
3856
+ if (cost.estimatedTotalUsd !== null) {
3857
+ if (typeof cost.ratesAsOf !== "string" || cost.ratesAsOf.length === 0) {
3858
+ findings.push("run cost summary claims a number estimatedTotalUsd without a ratesAsOf date");
3859
+ }
3860
+ if (round6(cost.estimatedTotalUsd) !== round6(knownSum)) {
3861
+ findings.push(`run cost estimatedTotalUsd ${cost.estimatedTotalUsd} does not equal the sum of its known breakdown lines (${round6(knownSum)})`);
3862
+ }
3863
+ }
3864
+ else if (anyKnown) {
3865
+ // Every-line-null is the only honest null total; a null total beside a known line hides spend.
3866
+ findings.push("run cost estimatedTotalUsd is null but a breakdown line carries a known (non-null) cost");
3867
+ }
3868
+ }
3869
+ for (const stream of bundle.streams) {
3870
+ const estimate = stream.actor?.estimatedCost;
3871
+ if (!estimate) {
3872
+ continue;
3873
+ }
3874
+ const laneLabel = stream.laneId ?? stream.id;
3875
+ if (estimate.schema !== "humanish.actor-estimated-cost.v1") {
3876
+ findings.push(`lane ${laneLabel} actor estimatedCost schema is ${String(estimate.schema)}, expected humanish.actor-estimated-cost.v1`);
3877
+ }
3878
+ if (estimate.estimatedCostUsd !== null) {
3879
+ if (typeof estimate.ratesAsOf !== "string" || estimate.ratesAsOf.length === 0) {
3880
+ findings.push(`lane ${laneLabel} claims a model-token cost $${estimate.estimatedCostUsd} without a ratesAsOf date`);
3881
+ }
3882
+ if (typeof estimate.source !== "string" || estimate.source.length === 0) {
3883
+ findings.push(`lane ${laneLabel} claims a model-token cost $${estimate.estimatedCostUsd} without a pricing source`);
3884
+ }
3885
+ }
3886
+ else {
3887
+ // Declared-absent honesty (invariant 5): a null estimate must say WHY and carry null ratesAsOf.
3888
+ if (estimate.reason === undefined) {
3889
+ findings.push(`lane ${laneLabel} records a null cost estimate without a reason`);
3890
+ }
3891
+ if (estimate.ratesAsOf !== null) {
3892
+ findings.push(`lane ${laneLabel} records a null cost estimate but carries a non-null ratesAsOf`);
3893
+ }
3894
+ }
3895
+ }
3896
+ return findings;
3897
+ }
3812
3898
  // SEQUENTIAL: the three disclosures a sequential shared-world bundle MUST pin (verify fails closed
3813
3899
  // if any is absent — omission overclaims): sequential turns only, no concurrency/races handled, and
3814
3900
  // a checkpoint delta is attributed to the TURN it followed, not a specific action (correlation).