@aacombarro89/praxis 0.1.7 → 0.1.9

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 (48) hide show
  1. package/README.md +34 -20
  2. package/dist/codex-marketplace.d.ts +19 -0
  3. package/dist/codex-marketplace.js +113 -0
  4. package/dist/codex-marketplace.js.map +1 -0
  5. package/dist/codex-security.d.ts +11 -0
  6. package/dist/codex-security.js +144 -0
  7. package/dist/codex-security.js.map +1 -0
  8. package/dist/emit.d.ts +38 -2
  9. package/dist/emit.js +167 -13
  10. package/dist/emit.js.map +1 -1
  11. package/dist/init.d.ts +16 -6
  12. package/dist/init.js +47 -10
  13. package/dist/init.js.map +1 -1
  14. package/dist/manifest.d.ts +2 -2
  15. package/dist/manifest.js +1 -1
  16. package/dist/manifest.js.map +1 -1
  17. package/dist/packages.d.ts +1 -1
  18. package/dist/plugins.d.ts +14 -0
  19. package/dist/plugins.js +9 -0
  20. package/dist/plugins.js.map +1 -1
  21. package/dist/program.d.ts +8 -0
  22. package/dist/program.js +93 -30
  23. package/dist/program.js.map +1 -1
  24. package/dist/shared-instructions.d.ts +21 -0
  25. package/dist/shared-instructions.js +63 -0
  26. package/dist/shared-instructions.js.map +1 -0
  27. package/dist/sync.d.ts +8 -1
  28. package/dist/sync.js +210 -7
  29. package/dist/sync.js.map +1 -1
  30. package/package.json +1 -1
  31. package/packages/external/ponytail/plugins.yaml +4 -1
  32. package/packages/layer1/instruction-upkeep/commands/instructions.md +14 -5
  33. package/packages/layer1/instruction-upkeep/rules.md +11 -23
  34. package/packages/layer1/onboarding/commands/onboard.md +42 -24
  35. package/packages/layer1/onboarding/rules.md +6 -10
  36. package/packages/layer1/safe-permissions/permissions.yaml +2 -2
  37. package/packages/layer1/session-handoff/commands/handoff.md +5 -5
  38. package/packages/layer1/session-handoff/rules.md +10 -57
  39. package/packages/layer1/upkeep/commands/upkeep.md +8 -5
  40. package/packages/layer1/upkeep/rules.md +12 -15
  41. package/packages/layer1/wiki-memory/commands/wiki.md +6 -6
  42. package/packages/layer1/wiki-memory/rules.md +11 -49
  43. package/packages/layer2/node-recipes/rules.md +4 -3
  44. package/packages/layer2/node-testing/rules.md +4 -0
  45. package/packages/layer2/python-backend-recipes/rules.md +4 -4
  46. package/packages/layer2/python-testing/rules.md +4 -0
  47. package/packages/layer2/react-components/rules.md +4 -0
  48. package/packages/layer2/react-testing/rules.md +4 -0
package/README.md CHANGED
@@ -4,10 +4,11 @@
4
4
  meta-development rules and authoring recipes that make AI coding agents produce
5
5
  correct, conformant work.
6
6
 
7
- Praxis is **not** implementation scaffolding and **not** a config-file
8
- generator. It writes _only_ the methodology layer — agent-instruction files,
9
- skills, slash commands, and its own manifest. It never touches your application
10
- code, dependencies, or runtime infrastructure.
7
+ Praxis is **not** implementation scaffolding and **not** an application config
8
+ generator. It writes _only_ the methodology layer — agent instructions,
9
+ native workflows, methodology permissions and plugin metadata, and its own
10
+ manifest. It never touches your application code, dependencies, or runtime
11
+ infrastructure.
11
12
 
