dsh-completion-guard 0.3.1 → 0.3.2

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.
@@ -2931,74 +2931,96 @@ function authorityCaptureCounts(blocks) {
2931
2931
 
2932
2932
  //#endregion
2933
2933
  //#region src/domain/host-lock.ts
2934
- const SUPPORTED_HOST_MANIFEST = {
2935
- manifestVersion: 1,
2936
- supportedGoalVersions: ["0.1.1-rc.2"],
2937
- capabilities: [
2938
- {
2939
- name: "goal_complete_precommit_guard",
2940
- value: {
2941
- k: "s",
2942
- v: "required"
2943
- }
2944
- },
2945
- {
2946
- name: "goal_disarm_readback",
2947
- value: {
2948
- k: "s",
2949
- v: "required"
2950
- }
2951
- },
2952
- {
2953
- name: "session_flush_before_control",
2954
- value: {
2955
- k: "s",
2956
- v: "required"
2957
- }
2958
- },
2959
- {
2960
- name: "tool_guard_monotonic",
2961
- value: {
2962
- k: "s",
2963
- v: "required"
2964
- }
2965
- },
2966
- {
2967
- name: "host_capability_model",
2968
- value: {
2969
- k: "s",
2970
- v: "action-platform-v1"
2971
- }
2972
- },
2973
- {
2974
- name: "external_wait_jobs_readback",
2975
- value: {
2976
- k: "s",
2977
- v: "dsh.jobs.v1"
2978
- }
2979
- },
2980
- {
2981
- name: "filesystem_tool_contract",
2982
- value: {
2983
- k: "s",
2984
- v: "dsh.fs-tools.v1"
2985
- }
2986
- },
2987
- ...SEMANTIC_ACTIONS.map((action) => ({
2988
- name: "supported_action",
2934
+ /**
2935
+ * Capability expectations shared by every audited host cohort. The rc.2 ->
2936
+ * alpha.2 source audit found no Guard-consumed contract change (session event
2937
+ * vocabulary, flush contract, Goal disarm, `update_goal` gating, tool
2938
+ * definition, renderer terminal markers), so the rows are identical; a future
2939
+ * cohort that changes any of them must declare its own rows instead.
2940
+ */
2941
+ const AUDITED_CAPABILITY_ROWS = [
2942
+ {
2943
+ name: "goal_complete_precommit_guard",
2944
+ value: {
2945
+ k: "s",
2946
+ v: "required"
2947
+ }
2948
+ },
2949
+ {
2950
+ name: "goal_disarm_readback",
2951
+ value: {
2952
+ k: "s",
2953
+ v: "required"
2954
+ }
2955
+ },
2956
+ {
2957
+ name: "session_flush_before_control",
2958
+ value: {
2959
+ k: "s",
2960
+ v: "required"
2961
+ }
2962
+ },
2963
+ {
2964
+ name: "tool_guard_monotonic",
2965
+ value: {
2966
+ k: "s",
2967
+ v: "required"
2968
+ }
2969
+ },
2970
+ {
2971
+ name: "host_capability_model",
2972
+ value: {
2973
+ k: "s",
2974
+ v: "action-platform-v1"
2975
+ }
2976
+ },
2977
+ {
2978
+ name: "external_wait_jobs_readback",
2979
+ value: {
2980
+ k: "s",
2981
+ v: "dsh.jobs.v1"
2982
+ }
2983
+ },
2984
+ {
2985
+ name: "filesystem_tool_contract",
2986
+ value: {
2987
+ k: "s",
2988
+ v: "dsh.fs-tools.v1"
2989
+ }
2990
+ },
2991
+ ...SEMANTIC_ACTIONS.map((action) => ({
2992
+ name: "supported_action",
2993
+ value: {
2994
+ k: "s",
2995
+ v: action
2996
+ }
2997
+ }))
2998
+ ];
2999
+ function defineCohort(id, supportedGoalVersions, auditedPlatforms, packages) {
3000
+ return {
3001
+ id,
3002
+ manifestVersion: 1,
3003
+ supportedGoalVersions,
3004
+ auditedPlatforms,
3005
+ packages,
3006
+ capabilities: [{
3007
+ name: "host_cohort",
2989
3008
  value: {
2990
3009
  k: "s",
2991
- v: action
3010
+ v: id
2992
3011
  }
2993
- }))
2994
- ]
2995
- };
3012
+ }, ...AUDITED_CAPABILITY_ROWS]
3013
+ };
3014
+ }
2996
3015
  /**
2997
- * Audited package identities. This is a catalogue, not one indivisible lock:
2998
- * evaluateHostLock requires only BASE_HOST_PACKAGES globally and evaluates the
2999
- * remaining action/platform groups independently.
3016
+ * Audited host cohort registry. The rc.2 cohort keeps the exact identities
3017
+ * audited for 0.3.0/0.3.1 on macOS and Windows. The alpha.2 cohort carries the
3018
+ * exact package graph extracted from native macOS and Windows DSH
3019
+ * `0.1.2-alpha.2` / dshmarket `1.38.1` runtimes. Graphs that mix cohorts,
3020
+ * lack rows, duplicate rows, or use
3021
+ * versions outside both cohorts fail closed.
3000
3022
  */
3001
- const EXPECTED_HOST_PACKAGES = [
3023
+ const HOST_COHORTS = [defineCohort("dsh-0.1.1-rc.2", ["0.1.1-rc.2"], ["posix", "windows"], [
3002
3024
  {
3003
3025
  name: "@deepseek-ai/cordis",
3004
3026
  version: "4.0.1",
@@ -3169,7 +3191,186 @@ const EXPECTED_HOST_PACKAGES = [
3169
3191
  version: "0.1.1-rc.2",
3170
3192
  integrity: "sha512-on4hjAlYI5uX9q7Sf95YkMMBVe6heywtA/H50ksrIMUub8U2B98hO9iQpHhjwIO1F1vu+5pLcPvRr6yUGGmtXQ=="
3171
3193
  }
3172
- ];
3194
+ ]), defineCohort("dsh-0.1.2-alpha.2", ["0.1.2-alpha.2"], ["posix", "windows"], [
3195
+ {
3196
+ name: "@deepseek-ai/cordis",
3197
+ version: "4.0.2",
3198
+ integrity: "sha512-asOnXP1TzFSFQlHb1iegDZp0z/8WD1c7YNrwJR/Tx2bzNuMXfcekE/I67Iv6SQXeLB4csxqCngzQKANP7gdw0g=="
3199
+ },
3200
+ {
3201
+ name: "@deepseek-ai/dsh",
3202
+ version: "0.1.2-alpha.2",
3203
+ integrity: "sha512-4TvTC5kRKlgtSU2UTBv+cID9a2Z+6+m6mpvjXWJfVzuTkflCff6s4MsQpFJTCmwFh/k7zNWe7qFXcLYMV/5VvA=="
3204
+ },
3205
+ {
3206
+ name: "@deepseek-ai/dsh-agent",
3207
+ version: "0.1.2-alpha.2",
3208
+ integrity: "sha512-K7B5XSQ7byB/IoNGj7n+lBgHCpVPJqEPvpGoHKc1dBS8fPo2yYp/ALFag4YOfrXVP3jQ9A8di20BbvIlp79SoA=="
3209
+ },
3210
+ {
3211
+ name: "@deepseek-ai/dsh-agent-loop",
3212
+ version: "0.1.2-alpha.2",
3213
+ integrity: "sha512-UU1i+rTuQV3Q5PGY4qFlojJ0Gbthib22pida5elZlg28dd8gtY2d1U5V9q2+rKK/469CO29rkz6TWMWk0g93Jg=="
3214
+ },
3215
+ {
3216
+ name: "@deepseek-ai/dsh-attachment",
3217
+ version: "0.1.2-alpha.2",
3218
+ integrity: "sha512-+e+zQCbBi94Jnyfpq/M+/J2R/66GbMh5zqr7yVdCjvAJp8d2hxQsZ0O/oaSV+iZQIMgJz+BcwvrS1VU+XmzQWg=="
3219
+ },
3220
+ {
3221
+ name: "@deepseek-ai/dsh-bash-sandbox",
3222
+ version: "0.1.2-alpha.2",
3223
+ integrity: "sha512-y5NZT7OkKi23N2fF+x9oo1QZH8LPfTU+llL86r+iETSSk5jzh91Hp2cP5Iq5S/L3BAQDaEw2J4Dg8VjF+fnnkg=="
3224
+ },
3225
+ {
3226
+ name: "@deepseek-ai/dsh-commands",
3227
+ version: "0.1.2-alpha.2",
3228
+ integrity: "sha512-KkyNkD5V80h+xXsByGdXH8uvKo/5uflb1CSY8O8IrciuptaJdneSAmTFsjmCKAjqCTGgigk2VDw6mqPwux2JYg=="
3229
+ },
3230
+ {
3231
+ name: "@deepseek-ai/dsh-fs",
3232
+ version: "0.1.2-alpha.2",
3233
+ integrity: "sha512-wx5n0QS5rfZ2LPVocMNfuOUh0RYH/QuLoCEy+qI8U3nKmSZ8GSTASURLg+0pVxckHpLElo38U+S/lkLxRK1rpQ=="
3234
+ },
3235
+ {
3236
+ name: "@deepseek-ai/dsh-fs-local",
3237
+ version: "0.1.2-alpha.2",
3238
+ integrity: "sha512-IIpZAxGw8wr+xpZQhvuHB9JtUeE6V03e45njfFah1eRl0miaHV5CxCRlFwkMLrow5I2zCCsCPPmdEaouGxTGSA=="
3239
+ },
3240
+ {
3241
+ name: "@deepseek-ai/dsh-fs-observation-policy",
3242
+ version: "0.1.2-alpha.2",
3243
+ integrity: "sha512-oMDSB1NTnj4rIGy5JXCtbzTFDwKkU/38KIKrVs3u6b65Y5spq3kjc1ITpjqo3Ze4H8umc8wJqGke2o/ms8eIEQ=="
3244
+ },
3245
+ {
3246
+ name: "@deepseek-ai/dsh-fs-sandbox",
3247
+ version: "0.1.2-alpha.2",
3248
+ integrity: "sha512-jTnGZUov95e9OANKG+uoWAczdGlzy24aXJ+z4N4J+rMvThfj5awV3ucsmX9S4YW2peHoTV9D7BNGgBQ84LxB+w=="
3249
+ },
3250
+ {
3251
+ name: "@deepseek-ai/dsh-goal",
3252
+ version: "0.1.2-alpha.2",
3253
+ integrity: "sha512-6E+QfBezGsQ2RI0KLZc8llRpukV9ujLjCcQ2UAboYJS7FPQMs7f/QfSrfTubwpB4lrnOok0H26JT2jHUhJeQbQ=="
3254
+ },
3255
+ {
3256
+ name: "@deepseek-ai/dsh-host-plugin-inventory",
3257
+ version: "0.1.2-alpha.2",
3258
+ integrity: "sha512-qWD+fTYTq8YoNa1TbYXy/Qk7bjjS4URJMgMa3m1vnyZ+xdwtRBF47dUa7wVAVX7oGg03bl7TD1Eo7GcKP/eajA=="
3259
+ },
3260
+ {
3261
+ name: "@deepseek-ai/dsh-host-webserver",
3262
+ version: "0.1.2-alpha.2",
3263
+ integrity: "sha512-cvsfM/cm5hZk/RqdIsardfqBIVpemdmUrP4M6UgdqhJy2nG5VnokLBg7k0bc8Yi11q0vIETfQK4xiDOSOMnu7Q=="
3264
+ },
3265
+ {
3266
+ name: "@deepseek-ai/dsh-jobs",
3267
+ version: "0.1.2-alpha.2",
3268
+ integrity: "sha512-yPNlYX/ZKphjzRY7oMf5uLgfSlJ8qBp49W6qNqzhmn8moXgJcPUCNqeOkT0C3a6GQ286mmmo09eyfDLGX7+lMQ=="
3269
+ },
3270
+ {
3271
+ name: "@deepseek-ai/dsh-jobs-local",
3272
+ version: "0.1.2-alpha.2",
3273
+ integrity: "sha512-nrK4ujL6QRS6GAysgBR08vaHub4vh7/iuGtmMvcg4Bp3hZeQ4rjWnpQAuItg9E9G3OUrvfjwzwENEM1TyVcbWw=="
3274
+ },
3275
+ {
3276
+ name: "@deepseek-ai/dsh-llm",
3277
+ version: "0.1.2-alpha.2",
3278
+ integrity: "sha512-ip6yMxwHugxQm4VCbwX/FDnlTeeBM9VBkIn0+74ityQy7Z3yKREJ1Ov8Z04l4G3duRzeGRsQ4ztOFZ01oNfKIw=="
3279
+ },
3280
+ {
3281
+ name: "@deepseek-ai/dsh-pwsh-sandbox",
3282
+ version: "0.1.2-alpha.2",
3283
+ integrity: "sha512-j/gUmv+nWYzg8o+oEEIK9FKeb6L24n2u7xjpIm7DcL5YjQlRDR6FgDvR2hpUK/d4Wk+zvnaPqZaEaXfUtOzEKQ=="
3284
+ },
3285
+ {
3286
+ name: "@deepseek-ai/dsh-sandbox",
3287
+ version: "0.1.2-alpha.2",
3288
+ integrity: "sha512-InfHYn5B0MxF5QLz0AjbwPS5W0G9VtIvjEFl5o/049KzH6khGKhjqOAVZtu1Z46f1+K/dbjF50VkTdnX3pgIJA=="
3289
+ },
3290
+ {
3291
+ name: "@deepseek-ai/dsh-sandbox-policy",
3292
+ version: "0.1.2-alpha.2",
3293
+ integrity: "sha512-Af7DWZTEjF/70YWSiN0jfbZli1XRk6Bo9W61QHxfShS79I8//mOPrItEPtJRWL/RCmGNfudFglNFyyGKdaqBIg=="
3294
+ },
3295
+ {
3296
+ name: "@deepseek-ai/dsh-session",
3297
+ version: "0.1.2-alpha.2",
3298
+ integrity: "sha512-RfikXscYTDXDr7CD7C/8oGJZaH8Egclj7pmXRtd90QcB5L8RIQ7069xrHZjds8OjNrFo69qQwNK3gYLUVZy9PA=="
3299
+ },
3300
+ {
3301
+ name: "@deepseek-ai/dsh-shell",
3302
+ version: "0.1.2-alpha.2",
3303
+ integrity: "sha512-i16e+OrCJ7GZ1XDnPds081NgVs/xzIVMLECzmLnXgVDKeePgWpdEgR//PgMqKPwoBoJ8z7DTzwKiOISAtOpNzA=="
3304
+ },
3305
+ {
3306
+ name: "@deepseek-ai/dsh-shell-env",
3307
+ version: "0.1.2-alpha.2",
3308
+ integrity: "sha512-OCf1iaPC5Qg6/DMLzvq5flGVSKP2uxAhgKs+8vrRuUiKc2UXXUE4uKayzZU7S18EysLZOVjMKKyUnHFXCVRQxg=="
3309
+ },
3310
+ {
3311
+ name: "@deepseek-ai/dsh-subprocess-local",
3312
+ version: "0.1.2-alpha.2",
3313
+ integrity: "sha512-IFneyTRqvbF/1Jm9h0WwBBxwlAd3vRh3SE/sZo2DTy9lzkRUMEBmWTiJZhVCMZ7hDLE0ALnjLLnLFLkA7bCP9Q=="
3314
+ },
3315
+ {
3316
+ name: "@deepseek-ai/dsh-system-prompt",
3317
+ version: "0.1.2-alpha.2",
3318
+ integrity: "sha512-qT9PZEVMAbszsg1UVUvuovfWFS5unjy08KV0rnOc89TJCgkb2CnlknSyIQs0lXc/UiqT6ZQ59i4ClAFrXhxfxQ=="
3319
+ },
3320
+ {
3321
+ name: "@deepseek-ai/dsh-tool-bash",
3322
+ version: "0.1.2-alpha.2",
3323
+ integrity: "sha512-Vt70FCPSE3Y7++2i9dKCNrsXTqhDpeJwqo44/GZow1xJ5acY9iNkjmjfq0UrTvacLLOEVnrMMBa9LojXi2WZUA=="
3324
+ },
3325
+ {
3326
+ name: "@deepseek-ai/dsh-tool-fs",
3327
+ version: "0.1.2-alpha.2",
3328
+ integrity: "sha512-zQ+zxunJ9BXFR/kAw0Z/LO5TEy87uf1X2giE1AmM9fqbev28vd4pzLq3y8F9b0E64461ANrfD1q2wx8Gy1w47g=="
3329
+ },
3330
+ {
3331
+ name: "@deepseek-ai/dsh-tool-goal",
3332
+ version: "0.1.2-alpha.2",
3333
+ integrity: "sha512-lvp60s3JKuTzncrlKCyS3qM/jYMLZSTMXJ/xQ8A0EIDvfPp7x1C3NNez66IJXPJ5YMtW9QYsqx2YmnUKhPOrow=="
3334
+ },
3335
+ {
3336
+ name: "@deepseek-ai/dsh-tool-jobs",
3337
+ version: "0.1.2-alpha.2",
3338
+ integrity: "sha512-QYq4almnoKNDu/ncrpGLTfkT5sIdqvRTyLd61VNJTFl4rNT2G/JCoEIhDgf50Rkwcchvvk/bNNdekjlENqZjKg=="
3339
+ },
3340
+ {
3341
+ name: "@deepseek-ai/dsh-tool-pwsh",
3342
+ version: "0.1.2-alpha.2",
3343
+ integrity: "sha512-sRGAmLWxxb+gglsqoftLojnFY1HaKMcwV9itkvv7JeACn5vkZuXTI0I/gNxjvt+g/b6sXT37hmQ7bmyo3dFHuQ=="
3344
+ },
3345
+ {
3346
+ name: "@deepseek-ai/dsh-tools",
3347
+ version: "0.1.2-alpha.2",
3348
+ integrity: "sha512-trk0fkmCDp64pqdcr8u7rCcRrwNi+93FKuznTnCD+YsPGFygcSG/6n+Wsh4+9A6oI1fM4/Ecq6Baa9vq1sNhJg=="
3349
+ },
3350
+ {
3351
+ name: "@deepseek-ai/dsh-user-approval",
3352
+ version: "0.1.2-alpha.2",
3353
+ integrity: "sha512-CcV3hf2Q0NYxRbnlE+IysaUkq/hvmjlvS9OGiHpARZVY4VlidlZRmsy5g5L17vDoxirX+WBJ9Cc5VcJMcjPrUg=="
3354
+ },
3355
+ {
3356
+ name: "@deepseek-ai/dsh-web-app",
3357
+ version: "0.1.2-alpha.2",
3358
+ integrity: "sha512-+SKilM9fCCCoYr3fKT7CxNiozGsNHgvvTGhL63tKXM7/3M96dyj7zhT5ztoTgIDW9b9m8J/CaJUa4KlSeUJGFQ=="
3359
+ },
3360
+ {
3361
+ name: "dshmarket",
3362
+ version: "1.38.1",
3363
+ integrity: "sha512-Z9VleLtCXwk5OlbSJKayWtbMaKACL8JUMyb/JHpErS4N3q//GJS+cgOhhxNkZYmXxB8/lv9IbhX1CBzlMhJeJg=="
3364
+ }
3365
+ ])];
3366
+ /**
3367
+ * rc.2 audited package identities (first registry cohort). The audited
3368
+ * cohort is an atomic whole-graph contract (CG-DSH-001): any drifted,
3369
+ * duplicated, unknown-version, unbound, OR MISSING row fails the whole lock
3370
+ * closed (`host_lock_missing`); no capability inherits independence from a
3371
+ * partially present graph.
3372
+ */
3373
+ const EXPECTED_HOST_PACKAGES = HOST_COHORTS[0].packages;
3173
3374
  const packageNames = (...names) => new Set(names);
3174
3375
  const BASE_HOST_PACKAGES = packageNames("@deepseek-ai/cordis", "@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-commands", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-tools");
3175
3376
  const GOAL_HOST_PACKAGES = packageNames("@deepseek-ai/dsh-goal", "@deepseek-ai/dsh-tool-goal");
@@ -3183,16 +3384,76 @@ const HOST_CAPABILITY_PACKAGE_GROUPS = {
3183
3384
  jobs: packageNames("@deepseek-ai/dsh-jobs", "@deepseek-ai/dsh-jobs-local", "@deepseek-ai/dsh-tool-jobs"),
3184
3385
  filesystem: packageNames("@deepseek-ai/dsh-tool-fs", "@deepseek-ai/dsh-fs", "@deepseek-ai/dsh-fs-local", "@deepseek-ai/dsh-fs-sandbox", "@deepseek-ai/dsh-fs-observation-policy", "@deepseek-ai/dsh-sandbox", "@deepseek-ai/dsh-sandbox-policy", "@deepseek-ai/dsh-user-approval", "@deepseek-ai/dsh-attachment", "@deepseek-ai/dsh-system-prompt")
3185
3386
  };
3387
+ /**
3388
+ * Atomically select the audited cohort for one supplied package graph. A
3389
+ * graph matches a cohort only when every row carries version and integrity,
3390
+ * each exactly equals that cohort's audited row, and the graph covers the
3391
+ * complete audited cohort (missing packages fail closed); graphs that mix
3392
+ * rows from different cohorts, use versions unknown to the registry, or
3393
+ * target a platform the cohort was never audited on never select
3394
+ * consistently.
3395
+ */
3396
+ function selectHostCohort(rows, platform) {
3397
+ const registryNames = new Set(HOST_COHORTS.flatMap((cohort) => cohort.packages.map((row) => row.name)));
3398
+ if (rows.some((row) => !registryNames.has(row.name))) return {
3399
+ cohort: HOST_COHORTS[0],
3400
+ consistent: false,
3401
+ reasonCode: "host_cohort_unknown_package"
3402
+ };
3403
+ if (rows.length === 0) return {
3404
+ cohort: HOST_COHORTS[0],
3405
+ consistent: false,
3406
+ reasonCode: "host_cohort_unbound_identity"
3407
+ };
3408
+ const bound = rows.filter((row) => row.version !== void 0 && row.integrity !== void 0);
3409
+ const unboundCount = rows.length - bound.length;
3410
+ const versionMatches = bound.map((row) => HOST_COHORTS.filter((cohort) => cohort.packages.some((p) => p.name === row.name && p.version === row.version)));
3411
+ const identityMatches = bound.map((row, index) => versionMatches[index].filter((cohort) => cohort.packages.some((p) => p.name === row.name && p.version === row.version && p.integrity === row.integrity)));
3412
+ const consistentCohort = HOST_COHORTS.find((cohort) => identityMatches.every((matches) => matches.includes(cohort)));
3413
+ if (consistentCohort !== void 0 && unboundCount === 0) {
3414
+ if (platform && !consistentCohort.auditedPlatforms.includes(platform)) return {
3415
+ cohort: consistentCohort,
3416
+ consistent: false,
3417
+ reasonCode: "host_cohort_platform_not_audited"
3418
+ };
3419
+ const suppliedCounts = /* @__PURE__ */ new Map();
3420
+ for (const row of rows) suppliedCounts.set(row.name, (suppliedCounts.get(row.name) ?? 0) + 1);
3421
+ if (!(consistentCohort.packages.every((row) => (suppliedCounts.get(row.name) ?? 0) === 1) && rows.length === consistentCohort.packages.length)) return {
3422
+ cohort: consistentCohort,
3423
+ consistent: false,
3424
+ reasonCode: "host_cohort_incomplete_graph"
3425
+ };
3426
+ return {
3427
+ cohort: consistentCohort,
3428
+ consistent: true
3429
+ };
3430
+ }
3431
+ const matchingIndices = identityMatches.flatMap((matches, index) => matches.length > 0 ? [index] : []);
3432
+ const mixtureCovered = HOST_COHORTS.filter((cohort) => matchingIndices.every((index) => identityMatches[index].includes(cohort)));
3433
+ let reasonCode;
3434
+ if (matchingIndices.length > 0 && mixtureCovered.length === 0) reasonCode = "host_cohort_mixed_graph";
3435
+ else if (bound.length > 0 && versionMatches.some((matches) => matches.length === 0)) reasonCode = "host_cohort_version_mismatch";
3436
+ else if (bound.length > 0 && identityMatches.some((matches) => matches.length === 0)) reasonCode = "host_cohort_integrity_mismatch";
3437
+ else reasonCode = "host_cohort_unbound_identity";
3438
+ return {
3439
+ cohort: [...HOST_COHORTS].sort((a, b) => {
3440
+ const scoreOf = (cohort) => identityMatches.filter((matches) => matches.includes(cohort)).length;
3441
+ return scoreOf(b) - scoreOf(a) || HOST_COHORTS.indexOf(a) - HOST_COHORTS.indexOf(b);
3442
+ })[0],
3443
+ consistent: false,
3444
+ reasonCode
3445
+ };
3446
+ }
3186
3447
  function stableRows(rows) {
3187
3448
  return [...rows].map((row) => ({ ...row })).sort((a, b) => a.name.localeCompare(b.name) || (a.version ?? "").localeCompare(b.version ?? "") || (a.integrity ?? "").localeCompare(b.integrity ?? ""));
3188
3449
  }
3189
- function statusForPackages(id, rows, requiredNames) {
3450
+ function statusForPackages(id, rows, requiredNames, cohort) {
3190
3451
  const requiredPackages = [...requiredNames].sort();
3191
3452
  const relevant = rows.filter((row) => requiredNames.has(row.name));
3192
3453
  const counts = /* @__PURE__ */ new Map();
3193
3454
  for (const row of relevant) counts.set(row.name, (counts.get(row.name) ?? 0) + 1);
3194
3455
  const missingPackages = requiredPackages.filter((name) => !counts.has(name));
3195
- const digest = safeHostLockDigest(relevant, { capabilityId: id });
3456
+ const digest = safeHostLockDigest(relevant, { capabilityId: id }, cohort);
3196
3457
  if ([...counts.values()].some((count) => count > 1)) return {
3197
3458
  id,
3198
3459
  status: "unavailable",
@@ -3209,7 +3470,7 @@ function statusForPackages(id, rows, requiredNames) {
3209
3470
  missingPackages,
3210
3471
  reasonCode: "host_capability_missing"
3211
3472
  };
3212
- const expected = new Map(EXPECTED_HOST_PACKAGES.map((row) => [row.name, row]));
3473
+ const expected = new Map(cohort.packages.map((row) => [row.name, row]));
3213
3474
  for (const row of relevant) {
3214
3475
  const pinned = expected.get(row.name);
3215
3476
  if (!row.version || !row.integrity) return {
@@ -3245,27 +3506,33 @@ function statusForPackages(id, rows, requiredNames) {
3245
3506
  missingPackages
3246
3507
  };
3247
3508
  }
3248
- function capabilityEvaluations(rows) {
3249
- return Object.fromEntries(Object.entries(HOST_CAPABILITY_PACKAGE_GROUPS).map(([id, packages]) => [id, statusForPackages(id, rows, packages)]));
3509
+ function capabilityEvaluations(rows, cohort) {
3510
+ return Object.fromEntries(Object.entries(HOST_CAPABILITY_PACKAGE_GROUPS).map(([id, packages]) => [id, statusForPackages(id, rows, packages, cohort)]));
3511
+ }
3512
+ function cohortForEvaluation(evaluation) {
3513
+ return HOST_COHORTS.find((cohort) => cohort.id === evaluation.cohortId) ?? HOST_COHORTS[0];
3250
3514
  }
3251
3515
  function evaluateHostLock(rows, context = {}) {
3252
3516
  const supplied = stableRows(rows);
3253
- const capabilities = capabilityEvaluations(supplied);
3517
+ const selection = selectHostCohort(supplied, context.platform);
3518
+ const cohort = selection.cohort;
3519
+ const capabilities = capabilityEvaluations(supplied, cohort);
3254
3520
  const counts = /* @__PURE__ */ new Map();
3255
3521
  for (const row of supplied) counts.set(row.name, (counts.get(row.name) ?? 0) + 1);
3256
3522
  const goalRows = [...GOAL_HOST_PACKAGES].filter((name) => counts.has(name));
3257
3523
  const goalAvailable = goalRows.length === GOAL_HOST_PACKAGES.size;
3258
- const digest = safeHostLockDigest(supplied, context);
3259
- const base = statusForPackages("base", supplied, BASE_HOST_PACKAGES);
3260
- const baseDuplicate = supplied.find((row) => BASE_HOST_PACKAGES.has(row.name) && (counts.get(row.name) ?? 0) > 1);
3261
- const goalDuplicate = supplied.find((row) => GOAL_HOST_PACKAGES.has(row.name) && (counts.get(row.name) ?? 0) > 1);
3262
- const expectedNames = new Set(EXPECTED_HOST_PACKAGES.map((row) => row.name));
3263
- const unknown = supplied.find((row) => !expectedNames.has(row.name));
3524
+ const digest = safeHostLockDigest(supplied, context, cohort);
3525
+ const base = statusForPackages("base", supplied, BASE_HOST_PACKAGES, cohort);
3526
+ const missingPackages = cohort.packages.map((row) => row.name).filter((name) => (counts.get(name) ?? 0) === 0).sort((a, b) => a.localeCompare(b));
3527
+ const registryNames = new Set(HOST_COHORTS.flatMap((entry) => entry.packages.map((row) => row.name)));
3528
+ const unknown = supplied.find((row) => !registryNames.has(row.name));
3264
3529
  const baseResult = {
3265
3530
  digest,
3266
3531
  goalAvailable,
3267
3532
  packages: supplied,
3268
3533
  capabilities,
3534
+ cohortId: cohort.id,
3535
+ missingPackages,
3269
3536
  ...context.platform ? { platform: context.platform } : {},
3270
3537
  ...context.profileKind ? { profileKind: context.profileKind } : {}
3271
3538
  };
@@ -3274,7 +3541,7 @@ function evaluateHostLock(rows, context = {}) {
3274
3541
  status: "unsupported",
3275
3542
  reasonCode: "host_lock_unknown_package"
3276
3543
  };
3277
- if (baseDuplicate || goalDuplicate) return {
3544
+ if (supplied.some((row) => (counts.get(row.name) ?? 0) > 1)) return {
3278
3545
  ...baseResult,
3279
3546
  status: "unavailable",
3280
3547
  goalAvailable: false,
@@ -3295,7 +3562,7 @@ function evaluateHostLock(rows, context = {}) {
3295
3562
  };
3296
3563
  }
3297
3564
  if (goalAvailable) {
3298
- const goal = statusForPackages("goal", supplied, GOAL_HOST_PACKAGES);
3565
+ const goal = statusForPackages("goal", supplied, GOAL_HOST_PACKAGES, cohort);
3299
3566
  if (goal.status !== "supported") return {
3300
3567
  ...baseResult,
3301
3568
  status: goal.status,
@@ -3303,6 +3570,44 @@ function evaluateHostLock(rows, context = {}) {
3303
3570
  reasonCode: goal.reasonCode === "host_capability_version_mismatch" ? "host_lock_version_mismatch" : goal.reasonCode === "host_capability_integrity_mismatch" ? "host_lock_integrity_mismatch" : "host_lock_missing"
3304
3571
  };
3305
3572
  }
3573
+ if (!selection.consistent) {
3574
+ const failure = {
3575
+ host_cohort_unknown_package: {
3576
+ status: "unsupported",
3577
+ reasonCode: "host_lock_unknown_package"
3578
+ },
3579
+ host_cohort_version_mismatch: {
3580
+ status: "unsupported",
3581
+ reasonCode: "host_lock_version_mismatch"
3582
+ },
3583
+ host_cohort_integrity_mismatch: {
3584
+ status: "unsupported",
3585
+ reasonCode: "host_lock_integrity_mismatch"
3586
+ },
3587
+ host_cohort_mixed_graph: {
3588
+ status: "unsupported",
3589
+ reasonCode: "host_lock_cohort_mixed_graph"
3590
+ },
3591
+ host_cohort_incomplete_graph: {
3592
+ status: "unavailable",
3593
+ reasonCode: "host_lock_missing"
3594
+ },
3595
+ host_cohort_unbound_identity: {
3596
+ status: "unsupported",
3597
+ reasonCode: "host_lock_cohort_unbound_identity"
3598
+ },
3599
+ host_cohort_platform_not_audited: {
3600
+ status: "unsupported",
3601
+ reasonCode: "host_lock_cohort_platform_not_audited"
3602
+ }
3603
+ }[selection.reasonCode ?? "host_cohort_unbound_identity"];
3604
+ return {
3605
+ ...baseResult,
3606
+ status: failure.status,
3607
+ goalAvailable: false,
3608
+ reasonCode: failure.reasonCode
3609
+ };
3610
+ }
3306
3611
  return {
3307
3612
  ...baseResult,
3308
3613
  status: "supported"
@@ -3351,7 +3656,7 @@ function evaluateHostCapability(evaluation, request) {
3351
3656
  };
3352
3657
  const required = new Set(BASE_HOST_PACKAGES);
3353
3658
  for (const group of groups) for (const name of HOST_CAPABILITY_PACKAGE_GROUPS[group]) required.add(name);
3354
- const result = statusForPackages(`action.${request.action}.${platform ?? "native"}.${profileKind ?? "unknown"}`, evaluation.packages, required);
3659
+ const result = statusForPackages(`action.${request.action}.${platform ?? "native"}.${profileKind ?? "unknown"}`, evaluation.packages, required, cohortForEvaluation(evaluation));
3355
3660
  if (evaluation.status !== "supported") return {
3356
3661
  ...result,
3357
3662
  status: evaluation.status,
@@ -3368,7 +3673,7 @@ function evaluateHostCapability(evaluation, request) {
3368
3673
  function evaluateExternalWaitCapability(evaluation) {
3369
3674
  const required = new Set(BASE_HOST_PACKAGES);
3370
3675
  for (const name of HOST_CAPABILITY_PACKAGE_GROUPS.jobs) required.add(name);
3371
- const result = statusForPackages("boundary.external_wait.jobs", evaluation.packages, required);
3676
+ const result = statusForPackages("boundary.external_wait.jobs", evaluation.packages, required, cohortForEvaluation(evaluation));
3372
3677
  if (evaluation.status !== "supported") return {
3373
3678
  ...result,
3374
3679
  status: evaluation.status,
@@ -3406,7 +3711,7 @@ function evaluateToolSurfaceCapability(evaluation, surface) {
3406
3711
  if (surface === "pwsh") groups.push("terminal_windows");
3407
3712
  const required = new Set(BASE_HOST_PACKAGES);
3408
3713
  for (const group of groups) for (const name of HOST_CAPABILITY_PACKAGE_GROUPS[group]) required.add(name);
3409
- const result = statusForPackages(`tool.${surface}.${platform ?? "native"}`, evaluation.packages, required);
3714
+ const result = statusForPackages(`tool.${surface}.${platform ?? "native"}`, evaluation.packages, required, cohortForEvaluation(evaluation));
3410
3715
  if (evaluation.status !== "supported") return {
3411
3716
  ...result,
3412
3717
  status: evaluation.status,
@@ -3414,10 +3719,10 @@ function evaluateToolSurfaceCapability(evaluation, surface) {
3414
3719
  };
3415
3720
  return result;
3416
3721
  }
3417
- function safeHostLockDigest(packages, context = {}) {
3722
+ function safeHostLockDigest(packages, context = {}, cohort) {
3418
3723
  try {
3419
3724
  const capabilities = [
3420
- ...SUPPORTED_HOST_MANIFEST.capabilities ?? [],
3725
+ ...cohort.capabilities,
3421
3726
  ...context.platform ? [{
3422
3727
  name: "active_platform",
3423
3728
  value: {
@@ -3441,7 +3746,8 @@ function safeHostLockDigest(packages, context = {}) {
3441
3746
  }] : []
3442
3747
  ];
3443
3748
  return hostLockDigest({
3444
- ...SUPPORTED_HOST_MANIFEST,
3749
+ manifestVersion: cohort.manifestVersion,
3750
+ supportedGoalVersions: [...cohort.supportedGoalVersions],
3445
3751
  capabilities,
3446
3752
  packages: [...packages]
3447
3753
  });
@@ -3514,7 +3820,7 @@ function bindExecutableIdentity(resolution, effect) {
3514
3820
  identity: { ...resolution }
3515
3821
  };
3516
3822
  }
3517
- const DEFAULT_HOST_LOCK = evaluateHostLock(EXPECTED_HOST_PACKAGES.filter((row) => BASE_HOST_PACKAGES.has(row.name)));
3823
+ const DEFAULT_HOST_LOCK = evaluateHostLock(EXPECTED_HOST_PACKAGES);
3518
3824
 
3519
3825
  //#endregion
3520
3826
  //#region src/domain/goal-gate.ts
@@ -5459,7 +5765,8 @@ async function executeRevalidatedGitEffect(resolved, manifest, target, currentSt
5459
5765
 
5460
5766
  //#endregion
5461
5767
  //#region src/domain/host-resolver.ts
5462
- const CRITICAL_NAMES = EXPECTED_HOST_PACKAGES.map((row) => row.name);
5768
+ /** Names audited in any registered cohort; rows outside the union are unknown. */
5769
+ const CRITICAL_NAMES = [...new Set(HOST_COHORTS.flatMap((cohort) => cohort.packages.map((row) => row.name)))];
5463
5770
  const HOST_LOCK_MARKER_BEGIN = "# >>> BEGIN DSH COMPLETION GUARD HOST LOCK (managed) >>>";
5464
5771
  const HOST_LOCK_MARKER_END = "# <<< END DSH COMPLETION GUARD HOST LOCK (managed) <<<";
5465
5772
  var HostProfileError = class extends Error {
@@ -5825,4 +6132,4 @@ function verifyComposedHostLockDump(text, expected) {
5825
6132
  }
5826
6133
 
5827
6134
  //#endregion
5828
- export { classifyUserInteraction as $, extractToolSubject as A, STOP_PROTOCOL_VERSION as At, DEFAULT_HOST_LOCK as B, COMMAND_SURFACE_MANIFEST as Bt, latestAssistantText as C, canonicalRegistryBase as Ct, supersedeItem as D, CERTIFICATE_VERSION as Dt, deriveProjection as E, ACTION_MANIFEST_VERSION as Et, parsePwshCommand as F, requestedTargetMatchesResolved as Ft, bindExecutableIdentity as G, sanitizeClauseText as Gt, GOAL_HOST_PACKAGES as H, canonicalizePath as Ht, parseShellCommand as I, semanticActionFromCommand as It, evaluateHostCapability as J, createProjection as Jt, bindLiveGoalCapability as K, sanitizeUrl as Kt, goalCompletionDenial as L, semanticActionFromText as Lt, withDurability as M, actionCompatible as Mt, canonicalArgvFromCommand as N, isStatefulAction as Nt, evidenceFromPersistedToolResult as O, SEMANTIC_ACTIONS as Ot, isRunExecutable as P, requestedTargetAuthorizesMutation as Pt, segmentAuthorityBlocks as Q, hasCurrentCertificate as R, validateActionManifest as Rt, isWholeTaskCompletionClaim as S, segmentClauses as St, PROTOCOL_V3_NOTICE as T, ACTION_MANIFEST as Tt, HOST_CAPABILITY_PACKAGE_GROUPS as U, digestStrings as Ut, EXPECTED_HOST_PACKAGES as V, validateManifest as Vt, SUPPORTED_HOST_MANIFEST as W, normalizeClause as Wt, evaluateToolSurfaceCapability as X, evaluateHostLock as Y, authorityCaptureCounts as Z, revalidateGitPrestate as _, classifyClause as _t, packageRowsFromActiveGraph as a, DEFAULT_RECOVERY_CHAR_BUDGET as at, decideTurnBoundary as b, extractOperation as bt, resolveInstalledHostLock as c, recoveryDigest as ct, commitIndexSnapshotDigest as d, evidenceCoverage as dt, availableBoundaryQualifications as et, commitTreeSnapshotDigest as f, evidenceMatchesItem as ft, parseGitCommandManifest as g, captureItem as gt, gitCommandMatchesTarget as h, captureClause as ht, injectActiveProfileHostLock as i, certifyCheckpoint as it, isDeterministicCheck as j, SUPPORTED_EVIDENCE_ADAPTERS as jt, extractTextContent as k, STATEFUL_ACTIONS as kt, verifyComposedHostLockDump as l, renderRecoveryPacket as lt, executeRevalidatedGitEffect as m, currentContractDigest as mt, hostLockContextFromComposedDump as n, isCurrentAcceptedBoundary as nt, packageRowsFromPnpmLock as o, closingHint as ot, createGitPrestateEnvelope as p, isVerifyingCapability as pt, evaluateExternalWaitCapability as q, sha256 as qt, hostLockRowsFromComposedDump as r, qualifyBoundary as rt, resolveActiveProfileHostLock as s, openItems$1 as st, HostProfileError as t, effectuateBoundary as tt, GIT_COMMAND_MANIFEST_IDS as u, bindingSatisfies as ut, verifiedLinearCommitReadback as v, extractArtifactPaths as vt, observeAssistantOutcome as w, npmEscapedPackageName as wt, decideTurnStopping as x, isInformationalMessage as xt, classifyCompletionClaim as y, extractMethod as yt, BASE_HOST_PACKAGES as z, validateActionTarget as zt };
6135
+ export { segmentAuthorityBlocks as $, extractToolSubject as A, STATEFUL_ACTIONS as At, DEFAULT_HOST_LOCK as B, validateActionTarget as Bt, latestAssistantText as C, segmentClauses as Ct, supersedeItem as D, ACTION_MANIFEST_VERSION as Dt, deriveProjection as E, ACTION_MANIFEST as Et, parsePwshCommand as F, requestedTargetAuthorizesMutation as Ft, bindExecutableIdentity as G, normalizeClause as Gt, GOAL_HOST_PACKAGES as H, validateManifest as Ht, parseShellCommand as I, requestedTargetMatchesResolved as It, evaluateHostCapability as J, sha256 as Jt, bindLiveGoalCapability as K, sanitizeClauseText as Kt, goalCompletionDenial as L, semanticActionFromCommand as Lt, withDurability as M, SUPPORTED_EVIDENCE_ADAPTERS as Mt, canonicalArgvFromCommand as N, actionCompatible as Nt, evidenceFromPersistedToolResult as O, CERTIFICATE_VERSION as Ot, isRunExecutable as P, isStatefulAction as Pt, authorityCaptureCounts as Q, hasCurrentCertificate as R, semanticActionFromText as Rt, isWholeTaskCompletionClaim as S, isInformationalMessage as St, PROTOCOL_V3_NOTICE as T, npmEscapedPackageName as Tt, HOST_CAPABILITY_PACKAGE_GROUPS as U, canonicalizePath as Ut, EXPECTED_HOST_PACKAGES as V, COMMAND_SURFACE_MANIFEST as Vt, HOST_COHORTS as W, digestStrings as Wt, evaluateToolSurfaceCapability as X, evaluateHostLock as Y, createProjection as Yt, selectHostCohort as Z, revalidateGitPrestate as _, captureItem as _t, packageRowsFromActiveGraph as a, certifyCheckpoint as at, decideTurnBoundary as b, extractMethod as bt, resolveInstalledHostLock as c, openItems$1 as ct, commitIndexSnapshotDigest as d, bindingSatisfies as dt, classifyUserInteraction as et, commitTreeSnapshotDigest as f, evidenceCoverage as ft, parseGitCommandManifest as g, captureClause as gt, gitCommandMatchesTarget as h, currentContractDigest as ht, injectActiveProfileHostLock as i, qualifyBoundary as it, isDeterministicCheck as j, STOP_PROTOCOL_VERSION as jt, extractTextContent as k, SEMANTIC_ACTIONS as kt, verifyComposedHostLockDump as l, recoveryDigest as lt, executeRevalidatedGitEffect as m, isVerifyingCapability as mt, hostLockContextFromComposedDump as n, effectuateBoundary as nt, packageRowsFromPnpmLock as o, DEFAULT_RECOVERY_CHAR_BUDGET as ot, createGitPrestateEnvelope as p, evidenceMatchesItem as pt, evaluateExternalWaitCapability as q, sanitizeUrl as qt, hostLockRowsFromComposedDump as r, isCurrentAcceptedBoundary as rt, resolveActiveProfileHostLock as s, closingHint as st, HostProfileError as t, availableBoundaryQualifications as tt, GIT_COMMAND_MANIFEST_IDS as u, renderRecoveryPacket as ut, verifiedLinearCommitReadback as v, classifyClause as vt, observeAssistantOutcome as w, canonicalRegistryBase as wt, decideTurnStopping as x, extractOperation as xt, classifyCompletionClaim as y, extractArtifactPaths as yt, BASE_HOST_PACKAGES as z, validateActionManifest as zt };