Cicero 0.13 to 0.20
Much has changed in the 0.20
release. This guide provides step-by-step instructions to port your Accord Project templates from version 0.13
or earlier to version 0.20
.
note
Before following those migration instructions, make sure to first install version 0.20
of Cicero, as described in the Install Cicero Section of this documentation.
Metadata Changes
You will first need to update the package.json
in your template. Remove the Ergo version which is now unnecessary, and change the Cicero version to ^0.20.0
.
Example
After those changes, the accordproject
field in your package.json
should look as follows (with the template
field being either clause
or contract
depending on the template):
...
"accordproject": {
"template": "clause",
"cicero": "^0.20.0"
}
...
Template Directory Changes
The layout of templates has changed to reflect the conceptual notion of Accord Project templates (as a triangle composed of text, model and logic). To migrate a template directory from version 0.13
or earlier to the new 0.20
layout:
- Rename your
lib
directory tologic
- Rename your
models
directory tomodel
- Rename your
grammar
directory totext
- Rename your template grammar from
text/template.tem
totext/grammar.tem.md
- Rename your samples from
sample.txt
totext/sample.md
(or generally any othersample*.txt
files totext/sample*.md
)
Example
Consider the late delivery and penalty clause. After applying those changes, the template directory should look as follows:
./.cucumber.js
./README.md
./package.json
./request-forcemajeure.json
./request.json
./state.json
./logic:
./logic/logic.ergo
./model:
./model/clause.cto
./test:
./test/logic.feature
./test/logic_default.feature
./text:
./text/grammar.tem.md
./text/sample-noforcemajeure.md
./text/sample.md
Text Changes
Both grammar and sample text for the templates has changed to support rich text annotations through CommonMark and a new syntax for variables. You can find complete information about the new syntax in the CiceroMark Section of this documentation. For an existing template, you should apply the following changes.
Text Grammar Changes
- Variables should be changed from
[{variableName}]
to{{variableName}}
- Formatted variables should be changed to from
[{variableName as "FORMAT"}]
to{{variableName as "FORMAT"}}
- Boolean variables should be changed to use the new block syntax, from
[{"This is a force majeure":?forceMajeure}]
to{{#if forceMajeure}}This is a force majeure{{/if}}
- Nested clauses should be changed to use the new block syntax, from
[{#payment}]As consideration in full for the rights granted herein...[{/payment}]
to{{#clause payment}}As consideration in full for the rights granted herein...{{/clause}}
note
- Template text is now interpreted as CommonMark which may lead to unexpected results if your text includes CommonMark characters or structure (e.g.,
#
or##
now become headings;1.
or-
now become lists). You should review both the grammar and samples so they follow the proper CommonMark rules. - The new lexer reserves
{{
instead of reserving[{
which means you should avoid using{{
in your text unless for Accord Project variables.
Text Samples Changes
You should ensure that any changes to the grammar text is reflected in the samples. Any change in the grammar text outside of variables should be applied to the corresponding sample.md
files as well.
tip
You can check that the samples and grammar are in agreement by using the cicero parse
command.
Example
Consider the text grammar for the late delivery and penalty clause:
Late Delivery and Penalty.
In case of delayed delivery[{" except for Force Majeure cases,":? forceMajeure}]
[{seller}] (the Seller) shall pay to [{buyer}] (the Buyer) for every [{penaltyDuration}]
of delay penalty amounting to [{penaltyPercentage}]% of the total value of the Equipment
whose delivery has been delayed. Any fractional part of a [{fractionalPart}] is to be
considered a full [{fractionalPart}]. The total amount of penalty shall not however,
exceed [{capPercentage}]% of the total value of the Equipment involved in late delivery.
If the delay is more than [{termination}], the Buyer is entitled to terminate this Contract.
After applying the above rules to the code for the 0.13
version, and identifying the heading for the clause using the new markdown features, the grammar text becomes:
## Late Delivery and Penalty.
In case of delayed delivery{{#if forceMajeure}} except for Force Majeure cases,{{/if}}
{{seller}} (the Seller) shall pay to {{buyer}} (the Buyer) for every {{penaltyDuration}}
of delay penalty amounting to {{penaltyPercentage}}% of the total value of the Equipment
whose delivery has been delayed. Any fractional part of a {{fractionalPart}} is to be
considered a full {{fractionalPart}}. The total amount of penalty shall not however,
exceed {{capPercentage}}% of the total value of the Equipment involved in late delivery.
If the delay is more than {{termination}}, the Buyer is entitled to terminate this Contract.
To make sure the sample.md
file parses as well, the heading needs to be similarly identified using markdown:
## Late Delivery and Penalty.
In case of delayed delivery except for Force Majeure cases,
"Dan" (the Seller) shall pay to "Steve" (the Buyer) for every 2 days
of delay penalty amounting to 10.5% of the total value of the Equipment
whose delivery has been delayed. Any fractional part of a days is to be
considered a full days. The total amount of penalty shall not however,
exceed 55% of the total value of the Equipment involved in late delivery.
If the delay is more than 15 days, the Buyer is entitled to terminate this Contract.
Model Changes
There is no model changes required for this version.
Logic Changes
Version 0.20
of Ergo has a few new features that are non backward compatible with version 0.13
. Those may require you to change your template logic. The main non-backward compatible feature is the new support for enumerated values.
Enumerated Values
Enumerated values are now proper values with a proper enum type, and not based on the type String
anymore.
For instance, consider the enum declaration:
enum Cardsuit {
o CLUBS
o DIAMONDS
o HEARTS
o SPADES
}
In version 0.13
or earlier the Ergo code would write "CLUBS"
for an enum value and treat the type Cardsuit
as if it was the type String
.
As of version 0.20
Ergo writes CLUBS
for that same enum value and the type Cardsuit
is now distinct from the type String
.
If you try to compile Ergo logic written for version 0.13
or earlier that features enumerated values, the compiler will likely throw type errors. You should apply the following changes:
- Remove the quotes (
"
) around any enum values in your logic. E.g.,"USD"
should now be replaced byUSD
for monetary amounts; - If enum values are bound to variables with a type annotation, you should change the type annotation from
String
to the correct enum type. E.g.,let x : String = "DIAMONDS"; ...
should becomelet x : Cardsuit = DIAMONDS; ...
; - If enum values are passed as parameters in clauses or functions, you should change the type annotation for that parameter from
String
to the correct enum type. - In a few cases the same enumerated value may be used in different enum types (e.g.,
days
andweeks
are used in bothTemporalUnit
andPeriodUnit
). Those two values will now have different types. If you need to distinguish, you can use the fully qualified name for the enum value (e.g.,~org.accordproject.time.TemporalUnit.days
or~org.accordproject.time.PeriodUnit.days
).
Other Changes
now
used to return the current time but is treated in0.20
like any other variables. If your logic used the variablenow
without declaring it, this will raise aVariable now not found
error. You should change your logic to use thenow()
function instead.
Example
Consider the Ergo logic for the acceptance of delivery clause. Applying the above rules to the code for the 0.13
version:
clause acceptanceofdelivery(request : InspectDeliverable) : InspectionResponse {
let received = request.deliverableReceivedAt;
enforce isBefore(received,now) else
throw ErgoErrorResponse{ message : "Transaction time is before the deliverable date." }
;
let dur =
Duration{
amount: contract.businessDays,
unit: "days"
};
let status =
if isAfter(now(), addDuration(received, dur))
then "OUTSIDE_INSPECTION_PERIOD"
else if request.inspectionPassed
then "PASSED_TESTING"
else "FAILED_TESTING"
;
return InspectionResponse{
status : status,
shipper : contract.shipper,
receiver : contract.receiver
}
}
results in the following new logic for the 0.20
version:
clause acceptanceofdelivery(request : InspectDeliverable) : InspectionResponse {
let received = request.deliverableReceivedAt;
enforce isBefore(received,now()) else // changed to now()
throw ErgoErrorResponse{ message : "Transaction time is before the deliverable date." }
;
let dur =
Duration{
amount: contract.businessDays,
unit: ~org.accordproject.time.TemporalUnit.days // enum value with fully qualified name
};
let status =
if isAfter(now(), addDuration(received, dur)) // changed to now()
then OUTSIDE_INSPECTION_PERIOD // enum value has no quotes
else if request.inspectionPassed
then PASSED_TESTING // enum value has no quotes
else FAILED_TESTING // enum value has no quotes
;
return InspectionResponse{
status : status,
shipper : contract.shipper,
receiver : contract.receiver
}
}
Command Line Changes
The Command Line interface for Cicero and Ergo has been completely overhauled for consistency. Release 0.20
also features new command line interfaces for Concerto and for the new markdown-transform
project.
If you are familiar with the previous Accord Project command line interfaces (or if you have scripts relying on the previous version of the command line), here is a list of changes:
- Ergo: A single new
ergo
command replaces bothergoc
andergorun
ergoc
has been replaced byergo compile
ergorun execute
has been replaced byergo trigger
ergorun init
has been replaced byergo initialize
- All other
ergorun <command>
commands should useergo <command>
instead
- Cicero:
- The
cicero execute
command has been replaced bycicero trigger
- The
cicero init
command has been replaced bycicero initialize
- The
cicero generateText
command has been replaced bycicero draft
- the
cicero generate
command has been replaced bycicero compile
- The
Note that several options have been renamed for consistency as well. Some of the main option changes are:
--out
and--outputDirectory
have both been replaced by--output
--format
has been replaced by--target
in the newcicero compile
command--contract
has been replaced by--data
in allergo
commands
For more details on the new command line interface, please consult the corresponding Cicero CLI, Concerto CLI, Ergo CLI, and Markus CLI Sections in the reference manual.
API Changes
A number of API changes may affect Node.js applications using Cicero or Ergo packages. The main API changes are:
- Ergo:
@accordproject/ergo-engine
package- the
Engine.execute()
call has been renamedEngine.trigger()
- the
- Cicero:
@accordproject/cicero-core
package- the
TemplateInstance.generateText()
call has been renamedTemplateInstance.draft
and is now anasync
call - the
Metadata.getErgoVersion()
call has been removed
- the
@accordproject/cicero-engine
package- the
Engine.execute()
call has been renamedEngine.trigger()
- the
Engine.generateText()
call has been renamedEngine.draft()
- the
Cicero Server Changes
Cicero server API has been changed to reflect the new underlying Cicero engine. Specifically:
- The
execute
endpoint has been renamedtrigger
- The path to the sample has to include the
text
directory, so instead ofexecute/templateName/sample.txt
it should usetrigger/templateName/text%2Fsample.md
Example
Following the README.md instructions, instead of calling:
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' http://localhost:6001/execute/latedeliveryandpenalty/sample.txt -d '{ "request": { "$class": "org.accordproject.latedeliveryandpenalty.LateDeliveryAndPenaltyRequest", "forceMajeure": false,"agreedDelivery": "December 17, 2017 03:24:00", "deliveredAt": null, "goodsValue": 200.00 }, "state": { "$class": "org.accordproject.cicero.contract.AccordContractState", "stateId" : "org.accordproject.cicero.contract.AccordContractState#1"}}'
You should call:
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' http://localhost:6001/trigger/latedeliveryandpenalty/sample.md -d '{ "request": { "$class": "org.accordproject.latedeliveryandpenalty.LateDeliveryAndPenaltyRequest", "forceMajeure": false,"agreedDelivery": "December 17, 2017 03:24:00", "deliveredAt": null, "goodsValue": 200.00 }, "state": { "$class": "org.accordproject.cicero.contract.AccordContractState", "stateId" : "org.accordproject.cicero.contract.AccordContractState#1"}}'