12
13
  ```bash
13
14
  npx @aacombarro89/praxis
@@ -22,20 +23,30 @@ Running `praxis` in a project:
22
23
  a `react` dependency → both `node` and `react`.
23
24
  2. **Offers a first-run fork** — _Quick start_ (recommended defaults, preview
24
25
  the diff, confirm) or _Customize_ (choose stacks, packages, and targets).
25
- 3. **Composes the methodology into your repo** — it merges managed blocks into
26
- files like `CLAUDE.md` without clobbering your own content, and records what
26
+ 3. **Composes the methodology into your repo** — it emits Claude Code rules,
27
+ Codex skills, and managed `AGENTS.md` blocks without clobbering your own content, and records what
27
28
  it did in a visible, committed, hand-editable manifest: `praxis.yaml`.
28
29
 
29
30
  It always previews a single diff before writing. Git is your undo.
30
31
 
31
32
  ## Why it's different
32
33
 
33
- Compared to `/init`-style tools, Praxis adds two things they lack:
34
+ Other tools _generate_ agent instructions once; Praxis **manages** them:
34
35
 
35
- - **A curated, opinionated methodology** Layer 1 behavioral rules plus Layer 2
36
- stack recipes, shipped as composable **packages**.
36
+ - **Versioned, pinned, drift-checked.** Methodology ships as composable
37
+ packages pinned in `praxis.yaml`, and `praxis check` fails CI when the
38
+ installed files drift — think Renovate/Dependabot, for your agent
39
+ instruction layer.
40
+ - **Peer-native project facts.** When Claude Code and Codex coexist, project-owned
41
+ shared sections live in both native instruction files. `praxis check` verifies
42
+ parity and upkeep fixes factual drift; neither tool depends on Praxis at runtime.
37
43
  - **A composition / merge step** that folds methodology into an _existing_
38
44
  project without overwriting project-specific content.
45
+ - **One neutral source, per-tool outputs** — first-class Claude Code and OpenAI
46
+ Codex support, plus a generic `AGENTS.md` target.
47
+
48
+ The curated methodology — Layer 1 behavioral rules plus Layer 2 stack recipes
49
+ — is the starting payload that rides this machinery.
39
50
 
40
51
  ## The two layers
41
52
 
@@ -60,7 +71,7 @@ sync`**. There is no `add`/`remove` — one obvious way to change things.
60
71
  version: 1
61
72
  methodology: "0.1.0" # pinned; `sync` offers to bump
62
73
  stacks: [node, react] # detection-seeded, user-editable
63
- targets: [claude-code, agents-md] # which agent files to emit
74
+ targets: [claude-code, codex] # which agent tools to support
64
75
  packages:
65
76
  - karpathy-claude # behavioral rules (Layer 1)
66
77
  - wiki-memory # the knowledge-wiki command (Layer 1)
@@ -79,24 +90,26 @@ pinned version — never behind your back.
79
90
  | `praxis sync` | Reconcile the repo to `praxis.yaml`; offer newer methodology; diff + confirm. |
80
91
  | `praxis check` | Dry-run; report drift; non-zero exit for CI. |
81
92
 
82
- `--yes` skips prompts (takes the Quick-start path) for non-interactive/CI use.
93
+ `--yes` skips prompts for non-interactive/CI use. Repeat `--target`, for example
94
+ `praxis --yes --target codex --target agents-md`, to override target detection.
83
95
 
84
96
  ## Tool-neutral by construction
85
97
 
86
98
  The methodology source is singular; Praxis _emits_ per-tool variants from it.
87
- **Claude Code** (`.claude/rules/`, skills, commands, `settings.json`) and the
88
- **`agents-md`** flat-file convention (`AGENTS.md`) are built today. Cursor is a
99
+ **Claude Code** (`.claude/rules/`, commands, `settings.json`), **OpenAI Codex**
100
+ (`AGENTS.md`, `.agents/skills/`, permission profiles/rules, plugin marketplace), and the
101
+ generic **`agents-md`** flat-file convention are built today. Cursor is a
89
102
  planned target; Copilot/Windsurf/Roo are deferred until they land.
90
103
 
