wingfoil 0.2.1
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/LICENSE +21 -0
- package/README.md +334 -0
- package/dist/cli/error.d.ts +11 -0
- package/dist/cli/error.d.ts.map +1 -0
- package/dist/cli/error.js +27 -0
- package/dist/cli/error.js.map +1 -0
- package/dist/cli/exit.d.ts +19 -0
- package/dist/cli/exit.d.ts.map +1 -0
- package/dist/cli/exit.js +14 -0
- package/dist/cli/exit.js.map +1 -0
- package/dist/cli/index.d.ts +28 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +36 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init-command.d.ts +34 -0
- package/dist/cli/init-command.d.ts.map +1 -0
- package/dist/cli/init-command.js +100 -0
- package/dist/cli/init-command.js.map +1 -0
- package/dist/cli/mcp-command.d.ts +24 -0
- package/dist/cli/mcp-command.d.ts.map +1 -0
- package/dist/cli/mcp-command.js +42 -0
- package/dist/cli/mcp-command.js.map +1 -0
- package/dist/cli/output.d.ts +13 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +28 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/program.d.ts +12 -0
- package/dist/cli/program.d.ts.map +1 -0
- package/dist/cli/program.js +279 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/registrar.d.ts +69 -0
- package/dist/cli/registrar.d.ts.map +1 -0
- package/dist/cli/registrar.js +82 -0
- package/dist/cli/registrar.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +45 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/approval-authority.d.ts +83 -0
- package/dist/core/approval-authority.d.ts.map +1 -0
- package/dist/core/approval-authority.js +112 -0
- package/dist/core/approval-authority.js.map +1 -0
- package/dist/core/builtin-asset.d.ts +71 -0
- package/dist/core/builtin-asset.d.ts.map +1 -0
- package/dist/core/builtin-asset.js +137 -0
- package/dist/core/builtin-asset.js.map +1 -0
- package/dist/core/builtin-integrity.d.ts +32 -0
- package/dist/core/builtin-integrity.d.ts.map +1 -0
- package/dist/core/builtin-integrity.js +148 -0
- package/dist/core/builtin-integrity.js.map +1 -0
- package/dist/core/confinement.d.ts +57 -0
- package/dist/core/confinement.d.ts.map +1 -0
- package/dist/core/confinement.js +108 -0
- package/dist/core/confinement.js.map +1 -0
- package/dist/core/context.d.ts +187 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +192 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/directive-assign.d.ts +131 -0
- package/dist/core/directive-assign.d.ts.map +1 -0
- package/dist/core/directive-assign.js +352 -0
- package/dist/core/directive-assign.js.map +1 -0
- package/dist/core/directives-list.d.ts +80 -0
- package/dist/core/directives-list.d.ts.map +1 -0
- package/dist/core/directives-list.js +148 -0
- package/dist/core/directives-list.js.map +1 -0
- package/dist/core/exit-code.d.ts +85 -0
- package/dist/core/exit-code.d.ts.map +1 -0
- package/dist/core/exit-code.js +163 -0
- package/dist/core/exit-code.js.map +1 -0
- package/dist/core/git-identity.d.ts +32 -0
- package/dist/core/git-identity.d.ts.map +1 -0
- package/dist/core/git-identity.js +72 -0
- package/dist/core/git-identity.js.map +1 -0
- package/dist/core/index.d.ts +388 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +1331 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/init.d.ts +78 -0
- package/dist/core/init.d.ts.map +1 -0
- package/dist/core/init.js +167 -0
- package/dist/core/init.js.map +1 -0
- package/dist/core/loaders.d.ts +174 -0
- package/dist/core/loaders.d.ts.map +1 -0
- package/dist/core/loaders.js +364 -0
- package/dist/core/loaders.js.map +1 -0
- package/dist/core/memory-add-type.d.ts +43 -0
- package/dist/core/memory-add-type.d.ts.map +1 -0
- package/dist/core/memory-add-type.js +151 -0
- package/dist/core/memory-add-type.js.map +1 -0
- package/dist/core/memory-transition.d.ts +111 -0
- package/dist/core/memory-transition.d.ts.map +1 -0
- package/dist/core/memory-transition.js +269 -0
- package/dist/core/memory-transition.js.map +1 -0
- package/dist/core/registry.d.ts +189 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +66 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/relevance.d.ts +86 -0
- package/dist/core/relevance.d.ts.map +1 -0
- package/dist/core/relevance.js +258 -0
- package/dist/core/relevance.js.map +1 -0
- package/dist/core/require-reason.d.ts +27 -0
- package/dist/core/require-reason.d.ts.map +1 -0
- package/dist/core/require-reason.js +95 -0
- package/dist/core/require-reason.js.map +1 -0
- package/dist/core/types.d.ts +45 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +22 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/usage-error.d.ts +20 -0
- package/dist/core/usage-error.d.ts.map +1 -0
- package/dist/core/usage-error.js +29 -0
- package/dist/core/usage-error.js.map +1 -0
- package/dist/core/write-guard.d.ts +99 -0
- package/dist/core/write-guard.d.ts.map +1 -0
- package/dist/core/write-guard.js +247 -0
- package/dist/core/write-guard.js.map +1 -0
- package/dist/directives/create.d.ts +47 -0
- package/dist/directives/create.d.ts.map +1 -0
- package/dist/directives/create.js +82 -0
- package/dist/directives/create.js.map +1 -0
- package/dist/directives/index.d.ts +20 -0
- package/dist/directives/index.d.ts.map +1 -0
- package/dist/directives/index.js +32 -0
- package/dist/directives/index.js.map +1 -0
- package/dist/directives/roles-edit.d.ts +53 -0
- package/dist/directives/roles-edit.d.ts.map +1 -0
- package/dist/directives/roles-edit.js +286 -0
- package/dist/directives/roles-edit.js.map +1 -0
- package/dist/directives/schema.d.ts +65 -0
- package/dist/directives/schema.d.ts.map +1 -0
- package/dist/directives/schema.js +68 -0
- package/dist/directives/schema.js.map +1 -0
- package/dist/dna/edit.d.ts +61 -0
- package/dist/dna/edit.d.ts.map +1 -0
- package/dist/dna/edit.js +429 -0
- package/dist/dna/edit.js.map +1 -0
- package/dist/dna/index.d.ts +24 -0
- package/dist/dna/index.d.ts.map +1 -0
- package/dist/dna/index.js +59 -0
- package/dist/dna/index.js.map +1 -0
- package/dist/dna/mutate.d.ts +74 -0
- package/dist/dna/mutate.d.ts.map +1 -0
- package/dist/dna/mutate.js +318 -0
- package/dist/dna/mutate.js.map +1 -0
- package/dist/dna/path.d.ts +175 -0
- package/dist/dna/path.d.ts.map +1 -0
- package/dist/dna/path.js +289 -0
- package/dist/dna/path.js.map +1 -0
- package/dist/dna/roles.d.ts +57 -0
- package/dist/dna/roles.d.ts.map +1 -0
- package/dist/dna/roles.js +50 -0
- package/dist/dna/roles.js.map +1 -0
- package/dist/dna/schema.d.ts +172 -0
- package/dist/dna/schema.d.ts.map +1 -0
- package/dist/dna/schema.js +182 -0
- package/dist/dna/schema.js.map +1 -0
- package/dist/dna/set.d.ts +145 -0
- package/dist/dna/set.d.ts.map +1 -0
- package/dist/dna/set.js +428 -0
- package/dist/dna/set.js.map +1 -0
- package/dist/mcp/dna-resource.d.ts +16 -0
- package/dist/mcp/dna-resource.d.ts.map +1 -0
- package/dist/mcp/dna-resource.js +56 -0
- package/dist/mcp/dna-resource.js.map +1 -0
- package/dist/mcp/index.d.ts +49 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +60 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/memory-resource.d.ts +17 -0
- package/dist/mcp/memory-resource.d.ts.map +1 -0
- package/dist/mcp/memory-resource.js +133 -0
- package/dist/mcp/memory-resource.js.map +1 -0
- package/dist/mcp/prompt.d.ts +48 -0
- package/dist/mcp/prompt.d.ts.map +1 -0
- package/dist/mcp/prompt.js +176 -0
- package/dist/mcp/prompt.js.map +1 -0
- package/dist/mcp/read-only.d.ts +42 -0
- package/dist/mcp/read-only.d.ts.map +1 -0
- package/dist/mcp/read-only.js +93 -0
- package/dist/mcp/read-only.js.map +1 -0
- package/dist/mcp/registrar.d.ts +54 -0
- package/dist/mcp/registrar.d.ts.map +1 -0
- package/dist/mcp/registrar.js +72 -0
- package/dist/mcp/registrar.js.map +1 -0
- package/dist/mcp/server.d.ts +58 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +64 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/workflow-resource.d.ts +17 -0
- package/dist/mcp/workflow-resource.d.ts.map +1 -0
- package/dist/mcp/workflow-resource.js +63 -0
- package/dist/mcp/workflow-resource.js.map +1 -0
- package/dist/memory/add.d.ts +50 -0
- package/dist/memory/add.d.ts.map +1 -0
- package/dist/memory/add.js +131 -0
- package/dist/memory/add.js.map +1 -0
- package/dist/memory/audit.d.ts +177 -0
- package/dist/memory/audit.d.ts.map +1 -0
- package/dist/memory/audit.js +287 -0
- package/dist/memory/audit.js.map +1 -0
- package/dist/memory/commit-message.d.ts +146 -0
- package/dist/memory/commit-message.d.ts.map +1 -0
- package/dist/memory/commit-message.js +203 -0
- package/dist/memory/commit-message.js.map +1 -0
- package/dist/memory/entry.d.ts +56 -0
- package/dist/memory/entry.d.ts.map +1 -0
- package/dist/memory/entry.js +28 -0
- package/dist/memory/entry.js.map +1 -0
- package/dist/memory/frontmatter-edit.d.ts +68 -0
- package/dist/memory/frontmatter-edit.d.ts.map +1 -0
- package/dist/memory/frontmatter-edit.js +333 -0
- package/dist/memory/frontmatter-edit.js.map +1 -0
- package/dist/memory/git-log.d.ts +32 -0
- package/dist/memory/git-log.d.ts.map +1 -0
- package/dist/memory/git-log.js +100 -0
- package/dist/memory/git-log.js.map +1 -0
- package/dist/memory/history.d.ts +142 -0
- package/dist/memory/history.d.ts.map +1 -0
- package/dist/memory/history.js +250 -0
- package/dist/memory/history.js.map +1 -0
- package/dist/memory/index.d.ts +58 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +107 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/query.d.ts +150 -0
- package/dist/memory/query.d.ts.map +1 -0
- package/dist/memory/query.js +307 -0
- package/dist/memory/query.js.map +1 -0
- package/dist/memory/reject.d.ts +11 -0
- package/dist/memory/reject.d.ts.map +1 -0
- package/dist/memory/reject.js +32 -0
- package/dist/memory/reject.js.map +1 -0
- package/dist/memory/schema.d.ts +104 -0
- package/dist/memory/schema.d.ts.map +1 -0
- package/dist/memory/schema.js +161 -0
- package/dist/memory/schema.js.map +1 -0
- package/dist/memory/state-machine.d.ts +166 -0
- package/dist/memory/state-machine.d.ts.map +1 -0
- package/dist/memory/state-machine.js +431 -0
- package/dist/memory/state-machine.js.map +1 -0
- package/dist/memory/submit.d.ts +11 -0
- package/dist/memory/submit.d.ts.map +1 -0
- package/dist/memory/submit.js +44 -0
- package/dist/memory/submit.js.map +1 -0
- package/dist/storage/builtin-directives.d.ts +54 -0
- package/dist/storage/builtin-directives.d.ts.map +1 -0
- package/dist/storage/builtin-directives.js +152 -0
- package/dist/storage/builtin-directives.js.map +1 -0
- package/dist/storage/commit.d.ts +92 -0
- package/dist/storage/commit.d.ts.map +1 -0
- package/dist/storage/commit.js +201 -0
- package/dist/storage/commit.js.map +1 -0
- package/dist/storage/confinement.d.ts +93 -0
- package/dist/storage/confinement.d.ts.map +1 -0
- package/dist/storage/confinement.js +164 -0
- package/dist/storage/confinement.js.map +1 -0
- package/dist/storage/document.d.ts +27 -0
- package/dist/storage/document.d.ts.map +1 -0
- package/dist/storage/document.js +52 -0
- package/dist/storage/document.js.map +1 -0
- package/dist/storage/errors.d.ts +36 -0
- package/dist/storage/errors.d.ts.map +1 -0
- package/dist/storage/errors.js +46 -0
- package/dist/storage/errors.js.map +1 -0
- package/dist/storage/frontmatter.d.ts +27 -0
- package/dist/storage/frontmatter.d.ts.map +1 -0
- package/dist/storage/frontmatter.js +37 -0
- package/dist/storage/frontmatter.js.map +1 -0
- package/dist/storage/git-root.d.ts +17 -0
- package/dist/storage/git-root.d.ts.map +1 -0
- package/dist/storage/git-root.js +49 -0
- package/dist/storage/git-root.js.map +1 -0
- package/dist/storage/index.d.ts +29 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +66 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/init-state.d.ts +9 -0
- package/dist/storage/init-state.d.ts.map +1 -0
- package/dist/storage/init-state.js +24 -0
- package/dist/storage/init-state.js.map +1 -0
- package/dist/storage/layout.d.ts +51 -0
- package/dist/storage/layout.d.ts.map +1 -0
- package/dist/storage/layout.js +88 -0
- package/dist/storage/layout.js.map +1 -0
- package/dist/storage/memory-path.d.ts +72 -0
- package/dist/storage/memory-path.d.ts.map +1 -0
- package/dist/storage/memory-path.js +127 -0
- package/dist/storage/memory-path.js.map +1 -0
- package/dist/storage/snapshot.d.ts +16 -0
- package/dist/storage/snapshot.d.ts.map +1 -0
- package/dist/storage/snapshot.js +72 -0
- package/dist/storage/snapshot.js.map +1 -0
- package/dist/storage/templates.d.ts +88 -0
- package/dist/storage/templates.d.ts.map +1 -0
- package/dist/storage/templates.js +422 -0
- package/dist/storage/templates.js.map +1 -0
- package/dist/validation/error-mapper.d.ts +16 -0
- package/dist/validation/error-mapper.d.ts.map +1 -0
- package/dist/validation/error-mapper.js +18 -0
- package/dist/validation/error-mapper.js.map +1 -0
- package/dist/validation/errors.d.ts +69 -0
- package/dist/validation/errors.d.ts.map +1 -0
- package/dist/validation/errors.js +69 -0
- package/dist/validation/errors.js.map +1 -0
- package/dist/validation/id.d.ts +16 -0
- package/dist/validation/id.d.ts.map +1 -0
- package/dist/validation/id.js +177 -0
- package/dist/validation/id.js.map +1 -0
- package/dist/validation/index.d.ts +18 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +37 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/secret-scan.d.ts +129 -0
- package/dist/validation/secret-scan.d.ts.map +1 -0
- package/dist/validation/secret-scan.js +367 -0
- package/dist/validation/secret-scan.js.map +1 -0
- package/dist/validation/two-pass.d.ts +24 -0
- package/dist/validation/two-pass.d.ts.map +1 -0
- package/dist/validation/two-pass.js +24 -0
- package/dist/validation/two-pass.js.map +1 -0
- package/dist/validation/warning.d.ts +31 -0
- package/dist/validation/warning.d.ts.map +1 -0
- package/dist/validation/warning.js +81 -0
- package/dist/validation/warning.js.map +1 -0
- package/dist/validation/yaml.d.ts +9 -0
- package/dist/validation/yaml.d.ts.map +1 -0
- package/dist/validation/yaml.js +30 -0
- package/dist/validation/yaml.js.map +1 -0
- package/dist/workflow/index.d.ts +10 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +16 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/schema.d.ts +89 -0
- package/dist/workflow/schema.d.ts.map +1 -0
- package/dist/workflow/schema.js +73 -0
- package/dist/workflow/schema.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.selectDirectivesById = selectDirectivesById;
|
|
4
|
+
exports.resolveRoleDirectives = resolveRoleDirectives;
|
|
5
|
+
exports.assembleExecutionContext = assembleExecutionContext;
|
|
6
|
+
/**
|
|
7
|
+
* Agent execution context assembly (task-037-role-task-scoped-context, REQ-STATE-05) — the
|
|
8
|
+
* `directive-loader` + a minimal `context-builder` slice of
|
|
9
|
+
* `spec-012-context-loader-relevance-filtering` (§1 "placement & responsibilities", §5 "Directive
|
|
10
|
+
* resolution"). Satisfies REQ-STATE-05's Fit Criterion, verbatim: "The assembled context object
|
|
11
|
+
* exposes separate `dna`, `memory`, `directives` sections; it contains 100% of the role's assigned
|
|
12
|
+
* directives and 0 directives of other roles."
|
|
13
|
+
*
|
|
14
|
+
* **Archived elements are excluded** (REQ-STATE-06, the `{deprecated, superseded}` set ratified by
|
|
15
|
+
* `dl-028-archived-states-excluded-from-context`): {@link assembleExecutionContext} drops a resolved
|
|
16
|
+
* element whose `status` is archived, through the shared `isArchivedStatus` primitive rather than any
|
|
17
|
+
* local notion of "archived". This closed `bug-010-deprecated-reaches-agent-context` — which this
|
|
18
|
+
* header previously recorded as an open gap — together with the `wingfoil://memory/{type}` collection
|
|
19
|
+
* Resource, the other surface that bug covered (`task-069-fix-archived-excluded-from-agent-context`).
|
|
20
|
+
*
|
|
21
|
+
* Still deliberately NOT the full spec-012 pipeline: no `ContextRequest`/`stateRef` pinning, no tiered
|
|
22
|
+
* (T1–T4) Memory relevance ranking, no bounding caps, and no canonical byte-for-byte Markdown
|
|
23
|
+
* serialization (§7). Those are split across sibling Wave-1 v0.2 tasks
|
|
24
|
+
* (task-035-bounded-context-relevance REQ-PERF-05, task-038-deprecated-excluded-from-context
|
|
25
|
+
* REQ-STATE-06) and v0.3 (`REQ-SYS-07`, `REQ-PERF-01`, `REQ-STATE-09`, the real `agent execute`
|
|
26
|
+
* CLI/MCP surface) — see this task's Execution Notes for the full scope decision. This module wraps
|
|
27
|
+
* only existing, already-shipped primitives: `loadDirectives`/`loadRolesYaml` (`./loaders`),
|
|
28
|
+
* `findMemoryDocumentByTypeAndId` and `isArchivedStatus` (`../memory`, task-011/task-035) — no
|
|
29
|
+
* scan/parse logic and no second status predicate is reimplemented here.
|
|
30
|
+
*/
|
|
31
|
+
const memory_1 = require("../memory");
|
|
32
|
+
const builtin_asset_1 = require("./builtin-asset");
|
|
33
|
+
/** `assignments` is a plain object parsed from YAML, so a role named `toString`, `constructor`,
|
|
34
|
+
* `valueOf`, `hasOwnProperty` or `__proto__` would otherwise resolve to an inherited
|
|
35
|
+
* `Object.prototype` member instead of `undefined`. Read own properties only. */
|
|
36
|
+
function ownAssignments(rolesYaml, role) {
|
|
37
|
+
return Object.prototype.hasOwnProperty.call(rolesYaml.assignments, role)
|
|
38
|
+
? rolesYaml.assignments[role]
|
|
39
|
+
: undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The single precedence rule between two directive files that share an id
|
|
43
|
+
* (`dl-037-builtin-vs-custom-directive-precedence` A.1, `spec-012` §5): negative when `a` wins.
|
|
44
|
+
*
|
|
45
|
+
* A `custom/` file beats any other — "custom" decided by REQ-SEC-07's structural discriminator
|
|
46
|
+
* {@link isRemovableCustomAssetPath}, which keys on the `custom` directory segment and accepts both
|
|
47
|
+
* path separators (`loadDirectives` builds `path` with the platform `join`). `frontmatter.kind` is not
|
|
48
|
+
* consulted: it can disagree with the directory, and the directory is what REQ-SEC-07 trusts. Within
|
|
49
|
+
* the same tier the lexicographically smallest `path` wins, so the order is total and independent of
|
|
50
|
+
* the order files arrive in (REQ-SYS-07).
|
|
51
|
+
*/
|
|
52
|
+
function compareDirectivePrecedence(a, b) {
|
|
53
|
+
const aCustom = (0, builtin_asset_1.isRemovableCustomAssetPath)('directive', a.path);
|
|
54
|
+
const bCustom = (0, builtin_asset_1.isRemovableCustomAssetPath)('directive', b.path);
|
|
55
|
+
if (aCustom !== bCustom)
|
|
56
|
+
return aCustom ? -1 : 1;
|
|
57
|
+
return a.path < b.path ? -1 : a.path > b.path ? 1 : 0;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Deduplicate `directiveFiles` by `frontmatter.id` — the one place WingFoil decides which of several
|
|
61
|
+
* same-id directive files is in force. Both {@link resolveRoleDirectives} (context assembly) and the
|
|
62
|
+
* `directives list` payload (`./directives-list.ts`, `dl-042-directives-list-output-contract` A) call
|
|
63
|
+
* this, so the rule the listing *reports* is the rule context assembly *applies*.
|
|
64
|
+
*
|
|
65
|
+
* - Precedence: `custom/` wins over `built-in/`, then smallest path (see `compareDirectivePrecedence`).
|
|
66
|
+
* - A shadowed file is **reported, never silently dropped** (dl-037 B.1): one warning per shadowed id,
|
|
67
|
+
* naming every file that defines it (in precedence-independent path order) and the winner.
|
|
68
|
+
* - `ids`, when given, restricts selection (and warnings) to those directive ids.
|
|
69
|
+
*/
|
|
70
|
+
function selectDirectivesById(directiveFiles, ids) {
|
|
71
|
+
const candidates = new Map();
|
|
72
|
+
for (const file of directiveFiles) {
|
|
73
|
+
const id = file.frontmatter.id;
|
|
74
|
+
if (ids !== undefined && !ids.has(id))
|
|
75
|
+
continue;
|
|
76
|
+
const list = candidates.get(id);
|
|
77
|
+
if (list === undefined)
|
|
78
|
+
candidates.set(id, [file]);
|
|
79
|
+
else
|
|
80
|
+
list.push(file);
|
|
81
|
+
}
|
|
82
|
+
const byId = new Map();
|
|
83
|
+
const warnings = [];
|
|
84
|
+
// Ascending by id (REQ-SYS-07): never `roles.yaml` listing order or file-system enumeration order.
|
|
85
|
+
// `candidates` is keyed by id, so no two keys are equal and a two-way compare is total here.
|
|
86
|
+
for (const [id, files] of [...candidates].sort(([a], [b]) => (a < b ? -1 : 1))) {
|
|
87
|
+
const [winner] = [...files].sort(compareDirectivePrecedence);
|
|
88
|
+
byId.set(id, winner);
|
|
89
|
+
if (files.length > 1) {
|
|
90
|
+
const paths = files.map((file) => file.path).sort();
|
|
91
|
+
warnings.push(`directive '${id}' defined in ${paths.join(', ')}; using ${winner.path}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { byId, warnings };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Resolve the directives bound to `role` — its own `roles.yaml` `assignments[role]` entries plus every
|
|
98
|
+
* `global` directive — per `spec-012-context-loader-relevance-filtering` §5 and
|
|
99
|
+
* `dl-029-role-with-no-directive-assignments` (`ready`, option (c)).
|
|
100
|
+
*
|
|
101
|
+
* Behaviour, point by point:
|
|
102
|
+
*
|
|
103
|
+
* - **Globals are unconditional** (spec-012 §5). Every role gets them, including a role with no
|
|
104
|
+
* bindings of its own — globals exist precisely so that no role can be configured out of
|
|
105
|
+
* `security-secrets` (dl-029, Rationale).
|
|
106
|
+
* - **A role that contributes no assignments of its own** — absent from `assignments`, or bound to an
|
|
107
|
+
* explicitly empty list — resolves to exactly the globals **and** produces the warning
|
|
108
|
+
* `no directives assigned to role '<role>'`. This is dl-029's ratified hybrid, and it is the
|
|
109
|
+
* behaviour the edge scenario of `p3-directives/P3.6-auto-load-by-role.feature` specifies
|
|
110
|
+
* ("the agent context contains only the global directives" + that warning). Never an error.
|
|
111
|
+
* Role-name lookup reads **own** properties only, so a role named after an `Object.prototype`
|
|
112
|
+
* member (`toString`, `constructor`, …) is treated as unbound like any other unknown role.
|
|
113
|
+
* - **Deduplicated by directive id, `custom/` winning over `built-in/`** (spec-012 §5, dl-037 A.1),
|
|
114
|
+
* through the shared {@link selectDirectivesById}; each shadowed id the role is bound to adds a
|
|
115
|
+
* warning naming the files and the winner (dl-037 B.1).
|
|
116
|
+
* - **A dangling binding is reported** — an id bound to the role (own assignment or global) with no
|
|
117
|
+
* file in `directiveFiles` adds `directive '<id>' bound to role '<role>' has no directive file`
|
|
118
|
+
* (`dl-042-directives-list-output-contract` D). It is still not an error: the rest resolves.
|
|
119
|
+
* - **Sorted ascending by directive id** (spec-012 §5: "never rely on `roles.yaml` listing order or
|
|
120
|
+
* file-system enumeration order", REQ-SYS-07).
|
|
121
|
+
* - `warnings` has a fixed order: the no-assignments warning, then dangling ids ascending, then
|
|
122
|
+
* shadowed ids ascending.
|
|
123
|
+
*
|
|
124
|
+
* This is REQ-STATE-05's Fit Criterion made concrete: for any two distinct roles with disjoint
|
|
125
|
+
* `assignments`, the resolved sets are disjoint too (100% of one role's directives, 0% of the other's).
|
|
126
|
+
*/
|
|
127
|
+
function resolveRoleDirectives(directiveFiles, rolesYaml, role) {
|
|
128
|
+
const assigned = ownAssignments(rolesYaml, role);
|
|
129
|
+
const warnings = assigned === undefined || assigned.length === 0
|
|
130
|
+
? [`no directives assigned to role '${role}'`]
|
|
131
|
+
: [];
|
|
132
|
+
const allowedIds = new Set([...(assigned ?? []), ...rolesYaml.global]);
|
|
133
|
+
const selection = selectDirectivesById(directiveFiles, allowedIds);
|
|
134
|
+
const dangling = [...allowedIds].filter((id) => !selection.byId.has(id)).sort();
|
|
135
|
+
for (const id of dangling)
|
|
136
|
+
warnings.push(`directive '${id}' bound to role '${role}' has no directive file`);
|
|
137
|
+
warnings.push(...selection.warnings);
|
|
138
|
+
return { directives: [...selection.byId.values()], warnings };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Assemble a role- and task-scoped {@link ExecutionContext} (REQ-STATE-05) from already-loaded pillar
|
|
142
|
+
* config. Given the same inputs and unchanged on-disk Memory content, the output is deep-equal across
|
|
143
|
+
* calls: the function itself introduces no wall-clock, randomness, or unordered iteration
|
|
144
|
+
* (REQ-SYS-07's discipline, applied to this narrower slice per REQ-STATE-05's own rationale "crisp,
|
|
145
|
+
* low-noise context; determinism"), and `directives` is totally ordered by
|
|
146
|
+
* {@link resolveRoleDirectives}.
|
|
147
|
+
*
|
|
148
|
+
* `memory` resolves `element` via `findMemoryDocumentByTypeAndId`
|
|
149
|
+
* (`task-011-mcp-resources-read-only`). Two properties of that primitive are inherited here and are
|
|
150
|
+
* worth stating plainly:
|
|
151
|
+
*
|
|
152
|
+
* - It is **not** a single addressed read. It walks the Memory document paths derived from
|
|
153
|
+
* `memoryYaml` in sorted order and YAML-parses each document's frontmatter until one matches
|
|
154
|
+
* `element.type`/`element.id`, so cost grows with the size of the Memory tree (bounding that is
|
|
155
|
+
* `task-035-bounded-context-relevance`'s REQ-PERF-05 scope, not this task's).
|
|
156
|
+
* - It therefore **can throw**. An `element` that matches nothing yields an empty `memory` array
|
|
157
|
+
* rather than an error — an unresolvable element is the caller's concern to surface — but a
|
|
158
|
+
* `ValidationError` (`E_YAML_PARSE_ERROR`) propagates out of assembly if any document visited
|
|
159
|
+
* during that walk has unparseable frontmatter. This function adds no `try`/`catch` of its own.
|
|
160
|
+
*
|
|
161
|
+
* `memory` **is** filtered by document status, in one direction only: a resolved element whose
|
|
162
|
+
* `status` is archived — `{deprecated, superseded}`, per the shared {@link isArchivedStatus}
|
|
163
|
+
* (`../memory`, the set ratified by `dl-028-archived-states-excluded-from-context`) — is dropped,
|
|
164
|
+
* leaving `memory` empty. That is REQ-STATE-06's Fit Criterion as amended: "a `deprecated` or
|
|
165
|
+
* `superseded` document never appears in an assembled agent context". The filter is applied to the
|
|
166
|
+
* lookup's *result* rather than pushed into `findMemoryDocumentByTypeAndId`, because that same
|
|
167
|
+
* primitive also serves `wingfoil://memory/{type}/{id}`, where explicit retrieval of archived content
|
|
168
|
+
* must keep working.
|
|
169
|
+
*
|
|
170
|
+
* `draft` is deliberately **not** excluded here, unlike in `./relevance.ts`. That module filters
|
|
171
|
+
* *candidate* documents for relevance (spec-012 §6, which does bar `draft` from a context); this
|
|
172
|
+
* function resolves the **subject** element the context is being assembled for (spec-012 §3's
|
|
173
|
+
* `resolve-element` stage), and blanking the context for a task still in `draft` would defeat the
|
|
174
|
+
* point of assembling it. dl-028 ratified the archived set as `{deprecated, superseded}` and did not
|
|
175
|
+
* put `draft` in it.
|
|
176
|
+
*
|
|
177
|
+
* An archived element produces no warning: {@link ExecutionContext.warnings} carries
|
|
178
|
+
* directive-resolution diagnostics only (dl-029, dl-037, dl-042), and adding an unratified entry would change a payload
|
|
179
|
+
* REQ-SYS-07 governs. An archived element is therefore indistinguishable here from an unresolvable
|
|
180
|
+
* one — both yield `memory: []`.
|
|
181
|
+
*/
|
|
182
|
+
function assembleExecutionContext(inputs) {
|
|
183
|
+
const { directives, warnings } = resolveRoleDirectives(inputs.directiveFiles, inputs.rolesYaml, inputs.role);
|
|
184
|
+
const doc = (0, memory_1.findMemoryDocumentByTypeAndId)(inputs.root, inputs.memoryYaml, inputs.element.type, inputs.element.id);
|
|
185
|
+
// `frontmatter` is untyped (`Record<string, unknown>`), so project `status` to the
|
|
186
|
+
// `string | undefined` shape `isArchivedStatus` takes — a non-string `status` is never archived,
|
|
187
|
+
// exactly as that predicate's contract states.
|
|
188
|
+
const status = typeof doc?.frontmatter.status === 'string' ? doc.frontmatter.status : undefined;
|
|
189
|
+
const memory = doc !== undefined && !(0, memory_1.isArchivedStatus)(status) ? [doc] : [];
|
|
190
|
+
return { dna: inputs.dna, directives, memory, warnings };
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { CoreError, CoreResult } from './types';
|
|
2
|
+
/** The outcome of {@link updateRoleAssignments}: the role's list as it stands afterwards. */
|
|
3
|
+
export interface RoleAssignmentUpdate {
|
|
4
|
+
/** `assignments.<role>` after the update (unchanged when nothing needed writing). */
|
|
5
|
+
readonly assignments: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Validate an assignment request before anything is written. The role is checked first (it is the
|
|
9
|
+
* binding's target and the REQ-SYS-08 check), then each id in argument order; the first failure wins.
|
|
10
|
+
*
|
|
11
|
+
* **The role catalogue is read from the `dna.yaml` committed at `HEAD`**, never from the working tree
|
|
12
|
+
* (task-091, `bug-082-directive-assign-validates-role-against-worktree`,
|
|
13
|
+
* `dl-080-which-baseline-each-command-reads` option (B)). This function therefore takes `root`, not a
|
|
14
|
+
* `DnaYaml`: a caller cannot hand it a working-tree catalogue even by accident, which is what makes
|
|
15
|
+
* the committed baseline a property of the read rather than of a precondition someone must remember
|
|
16
|
+
* to run. An uncommitted role used to be enough to commit a `roles.yaml` binding to a role no commit
|
|
17
|
+
* of the repository defines — a dangling reference by construction, since **REQ-SYS-08** binds
|
|
18
|
+
* directives by role and every other clone sees the binding without the role.
|
|
19
|
+
*
|
|
20
|
+
* The cost was measured and accepted at `dl-080`'s ratification: extending the catalogue becomes
|
|
21
|
+
* *edit, commit, then assign*. `dl-081`/`task-093` are building the `dna` verbs that fold the first
|
|
22
|
+
* two steps into one command; nothing here waits on them.
|
|
23
|
+
*
|
|
24
|
+
* Two fail-closed refusals come with the baseline, mirroring `requireApprovalAuthority`'s: no
|
|
25
|
+
* committed `dna.yaml` at all, and a committed one that does not parse or validate.
|
|
26
|
+
*
|
|
27
|
+
* **The directive inventory is read the same way**, since task-096 /
|
|
28
|
+
* `bug-086-directive-inventory-read-from-the-worktree` — `loadDirectivesAtHead`, the tree at `HEAD`.
|
|
29
|
+
* task-091 left this half on the files on disk and offered a boundary for it (the role catalogue is
|
|
30
|
+
* *governance*, the directive file is the *asset*); its reviewer showed the boundary does not hold,
|
|
31
|
+
* and `bug-086` settles that what actually separated them was **cost**: reading the inventory at a
|
|
32
|
+
* revision needs a directory listing at a revision, which `src/storage` did not have. It has one now
|
|
33
|
+
* (`listPathsAtRev`), so the parameter is gone too and the two halves of this one function read one
|
|
34
|
+
* baseline. Before that, an untracked directive file produced a committed `roles.yaml` binding to a
|
|
35
|
+
* directive present in no commit.
|
|
36
|
+
*
|
|
37
|
+
* An absent or empty committed inventory needs no special case: no id is known, so every request is
|
|
38
|
+
* refused with `unknown directive: <id>`. That is the right answer rather than a tolerated one — "may
|
|
39
|
+
* this id be bound" needs the *positive* fact that a directive with it exists, and a missing record
|
|
40
|
+
* cannot supply one. (Contrast {@link checkUnreferenced}, which needs the *absence* of a fact and is
|
|
41
|
+
* therefore satisfied by a missing record.)
|
|
42
|
+
*
|
|
43
|
+
* @param root - Project root; both committed baselines are read from it.
|
|
44
|
+
* @param role - The role to bind to.
|
|
45
|
+
* @param ids - The directive ids to bind.
|
|
46
|
+
* @returns `undefined` when assignable; otherwise an error carrying P3.2's exact message verbatim as
|
|
47
|
+
* its first sentence — `unknown role '<role>' (not defined in dna.yaml)` or
|
|
48
|
+
* `unknown directive: <id>` — or, for an absent/unreadable committed catalogue or an unreadable
|
|
49
|
+
* committed directive file, a `VALIDATION` refusal naming the baseline.
|
|
50
|
+
*/
|
|
51
|
+
export declare function checkAssignable(root: string, role: string, ids: readonly string[]): CoreError | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* REQ-SEC-07 clause (b) for the Directives surface — *"removal of a still-referenced custom asset is
|
|
54
|
+
* rejected naming the referrer"* — assigned to `task-052-directive-remove` by
|
|
55
|
+
* `dl-030-req-sec-07-referenced-asset-ownership` (`ready`, option (b)). The counterpart to
|
|
56
|
+
* {@link checkAssignable}: that one guards a binding being *made*, this one guards an asset being
|
|
57
|
+
* removed while a binding still names it. It lives here for the same reason, over the same
|
|
58
|
+
* `roles.yaml` shape.
|
|
59
|
+
*
|
|
60
|
+
* `roles.yaml` binds by directive **`frontmatter.id`** (`src/directives/schema.ts`'s `RolesYaml`), so
|
|
61
|
+
* the comparison is against the id, never the filename.
|
|
62
|
+
*
|
|
63
|
+
* Two referrer kinds, checked in this order:
|
|
64
|
+
*
|
|
65
|
+
* 1. A role whose own `assignments` entry names the id → P3.3's verbatim message
|
|
66
|
+
* `cannot remove '<id>': still assigned to role '<role>'`
|
|
67
|
+
* (`p3-directives/P3.3-directive-remove.feature`, "Error - removing a directive still referenced"
|
|
68
|
+
* — do not reword). When several roles bind it the **alphabetically first** is named: the message
|
|
69
|
+
* must be a pure function of the file's content, never of YAML mapping order (REQ-SYS-07), and
|
|
70
|
+
* `directives-list.ts` already walks role names in the same ascending order.
|
|
71
|
+
* 2. `roles.yaml`'s `global` list, which binds the directive to *every* role
|
|
72
|
+
* (`spec-012-context-loader-relevance-filtering` §5) and is therefore the strongest reference of
|
|
73
|
+
* all. `[AUTHORING]`: P3.3 pins only the per-role wording, and a global binding cannot be phrased
|
|
74
|
+
* in it without naming a role the file does not name — so the message is
|
|
75
|
+
* `cannot remove '<id>': still assigned to every role via roles.yaml 'global'`. Recorded in
|
|
76
|
+
* `task-052-directive-remove`'s Execution Notes and raised for ratification, not assumed settled.
|
|
77
|
+
*
|
|
78
|
+
* A directive referenced from a *workflow* step is deliberately not checked: `src/workflow/schema.ts`
|
|
79
|
+
* has no field that can reference a directive, so P3.3's "or workflow step" precondition is vacuous
|
|
80
|
+
* today, and P4.9's workflow half of clause (b) has no owner in v0.2 per `dl-030`.
|
|
81
|
+
*
|
|
82
|
+
* **The bindings are read from the `roles.yaml` committed at `HEAD`**, never from the working tree
|
|
83
|
+
* (task-096, `bug-086-directive-inventory-read-from-the-worktree`, `dl-080` option (B)). This
|
|
84
|
+
* function therefore takes `root`, not a `RolesYaml`: a caller cannot hand it a working-tree copy
|
|
85
|
+
* even by accident, which is what makes the committed baseline a property of the read. Before that,
|
|
86
|
+
* deleting the two `- <id>` lines **without committing** was enough to walk past this check entirely
|
|
87
|
+
* and **destroy** a file the committed `roles.yaml` still bound — on the only verb in the system that
|
|
88
|
+
* deletes an artefact, and against the one clause REQ-SEC-07 (b) exists to enforce.
|
|
89
|
+
*
|
|
90
|
+
* A `roles.yaml` that is **not committed at all** is still "no bindings yet" (task-051/task-053's
|
|
91
|
+
* reading) and permits the removal. That is not a fail-open tolerance: this check needs the *negative*
|
|
92
|
+
* fact *nothing names this id*, and a record that does not exist answers it. (Contrast
|
|
93
|
+
* {@link checkAssignable}, which needs a positive fact and therefore refuses when its record is
|
|
94
|
+
* missing.) A committed `roles.yaml` that does not **validate** is the genuinely unanswerable case,
|
|
95
|
+
* and it refuses.
|
|
96
|
+
*
|
|
97
|
+
* @param root - Project root; the committed `roles.yaml` is read from it (`loadRolesYamlAtHead`).
|
|
98
|
+
* @param id - The directive id about to be removed.
|
|
99
|
+
* @returns `undefined` when nothing references it; otherwise a `CONFLICT` error (exit 1) carrying the
|
|
100
|
+
* message above. `CONFLICT` and not `VALIDATION`: the request is well-formed and the *state*
|
|
101
|
+
* refuses it — the same distinction `directiveCreate` draws for `directive already exists: <name>`,
|
|
102
|
+
* as against `requireCustomAsset`'s `VALIDATION` for a request inadmissible on its own terms. An
|
|
103
|
+
* unreadable committed `roles.yaml` is `VALIDATION`, naming the baseline.
|
|
104
|
+
*/
|
|
105
|
+
export declare function checkUnreferenced(root: string, id: string): CoreError | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* Apply `update` to `assignments.<role>` in `.wingfoil/roles.yaml` and commit the result as ONE commit
|
|
108
|
+
* staging only that file.
|
|
109
|
+
*
|
|
110
|
+
* - A missing `roles.yaml` means "no bindings yet" (task-053's reading) and is created with a
|
|
111
|
+
* deterministic `dump` — there is nothing to preserve.
|
|
112
|
+
* - An unchanged list is an idempotent success: nothing is written and no commit is made.
|
|
113
|
+
* - The edit goes through `setRoleAssignmentsInText`, keeping every comment and unrelated line. When it
|
|
114
|
+
* cannot apply, a whole-file `dump` is used only if the file contains no `#` at all; otherwise the
|
|
115
|
+
* result is `CONFLICT` and the file is left untouched.
|
|
116
|
+
* - No second schema pass on the output is needed: the in-place edit is only accepted when its
|
|
117
|
+
* re-parse equals the validated input with `assignments.<role>` replaced by a string list
|
|
118
|
+
* (`setRoleAssignmentsInText`'s self-check), and the whole-file `dump` serializes exactly that object.
|
|
119
|
+
*
|
|
120
|
+
* Commits through `commitPaths`, which since bug-027's fix (`git commit --only -- <paths>`) records
|
|
121
|
+
* exactly the path it is given and leaves anything else staged untouched.
|
|
122
|
+
*
|
|
123
|
+
* @param root - Project root.
|
|
124
|
+
* @param role - The role whose list is updated (already validated by the caller).
|
|
125
|
+
* @param update - Pure function from the current list to the desired list.
|
|
126
|
+
* @param message - The commit subject.
|
|
127
|
+
* @returns The role's resulting list, with the commit when one was made.
|
|
128
|
+
* @throws whatever `git` raises inside `commitPaths`.
|
|
129
|
+
*/
|
|
130
|
+
export declare function updateRoleAssignments(root: string, role: string, update: (current: readonly string[]) => readonly string[], message: string): CoreResult<RoleAssignmentUpdate>;
|
|
131
|
+
//# sourceMappingURL=directive-assign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directive-assign.d.ts","sourceRoot":"","sources":["../../src/core/directive-assign.ts"],"names":[],"mappings":"AA2EA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAIrD,6FAA6F;AAC7F,MAAM,WAAW,oBAAoB;IACnC,qFAAqF;IACrF,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,SAAS,CAkDzG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CA8BjF;AAqBD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,KAAK,SAAS,MAAM,EAAE,EACzD,OAAO,EAAE,MAAM,GACd,UAAU,CAAC,oBAAoB,CAAC,CA6ClC"}
|