@godv61/dsh-task-engine 0.24.0 → 0.26.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/.acceptance.mjs +101 -39
- package/.assessment-batch1.mjs +32 -12
- package/.e2e-presets.mjs +40 -5
- package/.enforce-test.mjs +139 -0
- package/.evidence-test.mjs +118 -0
- package/.filter-test.mjs +93 -0
- package/.freeze-test.mjs +110 -1
- package/.hook-test.mjs +195 -190
- package/.p0-test.mjs +130 -46
- package/.preset-test.mjs +160 -160
- package/.revision-test.mjs +32 -3
- package/.roundtrip-test.mjs +178 -0
- package/.workflow-test.mjs +117 -4
- package/README.md +10 -8
- package/cordis.patch.yml +10 -10
- package/defaults/eng.json +70 -22
- package/docs/BRIEF-FOR-REVIEW.md +162 -162
- package/docs/CHANGELOG.md +49 -0
- package/docs/README.md +40 -40
- package/docs/configuration.md +14 -11
- package/docs/development.md +1 -1
- package/docs/faq.md +4 -4
- package/docs/listing/godv61__dsh-task-engine.yml +5 -5
- package/docs/listing/submission.md +83 -83
- package/docs/manual.html +31 -26
- package/docs/releases/0.23.2.md +21 -21
- package/docs/roadmap.md +34 -34
- package/docs/testing/0.23.2/R02/344/270/232/345/212/241/346/265/213/350/257/225/346/230/216/347/273/206.md +56 -56
- package/docs/testing/0.23.2/R03/344/270/232/345/212/241/346/265/213/350/257/225/346/230/216/347/273/206.md +38 -38
- package/docs/testing/0.23.2//346/265/213/350/257/225/346/212/245/345/221/212.md +65 -65
- package/hooks/commit-msg +159 -72
- package/lib/client.js +963 -571
- package/lib/client.js.map +3 -3
- package/lib/controller.d.ts +11 -2
- package/lib/controller.js +33 -5
- package/lib/controller.js.map +1 -1
- package/lib/dev-task.js +170 -28
- package/lib/dev-task.js.map +1 -1
- package/lib/engine.d.ts +105 -0
- package/lib/engine.js +93 -5
- package/lib/engine.js.map +1 -1
- package/lib/hook.js +17 -4
- package/lib/hook.js.map +1 -1
- package/lib/skill-audit.d.ts +14 -3
- package/lib/skill-audit.js +66 -3
- package/lib/skill-audit.js.map +1 -1
- package/lib/workflows.d.ts +78 -12
- package/lib/workflows.js +258 -94
- package/lib/workflows.js.map +1 -1
- package/package.json +9 -5
- package/preset/agent.cordis.yml +21 -21
- package/preset/enable.mjs +87 -87
- package/preset/persona.md +4 -4
- package/preset/preset.yml +1 -1
- package/rules/coding-conventions.md +6 -6
- package/rules/commit-conventions.md +6 -6
- package/rules/security-redlines.md +5 -5
- package/scripts/verify-dsh-compat.mjs +144 -144
- package/scripts/verify-package.mjs +1 -1
- package/skills/code-verify/SKILL.md +3 -3
package/.workflow-test.mjs
CHANGED
|
@@ -5,14 +5,41 @@ import { tmpdir } from 'node:os'
|
|
|
5
5
|
import { join, resolve, sep } from 'node:path'
|
|
6
6
|
import { registerDevTask } from './lib/dev-task.js'
|
|
7
7
|
import { newTask } from './lib/engine.js'
|
|
8
|
-
import { resolveFlow } from './lib/workflows.js'
|
|
8
|
+
import { adoptRecommendation, resolveFlow } from './lib/workflows.js'
|
|
9
9
|
import Controller from './lib/controller.js'
|
|
10
10
|
import { registerShippedSkills } from './lib/shipped-skills.js'
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* The preset as a project would actually run it: the skeleton plus the shipped
|
|
14
|
+
* recommendation, adopted exactly the way a user adopts it. A test that asserts
|
|
15
|
+
* on bindings, commit rules or artifacts wants this, because those no longer come
|
|
16
|
+
* from the preset itself.
|
|
17
|
+
* @param {string} id - preset id.
|
|
18
|
+
* @returns {import('./lib/engine.js').WorkflowConfig} the adopted config.
|
|
19
|
+
*/
|
|
20
|
+
function adoptedFlow(id, extra) {
|
|
21
|
+
const base = adoptRecommendation(id)
|
|
22
|
+
if (base === undefined) throw new Error('unknown preset: ' + id)
|
|
23
|
+
return resolveFlow(id, { ...base, ...extra }).config
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
12
27
|
function fixture(stage = '开发', extra = {}, services = {}) {
|
|
13
28
|
const cwd = resolve('test-project')
|
|
14
|
-
|
|
15
|
-
|
|
29
|
+
// A project running the standard flow: the skeleton plus the adopted
|
|
30
|
+
// recommendation, with one extra skill mounted on 完成 for the tests that need
|
|
31
|
+
// a binding beyond the shipped set. The bindings are MERGED, not replaced —
|
|
32
|
+
// replacing them would drop the recommended skills and artifacts the tests
|
|
33
|
+
// assert on, since the preset skeleton itself carries none.
|
|
34
|
+
const adopted = adoptRecommendation('standard')
|
|
35
|
+
const config = resolveFlow('standard', {
|
|
36
|
+
...adopted,
|
|
37
|
+
stage_bindings: {
|
|
38
|
+
...adopted.stage_bindings,
|
|
39
|
+
完成: { skills: [{ skill: { source: 'bundled', name: 'software-testing' }, rules: [] }] },
|
|
40
|
+
},
|
|
41
|
+
}).config
|
|
42
|
+
const state = newTask({ id: 'LIVE-1', title: 'EAM regression', branch: 'test', work_size: 'standard', risk_level: 'standard', flow: { flow: 'standard', version: 3, config }, root: cwd })
|
|
16
43
|
Object.assign(state, { stage, execution_version: 1, files: ['app.js'], requirement_confirmed: true, solution_confirmed: true, ...extra })
|
|
17
44
|
const records = new Map([[join(cwd, '.dsh/task-LIVE-1.json'), JSON.stringify(state)], [join(cwd, 'app.js'), 'source']])
|
|
18
45
|
const events = [], runs = []
|
|
@@ -48,6 +75,92 @@ function fixture(stage = '开发', extra = {}, services = {}) {
|
|
|
48
75
|
state: () => JSON.parse(records.get(join(cwd, '.dsh/task-LIVE-1.json'))) }
|
|
49
76
|
}
|
|
50
77
|
|
|
78
|
+
test('manual skill evidence is approved by the host without a shell command', async () => {
|
|
79
|
+
const config = resolveFlow('minimal', { flow: 'minimal', stage_bindings: {
|
|
80
|
+
'开发': { skills: [{ skill: { source: 'project', name: 'human-check' }, rules: [], evidence: 'manual' }] },
|
|
81
|
+
} }).config
|
|
82
|
+
const approvals = []
|
|
83
|
+
const f = fixture('开发', { flow: { flow: 'minimal', version: 3, config } }, {
|
|
84
|
+
approval: { request: async request => { approvals.push(request); return 'allowed-once' } },
|
|
85
|
+
})
|
|
86
|
+
f.load('human-check')
|
|
87
|
+
await f.call({ operation: 'skill_result', skill_name: 'human-check', evidence: ['checked by owner'] })
|
|
88
|
+
assert.equal(f.runs.length, 0)
|
|
89
|
+
assert.equal(approvals.length, 1)
|
|
90
|
+
assert.equal(f.state().skill_results['开发']['human-check'].approved, true)
|
|
91
|
+
assert.deepEqual(JSON.parse(await f.call({ operation: 'status' })).skill_blockers, [])
|
|
92
|
+
const denied = fixture('开发', { flow: { flow: 'minimal', version: 3, config } }, {
|
|
93
|
+
approval: { request: async () => 'rejected' },
|
|
94
|
+
})
|
|
95
|
+
denied.load('human-check')
|
|
96
|
+
await assert.rejects(denied.call({ operation: 'skill_result', skill_name: 'human-check', evidence: ['claimed approval'] }), /not approved/)
|
|
97
|
+
assert.equal(denied.state().skill_results?.['开发']?.['human-check'], undefined)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('completion rejects unresolved terminal skills and rules', async () => {
|
|
101
|
+
const config = resolveFlow('minimal', { flow: 'minimal', stage_bindings: {
|
|
102
|
+
'交付': { skills: [{ skill: { source: 'project', name: 'must-run' }, rules: [{ source: 'project', name: 'missing' }], evidence: 'command' }] },
|
|
103
|
+
} }).config
|
|
104
|
+
const f = fixture('交付', {
|
|
105
|
+
flow: { flow: 'minimal', version: 3, config },
|
|
106
|
+
items: [{ id: 'A', title: 'small', status: 'done', review: { spec: { outcome: 'pass' }, quality: { outcome: 'pass' } } }],
|
|
107
|
+
commits: [{ label: 'TASK', hash: 'abcdef1' }],
|
|
108
|
+
})
|
|
109
|
+
const status = JSON.parse(await f.call({ operation: 'status' }))
|
|
110
|
+
assert.ok(status.skill_blockers.length > 0)
|
|
111
|
+
assert.ok(status.missing_rules.length > 0)
|
|
112
|
+
await assert.rejects(f.call({ operation: 'complete' }), /cannot complete.*must-run|cannot complete.*missing/)
|
|
113
|
+
assert.equal(f.state().completed, undefined)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('same-named skill and rule freeze separately and disclose the rule body', async () => {
|
|
117
|
+
const f = fixture()
|
|
118
|
+
f.records.delete(join(f.cwd, '.dsh/task-LIVE-1.json'))
|
|
119
|
+
f.records.set(join(f.cwd, '.dsh/eng.json'), JSON.stringify({ flow: 'minimal', stage_bindings: {
|
|
120
|
+
'开发': { skills: [{ skill: { source: 'project', name: 'custom' }, rules: [{ source: 'project', name: 'custom' }], evidence: 'none' }] },
|
|
121
|
+
} }))
|
|
122
|
+
f.records.set(join(f.cwd, '.dsh/skills/custom/SKILL.md'), 'SKILL BODY')
|
|
123
|
+
f.records.set(join(f.cwd, '.dsh/rules/custom.md'), 'RULE BODY')
|
|
124
|
+
await f.call({ operation: 'create', title: 'collision', branch: 'main', files: ['app.js'] })
|
|
125
|
+
const resources = f.state().flow.resources.filter(resource => resource.ref.name === 'custom')
|
|
126
|
+
assert.deepEqual(resources.map(resource => resource.kind).sort(), ['rule', 'skill'])
|
|
127
|
+
assert.equal(JSON.parse(await f.call({ operation: 'status' })).bindings.rules[0].content, 'RULE BODY')
|
|
128
|
+
f.records.set(join(f.cwd, '.dsh/skills/custom/SKILL.md'), 'CHANGED SKILL')
|
|
129
|
+
assert.equal(JSON.parse(await f.call({ operation: 'status' })).bindings.skill_contents[0].content, 'SKILL BODY')
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('task creation applies skill_profiles rules even when legacy inline bindings are empty', async () => {
|
|
133
|
+
const f = fixture()
|
|
134
|
+
const skill = { source: 'project', name: 'custom' }
|
|
135
|
+
const rule = { source: 'project', name: 'my-rule' }
|
|
136
|
+
f.records.delete(join(f.cwd, '.dsh/task-LIVE-1.json'))
|
|
137
|
+
f.records.set(join(f.cwd, '.dsh/eng.json'), JSON.stringify({ flow: 'minimal',
|
|
138
|
+
stage_bindings: {
|
|
139
|
+
'开发': { skills: [{ skill, rules: [], evidence: 'none' }] },
|
|
140
|
+
'交付': { skills: [{ skill, rules: [], evidence: 'none' }] },
|
|
141
|
+
},
|
|
142
|
+
skill_profiles: { 'project:custom': { rules: [rule], evidence: 'none' } },
|
|
143
|
+
}))
|
|
144
|
+
f.records.set(join(f.cwd, '.dsh/skills/custom/SKILL.md'), 'SKILL BODY')
|
|
145
|
+
await assert.rejects(f.call({ operation: 'create', title: 'profile regression', branch: 'main', files: ['app.js'] }), /rule:project:my-rule/)
|
|
146
|
+
f.records.set(join(f.cwd, '.dsh/rules/my-rule.md'), 'RULE BODY')
|
|
147
|
+
await f.call({ operation: 'create', title: 'profile regression', branch: 'main', files: ['app.js'] })
|
|
148
|
+
assert.deepEqual(f.state().flow.config.stage_bindings['开发'].skills[0].rules, [rule])
|
|
149
|
+
assert.deepEqual(f.state().flow.config.stage_bindings['交付'].skills[0].rules, [rule])
|
|
150
|
+
assert.equal(f.state().flow.resources.find(resource => resource.kind === 'rule')?.content, 'RULE BODY')
|
|
151
|
+
assert.equal(JSON.parse(await f.call({ operation: 'status' })).bindings.rules[0].content, 'RULE BODY')
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
test('task creation rejects an unavailable skill or rule before writing a record', async () => {
|
|
155
|
+
const f = fixture()
|
|
156
|
+
f.records.delete(join(f.cwd, '.dsh/task-LIVE-1.json'))
|
|
157
|
+
f.records.set(join(f.cwd, '.dsh/eng.json'), JSON.stringify({ flow: 'minimal', stage_bindings: {
|
|
158
|
+
'开发': { skills: [{ skill: { source: 'project', name: 'missing-skill' }, rules: [] }] },
|
|
159
|
+
} }))
|
|
160
|
+
await assert.rejects(f.call({ operation: 'create', title: 'missing', branch: 'main' }), /unreadable bound resources/)
|
|
161
|
+
assert.equal(f.records.has(join(f.cwd, '.dsh/task-LIVE-1.json')), false)
|
|
162
|
+
})
|
|
163
|
+
|
|
51
164
|
test('审查通过后更新状态并激活下一项,保留已完成项的审计', async () => {
|
|
52
165
|
const f = fixture()
|
|
53
166
|
await f.call({ operation: 'items', items: [{ id: 'A', title: 'first', status: 'doing' }, { id: 'B', title: 'second' }] })
|
|
@@ -168,7 +281,7 @@ test('status 披露当前阶段记录字段和缺项,字段误用不写入且
|
|
|
168
281
|
})
|
|
169
282
|
|
|
170
283
|
test('记录字段来自冻结流程,精简流程不硬编码标准字段,无记录阶段返回空列表', async () => {
|
|
171
|
-
const config =
|
|
284
|
+
const config = adoptedFlow('agile')
|
|
172
285
|
const f = fixture('需求', { flow: { flow: 'agile', version: 1, config } })
|
|
173
286
|
assert.deepEqual(JSON.parse(await f.call({ operation: 'status' })).artifact_requirements, [{ id: 'requirement', name: '需求说明', fields: ['scope'], missing_fields: ['scope'] }])
|
|
174
287
|
await f.call({ operation: 'record', artifact: 'requirement', fields: { scope: '目标、验收与疑问' } })
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
让 AI 修改代码时,你可以先明确需求,再检查方案、推进实施、验证结果,最后审核提交。DSH Task Engine 把这些步骤组织成可检查、可追踪的任务流程,适合在本机使用 DeepSeek Harness 开发个人项目。
|
|
28
28
|
|
|
29
29
|
- **知道下一步做什么**:按所选流程推进,当前阶段需要的条件和产物清楚可查。
|
|
30
|
-
-
|
|
30
|
+
- **复用自己的工作方法**:把技能和规则安装到项目或个人目录,将规则配置在技能下,再把技能挂到节点上;同一技能在任何节点都使用同一套约束。
|
|
31
31
|
- **找得到过程记录**:任务台账集中查看阶段、实施项、验证与审核状态。
|
|
32
32
|
|
|
33
33
|
## 快速开始
|
|
@@ -51,22 +51,24 @@ dsh plugin --profile web add @godv61/dsh-task-engine
|
|
|
51
51
|
| 页面 | 你可以做什么 |
|
|
52
52
|
| :--- | :--- |
|
|
53
53
|
| **项目初始化** | 查看或编辑 `AGENTS.md`,让 AI 生成项目说明,预览后保存。 |
|
|
54
|
-
| **流程配置** |
|
|
54
|
+
| **流程配置** | 选择流程骨架,给节点挂技能,并在技能上配置它遵循的规则。需要现成起点时可「采用推荐配置」。 |
|
|
55
55
|
| **任务台账** | 查看实施、验证和审核记录,按关键词、阶段或风险筛选。 |
|
|
56
|
-
| **技能** |
|
|
56
|
+
| **技能** | 安装、编辑技能,并集中维护每个技能唯一的规则列表。 |
|
|
57
57
|
| **规则** | 选择 Markdown 文件安装规则,维护项目或个人开发约定。 |
|
|
58
58
|
|
|
59
59
|
内置技能和规则只读;项目与个人资源可编辑。安装、删除都会明确展示目标位置。
|
|
60
60
|
|
|
61
|
+
**流程与工作方法是两回事。** 流程只决定工作怎么流转(阶段顺序与门禁),预设不自带任何技能或提交格式。要用什么技能、遵守哪些规则、提交信息写什么,都由你配置——「采用推荐配置」只是把一份现成的起点**写入**你的配置,之后完全归你:删掉的不再补回,升级也不覆盖。规则挂在技能下,所以打开一个技能看到的就是它完整的规则列表,挂到任何节点都一样。
|
|
62
|
+
|
|
61
63
|
## 选择适合这次任务的流程
|
|
62
64
|
|
|
63
65
|
| 预设 | 阶段顺序 | 适用场景 |
|
|
64
66
|
| :--- | :--- | :--- |
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
67
|
+
| **完整研发** `standard` | 需求评审 → 设计 → 开发 → 交付 → 代码审核 → 完成 | 需要需求、方案和交付检查的完整开发任务。 |
|
|
68
|
+
| **日常迭代** `agile` | 需求 → 开发 → 交付 → 审查 | 目标明确的日常开发任务。 |
|
|
69
|
+
| **快速修改** `minimal` | 开发 → 交付 | 已明确做法的小改动。 |
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
阶段顺序和检查条件由预设固定;技能与规则由用户配置。选择流程不会强制加入内置技能;需要现成起点时可显式采用推荐配置。**可视化自定义流程不在计划内**,详见[功能规划](docs/roadmap.md)。
|
|
70
72
|
|
|
71
73
|
## 把自己的技能和规则带进来
|
|
72
74
|
|
|
@@ -96,7 +98,7 @@ dsh plugin --profile web add @godv61/dsh-task-engine
|
|
|
96
98
|
|
|
97
99
|
## 能力说明
|
|
98
100
|
|
|
99
|
-
`dev_task`
|
|
101
|
+
`dev_task` 按配置检查阶段、产物和提交条件。新任务的验证要求真实命令回执;技能可按自身配置要求命令、产物、审核、人工批准或无需额外证据,执行义务可在任务状态中查看。任务保存创建时的流程与资源快照,之后修改项目配置不会直接改变进行中的任务。
|
|
100
102
|
|
|
101
103
|
审核结论、实施项完成情况和测试覆盖面仍需要你判断。本地提交钩子提供即时检查,不能替代人工审核或项目自己的 CI。详细说明见[常见问题](docs/faq.md)。
|
|
102
104
|
|
package/cordis.patch.yml
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# dsh-task-engine bundle: one host-plane row that mounts the `task-engine`
|
|
2
|
-
# Remote namespace (what the browser workbench reads/writes) plus, via
|
|
3
|
-
# `dsh.client`, the workbench UI. This host row registers NO model-facing tool
|
|
4
|
-
# and NO skill — `dev_task` and the shipped skills live on the AGENT plane,
|
|
5
|
-
# behind the `@godv61/dsh-task-engine/agent` entry. A preset's
|
|
6
|
-
# `agent.cordis.yml` names that agent row to activate the flow for its
|
|
7
|
-
# sessions; presets that never name it get neither the tool nor the skills
|
|
8
|
-
# (the workbench stays available so a human can still configure the flow).
|
|
9
|
-
- insert:
|
|
10
|
-
- id: task-engine
|
|
1
|
+
# dsh-task-engine bundle: one host-plane row that mounts the `task-engine`
|
|
2
|
+
# Remote namespace (what the browser workbench reads/writes) plus, via
|
|
3
|
+
# `dsh.client`, the workbench UI. This host row registers NO model-facing tool
|
|
4
|
+
# and NO skill — `dev_task` and the shipped skills live on the AGENT plane,
|
|
5
|
+
# behind the `@godv61/dsh-task-engine/agent` entry. A preset's
|
|
6
|
+
# `agent.cordis.yml` names that agent row to activate the flow for its
|
|
7
|
+
# sessions; presets that never name it get neither the tool nor the skills
|
|
8
|
+
# (the workbench stays available so a human can still configure the flow).
|
|
9
|
+
- insert:
|
|
10
|
+
- id: task-engine
|
|
11
11
|
name: '@godv61/dsh-task-engine'
|
package/defaults/eng.json
CHANGED
|
@@ -2,48 +2,96 @@
|
|
|
2
2
|
"flow": "standard",
|
|
3
3
|
"stage_bindings": {
|
|
4
4
|
"需求评审": {
|
|
5
|
-
"
|
|
5
|
+
"skill_refs": [
|
|
6
6
|
{
|
|
7
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"source": "bundled",
|
|
8
|
+
"name": "requirement-analysis"
|
|
9
9
|
}
|
|
10
10
|
]
|
|
11
11
|
},
|
|
12
12
|
"设计": {
|
|
13
|
-
"
|
|
14
|
-
{
|
|
13
|
+
"skill_refs": [
|
|
14
|
+
{
|
|
15
|
+
"source": "bundled",
|
|
16
|
+
"name": "solution-design"
|
|
17
|
+
}
|
|
15
18
|
]
|
|
16
19
|
},
|
|
17
20
|
"开发": {
|
|
18
|
-
"
|
|
21
|
+
"skill_refs": [
|
|
19
22
|
{
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
{ "source": "bundled", "name": "coding-conventions" },
|
|
23
|
-
{ "source": "bundled", "name": "security-redlines" }
|
|
24
|
-
]
|
|
23
|
+
"source": "bundled",
|
|
24
|
+
"name": "code-implement"
|
|
25
25
|
}
|
|
26
26
|
]
|
|
27
27
|
},
|
|
28
28
|
"交付": {
|
|
29
|
-
"
|
|
30
|
-
{
|
|
29
|
+
"skill_refs": [
|
|
30
|
+
{
|
|
31
|
+
"source": "bundled",
|
|
32
|
+
"name": "code-verify"
|
|
33
|
+
}
|
|
31
34
|
]
|
|
32
35
|
},
|
|
33
36
|
"代码审核": {
|
|
34
|
-
"
|
|
37
|
+
"skill_refs": [
|
|
38
|
+
{
|
|
39
|
+
"source": "bundled",
|
|
40
|
+
"name": "code-review"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"source": "bundled",
|
|
44
|
+
"name": "code-commit"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"skill_profiles": {
|
|
50
|
+
"bundled:requirement-analysis": {
|
|
51
|
+
"rules": [
|
|
52
|
+
{
|
|
53
|
+
"source": "bundled",
|
|
54
|
+
"name": "security-redlines"
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"bundled:solution-design": {
|
|
59
|
+
"rules": []
|
|
60
|
+
},
|
|
61
|
+
"bundled:code-implement": {
|
|
62
|
+
"rules": [
|
|
35
63
|
{
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
{ "source": "bundled", "name": "coding-conventions" },
|
|
39
|
-
{ "source": "bundled", "name": "security-redlines" }
|
|
40
|
-
]
|
|
64
|
+
"source": "bundled",
|
|
65
|
+
"name": "coding-conventions"
|
|
41
66
|
},
|
|
42
67
|
{
|
|
43
|
-
"
|
|
44
|
-
"
|
|
68
|
+
"source": "bundled",
|
|
69
|
+
"name": "security-redlines"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"bundled:code-verify": {
|
|
74
|
+
"rules": []
|
|
75
|
+
},
|
|
76
|
+
"bundled:code-review": {
|
|
77
|
+
"rules": [
|
|
78
|
+
{
|
|
79
|
+
"source": "bundled",
|
|
80
|
+
"name": "coding-conventions"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"source": "bundled",
|
|
84
|
+
"name": "security-redlines"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
"bundled:code-commit": {
|
|
89
|
+
"rules": [
|
|
90
|
+
{
|
|
91
|
+
"source": "bundled",
|
|
92
|
+
"name": "commit-conventions"
|
|
45
93
|
}
|
|
46
94
|
]
|
|
47
95
|
}
|
|
48
96
|
}
|
|
49
|
-
}
|
|
97
|
+
}
|