91
104
  ## "Memory" means the agent's memory, not the app's
92
105
 
93
106
  In Praxis, _memory_ always refers to the **AI coding tool's** curated,
94
- file-based instruction layer (`CLAUDE.md`, the knowledge wiki, skills, decision
95
- notes) — not a runtime memory backend for your application (Mem0, Zep, Letta,
96
- etc.). Wiring a persistence backend into your app is implementation, and out of
97
- scope. The most Praxis ships on that topic is a Layer 2 _decision recipe_:
98
- guidance on whether you need runtime memory and how to choose — never the
99
- backend itself.
107
+ file-based instruction layer (`CLAUDE.md` or `AGENTS.md`, the knowledge wiki,
108
+ skills, decision notes) — not a runtime memory backend for your application
109
+ (Mem0, Zep, Letta, etc.). Wiring a persistence backend into your app is
110
+ implementation, and out of scope. The most Praxis ships on that topic is a
111
+ Layer 2 _decision recipe_: guidance on whether you need runtime memory and how
112
+ to choose — never the backend itself.
100
113
 
101
114
  ## Developing Praxis
102
115
 
@@ -123,4 +136,5 @@ lands on a feature branch and merges via PR — no direct pushes to `main`.
123
136
  - `docs/wiki/` — the durable, in-repo knowledge wiki and canonical design doc;
124
137
  start at [`docs/wiki/index.md`](docs/wiki/index.md).
125
138
 
