@kitsy/coop-core 1.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +249 -53
- package/dist/index.d.cts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +232 -52
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -72,6 +72,11 @@ __export(index_exports, {
|
|
|
72
72
|
compute_readiness_with_corrections: () => compute_readiness_with_corrections,
|
|
73
73
|
compute_score: () => compute_score,
|
|
74
74
|
compute_velocity: () => compute_velocity,
|
|
75
|
+
coop_project_config_path: () => coop_project_config_path,
|
|
76
|
+
coop_project_root: () => coop_project_root,
|
|
77
|
+
coop_projects_dir: () => coop_projects_dir,
|
|
78
|
+
coop_workspace_config_path: () => coop_workspace_config_path,
|
|
79
|
+
coop_workspace_dir: () => coop_workspace_dir,
|
|
75
80
|
createItem: () => createItem,
|
|
76
81
|
create_seeded_rng: () => create_seeded_rng,
|
|
77
82
|
critical_path_weight: () => critical_path_weight,
|
|
@@ -83,6 +88,7 @@ __export(index_exports, {
|
|
|
83
88
|
effective_weekly_hours: () => effective_weekly_hours,
|
|
84
89
|
effort_or_default: () => effort_or_default,
|
|
85
90
|
ensureCoopLayout: () => ensureCoopLayout,
|
|
91
|
+
ensure_workspace_layout: () => ensure_workspace_layout,
|
|
86
92
|
executor_fit_weight: () => executor_fit_weight,
|
|
87
93
|
external_dependencies_for_task: () => external_dependencies_for_task,
|
|
88
94
|
extract_subgraph: () => extract_subgraph,
|
|
@@ -91,7 +97,11 @@ __export(index_exports, {
|
|
|
91
97
|
getItemById: () => getItemById,
|
|
92
98
|
get_remaining_tokens: () => get_remaining_tokens,
|
|
93
99
|
get_user_role: () => get_user_role,
|
|
100
|
+
has_legacy_project_layout: () => has_legacy_project_layout,
|
|
101
|
+
has_v2_projects_layout: () => has_v2_projects_layout,
|
|
94
102
|
is_external_dependency: () => is_external_dependency,
|
|
103
|
+
is_project_initialized: () => is_project_initialized,
|
|
104
|
+
list_projects: () => list_projects,
|
|
95
105
|
loadState: () => loadState,
|
|
96
106
|
load_auth_config: () => load_auth_config,
|
|
97
107
|
load_completed_runs: () => load_completed_runs,
|
|
@@ -116,9 +126,14 @@ __export(index_exports, {
|
|
|
116
126
|
pert_stddev: () => pert_stddev,
|
|
117
127
|
priority_weight: () => priority_weight,
|
|
118
128
|
queryItems: () => queryItems,
|
|
129
|
+
read_project_config: () => read_project_config,
|
|
119
130
|
read_schema_version: () => read_schema_version,
|
|
131
|
+
read_workspace_config: () => read_workspace_config,
|
|
120
132
|
renderAgentPrompt: () => renderAgentPrompt,
|
|
133
|
+
repo_default_project_id: () => repo_default_project_id,
|
|
134
|
+
repo_default_project_name: () => repo_default_project_name,
|
|
121
135
|
resolve_external_dependencies: () => resolve_external_dependencies,
|
|
136
|
+
resolve_project: () => resolve_project,
|
|
122
137
|
risk_penalty: () => risk_penalty,
|
|
123
138
|
run_hook: () => run_hook,
|
|
124
139
|
run_monte_carlo_chunk: () => run_monte_carlo_chunk,
|
|
@@ -147,7 +162,8 @@ __export(index_exports, {
|
|
|
147
162
|
validate_transition: () => validate_transition,
|
|
148
163
|
writeTask: () => writeTask,
|
|
149
164
|
writeYamlFile: () => writeYamlFile,
|
|
150
|
-
write_schema_version: () => write_schema_version
|
|
165
|
+
write_schema_version: () => write_schema_version,
|
|
166
|
+
write_workspace_config: () => write_workspace_config
|
|
151
167
|
});
|
|
152
168
|
module.exports = __toCommonJS(index_exports);
|
|
153
169
|
|
|
@@ -2160,6 +2176,9 @@ var TASK_FIELD_ORDER = [
|
|
|
2160
2176
|
"depends_on",
|
|
2161
2177
|
"tags",
|
|
2162
2178
|
"delivery",
|
|
2179
|
+
"acceptance",
|
|
2180
|
+
"tests_required",
|
|
2181
|
+
"origin",
|
|
2163
2182
|
"complexity",
|
|
2164
2183
|
"determinism",
|
|
2165
2184
|
"estimate",
|
|
@@ -4694,6 +4713,7 @@ var import_node_path8 = __toESM(require("path"), 1);
|
|
|
4694
4713
|
var ID_PATTERN = /^[A-Z0-9]+(?:-[A-Z0-9]+)+$/;
|
|
4695
4714
|
var ALIAS_PATTERN = /^[A-Z0-9]+(?:[.-][A-Z0-9]+)*$/;
|
|
4696
4715
|
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
4716
|
+
var SHA256_RE = /^[a-f0-9]{64}$/i;
|
|
4697
4717
|
function error4(field, rule, message) {
|
|
4698
4718
|
return { level: "error", field, rule, message };
|
|
4699
4719
|
}
|
|
@@ -4707,6 +4727,23 @@ function isIsoDate(value) {
|
|
|
4707
4727
|
}
|
|
4708
4728
|
return date.toISOString().slice(0, 10) === value;
|
|
4709
4729
|
}
|
|
4730
|
+
function validateStringArrayField(errors, field, value, options = {}) {
|
|
4731
|
+
if (value === void 0) {
|
|
4732
|
+
return;
|
|
4733
|
+
}
|
|
4734
|
+
if (!Array.isArray(value)) {
|
|
4735
|
+
errors.push(error4(field, `struct.${field}_array`, `Field '${field}' must be an array of strings.`));
|
|
4736
|
+
return;
|
|
4737
|
+
}
|
|
4738
|
+
for (const entry of value) {
|
|
4739
|
+
if (typeof entry !== "string" || entry.trim().length < (options.minLength ?? 1)) {
|
|
4740
|
+
errors.push(
|
|
4741
|
+
error4(field, `struct.${field}_string`, `Field '${field}' entries must be non-empty strings.`)
|
|
4742
|
+
);
|
|
4743
|
+
return;
|
|
4744
|
+
}
|
|
4745
|
+
}
|
|
4746
|
+
}
|
|
4710
4747
|
function validateStructural(task, context = {}) {
|
|
4711
4748
|
const errors = [];
|
|
4712
4749
|
const required = ["id", "title", "type", "status", "created", "updated"];
|
|
@@ -4771,6 +4808,27 @@ function validateStructural(task, context = {}) {
|
|
|
4771
4808
|
}
|
|
4772
4809
|
}
|
|
4773
4810
|
}
|
|
4811
|
+
validateStringArrayField(errors, "acceptance", task.acceptance);
|
|
4812
|
+
validateStringArrayField(errors, "tests_required", task.tests_required);
|
|
4813
|
+
if (task.origin !== void 0) {
|
|
4814
|
+
if (!task.origin || typeof task.origin !== "object" || Array.isArray(task.origin)) {
|
|
4815
|
+
errors.push(error4("origin", "struct.origin_object", "Field 'origin' must be an object."));
|
|
4816
|
+
} else {
|
|
4817
|
+
validateStringArrayField(errors, "origin.authority_refs", task.origin.authority_refs);
|
|
4818
|
+
validateStringArrayField(errors, "origin.derived_refs", task.origin.derived_refs);
|
|
4819
|
+
validateStringArrayField(errors, "origin.promoted_from", task.origin.promoted_from);
|
|
4820
|
+
validateStringArrayField(errors, "origin.promoted_to", task.origin.promoted_to);
|
|
4821
|
+
if (task.origin.snapshot_sha256 !== void 0 && (typeof task.origin.snapshot_sha256 !== "string" || !SHA256_RE.test(task.origin.snapshot_sha256))) {
|
|
4822
|
+
errors.push(
|
|
4823
|
+
error4(
|
|
4824
|
+
"origin.snapshot_sha256",
|
|
4825
|
+
"struct.origin_snapshot_sha256",
|
|
4826
|
+
"Field 'origin.snapshot_sha256' must be a 64-character SHA-256 hex string."
|
|
4827
|
+
)
|
|
4828
|
+
);
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4831
|
+
}
|
|
4774
4832
|
return errors;
|
|
4775
4833
|
}
|
|
4776
4834
|
|
|
@@ -4858,9 +4916,131 @@ function validate(task, context = {}) {
|
|
|
4858
4916
|
};
|
|
4859
4917
|
}
|
|
4860
4918
|
|
|
4861
|
-
// src/
|
|
4919
|
+
// src/workspace.ts
|
|
4862
4920
|
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
4863
4921
|
var import_node_path9 = __toESM(require("path"), 1);
|
|
4922
|
+
var COOP_DIR_NAME = ".coop";
|
|
4923
|
+
function sanitizeProjectId(value, fallback) {
|
|
4924
|
+
const normalized = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-");
|
|
4925
|
+
return normalized || fallback;
|
|
4926
|
+
}
|
|
4927
|
+
function coop_workspace_dir(repoRoot) {
|
|
4928
|
+
return import_node_path9.default.join(import_node_path9.default.resolve(repoRoot), COOP_DIR_NAME);
|
|
4929
|
+
}
|
|
4930
|
+
function coop_projects_dir(repoRoot) {
|
|
4931
|
+
return import_node_path9.default.join(coop_workspace_dir(repoRoot), "projects");
|
|
4932
|
+
}
|
|
4933
|
+
function coop_workspace_config_path(repoRoot) {
|
|
4934
|
+
return import_node_path9.default.join(coop_workspace_dir(repoRoot), "config.yml");
|
|
4935
|
+
}
|
|
4936
|
+
function coop_project_root(repoRoot, projectId) {
|
|
4937
|
+
return import_node_path9.default.join(coop_projects_dir(repoRoot), projectId);
|
|
4938
|
+
}
|
|
4939
|
+
function coop_project_config_path(projectRoot) {
|
|
4940
|
+
return import_node_path9.default.join(projectRoot, "config.yml");
|
|
4941
|
+
}
|
|
4942
|
+
function repo_default_project_id(repoRoot) {
|
|
4943
|
+
return sanitizeProjectId(import_node_path9.default.basename(import_node_path9.default.resolve(repoRoot)), "workspace");
|
|
4944
|
+
}
|
|
4945
|
+
function repo_default_project_name(repoRoot) {
|
|
4946
|
+
const base = import_node_path9.default.basename(import_node_path9.default.resolve(repoRoot)).trim();
|
|
4947
|
+
return base || "COOP Workspace";
|
|
4948
|
+
}
|
|
4949
|
+
function has_v2_projects_layout(repoRoot) {
|
|
4950
|
+
return import_node_fs14.default.existsSync(coop_projects_dir(repoRoot));
|
|
4951
|
+
}
|
|
4952
|
+
function has_legacy_project_layout(repoRoot) {
|
|
4953
|
+
const workspaceDir = coop_workspace_dir(repoRoot);
|
|
4954
|
+
return import_node_fs14.default.existsSync(workspaceDir) && import_node_fs14.default.existsSync(import_node_path9.default.join(workspaceDir, "config.yml")) && !import_node_fs14.default.existsSync(coop_projects_dir(repoRoot));
|
|
4955
|
+
}
|
|
4956
|
+
function read_workspace_config(repoRoot) {
|
|
4957
|
+
const configPath = coop_workspace_config_path(repoRoot);
|
|
4958
|
+
if (!import_node_fs14.default.existsSync(configPath) || has_legacy_project_layout(repoRoot)) {
|
|
4959
|
+
return { version: 2 };
|
|
4960
|
+
}
|
|
4961
|
+
return parseYamlFile(configPath);
|
|
4962
|
+
}
|
|
4963
|
+
function write_workspace_config(repoRoot, config) {
|
|
4964
|
+
import_node_fs14.default.mkdirSync(coop_workspace_dir(repoRoot), { recursive: true });
|
|
4965
|
+
writeYamlFile(coop_workspace_config_path(repoRoot), {
|
|
4966
|
+
version: config.version ?? 2,
|
|
4967
|
+
...config.current_project ? { current_project: config.current_project } : {}
|
|
4968
|
+
});
|
|
4969
|
+
}
|
|
4970
|
+
function read_project_config(projectRoot) {
|
|
4971
|
+
return parseYamlFile(coop_project_config_path(projectRoot));
|
|
4972
|
+
}
|
|
4973
|
+
function project_ref_from_config(repoRoot, projectRoot, layout) {
|
|
4974
|
+
const config = read_project_config(projectRoot);
|
|
4975
|
+
const repoName = repo_default_project_name(repoRoot);
|
|
4976
|
+
const fallbackId = repo_default_project_id(repoRoot);
|
|
4977
|
+
return {
|
|
4978
|
+
id: sanitizeProjectId(config.project?.id ?? fallbackId, fallbackId),
|
|
4979
|
+
name: config.project?.name?.trim() || repoName,
|
|
4980
|
+
aliases: Array.isArray(config.project?.aliases) ? config.project.aliases.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [],
|
|
4981
|
+
root: projectRoot,
|
|
4982
|
+
repo_root: import_node_path9.default.resolve(repoRoot),
|
|
4983
|
+
layout
|
|
4984
|
+
};
|
|
4985
|
+
}
|
|
4986
|
+
function list_projects(repoRoot) {
|
|
4987
|
+
if (has_v2_projects_layout(repoRoot)) {
|
|
4988
|
+
const projectsDir = coop_projects_dir(repoRoot);
|
|
4989
|
+
return import_node_fs14.default.readdirSync(projectsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => import_node_path9.default.join(projectsDir, entry.name)).filter((projectRoot) => import_node_fs14.default.existsSync(coop_project_config_path(projectRoot))).map((projectRoot) => project_ref_from_config(repoRoot, projectRoot, "v2")).sort((a, b) => a.id.localeCompare(b.id));
|
|
4990
|
+
}
|
|
4991
|
+
if (has_legacy_project_layout(repoRoot)) {
|
|
4992
|
+
return [project_ref_from_config(repoRoot, coop_workspace_dir(repoRoot), "legacy")];
|
|
4993
|
+
}
|
|
4994
|
+
return [];
|
|
4995
|
+
}
|
|
4996
|
+
function resolve_project(repoRoot, options = {}) {
|
|
4997
|
+
const projects = list_projects(repoRoot);
|
|
4998
|
+
const requested = options.project?.trim().toLowerCase();
|
|
4999
|
+
if (requested) {
|
|
5000
|
+
const match = projects.find(
|
|
5001
|
+
(project) => project.id.toLowerCase() === requested || project.name.toLowerCase() === requested || project.aliases.some((alias) => alias.toLowerCase() === requested)
|
|
5002
|
+
);
|
|
5003
|
+
if (!match) {
|
|
5004
|
+
throw new Error(`Project '${options.project}' not found.`);
|
|
5005
|
+
}
|
|
5006
|
+
return match;
|
|
5007
|
+
}
|
|
5008
|
+
if (projects.length === 1) {
|
|
5009
|
+
return projects[0];
|
|
5010
|
+
}
|
|
5011
|
+
const workspaceConfig = read_workspace_config(repoRoot);
|
|
5012
|
+
if (workspaceConfig.current_project) {
|
|
5013
|
+
const match = projects.find((project) => project.id === workspaceConfig.current_project);
|
|
5014
|
+
if (match) return match;
|
|
5015
|
+
}
|
|
5016
|
+
if (!options.require && projects.length === 0) {
|
|
5017
|
+
return {
|
|
5018
|
+
id: repo_default_project_id(repoRoot),
|
|
5019
|
+
name: repo_default_project_name(repoRoot),
|
|
5020
|
+
aliases: [],
|
|
5021
|
+
root: coop_project_root(repoRoot, repo_default_project_id(repoRoot)),
|
|
5022
|
+
repo_root: import_node_path9.default.resolve(repoRoot),
|
|
5023
|
+
layout: "v2"
|
|
5024
|
+
};
|
|
5025
|
+
}
|
|
5026
|
+
if (projects.length === 0) {
|
|
5027
|
+
throw new Error("No COOP project found. Run 'coop init'.");
|
|
5028
|
+
}
|
|
5029
|
+
throw new Error("Multiple COOP projects found. Pass --project <id> or run 'coop project use <id>'.");
|
|
5030
|
+
}
|
|
5031
|
+
function ensure_workspace_layout(repoRoot) {
|
|
5032
|
+
const workspaceDir = coop_workspace_dir(repoRoot);
|
|
5033
|
+
import_node_fs14.default.mkdirSync(workspaceDir, { recursive: true });
|
|
5034
|
+
import_node_fs14.default.mkdirSync(coop_projects_dir(repoRoot), { recursive: true });
|
|
5035
|
+
return workspaceDir;
|
|
5036
|
+
}
|
|
5037
|
+
function is_project_initialized(projectRoot) {
|
|
5038
|
+
return import_node_fs14.default.existsSync(coop_project_config_path(projectRoot));
|
|
5039
|
+
}
|
|
5040
|
+
|
|
5041
|
+
// src/core.ts
|
|
5042
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
5043
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
4864
5044
|
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
4865
5045
|
|
|
4866
5046
|
// src/types.ts
|
|
@@ -4886,17 +5066,17 @@ function toIdKey(value) {
|
|
|
4886
5066
|
return value.trim().toUpperCase();
|
|
4887
5067
|
}
|
|
4888
5068
|
function repoRootByPackage(cwd) {
|
|
4889
|
-
let current =
|
|
5069
|
+
let current = import_node_path10.default.resolve(cwd);
|
|
4890
5070
|
let lastWorkspaceRoot = null;
|
|
4891
5071
|
while (true) {
|
|
4892
|
-
const packageJson =
|
|
4893
|
-
const workspaceYaml =
|
|
4894
|
-
if (
|
|
5072
|
+
const packageJson = import_node_path10.default.join(current, "package.json");
|
|
5073
|
+
const workspaceYaml = import_node_path10.default.join(current, "pnpm-workspace.yaml");
|
|
5074
|
+
if (import_node_fs15.default.existsSync(packageJson) && import_node_fs15.default.existsSync(workspaceYaml)) {
|
|
4895
5075
|
lastWorkspaceRoot = current;
|
|
4896
|
-
const hasCoop =
|
|
5076
|
+
const hasCoop = import_node_fs15.default.existsSync(import_node_path10.default.join(current, COOP_DIR, "config.yml"));
|
|
4897
5077
|
if (hasCoop) return current;
|
|
4898
5078
|
}
|
|
4899
|
-
const parent =
|
|
5079
|
+
const parent = import_node_path10.default.dirname(current);
|
|
4900
5080
|
if (parent === current) return lastWorkspaceRoot;
|
|
4901
5081
|
current = parent;
|
|
4902
5082
|
}
|
|
@@ -4905,24 +5085,24 @@ function findRepoRoot(cwd = process.cwd()) {
|
|
|
4905
5085
|
return repoRootByPackage(cwd);
|
|
4906
5086
|
}
|
|
4907
5087
|
function configPathFor(rootDir, workspaceDir) {
|
|
4908
|
-
return
|
|
5088
|
+
return import_node_path10.default.join(rootDir, workspaceDir, "config.yml");
|
|
4909
5089
|
}
|
|
4910
5090
|
function backlogPathFor(rootDir, workspaceDir) {
|
|
4911
|
-
return
|
|
5091
|
+
return import_node_path10.default.join(rootDir, workspaceDir, "backlog");
|
|
4912
5092
|
}
|
|
4913
5093
|
function releasesPathFor(rootDir, workspaceDir) {
|
|
4914
|
-
return
|
|
5094
|
+
return import_node_path10.default.join(rootDir, workspaceDir, "releases");
|
|
4915
5095
|
}
|
|
4916
5096
|
function detectWorkspaceDir(rootDir) {
|
|
4917
|
-
if (
|
|
4918
|
-
if (
|
|
5097
|
+
if (import_node_fs15.default.existsSync(configPathFor(rootDir, COOP_DIR))) return COOP_DIR;
|
|
5098
|
+
if (import_node_fs15.default.existsSync(import_node_path10.default.join(rootDir, COOP_DIR))) return COOP_DIR;
|
|
4919
5099
|
return null;
|
|
4920
5100
|
}
|
|
4921
5101
|
function preferredWorkspaceDir(rootDir) {
|
|
4922
5102
|
return detectWorkspaceDir(rootDir) ?? COOP_DIR;
|
|
4923
5103
|
}
|
|
4924
5104
|
function missingConfigError(rootDir) {
|
|
4925
|
-
const coopConfig =
|
|
5105
|
+
const coopConfig = import_node_path10.default.relative(rootDir, configPathFor(rootDir, COOP_DIR));
|
|
4926
5106
|
return new Error(`COOP config missing at ${coopConfig}. Run: coop init`);
|
|
4927
5107
|
}
|
|
4928
5108
|
function parseConfig(raw) {
|
|
@@ -4968,10 +5148,10 @@ function configToString(config) {
|
|
|
4968
5148
|
return lines.join("\n");
|
|
4969
5149
|
}
|
|
4970
5150
|
function toPortablePath(value) {
|
|
4971
|
-
return value.split(
|
|
5151
|
+
return value.split(import_node_path10.default.sep).join("/");
|
|
4972
5152
|
}
|
|
4973
5153
|
function ensureReleasesDir(rootDir, workspaceDir) {
|
|
4974
|
-
|
|
5154
|
+
import_node_fs15.default.mkdirSync(releasesPathFor(rootDir, workspaceDir), { recursive: true });
|
|
4975
5155
|
}
|
|
4976
5156
|
function releaseHeader(date) {
|
|
4977
5157
|
return `## ${date}`;
|
|
@@ -4993,12 +5173,12 @@ function appendReleaseEntry(rootDir, workspaceDir, item, previousStatus, nextSta
|
|
|
4993
5173
|
ensureReleasesDir(rootDir, workspaceDir);
|
|
4994
5174
|
const now = /* @__PURE__ */ new Date();
|
|
4995
5175
|
const date = now.toISOString().slice(0, 10);
|
|
4996
|
-
const releasePath =
|
|
5176
|
+
const releasePath = import_node_path10.default.join(releasesPathFor(rootDir, workspaceDir), `${date}.md`);
|
|
4997
5177
|
const heading = "# COOP Release Notes";
|
|
4998
5178
|
const dayHeader = releaseHeader(date);
|
|
4999
5179
|
const entry = releaseEntryLine(item, previousStatus, nextStatus);
|
|
5000
|
-
if (!
|
|
5001
|
-
|
|
5180
|
+
if (!import_node_fs15.default.existsSync(releasePath)) {
|
|
5181
|
+
import_node_fs15.default.writeFileSync(
|
|
5002
5182
|
releasePath,
|
|
5003
5183
|
[
|
|
5004
5184
|
`${heading}
|
|
@@ -5011,10 +5191,10 @@ function appendReleaseEntry(rootDir, workspaceDir, item, previousStatus, nextSta
|
|
|
5011
5191
|
].join("\n"),
|
|
5012
5192
|
"utf8"
|
|
5013
5193
|
);
|
|
5014
|
-
return toPortablePath(
|
|
5194
|
+
return toPortablePath(import_node_path10.default.relative(rootDir, releasePath));
|
|
5015
5195
|
}
|
|
5016
|
-
const existing =
|
|
5017
|
-
if (hasReleaseEntry(existing, item.id)) return toPortablePath(
|
|
5196
|
+
const existing = import_node_fs15.default.readFileSync(releasePath, "utf8");
|
|
5197
|
+
if (hasReleaseEntry(existing, item.id)) return toPortablePath(import_node_path10.default.relative(rootDir, releasePath));
|
|
5018
5198
|
let nextContent = existing;
|
|
5019
5199
|
if (!existing.includes(`## ${date}`)) {
|
|
5020
5200
|
if (!nextContent.endsWith("\n")) nextContent += "\n";
|
|
@@ -5024,9 +5204,9 @@ function appendReleaseEntry(rootDir, workspaceDir, item, previousStatus, nextSta
|
|
|
5024
5204
|
if (!nextContent.endsWith("\n")) nextContent += "\n";
|
|
5025
5205
|
nextContent += `${entry}
|
|
5026
5206
|
`;
|
|
5027
|
-
|
|
5207
|
+
import_node_fs15.default.writeFileSync(releasePath, `${nextContent}
|
|
5028
5208
|
`, "utf8");
|
|
5029
|
-
return toPortablePath(
|
|
5209
|
+
return toPortablePath(import_node_path10.default.relative(rootDir, releasePath));
|
|
5030
5210
|
}
|
|
5031
5211
|
function completeItem(rootDir, id) {
|
|
5032
5212
|
const state = loadState(rootDir);
|
|
@@ -5104,28 +5284,28 @@ function validateAndNormalize(data, sourceFile) {
|
|
|
5104
5284
|
};
|
|
5105
5285
|
}
|
|
5106
5286
|
function parseItem(filePath, rootDir) {
|
|
5107
|
-
const raw =
|
|
5287
|
+
const raw = import_node_fs15.default.readFileSync(filePath, "utf8");
|
|
5108
5288
|
const parsed = (0, import_gray_matter.default)(raw);
|
|
5109
|
-
const data = validateAndNormalize(parsed.data,
|
|
5289
|
+
const data = validateAndNormalize(parsed.data, import_node_path10.default.relative(rootDir, filePath));
|
|
5110
5290
|
return {
|
|
5111
5291
|
...data,
|
|
5112
5292
|
body: parsed.content || "",
|
|
5113
|
-
filePath:
|
|
5293
|
+
filePath: import_node_path10.default.relative(rootDir, filePath)
|
|
5114
5294
|
};
|
|
5115
5295
|
}
|
|
5116
5296
|
function walk(dir) {
|
|
5117
5297
|
const out = [];
|
|
5118
|
-
if (!
|
|
5119
|
-
const entries =
|
|
5298
|
+
if (!import_node_fs15.default.existsSync(dir)) return out;
|
|
5299
|
+
const entries = import_node_fs15.default.readdirSync(dir, { withFileTypes: true });
|
|
5120
5300
|
for (const entry of entries) {
|
|
5121
|
-
const file =
|
|
5301
|
+
const file = import_node_path10.default.join(dir, entry.name);
|
|
5122
5302
|
if (entry.isDirectory()) out.push(...walk(file));
|
|
5123
5303
|
if (entry.isFile() && file.endsWith(".md")) out.push(file);
|
|
5124
5304
|
}
|
|
5125
5305
|
return out;
|
|
5126
5306
|
}
|
|
5127
5307
|
function itemPath(type, id, rootDir, workspaceDir) {
|
|
5128
|
-
return
|
|
5308
|
+
return import_node_path10.default.join(backlogPathFor(rootDir, workspaceDir), ITEM_DIRS[type], `${id}.md`);
|
|
5129
5309
|
}
|
|
5130
5310
|
function normalizeFrontmatterValue(value) {
|
|
5131
5311
|
if (value == null) return void 0;
|
|
@@ -5212,30 +5392,30 @@ function nextGeneratedId(config, title, existing) {
|
|
|
5212
5392
|
}
|
|
5213
5393
|
function ensureCoopLayout(rootDir) {
|
|
5214
5394
|
const workspaceDir = preferredWorkspaceDir(rootDir);
|
|
5215
|
-
const root =
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5395
|
+
const root = import_node_path10.default.join(rootDir, workspaceDir);
|
|
5396
|
+
import_node_fs15.default.mkdirSync(root, { recursive: true });
|
|
5397
|
+
import_node_fs15.default.mkdirSync(import_node_path10.default.join(root, "releases"), { recursive: true });
|
|
5398
|
+
import_node_fs15.default.mkdirSync(import_node_path10.default.join(root, "plans"), { recursive: true });
|
|
5399
|
+
import_node_fs15.default.mkdirSync(import_node_path10.default.join(root, "views"), { recursive: true });
|
|
5400
|
+
import_node_fs15.default.mkdirSync(import_node_path10.default.join(root, "templates"), { recursive: true });
|
|
5221
5401
|
for (const dir of Object.values(ITEM_DIRS)) {
|
|
5222
|
-
|
|
5402
|
+
import_node_fs15.default.mkdirSync(import_node_path10.default.join(root, "backlog", dir), { recursive: true });
|
|
5223
5403
|
}
|
|
5224
|
-
const configFile =
|
|
5225
|
-
if (!
|
|
5226
|
-
|
|
5404
|
+
const configFile = import_node_path10.default.join(root, "config.yml");
|
|
5405
|
+
if (!import_node_fs15.default.existsSync(configFile)) {
|
|
5406
|
+
import_node_fs15.default.writeFileSync(configFile, configToString(DEFAULT_CONFIG3), "utf8");
|
|
5227
5407
|
}
|
|
5228
5408
|
}
|
|
5229
5409
|
function loadState(rootDir) {
|
|
5230
5410
|
const workspaceDir = detectWorkspaceDir(rootDir);
|
|
5231
5411
|
if (!workspaceDir) throw missingConfigError(rootDir);
|
|
5232
5412
|
const configPath = configPathFor(rootDir, workspaceDir);
|
|
5233
|
-
if (!
|
|
5234
|
-
const config = parseConfig(
|
|
5413
|
+
if (!import_node_fs15.default.existsSync(configPath)) throw missingConfigError(rootDir);
|
|
5414
|
+
const config = parseConfig(import_node_fs15.default.readFileSync(configPath, "utf8"));
|
|
5235
5415
|
const items = [];
|
|
5236
5416
|
const itemsById = /* @__PURE__ */ new Map();
|
|
5237
5417
|
for (const type of ITEM_TYPES) {
|
|
5238
|
-
const dir =
|
|
5418
|
+
const dir = import_node_path10.default.join(backlogPathFor(rootDir, workspaceDir), ITEM_DIRS[type]);
|
|
5239
5419
|
const files = walk(dir);
|
|
5240
5420
|
for (const file of files) {
|
|
5241
5421
|
const item = parseItem(file, rootDir);
|
|
@@ -5319,21 +5499,21 @@ function createItem(rootDir, params) {
|
|
|
5319
5499
|
parent_id: params.parent_id
|
|
5320
5500
|
};
|
|
5321
5501
|
const itemPathName = itemPath(params.type, item.id, rootDir, state.workspaceDir);
|
|
5322
|
-
|
|
5502
|
+
import_node_fs15.default.writeFileSync(itemPathName, serialize(item, params.body || ""), "utf8");
|
|
5323
5503
|
if ((config.id_strategy ?? "text") === "counter") {
|
|
5324
5504
|
const numericMatch = /-(\d+)$/.exec(item.id);
|
|
5325
5505
|
if (numericMatch) {
|
|
5326
5506
|
const numericValue = Number(numericMatch[1]);
|
|
5327
5507
|
if (Number.isInteger(numericValue) && numericValue >= (config.next_id ?? 1)) {
|
|
5328
5508
|
config.next_id = numericValue + 1;
|
|
5329
|
-
|
|
5509
|
+
import_node_fs15.default.writeFileSync(configPathFor(rootDir, state.workspaceDir), configToString(config), "utf8");
|
|
5330
5510
|
}
|
|
5331
5511
|
}
|
|
5332
5512
|
}
|
|
5333
5513
|
return {
|
|
5334
5514
|
...item,
|
|
5335
5515
|
body: params.body || "",
|
|
5336
|
-
filePath:
|
|
5516
|
+
filePath: import_node_path10.default.relative(rootDir, itemPathName)
|
|
5337
5517
|
};
|
|
5338
5518
|
}
|
|
5339
5519
|
function updateItem(rootDir, id, patch) {
|
|
@@ -5359,8 +5539,8 @@ function updateItem(rootDir, id, patch) {
|
|
|
5359
5539
|
};
|
|
5360
5540
|
if (!ITEM_TYPES.includes(next.type)) throw new Error(`Unknown type ${next.type}.`);
|
|
5361
5541
|
if (!ITEM_STATUSES.includes(next.status)) throw new Error(`Unknown status ${next.status}.`);
|
|
5362
|
-
const filePath =
|
|
5363
|
-
|
|
5542
|
+
const filePath = import_node_path10.default.join(rootDir, existing.filePath);
|
|
5543
|
+
import_node_fs15.default.writeFileSync(filePath, serialize(next, patch.body || existing.body), "utf8");
|
|
5364
5544
|
return {
|
|
5365
5545
|
...next,
|
|
5366
5546
|
body: patch.body || existing.body,
|
|
@@ -5376,7 +5556,7 @@ function deleteItem(rootDir, id) {
|
|
|
5376
5556
|
if (children.length > 0) {
|
|
5377
5557
|
throw new Error(`Cannot delete ${existing.id} because it has ${children.length} child item(s). Remove children first.`);
|
|
5378
5558
|
}
|
|
5379
|
-
|
|
5559
|
+
import_node_fs15.default.unlinkSync(import_node_path10.default.join(rootDir, existing.filePath));
|
|
5380
5560
|
return existing;
|
|
5381
5561
|
}
|
|
5382
5562
|
function renderAgentPrompt(item) {
|
|
@@ -5415,8 +5595,8 @@ function validateRepo(rootDir) {
|
|
|
5415
5595
|
const errors = [];
|
|
5416
5596
|
const warnings = [];
|
|
5417
5597
|
const workspaceDir = detectWorkspaceDir(rootDir);
|
|
5418
|
-
if (!workspaceDir || !
|
|
5419
|
-
errors.push("Missing
|
|
5598
|
+
if (!workspaceDir || !import_node_fs15.default.existsSync(configPathFor(rootDir, workspaceDir))) {
|
|
5599
|
+
errors.push("Missing COOP config. Run coop init first.");
|
|
5420
5600
|
return { valid: false, errors, warnings };
|
|
5421
5601
|
}
|
|
5422
5602
|
let state;
|
|
@@ -5490,6 +5670,11 @@ function validateRepo(rootDir) {
|
|
|
5490
5670
|
compute_readiness_with_corrections,
|
|
5491
5671
|
compute_score,
|
|
5492
5672
|
compute_velocity,
|
|
5673
|
+
coop_project_config_path,
|
|
5674
|
+
coop_project_root,
|
|
5675
|
+
coop_projects_dir,
|
|
5676
|
+
coop_workspace_config_path,
|
|
5677
|
+
coop_workspace_dir,
|
|
5493
5678
|
createItem,
|
|
5494
5679
|
create_seeded_rng,
|
|
5495
5680
|
critical_path_weight,
|
|
@@ -5501,6 +5686,7 @@ function validateRepo(rootDir) {
|
|
|
5501
5686
|
effective_weekly_hours,
|
|
5502
5687
|
effort_or_default,
|
|
5503
5688
|
ensureCoopLayout,
|
|
5689
|
+
ensure_workspace_layout,
|
|
5504
5690
|
executor_fit_weight,
|
|
5505
5691
|
external_dependencies_for_task,
|
|
5506
5692
|
extract_subgraph,
|
|
@@ -5509,7 +5695,11 @@ function validateRepo(rootDir) {
|
|
|
5509
5695
|
getItemById,
|
|
5510
5696
|
get_remaining_tokens,
|
|
5511
5697
|
get_user_role,
|
|
5698
|
+
has_legacy_project_layout,
|
|
5699
|
+
has_v2_projects_layout,
|
|
5512
5700
|
is_external_dependency,
|
|
5701
|
+
is_project_initialized,
|
|
5702
|
+
list_projects,
|
|
5513
5703
|
loadState,
|
|
5514
5704
|
load_auth_config,
|
|
5515
5705
|
load_completed_runs,
|
|
@@ -5534,9 +5724,14 @@ function validateRepo(rootDir) {
|
|
|
5534
5724
|
pert_stddev,
|
|
5535
5725
|
priority_weight,
|
|
5536
5726
|
queryItems,
|
|
5727
|
+
read_project_config,
|
|
5537
5728
|
read_schema_version,
|
|
5729
|
+
read_workspace_config,
|
|
5538
5730
|
renderAgentPrompt,
|
|
5731
|
+
repo_default_project_id,
|
|
5732
|
+
repo_default_project_name,
|
|
5539
5733
|
resolve_external_dependencies,
|
|
5734
|
+
resolve_project,
|
|
5540
5735
|
risk_penalty,
|
|
5541
5736
|
run_hook,
|
|
5542
5737
|
run_monte_carlo_chunk,
|
|
@@ -5565,5 +5760,6 @@ function validateRepo(rootDir) {
|
|
|
5565
5760
|
validate_transition,
|
|
5566
5761
|
writeTask,
|
|
5567
5762
|
writeYamlFile,
|
|
5568
|
-
write_schema_version
|
|
5763
|
+
write_schema_version,
|
|
5764
|
+
write_workspace_config
|
|
5569
5765
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -293,6 +293,15 @@ interface TaskPlanning {
|
|
|
293
293
|
depends_on?: string[];
|
|
294
294
|
tags?: string[];
|
|
295
295
|
delivery?: string | null;
|
|
296
|
+
acceptance?: string[];
|
|
297
|
+
tests_required?: string[];
|
|
298
|
+
origin?: {
|
|
299
|
+
authority_refs?: string[];
|
|
300
|
+
derived_refs?: string[];
|
|
301
|
+
promoted_from?: string[];
|
|
302
|
+
promoted_to?: string[];
|
|
303
|
+
snapshot_sha256?: string;
|
|
304
|
+
};
|
|
296
305
|
}
|
|
297
306
|
interface TaskEstimate {
|
|
298
307
|
optimistic_hours: number;
|
|
@@ -1386,6 +1395,39 @@ interface ValidationResult {
|
|
|
1386
1395
|
}
|
|
1387
1396
|
declare function validate(task: Task, context?: ValidationContext): ValidationResult;
|
|
1388
1397
|
|
|
1398
|
+
type CoopWorkspaceConfig = {
|
|
1399
|
+
version?: number;
|
|
1400
|
+
current_project?: string;
|
|
1401
|
+
};
|
|
1402
|
+
type CoopProjectRef = {
|
|
1403
|
+
id: string;
|
|
1404
|
+
name: string;
|
|
1405
|
+
aliases: string[];
|
|
1406
|
+
root: string;
|
|
1407
|
+
repo_root: string;
|
|
1408
|
+
layout: "legacy" | "v2";
|
|
1409
|
+
};
|
|
1410
|
+
type ResolveProjectOptions = {
|
|
1411
|
+
project?: string;
|
|
1412
|
+
require?: boolean;
|
|
1413
|
+
};
|
|
1414
|
+
declare function coop_workspace_dir(repoRoot: string): string;
|
|
1415
|
+
declare function coop_projects_dir(repoRoot: string): string;
|
|
1416
|
+
declare function coop_workspace_config_path(repoRoot: string): string;
|
|
1417
|
+
declare function coop_project_root(repoRoot: string, projectId: string): string;
|
|
1418
|
+
declare function coop_project_config_path(projectRoot: string): string;
|
|
1419
|
+
declare function repo_default_project_id(repoRoot: string): string;
|
|
1420
|
+
declare function repo_default_project_name(repoRoot: string): string;
|
|
1421
|
+
declare function has_v2_projects_layout(repoRoot: string): boolean;
|
|
1422
|
+
declare function has_legacy_project_layout(repoRoot: string): boolean;
|
|
1423
|
+
declare function read_workspace_config(repoRoot: string): CoopWorkspaceConfig;
|
|
1424
|
+
declare function write_workspace_config(repoRoot: string, config: CoopWorkspaceConfig): void;
|
|
1425
|
+
declare function read_project_config(projectRoot: string): CoopConfig;
|
|
1426
|
+
declare function list_projects(repoRoot: string): CoopProjectRef[];
|
|
1427
|
+
declare function resolve_project(repoRoot: string, options?: ResolveProjectOptions): CoopProjectRef;
|
|
1428
|
+
declare function ensure_workspace_layout(repoRoot: string): string;
|
|
1429
|
+
declare function is_project_initialized(projectRoot: string): boolean;
|
|
1430
|
+
|
|
1389
1431
|
/**
|
|
1390
1432
|
* Finds the nearest workspace root that contains package + workspace metadata.
|
|
1391
1433
|
* [SPEC: Architecture v2.0 §2]
|
|
@@ -1452,4 +1494,4 @@ declare function validateRepo(rootDir: string): {
|
|
|
1452
1494
|
warnings: string[];
|
|
1453
1495
|
};
|
|
1454
1496
|
|
|
1455
|
-
export { type AIAgent, type AIResource, type AgentSpec, type AllocationResult, ArtifactType, type AuthConfig, type AuthPolicy, type AutoTransitionResult, type AvailabilityWindow, type BacklogItem, type BacklogItemData, COOP_EVENT_TYPES, CURRENT_SCHEMA_VERSION, type CapacityLedger, type ComparisonResult, type ComparisonRow, type ComputeNode, type ComputeResource, type CoopConfig, type CoopEvent, CoopEventEmitter, type CoopEventType, type CreateItemParams, type CriticalPathResult, type CriticalPathTaskMetrics, DEFAULT_SCORE_WEIGHTS, type Delivery, type DeliveryAtRisk, type DeliveryBudget, type DeliveryCommitted, type DeliveryGovernance, type DeliveryRisk, type DeliveryRiskType, type DeliveryScope, DeliveryStatus, type DetectedDeliveryRisk, type EffectiveCapacity, type EventByType, type ExecutionConstraints, type ExecutionPermissions, ExecutorType, type ExternalDependencyRef, type ExternalDependencyResolution, type ExternalDependencyResolutionStatus, type ExternalDependencyResolverOptions, type ExternalRepoConfig, type FeasibilityResult, type FeasibilityRisk, type FeasibilityStatus, type FeasibilitySummary, type FilterSpec, type FrontmatterParseResult, type GraphCycleDetected, type GraphValidationContext, type GraphValidationResult, type HookRunResult, type HumanMember, type HumanResource, ITEM_STATUSES, ITEM_TYPES, type Idea, IdeaStatus, IndexManager, type IndexStatus, type ItemLinks, type ItemStatus, type ItemType, MIGRATIONS, type MigrateRepositoryOptions, type MigrationContext, type MigrationDefinition, type MigrationReport, type MonteCarloHistogramBucket, type MonteCarloOptions, type MonteCarloResult, type MonteCarloWorkerPayload, type ParsedDelivery, type ParsedIdea, type ParsedTask, type Permission, type PermissionContext, type PluginAction, type PluginActionConsole, type PluginActionGitHubPr, type PluginActionHandler, type PluginActionHandlerResult, type PluginActionWebhook, type PluginManifest, type PluginRunOptions, type PluginRunRecord, type PluginTrigger, type PolicyAction, type ReadinessComputation, type ReadinessPartitions, type ReadinessState, type ReadinessTransitionEvent, type ReadinessWarning, type ReferentialValidationContext, type RepoConfig, type RepoState, type ResourceProfile, RiskLevel, type Role, type Run, type RunCompleted, type RunFailed, type RunResourcesConsumed, type RunStarted, RunStatus, type RunStepResult, RunStepStatus, RunbookAction, type RunbookStep, type ScheduleOptions, type ScoreContext, type ScoredTask, type SemanticValidationContext, type SimulationResult, type StructuralValidationContext, type Task, type TaskAssigned, TaskComplexity, type TaskComputed, type TaskCore, type TaskCreated, TaskDeterminism, type TaskEstimate, type TaskEstimation, type TaskExecution, type TaskGovernance, type TaskGraph, type TaskPlanning, TaskPriority, type TaskResources, type TaskScheduleEntry, TaskStatus, type TaskTransitioned, type TaskTransitionedEvent, TaskType, type Track, type TrackUtilization, type TrackWip, type TransitionContext, type TransitionResult, type TransitionValidationContext, type UpdateItemParams, VALID_TASK_TRANSITIONS, VALID_TRANSITIONS, type ValidationContext, type ValidationError, type ValidationLevel, type ValidationResult, type VelocityMetrics, type VelocityPoint, type VelocityTrend, type WhatIfBaseline, type WhatIfModification, type WriteTaskOptions, allocate, allocate_ai, allocate_ai_tokens, analyze_feasibility, analyze_what_if, build_capacity_ledger, build_graph, check_blocked, check_permission, check_unblocked, check_wip, completeItem, complexity_penalty, compute_all_readiness, compute_critical_path, compute_readiness, compute_readiness_with_corrections, compute_score, compute_velocity, createItem, create_seeded_rng, critical_path_weight, deleteItem, dependency_unlock_weight, detect_cycle, detect_delivery_risks, determinism_weight, effective_weekly_hours, effort_or_default, ensureCoopLayout, executor_fit_weight, external_dependencies_for_task, extract_subgraph, findRepoRoot, find_external_dependencies, getItemById, get_remaining_tokens, get_user_role, is_external_dependency, loadState, load_auth_config, load_completed_runs, load_graph, load_plugins, migrate_repository, migrate_task, monte_carlo_forecast, parseDeliveryContent, parseDeliveryFile, parseFrontmatterContent, parseFrontmatterFile, parseIdeaContent, parseIdeaFile, parseTaskContent, parseTaskFile, parseYamlContent, parseYamlFile, parse_external_dependency, partition_by_readiness, pert_hours, pert_stddev, priority_weight, queryItems, read_schema_version, renderAgentPrompt, resolve_external_dependencies, risk_penalty, run_hook, run_monte_carlo_chunk, run_plugins_for_event, sample_pert_beta, sample_task_hours, schedule_next, simulate_schedule, stringifyFrontmatter, stringifyYamlContent, task_effort_hours, topological_sort, transition, transitive_dependencies, transitive_dependents, type_weight, updateItem, urgency_weight, validate, validateReferential, validateRepo, validateSemantic, validateStructural, validateTransition, validate_graph, validate_transition, writeTask, writeYamlFile, write_schema_version };
|
|
1497
|
+
export { type AIAgent, type AIResource, type AgentSpec, type AllocationResult, ArtifactType, type AuthConfig, type AuthPolicy, type AutoTransitionResult, type AvailabilityWindow, type BacklogItem, type BacklogItemData, COOP_EVENT_TYPES, CURRENT_SCHEMA_VERSION, type CapacityLedger, type ComparisonResult, type ComparisonRow, type ComputeNode, type ComputeResource, type CoopConfig, type CoopEvent, CoopEventEmitter, type CoopEventType, type CoopProjectRef, type CoopWorkspaceConfig, type CreateItemParams, type CriticalPathResult, type CriticalPathTaskMetrics, DEFAULT_SCORE_WEIGHTS, type Delivery, type DeliveryAtRisk, type DeliveryBudget, type DeliveryCommitted, type DeliveryGovernance, type DeliveryRisk, type DeliveryRiskType, type DeliveryScope, DeliveryStatus, type DetectedDeliveryRisk, type EffectiveCapacity, type EventByType, type ExecutionConstraints, type ExecutionPermissions, ExecutorType, type ExternalDependencyRef, type ExternalDependencyResolution, type ExternalDependencyResolutionStatus, type ExternalDependencyResolverOptions, type ExternalRepoConfig, type FeasibilityResult, type FeasibilityRisk, type FeasibilityStatus, type FeasibilitySummary, type FilterSpec, type FrontmatterParseResult, type GraphCycleDetected, type GraphValidationContext, type GraphValidationResult, type HookRunResult, type HumanMember, type HumanResource, ITEM_STATUSES, ITEM_TYPES, type Idea, IdeaStatus, IndexManager, type IndexStatus, type ItemLinks, type ItemStatus, type ItemType, MIGRATIONS, type MigrateRepositoryOptions, type MigrationContext, type MigrationDefinition, type MigrationReport, type MonteCarloHistogramBucket, type MonteCarloOptions, type MonteCarloResult, type MonteCarloWorkerPayload, type ParsedDelivery, type ParsedIdea, type ParsedTask, type Permission, type PermissionContext, type PluginAction, type PluginActionConsole, type PluginActionGitHubPr, type PluginActionHandler, type PluginActionHandlerResult, type PluginActionWebhook, type PluginManifest, type PluginRunOptions, type PluginRunRecord, type PluginTrigger, type PolicyAction, type ReadinessComputation, type ReadinessPartitions, type ReadinessState, type ReadinessTransitionEvent, type ReadinessWarning, type ReferentialValidationContext, type RepoConfig, type RepoState, type ResourceProfile, RiskLevel, type Role, type Run, type RunCompleted, type RunFailed, type RunResourcesConsumed, type RunStarted, RunStatus, type RunStepResult, RunStepStatus, RunbookAction, type RunbookStep, type ScheduleOptions, type ScoreContext, type ScoredTask, type SemanticValidationContext, type SimulationResult, type StructuralValidationContext, type Task, type TaskAssigned, TaskComplexity, type TaskComputed, type TaskCore, type TaskCreated, TaskDeterminism, type TaskEstimate, type TaskEstimation, type TaskExecution, type TaskGovernance, type TaskGraph, type TaskPlanning, TaskPriority, type TaskResources, type TaskScheduleEntry, TaskStatus, type TaskTransitioned, type TaskTransitionedEvent, TaskType, type Track, type TrackUtilization, type TrackWip, type TransitionContext, type TransitionResult, type TransitionValidationContext, type UpdateItemParams, VALID_TASK_TRANSITIONS, VALID_TRANSITIONS, type ValidationContext, type ValidationError, type ValidationLevel, type ValidationResult, type VelocityMetrics, type VelocityPoint, type VelocityTrend, type WhatIfBaseline, type WhatIfModification, type WriteTaskOptions, allocate, allocate_ai, allocate_ai_tokens, analyze_feasibility, analyze_what_if, build_capacity_ledger, build_graph, check_blocked, check_permission, check_unblocked, check_wip, completeItem, complexity_penalty, compute_all_readiness, compute_critical_path, compute_readiness, compute_readiness_with_corrections, compute_score, compute_velocity, coop_project_config_path, coop_project_root, coop_projects_dir, coop_workspace_config_path, coop_workspace_dir, createItem, create_seeded_rng, critical_path_weight, deleteItem, dependency_unlock_weight, detect_cycle, detect_delivery_risks, determinism_weight, effective_weekly_hours, effort_or_default, ensureCoopLayout, ensure_workspace_layout, executor_fit_weight, external_dependencies_for_task, extract_subgraph, findRepoRoot, find_external_dependencies, getItemById, get_remaining_tokens, get_user_role, has_legacy_project_layout, has_v2_projects_layout, is_external_dependency, is_project_initialized, list_projects, loadState, load_auth_config, load_completed_runs, load_graph, load_plugins, migrate_repository, migrate_task, monte_carlo_forecast, parseDeliveryContent, parseDeliveryFile, parseFrontmatterContent, parseFrontmatterFile, parseIdeaContent, parseIdeaFile, parseTaskContent, parseTaskFile, parseYamlContent, parseYamlFile, parse_external_dependency, partition_by_readiness, pert_hours, pert_stddev, priority_weight, queryItems, read_project_config, read_schema_version, read_workspace_config, renderAgentPrompt, repo_default_project_id, repo_default_project_name, resolve_external_dependencies, resolve_project, risk_penalty, run_hook, run_monte_carlo_chunk, run_plugins_for_event, sample_pert_beta, sample_task_hours, schedule_next, simulate_schedule, stringifyFrontmatter, stringifyYamlContent, task_effort_hours, topological_sort, transition, transitive_dependencies, transitive_dependents, type_weight, updateItem, urgency_weight, validate, validateReferential, validateRepo, validateSemantic, validateStructural, validateTransition, validate_graph, validate_transition, writeTask, writeYamlFile, write_schema_version, write_workspace_config };
|
package/dist/index.d.ts
CHANGED
|
@@ -293,6 +293,15 @@ interface TaskPlanning {
|
|
|
293
293
|
depends_on?: string[];
|
|
294
294
|
tags?: string[];
|
|
295
295
|
delivery?: string | null;
|
|
296
|
+
acceptance?: string[];
|
|
297
|
+
tests_required?: string[];
|
|
298
|
+
origin?: {
|
|
299
|
+
authority_refs?: string[];
|
|
300
|
+
derived_refs?: string[];
|
|
301
|
+
promoted_from?: string[];
|
|
302
|
+
promoted_to?: string[];
|
|
303
|
+
snapshot_sha256?: string;
|
|
304
|
+
};
|
|
296
305
|
}
|
|
297
306
|
interface TaskEstimate {
|
|
298
307
|
optimistic_hours: number;
|
|
@@ -1386,6 +1395,39 @@ interface ValidationResult {
|
|
|
1386
1395
|
}
|
|
1387
1396
|
declare function validate(task: Task, context?: ValidationContext): ValidationResult;
|
|
1388
1397
|
|
|
1398
|
+
type CoopWorkspaceConfig = {
|
|
1399
|
+
version?: number;
|
|
1400
|
+
current_project?: string;
|
|
1401
|
+
};
|
|
1402
|
+
type CoopProjectRef = {
|
|
1403
|
+
id: string;
|
|
1404
|
+
name: string;
|
|
1405
|
+
aliases: string[];
|
|
1406
|
+
root: string;
|
|
1407
|
+
repo_root: string;
|
|
1408
|
+
layout: "legacy" | "v2";
|
|
1409
|
+
};
|
|
1410
|
+
type ResolveProjectOptions = {
|
|
1411
|
+
project?: string;
|
|
1412
|
+
require?: boolean;
|
|
1413
|
+
};
|
|
1414
|
+
declare function coop_workspace_dir(repoRoot: string): string;
|
|
1415
|
+
declare function coop_projects_dir(repoRoot: string): string;
|
|
1416
|
+
declare function coop_workspace_config_path(repoRoot: string): string;
|
|
1417
|
+
declare function coop_project_root(repoRoot: string, projectId: string): string;
|
|
1418
|
+
declare function coop_project_config_path(projectRoot: string): string;
|
|
1419
|
+
declare function repo_default_project_id(repoRoot: string): string;
|
|
1420
|
+
declare function repo_default_project_name(repoRoot: string): string;
|
|
1421
|
+
declare function has_v2_projects_layout(repoRoot: string): boolean;
|
|
1422
|
+
declare function has_legacy_project_layout(repoRoot: string): boolean;
|
|
1423
|
+
declare function read_workspace_config(repoRoot: string): CoopWorkspaceConfig;
|
|
1424
|
+
declare function write_workspace_config(repoRoot: string, config: CoopWorkspaceConfig): void;
|
|
1425
|
+
declare function read_project_config(projectRoot: string): CoopConfig;
|
|
1426
|
+
declare function list_projects(repoRoot: string): CoopProjectRef[];
|
|
1427
|
+
declare function resolve_project(repoRoot: string, options?: ResolveProjectOptions): CoopProjectRef;
|
|
1428
|
+
declare function ensure_workspace_layout(repoRoot: string): string;
|
|
1429
|
+
declare function is_project_initialized(projectRoot: string): boolean;
|
|
1430
|
+
|
|
1389
1431
|
/**
|
|
1390
1432
|
* Finds the nearest workspace root that contains package + workspace metadata.
|
|
1391
1433
|
* [SPEC: Architecture v2.0 §2]
|
|
@@ -1452,4 +1494,4 @@ declare function validateRepo(rootDir: string): {
|
|
|
1452
1494
|
warnings: string[];
|
|
1453
1495
|
};
|
|
1454
1496
|
|
|
1455
|
-
export { type AIAgent, type AIResource, type AgentSpec, type AllocationResult, ArtifactType, type AuthConfig, type AuthPolicy, type AutoTransitionResult, type AvailabilityWindow, type BacklogItem, type BacklogItemData, COOP_EVENT_TYPES, CURRENT_SCHEMA_VERSION, type CapacityLedger, type ComparisonResult, type ComparisonRow, type ComputeNode, type ComputeResource, type CoopConfig, type CoopEvent, CoopEventEmitter, type CoopEventType, type CreateItemParams, type CriticalPathResult, type CriticalPathTaskMetrics, DEFAULT_SCORE_WEIGHTS, type Delivery, type DeliveryAtRisk, type DeliveryBudget, type DeliveryCommitted, type DeliveryGovernance, type DeliveryRisk, type DeliveryRiskType, type DeliveryScope, DeliveryStatus, type DetectedDeliveryRisk, type EffectiveCapacity, type EventByType, type ExecutionConstraints, type ExecutionPermissions, ExecutorType, type ExternalDependencyRef, type ExternalDependencyResolution, type ExternalDependencyResolutionStatus, type ExternalDependencyResolverOptions, type ExternalRepoConfig, type FeasibilityResult, type FeasibilityRisk, type FeasibilityStatus, type FeasibilitySummary, type FilterSpec, type FrontmatterParseResult, type GraphCycleDetected, type GraphValidationContext, type GraphValidationResult, type HookRunResult, type HumanMember, type HumanResource, ITEM_STATUSES, ITEM_TYPES, type Idea, IdeaStatus, IndexManager, type IndexStatus, type ItemLinks, type ItemStatus, type ItemType, MIGRATIONS, type MigrateRepositoryOptions, type MigrationContext, type MigrationDefinition, type MigrationReport, type MonteCarloHistogramBucket, type MonteCarloOptions, type MonteCarloResult, type MonteCarloWorkerPayload, type ParsedDelivery, type ParsedIdea, type ParsedTask, type Permission, type PermissionContext, type PluginAction, type PluginActionConsole, type PluginActionGitHubPr, type PluginActionHandler, type PluginActionHandlerResult, type PluginActionWebhook, type PluginManifest, type PluginRunOptions, type PluginRunRecord, type PluginTrigger, type PolicyAction, type ReadinessComputation, type ReadinessPartitions, type ReadinessState, type ReadinessTransitionEvent, type ReadinessWarning, type ReferentialValidationContext, type RepoConfig, type RepoState, type ResourceProfile, RiskLevel, type Role, type Run, type RunCompleted, type RunFailed, type RunResourcesConsumed, type RunStarted, RunStatus, type RunStepResult, RunStepStatus, RunbookAction, type RunbookStep, type ScheduleOptions, type ScoreContext, type ScoredTask, type SemanticValidationContext, type SimulationResult, type StructuralValidationContext, type Task, type TaskAssigned, TaskComplexity, type TaskComputed, type TaskCore, type TaskCreated, TaskDeterminism, type TaskEstimate, type TaskEstimation, type TaskExecution, type TaskGovernance, type TaskGraph, type TaskPlanning, TaskPriority, type TaskResources, type TaskScheduleEntry, TaskStatus, type TaskTransitioned, type TaskTransitionedEvent, TaskType, type Track, type TrackUtilization, type TrackWip, type TransitionContext, type TransitionResult, type TransitionValidationContext, type UpdateItemParams, VALID_TASK_TRANSITIONS, VALID_TRANSITIONS, type ValidationContext, type ValidationError, type ValidationLevel, type ValidationResult, type VelocityMetrics, type VelocityPoint, type VelocityTrend, type WhatIfBaseline, type WhatIfModification, type WriteTaskOptions, allocate, allocate_ai, allocate_ai_tokens, analyze_feasibility, analyze_what_if, build_capacity_ledger, build_graph, check_blocked, check_permission, check_unblocked, check_wip, completeItem, complexity_penalty, compute_all_readiness, compute_critical_path, compute_readiness, compute_readiness_with_corrections, compute_score, compute_velocity, createItem, create_seeded_rng, critical_path_weight, deleteItem, dependency_unlock_weight, detect_cycle, detect_delivery_risks, determinism_weight, effective_weekly_hours, effort_or_default, ensureCoopLayout, executor_fit_weight, external_dependencies_for_task, extract_subgraph, findRepoRoot, find_external_dependencies, getItemById, get_remaining_tokens, get_user_role, is_external_dependency, loadState, load_auth_config, load_completed_runs, load_graph, load_plugins, migrate_repository, migrate_task, monte_carlo_forecast, parseDeliveryContent, parseDeliveryFile, parseFrontmatterContent, parseFrontmatterFile, parseIdeaContent, parseIdeaFile, parseTaskContent, parseTaskFile, parseYamlContent, parseYamlFile, parse_external_dependency, partition_by_readiness, pert_hours, pert_stddev, priority_weight, queryItems, read_schema_version, renderAgentPrompt, resolve_external_dependencies, risk_penalty, run_hook, run_monte_carlo_chunk, run_plugins_for_event, sample_pert_beta, sample_task_hours, schedule_next, simulate_schedule, stringifyFrontmatter, stringifyYamlContent, task_effort_hours, topological_sort, transition, transitive_dependencies, transitive_dependents, type_weight, updateItem, urgency_weight, validate, validateReferential, validateRepo, validateSemantic, validateStructural, validateTransition, validate_graph, validate_transition, writeTask, writeYamlFile, write_schema_version };
|
|
1497
|
+
export { type AIAgent, type AIResource, type AgentSpec, type AllocationResult, ArtifactType, type AuthConfig, type AuthPolicy, type AutoTransitionResult, type AvailabilityWindow, type BacklogItem, type BacklogItemData, COOP_EVENT_TYPES, CURRENT_SCHEMA_VERSION, type CapacityLedger, type ComparisonResult, type ComparisonRow, type ComputeNode, type ComputeResource, type CoopConfig, type CoopEvent, CoopEventEmitter, type CoopEventType, type CoopProjectRef, type CoopWorkspaceConfig, type CreateItemParams, type CriticalPathResult, type CriticalPathTaskMetrics, DEFAULT_SCORE_WEIGHTS, type Delivery, type DeliveryAtRisk, type DeliveryBudget, type DeliveryCommitted, type DeliveryGovernance, type DeliveryRisk, type DeliveryRiskType, type DeliveryScope, DeliveryStatus, type DetectedDeliveryRisk, type EffectiveCapacity, type EventByType, type ExecutionConstraints, type ExecutionPermissions, ExecutorType, type ExternalDependencyRef, type ExternalDependencyResolution, type ExternalDependencyResolutionStatus, type ExternalDependencyResolverOptions, type ExternalRepoConfig, type FeasibilityResult, type FeasibilityRisk, type FeasibilityStatus, type FeasibilitySummary, type FilterSpec, type FrontmatterParseResult, type GraphCycleDetected, type GraphValidationContext, type GraphValidationResult, type HookRunResult, type HumanMember, type HumanResource, ITEM_STATUSES, ITEM_TYPES, type Idea, IdeaStatus, IndexManager, type IndexStatus, type ItemLinks, type ItemStatus, type ItemType, MIGRATIONS, type MigrateRepositoryOptions, type MigrationContext, type MigrationDefinition, type MigrationReport, type MonteCarloHistogramBucket, type MonteCarloOptions, type MonteCarloResult, type MonteCarloWorkerPayload, type ParsedDelivery, type ParsedIdea, type ParsedTask, type Permission, type PermissionContext, type PluginAction, type PluginActionConsole, type PluginActionGitHubPr, type PluginActionHandler, type PluginActionHandlerResult, type PluginActionWebhook, type PluginManifest, type PluginRunOptions, type PluginRunRecord, type PluginTrigger, type PolicyAction, type ReadinessComputation, type ReadinessPartitions, type ReadinessState, type ReadinessTransitionEvent, type ReadinessWarning, type ReferentialValidationContext, type RepoConfig, type RepoState, type ResourceProfile, RiskLevel, type Role, type Run, type RunCompleted, type RunFailed, type RunResourcesConsumed, type RunStarted, RunStatus, type RunStepResult, RunStepStatus, RunbookAction, type RunbookStep, type ScheduleOptions, type ScoreContext, type ScoredTask, type SemanticValidationContext, type SimulationResult, type StructuralValidationContext, type Task, type TaskAssigned, TaskComplexity, type TaskComputed, type TaskCore, type TaskCreated, TaskDeterminism, type TaskEstimate, type TaskEstimation, type TaskExecution, type TaskGovernance, type TaskGraph, type TaskPlanning, TaskPriority, type TaskResources, type TaskScheduleEntry, TaskStatus, type TaskTransitioned, type TaskTransitionedEvent, TaskType, type Track, type TrackUtilization, type TrackWip, type TransitionContext, type TransitionResult, type TransitionValidationContext, type UpdateItemParams, VALID_TASK_TRANSITIONS, VALID_TRANSITIONS, type ValidationContext, type ValidationError, type ValidationLevel, type ValidationResult, type VelocityMetrics, type VelocityPoint, type VelocityTrend, type WhatIfBaseline, type WhatIfModification, type WriteTaskOptions, allocate, allocate_ai, allocate_ai_tokens, analyze_feasibility, analyze_what_if, build_capacity_ledger, build_graph, check_blocked, check_permission, check_unblocked, check_wip, completeItem, complexity_penalty, compute_all_readiness, compute_critical_path, compute_readiness, compute_readiness_with_corrections, compute_score, compute_velocity, coop_project_config_path, coop_project_root, coop_projects_dir, coop_workspace_config_path, coop_workspace_dir, createItem, create_seeded_rng, critical_path_weight, deleteItem, dependency_unlock_weight, detect_cycle, detect_delivery_risks, determinism_weight, effective_weekly_hours, effort_or_default, ensureCoopLayout, ensure_workspace_layout, executor_fit_weight, external_dependencies_for_task, extract_subgraph, findRepoRoot, find_external_dependencies, getItemById, get_remaining_tokens, get_user_role, has_legacy_project_layout, has_v2_projects_layout, is_external_dependency, is_project_initialized, list_projects, loadState, load_auth_config, load_completed_runs, load_graph, load_plugins, migrate_repository, migrate_task, monte_carlo_forecast, parseDeliveryContent, parseDeliveryFile, parseFrontmatterContent, parseFrontmatterFile, parseIdeaContent, parseIdeaFile, parseTaskContent, parseTaskFile, parseYamlContent, parseYamlFile, parse_external_dependency, partition_by_readiness, pert_hours, pert_stddev, priority_weight, queryItems, read_project_config, read_schema_version, read_workspace_config, renderAgentPrompt, repo_default_project_id, repo_default_project_name, resolve_external_dependencies, resolve_project, risk_penalty, run_hook, run_monte_carlo_chunk, run_plugins_for_event, sample_pert_beta, sample_task_hours, schedule_next, simulate_schedule, stringifyFrontmatter, stringifyYamlContent, task_effort_hours, topological_sort, transition, transitive_dependencies, transitive_dependents, type_weight, updateItem, urgency_weight, validate, validateReferential, validateRepo, validateSemantic, validateStructural, validateTransition, validate_graph, validate_transition, writeTask, writeYamlFile, write_schema_version, write_workspace_config };
|
package/dist/index.js
CHANGED
|
@@ -1966,6 +1966,9 @@ var TASK_FIELD_ORDER = [
|
|
|
1966
1966
|
"depends_on",
|
|
1967
1967
|
"tags",
|
|
1968
1968
|
"delivery",
|
|
1969
|
+
"acceptance",
|
|
1970
|
+
"tests_required",
|
|
1971
|
+
"origin",
|
|
1969
1972
|
"complexity",
|
|
1970
1973
|
"determinism",
|
|
1971
1974
|
"estimate",
|
|
@@ -3627,6 +3630,7 @@ import path8 from "path";
|
|
|
3627
3630
|
var ID_PATTERN = /^[A-Z0-9]+(?:-[A-Z0-9]+)+$/;
|
|
3628
3631
|
var ALIAS_PATTERN = /^[A-Z0-9]+(?:[.-][A-Z0-9]+)*$/;
|
|
3629
3632
|
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
3633
|
+
var SHA256_RE = /^[a-f0-9]{64}$/i;
|
|
3630
3634
|
function error4(field, rule, message) {
|
|
3631
3635
|
return { level: "error", field, rule, message };
|
|
3632
3636
|
}
|
|
@@ -3640,6 +3644,23 @@ function isIsoDate(value) {
|
|
|
3640
3644
|
}
|
|
3641
3645
|
return date.toISOString().slice(0, 10) === value;
|
|
3642
3646
|
}
|
|
3647
|
+
function validateStringArrayField(errors, field, value, options = {}) {
|
|
3648
|
+
if (value === void 0) {
|
|
3649
|
+
return;
|
|
3650
|
+
}
|
|
3651
|
+
if (!Array.isArray(value)) {
|
|
3652
|
+
errors.push(error4(field, `struct.${field}_array`, `Field '${field}' must be an array of strings.`));
|
|
3653
|
+
return;
|
|
3654
|
+
}
|
|
3655
|
+
for (const entry of value) {
|
|
3656
|
+
if (typeof entry !== "string" || entry.trim().length < (options.minLength ?? 1)) {
|
|
3657
|
+
errors.push(
|
|
3658
|
+
error4(field, `struct.${field}_string`, `Field '${field}' entries must be non-empty strings.`)
|
|
3659
|
+
);
|
|
3660
|
+
return;
|
|
3661
|
+
}
|
|
3662
|
+
}
|
|
3663
|
+
}
|
|
3643
3664
|
function validateStructural(task, context = {}) {
|
|
3644
3665
|
const errors = [];
|
|
3645
3666
|
const required = ["id", "title", "type", "status", "created", "updated"];
|
|
@@ -3704,6 +3725,27 @@ function validateStructural(task, context = {}) {
|
|
|
3704
3725
|
}
|
|
3705
3726
|
}
|
|
3706
3727
|
}
|
|
3728
|
+
validateStringArrayField(errors, "acceptance", task.acceptance);
|
|
3729
|
+
validateStringArrayField(errors, "tests_required", task.tests_required);
|
|
3730
|
+
if (task.origin !== void 0) {
|
|
3731
|
+
if (!task.origin || typeof task.origin !== "object" || Array.isArray(task.origin)) {
|
|
3732
|
+
errors.push(error4("origin", "struct.origin_object", "Field 'origin' must be an object."));
|
|
3733
|
+
} else {
|
|
3734
|
+
validateStringArrayField(errors, "origin.authority_refs", task.origin.authority_refs);
|
|
3735
|
+
validateStringArrayField(errors, "origin.derived_refs", task.origin.derived_refs);
|
|
3736
|
+
validateStringArrayField(errors, "origin.promoted_from", task.origin.promoted_from);
|
|
3737
|
+
validateStringArrayField(errors, "origin.promoted_to", task.origin.promoted_to);
|
|
3738
|
+
if (task.origin.snapshot_sha256 !== void 0 && (typeof task.origin.snapshot_sha256 !== "string" || !SHA256_RE.test(task.origin.snapshot_sha256))) {
|
|
3739
|
+
errors.push(
|
|
3740
|
+
error4(
|
|
3741
|
+
"origin.snapshot_sha256",
|
|
3742
|
+
"struct.origin_snapshot_sha256",
|
|
3743
|
+
"Field 'origin.snapshot_sha256' must be a 64-character SHA-256 hex string."
|
|
3744
|
+
)
|
|
3745
|
+
);
|
|
3746
|
+
}
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3707
3749
|
return errors;
|
|
3708
3750
|
}
|
|
3709
3751
|
|
|
@@ -3791,9 +3833,131 @@ function validate(task, context = {}) {
|
|
|
3791
3833
|
};
|
|
3792
3834
|
}
|
|
3793
3835
|
|
|
3794
|
-
// src/
|
|
3836
|
+
// src/workspace.ts
|
|
3795
3837
|
import fs13 from "fs";
|
|
3796
3838
|
import path9 from "path";
|
|
3839
|
+
var COOP_DIR_NAME = ".coop";
|
|
3840
|
+
function sanitizeProjectId(value, fallback) {
|
|
3841
|
+
const normalized = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-");
|
|
3842
|
+
return normalized || fallback;
|
|
3843
|
+
}
|
|
3844
|
+
function coop_workspace_dir(repoRoot) {
|
|
3845
|
+
return path9.join(path9.resolve(repoRoot), COOP_DIR_NAME);
|
|
3846
|
+
}
|
|
3847
|
+
function coop_projects_dir(repoRoot) {
|
|
3848
|
+
return path9.join(coop_workspace_dir(repoRoot), "projects");
|
|
3849
|
+
}
|
|
3850
|
+
function coop_workspace_config_path(repoRoot) {
|
|
3851
|
+
return path9.join(coop_workspace_dir(repoRoot), "config.yml");
|
|
3852
|
+
}
|
|
3853
|
+
function coop_project_root(repoRoot, projectId) {
|
|
3854
|
+
return path9.join(coop_projects_dir(repoRoot), projectId);
|
|
3855
|
+
}
|
|
3856
|
+
function coop_project_config_path(projectRoot) {
|
|
3857
|
+
return path9.join(projectRoot, "config.yml");
|
|
3858
|
+
}
|
|
3859
|
+
function repo_default_project_id(repoRoot) {
|
|
3860
|
+
return sanitizeProjectId(path9.basename(path9.resolve(repoRoot)), "workspace");
|
|
3861
|
+
}
|
|
3862
|
+
function repo_default_project_name(repoRoot) {
|
|
3863
|
+
const base = path9.basename(path9.resolve(repoRoot)).trim();
|
|
3864
|
+
return base || "COOP Workspace";
|
|
3865
|
+
}
|
|
3866
|
+
function has_v2_projects_layout(repoRoot) {
|
|
3867
|
+
return fs13.existsSync(coop_projects_dir(repoRoot));
|
|
3868
|
+
}
|
|
3869
|
+
function has_legacy_project_layout(repoRoot) {
|
|
3870
|
+
const workspaceDir = coop_workspace_dir(repoRoot);
|
|
3871
|
+
return fs13.existsSync(workspaceDir) && fs13.existsSync(path9.join(workspaceDir, "config.yml")) && !fs13.existsSync(coop_projects_dir(repoRoot));
|
|
3872
|
+
}
|
|
3873
|
+
function read_workspace_config(repoRoot) {
|
|
3874
|
+
const configPath = coop_workspace_config_path(repoRoot);
|
|
3875
|
+
if (!fs13.existsSync(configPath) || has_legacy_project_layout(repoRoot)) {
|
|
3876
|
+
return { version: 2 };
|
|
3877
|
+
}
|
|
3878
|
+
return parseYamlFile(configPath);
|
|
3879
|
+
}
|
|
3880
|
+
function write_workspace_config(repoRoot, config) {
|
|
3881
|
+
fs13.mkdirSync(coop_workspace_dir(repoRoot), { recursive: true });
|
|
3882
|
+
writeYamlFile(coop_workspace_config_path(repoRoot), {
|
|
3883
|
+
version: config.version ?? 2,
|
|
3884
|
+
...config.current_project ? { current_project: config.current_project } : {}
|
|
3885
|
+
});
|
|
3886
|
+
}
|
|
3887
|
+
function read_project_config(projectRoot) {
|
|
3888
|
+
return parseYamlFile(coop_project_config_path(projectRoot));
|
|
3889
|
+
}
|
|
3890
|
+
function project_ref_from_config(repoRoot, projectRoot, layout) {
|
|
3891
|
+
const config = read_project_config(projectRoot);
|
|
3892
|
+
const repoName = repo_default_project_name(repoRoot);
|
|
3893
|
+
const fallbackId = repo_default_project_id(repoRoot);
|
|
3894
|
+
return {
|
|
3895
|
+
id: sanitizeProjectId(config.project?.id ?? fallbackId, fallbackId),
|
|
3896
|
+
name: config.project?.name?.trim() || repoName,
|
|
3897
|
+
aliases: Array.isArray(config.project?.aliases) ? config.project.aliases.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [],
|
|
3898
|
+
root: projectRoot,
|
|
3899
|
+
repo_root: path9.resolve(repoRoot),
|
|
3900
|
+
layout
|
|
3901
|
+
};
|
|
3902
|
+
}
|
|
3903
|
+
function list_projects(repoRoot) {
|
|
3904
|
+
if (has_v2_projects_layout(repoRoot)) {
|
|
3905
|
+
const projectsDir = coop_projects_dir(repoRoot);
|
|
3906
|
+
return fs13.readdirSync(projectsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path9.join(projectsDir, entry.name)).filter((projectRoot) => fs13.existsSync(coop_project_config_path(projectRoot))).map((projectRoot) => project_ref_from_config(repoRoot, projectRoot, "v2")).sort((a, b) => a.id.localeCompare(b.id));
|
|
3907
|
+
}
|
|
3908
|
+
if (has_legacy_project_layout(repoRoot)) {
|
|
3909
|
+
return [project_ref_from_config(repoRoot, coop_workspace_dir(repoRoot), "legacy")];
|
|
3910
|
+
}
|
|
3911
|
+
return [];
|
|
3912
|
+
}
|
|
3913
|
+
function resolve_project(repoRoot, options = {}) {
|
|
3914
|
+
const projects = list_projects(repoRoot);
|
|
3915
|
+
const requested = options.project?.trim().toLowerCase();
|
|
3916
|
+
if (requested) {
|
|
3917
|
+
const match = projects.find(
|
|
3918
|
+
(project) => project.id.toLowerCase() === requested || project.name.toLowerCase() === requested || project.aliases.some((alias) => alias.toLowerCase() === requested)
|
|
3919
|
+
);
|
|
3920
|
+
if (!match) {
|
|
3921
|
+
throw new Error(`Project '${options.project}' not found.`);
|
|
3922
|
+
}
|
|
3923
|
+
return match;
|
|
3924
|
+
}
|
|
3925
|
+
if (projects.length === 1) {
|
|
3926
|
+
return projects[0];
|
|
3927
|
+
}
|
|
3928
|
+
const workspaceConfig = read_workspace_config(repoRoot);
|
|
3929
|
+
if (workspaceConfig.current_project) {
|
|
3930
|
+
const match = projects.find((project) => project.id === workspaceConfig.current_project);
|
|
3931
|
+
if (match) return match;
|
|
3932
|
+
}
|
|
3933
|
+
if (!options.require && projects.length === 0) {
|
|
3934
|
+
return {
|
|
3935
|
+
id: repo_default_project_id(repoRoot),
|
|
3936
|
+
name: repo_default_project_name(repoRoot),
|
|
3937
|
+
aliases: [],
|
|
3938
|
+
root: coop_project_root(repoRoot, repo_default_project_id(repoRoot)),
|
|
3939
|
+
repo_root: path9.resolve(repoRoot),
|
|
3940
|
+
layout: "v2"
|
|
3941
|
+
};
|
|
3942
|
+
}
|
|
3943
|
+
if (projects.length === 0) {
|
|
3944
|
+
throw new Error("No COOP project found. Run 'coop init'.");
|
|
3945
|
+
}
|
|
3946
|
+
throw new Error("Multiple COOP projects found. Pass --project <id> or run 'coop project use <id>'.");
|
|
3947
|
+
}
|
|
3948
|
+
function ensure_workspace_layout(repoRoot) {
|
|
3949
|
+
const workspaceDir = coop_workspace_dir(repoRoot);
|
|
3950
|
+
fs13.mkdirSync(workspaceDir, { recursive: true });
|
|
3951
|
+
fs13.mkdirSync(coop_projects_dir(repoRoot), { recursive: true });
|
|
3952
|
+
return workspaceDir;
|
|
3953
|
+
}
|
|
3954
|
+
function is_project_initialized(projectRoot) {
|
|
3955
|
+
return fs13.existsSync(coop_project_config_path(projectRoot));
|
|
3956
|
+
}
|
|
3957
|
+
|
|
3958
|
+
// src/core.ts
|
|
3959
|
+
import fs14 from "fs";
|
|
3960
|
+
import path10 from "path";
|
|
3797
3961
|
import matter from "gray-matter";
|
|
3798
3962
|
|
|
3799
3963
|
// src/types.ts
|
|
@@ -3819,17 +3983,17 @@ function toIdKey(value) {
|
|
|
3819
3983
|
return value.trim().toUpperCase();
|
|
3820
3984
|
}
|
|
3821
3985
|
function repoRootByPackage(cwd) {
|
|
3822
|
-
let current =
|
|
3986
|
+
let current = path10.resolve(cwd);
|
|
3823
3987
|
let lastWorkspaceRoot = null;
|
|
3824
3988
|
while (true) {
|
|
3825
|
-
const packageJson =
|
|
3826
|
-
const workspaceYaml =
|
|
3827
|
-
if (
|
|
3989
|
+
const packageJson = path10.join(current, "package.json");
|
|
3990
|
+
const workspaceYaml = path10.join(current, "pnpm-workspace.yaml");
|
|
3991
|
+
if (fs14.existsSync(packageJson) && fs14.existsSync(workspaceYaml)) {
|
|
3828
3992
|
lastWorkspaceRoot = current;
|
|
3829
|
-
const hasCoop =
|
|
3993
|
+
const hasCoop = fs14.existsSync(path10.join(current, COOP_DIR, "config.yml"));
|
|
3830
3994
|
if (hasCoop) return current;
|
|
3831
3995
|
}
|
|
3832
|
-
const parent =
|
|
3996
|
+
const parent = path10.dirname(current);
|
|
3833
3997
|
if (parent === current) return lastWorkspaceRoot;
|
|
3834
3998
|
current = parent;
|
|
3835
3999
|
}
|
|
@@ -3838,24 +4002,24 @@ function findRepoRoot(cwd = process.cwd()) {
|
|
|
3838
4002
|
return repoRootByPackage(cwd);
|
|
3839
4003
|
}
|
|
3840
4004
|
function configPathFor(rootDir, workspaceDir) {
|
|
3841
|
-
return
|
|
4005
|
+
return path10.join(rootDir, workspaceDir, "config.yml");
|
|
3842
4006
|
}
|
|
3843
4007
|
function backlogPathFor(rootDir, workspaceDir) {
|
|
3844
|
-
return
|
|
4008
|
+
return path10.join(rootDir, workspaceDir, "backlog");
|
|
3845
4009
|
}
|
|
3846
4010
|
function releasesPathFor(rootDir, workspaceDir) {
|
|
3847
|
-
return
|
|
4011
|
+
return path10.join(rootDir, workspaceDir, "releases");
|
|
3848
4012
|
}
|
|
3849
4013
|
function detectWorkspaceDir(rootDir) {
|
|
3850
|
-
if (
|
|
3851
|
-
if (
|
|
4014
|
+
if (fs14.existsSync(configPathFor(rootDir, COOP_DIR))) return COOP_DIR;
|
|
4015
|
+
if (fs14.existsSync(path10.join(rootDir, COOP_DIR))) return COOP_DIR;
|
|
3852
4016
|
return null;
|
|
3853
4017
|
}
|
|
3854
4018
|
function preferredWorkspaceDir(rootDir) {
|
|
3855
4019
|
return detectWorkspaceDir(rootDir) ?? COOP_DIR;
|
|
3856
4020
|
}
|
|
3857
4021
|
function missingConfigError(rootDir) {
|
|
3858
|
-
const coopConfig =
|
|
4022
|
+
const coopConfig = path10.relative(rootDir, configPathFor(rootDir, COOP_DIR));
|
|
3859
4023
|
return new Error(`COOP config missing at ${coopConfig}. Run: coop init`);
|
|
3860
4024
|
}
|
|
3861
4025
|
function parseConfig(raw) {
|
|
@@ -3901,10 +4065,10 @@ function configToString(config) {
|
|
|
3901
4065
|
return lines.join("\n");
|
|
3902
4066
|
}
|
|
3903
4067
|
function toPortablePath(value) {
|
|
3904
|
-
return value.split(
|
|
4068
|
+
return value.split(path10.sep).join("/");
|
|
3905
4069
|
}
|
|
3906
4070
|
function ensureReleasesDir(rootDir, workspaceDir) {
|
|
3907
|
-
|
|
4071
|
+
fs14.mkdirSync(releasesPathFor(rootDir, workspaceDir), { recursive: true });
|
|
3908
4072
|
}
|
|
3909
4073
|
function releaseHeader(date) {
|
|
3910
4074
|
return `## ${date}`;
|
|
@@ -3926,12 +4090,12 @@ function appendReleaseEntry(rootDir, workspaceDir, item, previousStatus, nextSta
|
|
|
3926
4090
|
ensureReleasesDir(rootDir, workspaceDir);
|
|
3927
4091
|
const now = /* @__PURE__ */ new Date();
|
|
3928
4092
|
const date = now.toISOString().slice(0, 10);
|
|
3929
|
-
const releasePath =
|
|
4093
|
+
const releasePath = path10.join(releasesPathFor(rootDir, workspaceDir), `${date}.md`);
|
|
3930
4094
|
const heading = "# COOP Release Notes";
|
|
3931
4095
|
const dayHeader = releaseHeader(date);
|
|
3932
4096
|
const entry = releaseEntryLine(item, previousStatus, nextStatus);
|
|
3933
|
-
if (!
|
|
3934
|
-
|
|
4097
|
+
if (!fs14.existsSync(releasePath)) {
|
|
4098
|
+
fs14.writeFileSync(
|
|
3935
4099
|
releasePath,
|
|
3936
4100
|
[
|
|
3937
4101
|
`${heading}
|
|
@@ -3944,10 +4108,10 @@ function appendReleaseEntry(rootDir, workspaceDir, item, previousStatus, nextSta
|
|
|
3944
4108
|
].join("\n"),
|
|
3945
4109
|
"utf8"
|
|
3946
4110
|
);
|
|
3947
|
-
return toPortablePath(
|
|
4111
|
+
return toPortablePath(path10.relative(rootDir, releasePath));
|
|
3948
4112
|
}
|
|
3949
|
-
const existing =
|
|
3950
|
-
if (hasReleaseEntry(existing, item.id)) return toPortablePath(
|
|
4113
|
+
const existing = fs14.readFileSync(releasePath, "utf8");
|
|
4114
|
+
if (hasReleaseEntry(existing, item.id)) return toPortablePath(path10.relative(rootDir, releasePath));
|
|
3951
4115
|
let nextContent = existing;
|
|
3952
4116
|
if (!existing.includes(`## ${date}`)) {
|
|
3953
4117
|
if (!nextContent.endsWith("\n")) nextContent += "\n";
|
|
@@ -3957,9 +4121,9 @@ function appendReleaseEntry(rootDir, workspaceDir, item, previousStatus, nextSta
|
|
|
3957
4121
|
if (!nextContent.endsWith("\n")) nextContent += "\n";
|
|
3958
4122
|
nextContent += `${entry}
|
|
3959
4123
|
`;
|
|
3960
|
-
|
|
4124
|
+
fs14.writeFileSync(releasePath, `${nextContent}
|
|
3961
4125
|
`, "utf8");
|
|
3962
|
-
return toPortablePath(
|
|
4126
|
+
return toPortablePath(path10.relative(rootDir, releasePath));
|
|
3963
4127
|
}
|
|
3964
4128
|
function completeItem(rootDir, id) {
|
|
3965
4129
|
const state = loadState(rootDir);
|
|
@@ -4037,28 +4201,28 @@ function validateAndNormalize(data, sourceFile) {
|
|
|
4037
4201
|
};
|
|
4038
4202
|
}
|
|
4039
4203
|
function parseItem(filePath, rootDir) {
|
|
4040
|
-
const raw =
|
|
4204
|
+
const raw = fs14.readFileSync(filePath, "utf8");
|
|
4041
4205
|
const parsed = matter(raw);
|
|
4042
|
-
const data = validateAndNormalize(parsed.data,
|
|
4206
|
+
const data = validateAndNormalize(parsed.data, path10.relative(rootDir, filePath));
|
|
4043
4207
|
return {
|
|
4044
4208
|
...data,
|
|
4045
4209
|
body: parsed.content || "",
|
|
4046
|
-
filePath:
|
|
4210
|
+
filePath: path10.relative(rootDir, filePath)
|
|
4047
4211
|
};
|
|
4048
4212
|
}
|
|
4049
4213
|
function walk(dir) {
|
|
4050
4214
|
const out = [];
|
|
4051
|
-
if (!
|
|
4052
|
-
const entries =
|
|
4215
|
+
if (!fs14.existsSync(dir)) return out;
|
|
4216
|
+
const entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
4053
4217
|
for (const entry of entries) {
|
|
4054
|
-
const file =
|
|
4218
|
+
const file = path10.join(dir, entry.name);
|
|
4055
4219
|
if (entry.isDirectory()) out.push(...walk(file));
|
|
4056
4220
|
if (entry.isFile() && file.endsWith(".md")) out.push(file);
|
|
4057
4221
|
}
|
|
4058
4222
|
return out;
|
|
4059
4223
|
}
|
|
4060
4224
|
function itemPath(type, id, rootDir, workspaceDir) {
|
|
4061
|
-
return
|
|
4225
|
+
return path10.join(backlogPathFor(rootDir, workspaceDir), ITEM_DIRS[type], `${id}.md`);
|
|
4062
4226
|
}
|
|
4063
4227
|
function normalizeFrontmatterValue(value) {
|
|
4064
4228
|
if (value == null) return void 0;
|
|
@@ -4145,30 +4309,30 @@ function nextGeneratedId(config, title, existing) {
|
|
|
4145
4309
|
}
|
|
4146
4310
|
function ensureCoopLayout(rootDir) {
|
|
4147
4311
|
const workspaceDir = preferredWorkspaceDir(rootDir);
|
|
4148
|
-
const root =
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4312
|
+
const root = path10.join(rootDir, workspaceDir);
|
|
4313
|
+
fs14.mkdirSync(root, { recursive: true });
|
|
4314
|
+
fs14.mkdirSync(path10.join(root, "releases"), { recursive: true });
|
|
4315
|
+
fs14.mkdirSync(path10.join(root, "plans"), { recursive: true });
|
|
4316
|
+
fs14.mkdirSync(path10.join(root, "views"), { recursive: true });
|
|
4317
|
+
fs14.mkdirSync(path10.join(root, "templates"), { recursive: true });
|
|
4154
4318
|
for (const dir of Object.values(ITEM_DIRS)) {
|
|
4155
|
-
|
|
4319
|
+
fs14.mkdirSync(path10.join(root, "backlog", dir), { recursive: true });
|
|
4156
4320
|
}
|
|
4157
|
-
const configFile =
|
|
4158
|
-
if (!
|
|
4159
|
-
|
|
4321
|
+
const configFile = path10.join(root, "config.yml");
|
|
4322
|
+
if (!fs14.existsSync(configFile)) {
|
|
4323
|
+
fs14.writeFileSync(configFile, configToString(DEFAULT_CONFIG2), "utf8");
|
|
4160
4324
|
}
|
|
4161
4325
|
}
|
|
4162
4326
|
function loadState(rootDir) {
|
|
4163
4327
|
const workspaceDir = detectWorkspaceDir(rootDir);
|
|
4164
4328
|
if (!workspaceDir) throw missingConfigError(rootDir);
|
|
4165
4329
|
const configPath = configPathFor(rootDir, workspaceDir);
|
|
4166
|
-
if (!
|
|
4167
|
-
const config = parseConfig(
|
|
4330
|
+
if (!fs14.existsSync(configPath)) throw missingConfigError(rootDir);
|
|
4331
|
+
const config = parseConfig(fs14.readFileSync(configPath, "utf8"));
|
|
4168
4332
|
const items = [];
|
|
4169
4333
|
const itemsById = /* @__PURE__ */ new Map();
|
|
4170
4334
|
for (const type of ITEM_TYPES) {
|
|
4171
|
-
const dir =
|
|
4335
|
+
const dir = path10.join(backlogPathFor(rootDir, workspaceDir), ITEM_DIRS[type]);
|
|
4172
4336
|
const files = walk(dir);
|
|
4173
4337
|
for (const file of files) {
|
|
4174
4338
|
const item = parseItem(file, rootDir);
|
|
@@ -4252,21 +4416,21 @@ function createItem(rootDir, params) {
|
|
|
4252
4416
|
parent_id: params.parent_id
|
|
4253
4417
|
};
|
|
4254
4418
|
const itemPathName = itemPath(params.type, item.id, rootDir, state.workspaceDir);
|
|
4255
|
-
|
|
4419
|
+
fs14.writeFileSync(itemPathName, serialize(item, params.body || ""), "utf8");
|
|
4256
4420
|
if ((config.id_strategy ?? "text") === "counter") {
|
|
4257
4421
|
const numericMatch = /-(\d+)$/.exec(item.id);
|
|
4258
4422
|
if (numericMatch) {
|
|
4259
4423
|
const numericValue = Number(numericMatch[1]);
|
|
4260
4424
|
if (Number.isInteger(numericValue) && numericValue >= (config.next_id ?? 1)) {
|
|
4261
4425
|
config.next_id = numericValue + 1;
|
|
4262
|
-
|
|
4426
|
+
fs14.writeFileSync(configPathFor(rootDir, state.workspaceDir), configToString(config), "utf8");
|
|
4263
4427
|
}
|
|
4264
4428
|
}
|
|
4265
4429
|
}
|
|
4266
4430
|
return {
|
|
4267
4431
|
...item,
|
|
4268
4432
|
body: params.body || "",
|
|
4269
|
-
filePath:
|
|
4433
|
+
filePath: path10.relative(rootDir, itemPathName)
|
|
4270
4434
|
};
|
|
4271
4435
|
}
|
|
4272
4436
|
function updateItem(rootDir, id, patch) {
|
|
@@ -4292,8 +4456,8 @@ function updateItem(rootDir, id, patch) {
|
|
|
4292
4456
|
};
|
|
4293
4457
|
if (!ITEM_TYPES.includes(next.type)) throw new Error(`Unknown type ${next.type}.`);
|
|
4294
4458
|
if (!ITEM_STATUSES.includes(next.status)) throw new Error(`Unknown status ${next.status}.`);
|
|
4295
|
-
const filePath =
|
|
4296
|
-
|
|
4459
|
+
const filePath = path10.join(rootDir, existing.filePath);
|
|
4460
|
+
fs14.writeFileSync(filePath, serialize(next, patch.body || existing.body), "utf8");
|
|
4297
4461
|
return {
|
|
4298
4462
|
...next,
|
|
4299
4463
|
body: patch.body || existing.body,
|
|
@@ -4309,7 +4473,7 @@ function deleteItem(rootDir, id) {
|
|
|
4309
4473
|
if (children.length > 0) {
|
|
4310
4474
|
throw new Error(`Cannot delete ${existing.id} because it has ${children.length} child item(s). Remove children first.`);
|
|
4311
4475
|
}
|
|
4312
|
-
|
|
4476
|
+
fs14.unlinkSync(path10.join(rootDir, existing.filePath));
|
|
4313
4477
|
return existing;
|
|
4314
4478
|
}
|
|
4315
4479
|
function renderAgentPrompt(item) {
|
|
@@ -4348,8 +4512,8 @@ function validateRepo(rootDir) {
|
|
|
4348
4512
|
const errors = [];
|
|
4349
4513
|
const warnings = [];
|
|
4350
4514
|
const workspaceDir = detectWorkspaceDir(rootDir);
|
|
4351
|
-
if (!workspaceDir || !
|
|
4352
|
-
errors.push("Missing
|
|
4515
|
+
if (!workspaceDir || !fs14.existsSync(configPathFor(rootDir, workspaceDir))) {
|
|
4516
|
+
errors.push("Missing COOP config. Run coop init first.");
|
|
4353
4517
|
return { valid: false, errors, warnings };
|
|
4354
4518
|
}
|
|
4355
4519
|
let state;
|
|
@@ -4422,6 +4586,11 @@ export {
|
|
|
4422
4586
|
compute_readiness_with_corrections,
|
|
4423
4587
|
compute_score,
|
|
4424
4588
|
compute_velocity,
|
|
4589
|
+
coop_project_config_path,
|
|
4590
|
+
coop_project_root,
|
|
4591
|
+
coop_projects_dir,
|
|
4592
|
+
coop_workspace_config_path,
|
|
4593
|
+
coop_workspace_dir,
|
|
4425
4594
|
createItem,
|
|
4426
4595
|
create_seeded_rng,
|
|
4427
4596
|
critical_path_weight,
|
|
@@ -4433,6 +4602,7 @@ export {
|
|
|
4433
4602
|
effective_weekly_hours,
|
|
4434
4603
|
effort_or_default,
|
|
4435
4604
|
ensureCoopLayout,
|
|
4605
|
+
ensure_workspace_layout,
|
|
4436
4606
|
executor_fit_weight,
|
|
4437
4607
|
external_dependencies_for_task,
|
|
4438
4608
|
extract_subgraph,
|
|
@@ -4441,7 +4611,11 @@ export {
|
|
|
4441
4611
|
getItemById,
|
|
4442
4612
|
get_remaining_tokens,
|
|
4443
4613
|
get_user_role,
|
|
4614
|
+
has_legacy_project_layout,
|
|
4615
|
+
has_v2_projects_layout,
|
|
4444
4616
|
is_external_dependency,
|
|
4617
|
+
is_project_initialized,
|
|
4618
|
+
list_projects,
|
|
4445
4619
|
loadState,
|
|
4446
4620
|
load_auth_config,
|
|
4447
4621
|
load_completed_runs,
|
|
@@ -4466,9 +4640,14 @@ export {
|
|
|
4466
4640
|
pert_stddev,
|
|
4467
4641
|
priority_weight,
|
|
4468
4642
|
queryItems,
|
|
4643
|
+
read_project_config,
|
|
4469
4644
|
read_schema_version,
|
|
4645
|
+
read_workspace_config,
|
|
4470
4646
|
renderAgentPrompt,
|
|
4647
|
+
repo_default_project_id,
|
|
4648
|
+
repo_default_project_name,
|
|
4471
4649
|
resolve_external_dependencies,
|
|
4650
|
+
resolve_project,
|
|
4472
4651
|
risk_penalty,
|
|
4473
4652
|
run_hook,
|
|
4474
4653
|
run_monte_carlo_chunk,
|
|
@@ -4497,5 +4676,6 @@ export {
|
|
|
4497
4676
|
validate_transition,
|
|
4498
4677
|
writeTask,
|
|
4499
4678
|
writeYamlFile,
|
|
4500
|
-
write_schema_version
|
|
4679
|
+
write_schema_version,
|
|
4680
|
+
write_workspace_config
|
|
4501
4681
|
};
|