126
- See [`CLAUDE.md`](CLAUDE.md) for the project's non-negotiable rails.
139
+ See the peer-native [`CLAUDE.md`](CLAUDE.md) and [`AGENTS.md`](AGENTS.md) for
140
+ the project's non-negotiable rails.
@@ -0,0 +1,19 @@
1
+ export declare const CODEX_MARKETPLACE_PATH = ".agents/plugins/marketplace.json";
2
+ export declare const CODEX_MARKETPLACE_STATE_PATH = ".praxis/codex-marketplace-state.json";
3
+ export interface CodexPluginEntry {
4
+ name: string;
5
+ source: Record<string, string>;
6
+ policy: {
7
+ installation: string;
8
+ authentication: string;
9
+ };
10
+ category: string;
11
+ }
12
+ export interface MarketplaceReconcileResult {
13
+ marketplaceText: string;
14
+ stateText: string;
15
+ marketplaceChanged: boolean;
16
+ stateChanged: boolean;
17
+ conflicts: string[];
18
+ }
19
+ export declare function reconcileCodexMarketplace(marketplaceText: string, stateText: string, desired: CodexPluginEntry[]): MarketplaceReconcileResult;
@@ -0,0 +1,113 @@
1
+ import { createHash } from "node:crypto";
2
+ export const CODEX_MARKETPLACE_PATH = ".agents/plugins/marketplace.json";
3
+ export const CODEX_MARKETPLACE_STATE_PATH = ".praxis/codex-marketplace-state.json";
4
+ /** Deeply sorts object keys so hashing is insensitive to cosmetic key
5
+ * reordering (e.g. a formatter running `jq -S` over marketplace.json). */
6
+ function canonicalize(value) {
7
+ if (Array.isArray(value))
8
+ return value.map(canonicalize);
9
+ if (value && typeof value === "object") {
10
+ const sorted = {};
11
+ for (const key of Object.keys(value).sort()) {
12
+ sorted[key] = canonicalize(value[key]);
13
+ }
14
+ return sorted;
15
+ }
16
+ return value;
17
+ }
18
+ function hashEntry(entry) {
19
+ return createHash("sha256").update(JSON.stringify(canonicalize(entry))).digest("hex");
20
+ }
21
+ function parseJson(text, label) {
22
+ if (!text.trim())
23
+ return {};
24
+ const parsed = JSON.parse(text);
25
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
26
+ throw new Error(`${label} must contain a JSON object.`);
27
+ }
28
+ return parsed;
29
+ }
30
+ function parseState(text) {
31
+ if (!text.trim())
32
+ return { version: 1, entries: {} };
33
+ const parsed = parseJson(text, CODEX_MARKETPLACE_STATE_PATH);
34
+ if (parsed.version !== 1 || !parsed.entries || typeof parsed.entries !== "object" || Array.isArray(parsed.entries)) {
35
+ throw new Error(`${CODEX_MARKETPLACE_STATE_PATH} has an unsupported ownership-state shape.`);
36
+ }
37
+ const entries = {};
38
+ for (const [name, value] of Object.entries(parsed.entries)) {
39
+ if (typeof value !== "string")
40
+ throw new Error(`${CODEX_MARKETPLACE_STATE_PATH} has a non-string hash for ${name}.`);
41
+ entries[name] = value;
42
+ }
43
+ return { version: 1, entries };
44
+ }
45
+ function render(value) {
46
+ return `${JSON.stringify(value, null, 2)}\n`;
47
+ }
48
+ export function reconcileCodexMarketplace(marketplaceText, stateText, desired) {
49
+ const root = parseJson(marketplaceText, CODEX_MARKETPLACE_PATH);
50
+ const state = parseState(stateText);
51
+ const rawPlugins = root.plugins ?? [];
52
+ if (!Array.isArray(rawPlugins))
53
+ throw new Error(`${CODEX_MARKETPLACE_PATH} field "plugins" must be an array.`);
54
+ const plugins = [...rawPlugins];
55
+ const conflicts = [];
56
+ const desiredByName = new Map(desired.map((entry) => [entry.name, entry]));
57
+ const nextHashes = {};
58
+ const findIndex = (name) => plugins.findIndex((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && entry.name === name));
59
+ for (const [name, recordedHash] of Object.entries(state.entries)) {
60
+ const index = findIndex(name);
61
+ const wanted = desiredByName.get(name);
62
+ if (index === -1)
63
+ continue;
64
+ if (hashEntry(plugins[index]) !== recordedHash) {
65
+ conflicts.push(name);
66
+ nextHashes[name] = recordedHash;
67
+ desiredByName.delete(name);
68
+ continue;
69
+ }
70
+ if (!wanted) {
71
+ plugins.splice(index, 1);
72
+ }
73
+ }
74
+ for (const entry of desired) {
75
+ if (!desiredByName.has(entry.name))
76
+ continue;
77
+ const index = findIndex(entry.name);
78
+ const desiredHash = hashEntry(entry);
79
+ if (index === -1) {
80
+ plugins.push(entry);
81
+ nextHashes[entry.name] = desiredHash;
82
+ continue;
83
+ }
84
+ const recordedHash = state.entries[entry.name];
85
+ if (recordedHash || hashEntry(plugins[index]) === desiredHash) {
86
+ plugins[index] = entry;
87
+ nextHashes[entry.name] = desiredHash;
88
+ }
89
+ else {
90
+ conflicts.push(entry.name);
91
+ }
92
+ }
93
+ for (const [name, recordedHash] of Object.entries(state.entries)) {
94
+ if (conflicts.includes(name))
95
+ nextHashes[name] = recordedHash;
96
+ }
97
+ if (!("name" in root))
98
+ root.name = "praxis";
99
+ if (!("interface" in root))
100
+ root.interface = { displayName: "Praxis" };
101
+ root.plugins = plugins;
102
+ const nextState = { version: 1, entries: nextHashes };
103
+ const nextMarketplaceText = render(root);
104
+ const nextStateText = render(nextState);
105
+ return {
106
+ marketplaceText: nextMarketplaceText,
107
+ stateText: nextStateText,
108
+ marketplaceChanged: nextMarketplaceText !== marketplaceText,
109
+ stateChanged: nextStateText !== stateText,
110
+ conflicts,
111
+ };
112
+ }
113
+ //# sourceMappingURL=codex-marketplace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-marketplace.js","sourceRoot":"","sources":["../src/codex-marketplace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Capability, Policy } from "./permissions.js";
2
+ export declare const CODEX_CONFIG_BODY = "default_permissions = \"praxis-safe-permissions\"\n\n[permissions.praxis-safe-permissions]\ndescription = \"Workspace editing with Praxis secret-file protections and no sandbox network access.\"\nextends = \":workspace\"\n\n[permissions.praxis-safe-permissions.filesystem]\nglob_scan_max_depth = 12\n\n[permissions.praxis-safe-permissions.filesystem.\":workspace_roots\"]\n\".env\" = \"deny\"\n\"**/.env*\" = \"deny\"\n\"**/*.pem\" = \"deny\"\n\"**/credentials*\" = \"deny\"\n\n[permissions.praxis-safe-permissions.network]\nenabled = false";
3
+ export declare function reconcileCodexConfig(existing: string, enabled: boolean): {
4
+ text: string;
5
+ changed: boolean;
6
+ conflicts: string[];
7
+ };
8
+ /** Every neutral capability is handled by command rules or explicitly delegated
9
+ * to the permission profile. Exported as the Codex conformance seam. */
10
+ export declare function codexCapabilityMode(capability: Capability): "profile" | "rules" | undefined;
11
+ export declare function renderCodexRules(policy: Policy): string;
@@ -0,0 +1,144 @@
1
+ import { createHash } from "node:crypto";
2
+ const BLOCK_ID = "safe-permissions";
3
+ const BEGIN = /^# praxis:begin safe-permissions sha256=([a-f0-9]{64})$/m;
4
+ const END = /^# praxis:end safe-permissions$/m;
5
+ function hash(text) {
6
+ return createHash("sha256").update(text).digest("hex");
7
+ }
8
+ export const CODEX_CONFIG_BODY = `default_permissions = "praxis-safe-permissions"
9
+
10
+ [permissions.praxis-safe-permissions]
11
+ description = "Workspace editing with Praxis secret-file protections and no sandbox network access."
12
+ extends = ":workspace"
13
+
14
+ [permissions.praxis-safe-permissions.filesystem]
15
+ glob_scan_max_depth = 12
16
+
17
+ [permissions.praxis-safe-permissions.filesystem.":workspace_roots"]
18
+ ".env" = "deny"
19
+ "**/.env*" = "deny"
20
+ "**/*.pem" = "deny"
21
+ "**/credentials*" = "deny"
22
+
23
+ [permissions.praxis-safe-permissions.network]
24
+ enabled = false`;
25
+ function managedBlock(body) {
26
+ return `# praxis:begin ${BLOCK_ID} sha256=${hash(body)}\n${body}\n# praxis:end ${BLOCK_ID}`;
27
+ }
28
+ function locate(text) {
29
+ const begin = BEGIN.exec(text);
30
+ if (!begin || begin.index === undefined)
31
+ return undefined;
32
+ END.lastIndex = 0;
33
+ const afterBegin = begin.index + begin[0].length;
34
+ const end = END.exec(text.slice(afterBegin));
35
+ if (!end || end.index === undefined)
36
+ return undefined;
37
+ const bodyStart = afterBegin + 1;
38
+ const endStart = afterBegin + end.index;
39
+ return {
40
+ start: begin.index,
41
+ end: endStart + end[0].length,
42
+ body: text.slice(bodyStart, endStart).replace(/\n$/, ""),
43
+ recordedHash: begin[1],
44
+ };
45
+ }
46
+ function withoutBlock(text, block) {
47
+ if (!block)
48
+ return text;
49
+ return `${text.slice(0, block.start)}${text.slice(block.end)}`;
50
+ }
51
+ function externalConflicts(text) {
52
+ const conflicts = [];
53
+ if (/^\s*default_permissions\s*=/m.test(text))
54
+ conflicts.push("default_permissions");
55
+ if (/^\s*sandbox_mode\s*=/m.test(text))
56
+ conflicts.push("sandbox_mode");
57
+ if (/^\s*\[sandbox_workspace_write\]/m.test(text))
58
+ conflicts.push("sandbox_workspace_write");
59
+ if (/^\s*\[permissions\.praxis-safe-permissions(?:\.|\])/m.test(text)) {
60
+ conflicts.push("permissions.praxis-safe-permissions");
61
+ }
62
+ return conflicts;
63
+ }
64
+ export function reconcileCodexConfig(existing, enabled) {
65
+ const block = locate(existing);
66
+ if (block && hash(block.body) !== block.recordedHash) {
67
+ return { text: existing, changed: false, conflicts: [BLOCK_ID] };
68
+ }
69
+ const outside = withoutBlock(existing, block);
70
+ if (enabled) {
71
+ const conflicts = externalConflicts(outside);
72
+ if (conflicts.length > 0)
73
+ return { text: existing, changed: false, conflicts };
74
+ const rest = outside.trim();
75
+ // Inserted first, not appended: a bare `key = value` line in TOML belongs
76
+ // to whatever `[table]` precedes it, so placing our block after user
77
+ // content risks default_permissions being silently absorbed into a table
78
+ // the user's file happens to end inside. Leading in the file guarantees
79
+ // root-table scope regardless of what follows.
80
+ const text = `${managedBlock(CODEX_CONFIG_BODY)}\n${rest ? `\n${rest}\n` : ""}`;
81
+ return { text, changed: text !== existing, conflicts: [] };
82
+ }
83
+ if (!block)
84
+ return { text: existing, changed: false, conflicts: [] };
85
+ const rest = outside.trim();
86
+ const text = rest ? `${rest}\n` : "";
87
+ return { text, changed: text !== existing, conflicts: [] };
88
+ }
89
+ const COMMAND_PATTERNS = {
90
+ "run-dev-scripts": [
91
+ ["npm", "run", "test"],
92
+ ["npm", "run", "lint"],
93
+ ["npm", "run", "typecheck"],
94
+ ["npm", "run", "build"],
95
+ ],
96
+ "read-only-git": [["git", "status"], ["git", "diff"], ["git", "log"]],
97
+ "git-commit": [["git", "commit"]],
98
+ "git-push": [["git", "push"]],
99
+ "install-deps": [["npm", "install"], ["npm", "i"], ["npm", "ci"]],
100
+ "destructive-delete": [["rm", "-rf"]],
101
+ "force-push": [["git", "push", "--force"], ["git", "push", "-f"]],
102
+ "global-install": [
103
+ ["npm", "install", "-g"],
104
+ ["npm", "install", "--global"],
105
+ ["npm", "i", "-g"],
106
+ ["npm", "i", "--global"],
107
+ ["pnpm", "add", "-g"],
108
+ ["pnpm", "add", "--global"],
109
+ ],
110
+ };
111
+ const PROFILE_CAPABILITIES = new Set(["read-repo", "edit-repo", "read-secrets"]);
112
+ /** Every neutral capability is handled by command rules or explicitly delegated
113
+ * to the permission profile. Exported as the Codex conformance seam. */
114
+ export function codexCapabilityMode(capability) {
115
+ if (PROFILE_CAPABILITIES.has(capability))
116
+ return "profile";
117
+ if (COMMAND_PATTERNS[capability])
118
+ return "rules";
119
+ return undefined;
120
+ }
121
+ function starlarkString(value) {
122
+ return JSON.stringify(value);
123
+ }
124
+ export function renderCodexRules(policy) {
125
+ const decisions = [
126
+ ["allow", "allow"],
127
+ ["ask", "prompt"],
128
+ ["deny", "forbidden"],
129
+ ];
130
+ const lines = [
131
+ "# Generated by Praxis. Project rules load only after this repository is trusted.",
132
+ "# Filesystem capabilities are enforced by the praxis-safe-permissions profile in ../config.toml.",
133
+ "",
134
+ ];
135
+ for (const [bucket, decision] of decisions) {
136
+ for (const capability of policy[bucket]) {
137
+ for (const pattern of COMMAND_PATTERNS[capability] ?? []) {
138
+ lines.push(`prefix_rule(pattern = [${pattern.map(starlarkString).join(", ")}], decision = ${starlarkString(decision)}, justification = ${starlarkString(`Praxis capability: ${capability}`)})`);
139
+ }
140
+ }
141
+ }
142
+ return `${lines.join("\n").trimEnd()}\n`;
143
+ }
144
+ //# sourceMappingURL=codex-security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-security.js","sourceRoot":"","sources":["../src/codex-security.ts"],"names":[],"mappings":"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"}
package/dist/emit.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import type { Manifest, Target } from "./manifest.js";
2
2
  import { type PluginsDesired, type RuleSet } from "./merge-json.js";
3
+ import { CODEX_MARKETPLACE_PATH, CODEX_MARKETPLACE_STATE_PATH, type CodexPluginEntry } from "./codex-marketplace.js";
4
+ export declare const BLOCK_FILE: Partial<Record<Target, string>>;
3
5
  /** The neutral methodology source for a content package, or undefined if the
4
6
  * package has no rules.md (e.g. skills, Layer 2 recipes handled by other phases). */
5
7
  export declare function loadPackageSource(pkg: string): string | undefined;
6
- /** A package's slash commands: one file per command, named for the command it
7
- * becomes (the filename, sans extension, is what the user types after `/`). */
8
+ /** A package's workflow sources: one file per workflow, named for its target-native invocation. */
8
9
  export interface CommandSource {
9
10
  name: string;
10
11
  content: string;
@@ -33,10 +34,45 @@ export type EmitOp = {
33
34
  path: string;
34
35
  rules?: RuleSet;
35
36
  plugins?: PluginsDesired;
37
+ } | {
38
+ kind: "codex-config";
39
+ target: "codex";
40
+ path: ".codex/config.toml";
41
+ enabled: boolean;
42
+ } | {
43
+ kind: "codex-marketplace";
44
+ target: "codex";
45
+ path: typeof CODEX_MARKETPLACE_PATH;
46
+ statePath: typeof CODEX_MARKETPLACE_STATE_PATH;
47
+ plugins: CodexPluginEntry[];
36
48
  };
37
49
  /** Build the emit plan from a manifest: the file operations needed to install
38
50
  * the selected methodology for each target. */
39
51
  export declare function planEmit(manifest: Manifest): EmitOp[];
52
+ export interface MethodologySize {
53
+ /** Total content lines across the counted rule artifacts. */
54
+ totalLines: number;
55
+ /** Number of always-loaded rule artifacts counted. */
56
+ fileCount: number;
57
+ }
58
+ /**
59
+ * The always-loaded methodology surface size: total lines and file count for
60
+ * the rule artifacts (`provides: rules`) a session loads at start. Computed
61
+ * from the **planned emit** (manifest → resolve → planEmit), not from files on
62
+ * disk, so it reports what the manifest implies — the same discipline `check`
63
+ * already uses for drift.
64
+ *
65
+ * Counts the claude-code target's owned `.claude/rules/*` files (one per rules
66
+ * package). If claude-code isn't a manifest target, falls back to the
67
+ * Codex/agents-md managed block content, one artifact per block, so the targets'
68
+ * shared source is never double-counted. Commands, permissions/plugins JSON,
69
+ * and the wiki are never counted — none are loaded at session start.
70
+ *
71
+ * Throws if the manifest can't resolve (propagates planEmit's error, e.g. an
72
+ * unknown package) — callers in check mode should catch and omit the line
73
+ * rather than let it mask the sync error (D40's degrade-by-omission model).
74
+ */
75
+ export declare function computeMethodologySize(manifest: Manifest): MethodologySize;
40
76
  export interface ApplyResult {
41
77
  text: string;
42
78
  changed: boolean;